Array unification switch
[hiphop-php.git] / hphp / hack / src / decl / direct_decl_smart_constructors.rs
blob9c3106544a727f810f811ab2754d48eefb737e26
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 std::collections::BTreeMap;
7 use std::rc::Rc;
9 use bstr::BStr;
10 use bumpalo::{
11     collections::{String, Vec},
12     Bump,
15 use hh_autoimport_rust as hh_autoimport;
16 use naming_special_names_rust as naming_special_names;
18 use arena_collections::{AssocListMut, MultiSetMut};
19 use flatten_smart_constructors::{FlattenOp, FlattenSmartConstructors};
20 use namespaces::ElaborateKind;
21 use namespaces_rust as namespaces;
22 use oxidized_by_ref::{
23     aast, aast_defs,
24     ast_defs::{Bop, ClassKind, ConstraintKind, FunKind, Id, ShapeFieldName, Uop, Variance},
25     decl_defs::MethodReactivity,
26     direct_decl_parser::Decls,
27     file_info::Mode,
28     method_flags::MethodFlags,
29     namespace_env::Env as NamespaceEnv,
30     nast,
31     pos::Pos,
32     prop_flags::PropFlags,
33     relative_path::RelativePath,
34     s_map::SMap,
35     shallow_decl_defs::{
36         self, Decl, ShallowClassConst, ShallowMethod, ShallowProp, ShallowTypeconst,
37     },
38     shape_map::ShapeField,
39     typing_defs::{
40         self, Capability::*, ConstDecl, EnumType, FunArity, FunElt, FunImplicitParams, FunParam,
41         FunParams, FunType, IfcFunDecl, ParamMode, ParamMutability, ParamRxAnnotation,
42         PossiblyEnforcedTy, Reactivity, RecordFieldReq, ShapeFieldType, ShapeKind, TaccessType,
43         Tparam, Ty, Ty_, TypeconstAbstractKind, TypedefType, WhereConstraint, XhpAttrTag,
44     },
45     typing_defs_flags::{FunParamFlags, FunTypeFlags},
46     typing_reason::Reason,
48 use parser_core_types::{
49     compact_token::CompactToken, indexed_source_text::IndexedSourceText, source_text::SourceText,
50     syntax_kind::SyntaxKind, token_factory::SimpleTokenFactoryImpl, token_kind::TokenKind,
53 mod direct_decl_smart_constructors_generated;
55 type SK = SyntaxKind;
57 type SSet<'a> = arena_collections::SortedSet<'a, &'a str>;
59 type NamespaceMap = BTreeMap<std::string::String, std::string::String>;
61 #[derive(Clone)]
62 pub struct DirectDeclSmartConstructors<'a> {
63     pub token_factory: SimpleTokenFactoryImpl<CompactToken>,
65     pub source_text: IndexedSourceText<'a>,
66     pub arena: &'a bumpalo::Bump,
67     pub decls: Decls<'a>,
68     pub disable_xhp_element_mangling: bool,
69     pub array_unification: bool,
70     filename: &'a RelativePath<'a>,
71     file_mode: Mode,
72     namespace_builder: Rc<NamespaceBuilder<'a>>,
73     classish_name_builder: ClassishNameBuilder<'a>,
74     type_parameters: Rc<Vec<'a, SSet<'a>>>,
76     previous_token_kind: TokenKind,
79 impl<'a> DirectDeclSmartConstructors<'a> {
80     pub fn new(
81         src: &SourceText<'a>,
82         file_mode: Mode,
83         disable_xhp_element_mangling: bool,
84         array_unification: bool,
85         auto_namespace_map: &'a NamespaceMap,
86         arena: &'a Bump,
87     ) -> Self {
88         let source_text = IndexedSourceText::new(src.clone());
89         let path = source_text.source_text().file_path();
90         let prefix = path.prefix();
91         let path = String::from_str_in(path.path_str(), arena).into_bump_str();
92         let filename = RelativePath::make(prefix, path);
93         Self {
94             token_factory: SimpleTokenFactoryImpl::new(),
96             source_text,
97             arena,
98             filename: arena.alloc(filename),
99             file_mode,
100             disable_xhp_element_mangling,
101             array_unification,
102             decls: Decls::empty(),
103             namespace_builder: Rc::new(NamespaceBuilder::new_in(
104                 auto_namespace_map,
105                 disable_xhp_element_mangling,
106                 arena,
107             )),
108             classish_name_builder: ClassishNameBuilder::new(),
109             type_parameters: Rc::new(Vec::new_in(arena)),
110             // EndOfFile is used here as a None value (signifying "beginning of
111             // file") to save space. There is no legitimate circumstance where
112             // we would parse a token and the previous token kind would be
113             // EndOfFile.
114             previous_token_kind: TokenKind::EndOfFile,
115         }
116     }
118     #[inline(always)]
119     pub fn alloc<T>(&self, val: T) -> &'a T {
120         self.arena.alloc(val)
121     }
123     fn qualified_name_from_parts(&self, parts: &'a [Node<'a>], pos: &'a Pos<'a>) -> Id<'a> {
124         // Count the length of the qualified name, so that we can allocate
125         // exactly the right amount of space for it in our arena.
126         let mut len = 0;
127         for part in parts {
128             match part {
129                 Node::Name(&(name, _)) => len += name.len(),
130                 Node::Token(t) if t.kind() == TokenKind::Backslash => len += 1,
131                 Node::ListItem(&(Node::Name(&(name, _)), _backslash)) => len += name.len() + 1,
132                 Node::ListItem(&(Node::Token(t), _backslash))
133                     if t.kind() == TokenKind::Namespace =>
134                 {
135                     len += t.width() + 1;
136                 }
137                 _ => {}
138             }
139         }
140         // If there's no internal trivia, then we can just reference the
141         // qualified name in the original source text instead of copying it.
142         let source_len = pos.end_cnum() - pos.start_cnum();
143         if source_len == len {
144             let qualified_name = self.str_from_utf8(self.source_text_at_pos(pos));
145             return Id(pos, qualified_name);
146         }
147         // Allocate `len` bytes and fill them with the fully qualified name.
148         let mut qualified_name = String::with_capacity_in(len, self.arena);
149         for part in parts {
150             match part {
151                 Node::Name(&(name, _pos)) => qualified_name.push_str(&name),
152                 Node::Token(t) if t.kind() == TokenKind::Backslash => qualified_name.push('\\'),
153                 &Node::ListItem(&(Node::Name(&(name, _)), _backslash)) => {
154                     qualified_name.push_str(&name);
155                     qualified_name.push_str("\\");
156                 }
157                 &Node::ListItem(&(Node::Token(t), _backslash))
158                     if t.kind() == TokenKind::Namespace =>
159                 {
160                     qualified_name.push_str("namespace\\");
161                 }
162                 Node::ListItem(listitem) => {
163                     panic!(
164                         "Expected ListItem with name and backslash, but got {:?}",
165                         listitem
166                     );
167                 }
168                 n => {
169                     panic!("Expected a name, backslash, or list item, but got {:?}", n);
170                 }
171             }
172         }
173         debug_assert_eq!(len, qualified_name.len());
174         debug_assert_eq!(len, qualified_name.capacity());
175         Id(pos, qualified_name.into_bump_str())
176     }
178     /// If the given node is an identifier, XHP name, or qualified name,
179     /// elaborate it in the current namespace and return Some. To be used for
180     /// the name of a decl in its definition (e.g., "C" in `class C {}` or "f"
181     /// in `function f() {}`).
182     fn elaborate_defined_id(&self, name: Node<'a>) -> Option<Id<'a>> {
183         let id = match name {
184             Node::Name(&(name, pos)) => Id(pos, name),
185             Node::XhpName(&(name, pos)) => Id(pos, name),
186             Node::QualifiedName(&(parts, pos)) => self.qualified_name_from_parts(parts, pos),
187             _ => return None,
188         };
189         Some(self.namespace_builder.elaborate_defined_id(id))
190     }
192     /// If the given node is a name (i.e., an identifier or a qualified name),
193     /// return Some. No namespace elaboration is performed.
194     fn expect_name(&self, name: Node<'a>) -> Option<Id<'a>> {
195         // If it's a simple identifier, return it.
196         if let id @ Some(_) = name.as_id() {
197             return id;
198         }
199         match name {
200             Node::QualifiedName(&(parts, pos)) => Some(self.qualified_name_from_parts(parts, pos)),
201             Node::Token(t) if t.kind() == TokenKind::XHP => {
202                 let pos = self.token_pos(t);
203                 let text = self.str_from_utf8(self.source_text_at_pos(pos));
204                 Some(Id(pos, text))
205             }
206             _ => None,
207         }
208     }
210     /// Fully qualify the given identifier as a type name (with consideration
211     /// to `use` statements in scope).
212     fn elaborate_id(&self, id: Id<'a>) -> Id<'a> {
213         let Id(pos, name) = id;
214         Id(pos, self.elaborate_raw_id(name))
215     }
217     /// Fully qualify the given identifier as a type name (with consideration
218     /// to `use` statements in scope).
219     fn elaborate_raw_id(&self, id: &'a str) -> &'a str {
220         self.namespace_builder
221             .elaborate_raw_id(ElaborateKind::Class, id)
222     }
224     /// Fully qualify the given identifier as a constant name (with
225     /// consideration to `use` statements in scope).
226     fn elaborate_const_id(&self, id: Id<'a>) -> Id<'a> {
227         let Id(pos, name) = id;
228         Id(
229             pos,
230             self.namespace_builder
231                 .elaborate_raw_id(ElaborateKind::Const, name),
232         )
233     }
235     fn slice<T>(&self, iter: impl Iterator<Item = T>) -> &'a [T] {
236         let mut result = match iter.size_hint().1 {
237             Some(upper_bound) => Vec::with_capacity_in(upper_bound, self.arena),
238             None => Vec::new_in(self.arena),
239         };
240         for item in iter {
241             result.push(item);
242         }
243         result.into_bump_slice()
244     }
246     fn unwrap_mutability(hint: Node<'a>) -> (Node<'a>, Option<ParamMutability>) {
247         match hint {
248             Node::Ty(Ty(_, Ty_::Tapply((hn, [t])))) if hn.1 == "\\Mutable" => {
249                 (Node::Ty(t), Some(ParamMutability::ParamBorrowedMutable))
250             }
251             Node::Ty(Ty(_, Ty_::Tapply((hn, [t])))) if hn.1 == "\\OwnedMutable" => {
252                 (Node::Ty(t), Some(ParamMutability::ParamOwnedMutable))
253             }
254             Node::Ty(Ty(_, Ty_::Tapply((hn, [t])))) if hn.1 == "\\MaybeMutable" => {
255                 (Node::Ty(t), Some(ParamMutability::ParamMaybeMutable))
256             }
257             _ => (hint, None),
258         }
259     }
262 fn prefix_slash<'a>(arena: &'a Bump, name: &str) -> &'a str {
263     let mut s = String::with_capacity_in(1 + name.len(), arena);
264     s.push('\\');
265     s.push_str(name);
266     s.into_bump_str()
269 fn prefix_colon<'a>(arena: &'a Bump, name: &str) -> &'a str {
270     let mut s = String::with_capacity_in(1 + name.len(), arena);
271     s.push(':');
272     s.push_str(name);
273     s.into_bump_str()
276 fn concat<'a>(arena: &'a Bump, str1: &str, str2: &str) -> &'a str {
277     let mut result = String::with_capacity_in(str1.len() + str2.len(), arena);
278     result.push_str(str1);
279     result.push_str(str2);
280     result.into_bump_str()
283 fn str_from_utf8<'a>(arena: &'a Bump, slice: &'a [u8]) -> &'a str {
284     if let Ok(s) = std::str::from_utf8(slice) {
285         s
286     } else {
287         String::from_utf8_lossy_in(slice, arena).into_bump_str()
288     }
291 fn strip_dollar_prefix<'a>(name: &'a str) -> &'a str {
292     name.trim_start_matches("$")
295 const TANY_: Ty_<'_> = Ty_::Tany(oxidized_by_ref::tany_sentinel::TanySentinel);
296 const TANY: &Ty<'_> = &Ty(Reason::none(), TANY_);
298 fn tany() -> &'static Ty<'static> {
299     TANY
302 fn default_ifc_fun_decl<'a>() -> IfcFunDecl<'a> {
303     IfcFunDecl::FDPolicied(Some("PUBLIC"))
306 #[derive(Debug)]
307 struct Modifiers {
308     is_static: bool,
309     visibility: aast::Visibility,
310     is_abstract: bool,
311     is_final: bool,
314 fn read_member_modifiers<'a: 'b, 'b>(modifiers: impl Iterator<Item = &'b Node<'a>>) -> Modifiers {
315     let mut ret = Modifiers {
316         is_static: false,
317         visibility: aast::Visibility::Public,
318         is_abstract: false,
319         is_final: false,
320     };
321     for modifier in modifiers {
322         if let Some(vis) = modifier.as_visibility() {
323             ret.visibility = vis;
324         }
325         match modifier.token_kind() {
326             Some(TokenKind::Static) => ret.is_static = true,
327             Some(TokenKind::Abstract) => ret.is_abstract = true,
328             Some(TokenKind::Final) => ret.is_final = true,
329             _ => {}
330         }
331     }
332     ret
335 #[derive(Clone, Debug)]
336 struct NamespaceBuilder<'a> {
337     arena: &'a Bump,
338     stack: Vec<'a, NamespaceEnv<'a>>,
339     auto_ns_map: &'a [(&'a str, &'a str)],
342 impl<'a> NamespaceBuilder<'a> {
343     fn new_in(
344         auto_ns_map: &'a NamespaceMap,
345         disable_xhp_element_mangling: bool,
346         arena: &'a Bump,
347     ) -> Self {
348         let mut arena_ns_map = Vec::with_capacity_in(auto_ns_map.len(), arena);
349         for (k, v) in auto_ns_map.iter() {
350             arena_ns_map.push((k.as_str(), v.as_str()));
351         }
352         let auto_ns_map = arena_ns_map.into_bump_slice();
354         let mut ns_uses = SMap::empty();
355         for &alias in hh_autoimport::NAMESPACES {
356             ns_uses = ns_uses.add(arena, alias, concat(arena, "HH\\", alias));
357         }
358         for (alias, ns) in auto_ns_map.iter() {
359             ns_uses = ns_uses.add(arena, alias, ns);
360         }
362         let mut class_uses = SMap::empty();
363         for &alias in hh_autoimport::TYPES {
364             class_uses = class_uses.add(arena, alias, concat(arena, "HH\\", alias));
365         }
367         NamespaceBuilder {
368             arena,
369             stack: bumpalo::vec![in arena; NamespaceEnv {
370                 ns_uses,
371                 class_uses,
372                 fun_uses: SMap::empty(),
373                 const_uses: SMap::empty(),
374                 record_def_uses: SMap::empty(),
375                 name: None,
376                 auto_ns_map,
377                 is_codegen: false,
378                 disable_xhp_element_mangling,
379             }],
380             auto_ns_map,
381         }
382     }
384     fn empty_with_ns_in(ns: &'a str, arena: &'a Bump) -> Self {
385         NamespaceBuilder {
386             arena,
387             stack: bumpalo::vec![in arena; NamespaceEnv {
388                 ns_uses: SMap::empty(),
389                 class_uses: SMap::empty(),
390                 fun_uses: SMap::empty(),
391                 const_uses: SMap::empty(),
392                 record_def_uses: SMap::empty(),
393                 name: Some(ns),
394                 auto_ns_map: &[],
395                 is_codegen: false,
396                 disable_xhp_element_mangling: false,
397             }],
398             auto_ns_map: &[],
399         }
400     }
402     fn push_namespace(&mut self, name: Option<&str>) {
403         let current = self.current_namespace();
404         let nsenv = self.stack.last().unwrap().clone(); // shallow clone
405         if let Some(name) = name {
406             let mut fully_qualified = match current {
407                 None => String::with_capacity_in(name.len(), self.arena),
408                 Some(current) => {
409                     let mut fully_qualified =
410                         String::with_capacity_in(current.len() + name.len() + 1, self.arena);
411                     fully_qualified.push_str(current);
412                     fully_qualified.push('\\');
413                     fully_qualified
414                 }
415             };
416             fully_qualified.push_str(name);
417             self.stack.push(NamespaceEnv {
418                 name: Some(fully_qualified.into_bump_str()),
419                 ..nsenv
420             });
421         } else {
422             self.stack.push(NamespaceEnv {
423                 name: current,
424                 ..nsenv
425             });
426         }
427     }
429     fn pop_namespace(&mut self) {
430         // We'll never push a namespace for a declaration of items in the global
431         // namespace (e.g., `namespace { ... }`), so only pop if we are in some
432         // namespace other than the global one.
433         if self.stack.len() > 1 {
434             self.stack.pop().unwrap();
435         }
436     }
438     // push_namespace(Y) + pop_namespace() + push_namespace(X) should be equivalent to
439     // push_namespace(Y) + push_namespace(X) + pop_previous_namespace()
440     fn pop_previous_namespace(&mut self) {
441         if self.stack.len() > 2 {
442             let last = self.stack.pop().unwrap().name.unwrap_or("\\");
443             let previous = self.stack.pop().unwrap().name.unwrap_or("\\");
444             assert!(last.starts_with(previous));
445             let name = &last[previous.len() + 1..last.len()];
446             self.push_namespace(Some(name));
447         }
448     }
450     fn current_namespace(&self) -> Option<&'a str> {
451         self.stack.last().and_then(|nsenv| nsenv.name)
452     }
454     fn add_import(&mut self, kind: TokenKind, name: &'a str, aliased_name: Option<&'a str>) {
455         let stack_top = &mut self
456             .stack
457             .last_mut()
458             .expect("Attempted to get the current import map, but namespace stack was empty");
459         let aliased_name = aliased_name.unwrap_or_else(|| {
460             name.rsplit_terminator('\\')
461                 .nth(0)
462                 .expect("Expected at least one entry in import name")
463         });
464         let name = name.trim_end_matches('\\');
465         let name = if name.starts_with('\\') {
466             name
467         } else {
468             prefix_slash(self.arena, name)
469         };
470         match kind {
471             TokenKind::Type => {
472                 stack_top.class_uses = stack_top.class_uses.add(self.arena, aliased_name, name);
473             }
474             TokenKind::Namespace => {
475                 stack_top.ns_uses = stack_top.ns_uses.add(self.arena, aliased_name, name);
476             }
477             TokenKind::Mixed => {
478                 stack_top.class_uses = stack_top.class_uses.add(self.arena, aliased_name, name);
479                 stack_top.ns_uses = stack_top.ns_uses.add(self.arena, aliased_name, name);
480             }
481             _ => panic!("Unexpected import kind: {:?}", kind),
482         }
483     }
485     fn elaborate_raw_id(&self, kind: ElaborateKind, name: &'a str) -> &'a str {
486         if name.starts_with('\\') {
487             return name;
488         }
489         let env = self.stack.last().unwrap();
490         namespaces::elaborate_raw_id_in(self.arena, env, kind, name)
491     }
493     fn elaborate_defined_id(&self, id: Id<'a>) -> Id<'a> {
494         let Id(pos, name) = id;
495         let env = self.stack.last().unwrap();
496         let name = if env.disable_xhp_element_mangling && name.contains(':') {
497             let xhp_name_opt = namespaces::elaborate_xhp_namespace(name);
498             let name = xhp_name_opt.map_or(name, |s| self.arena.alloc_str(&s));
499             if !name.starts_with('\\') {
500                 namespaces::elaborate_into_current_ns_in(self.arena, env, name)
501             } else {
502                 name
503             }
504         } else {
505             namespaces::elaborate_into_current_ns_in(self.arena, env, name)
506         };
507         Id(pos, name)
508     }
511 #[derive(Clone, Debug)]
512 enum ClassishNameBuilder<'a> {
513     /// We are not in a classish declaration.
514     NotInClassish,
516     /// We saw a classish keyword token followed by a Name, so we make it
517     /// available as the name of the containing class declaration.
518     InClassish(&'a (&'a str, &'a Pos<'a>, TokenKind)),
521 impl<'a> ClassishNameBuilder<'a> {
522     fn new() -> Self {
523         ClassishNameBuilder::NotInClassish
524     }
526     fn lexed_name_after_classish_keyword(
527         &mut self,
528         arena: &'a Bump,
529         name: &'a str,
530         pos: &'a Pos<'a>,
531         token_kind: TokenKind,
532     ) {
533         use ClassishNameBuilder::*;
534         match self {
535             NotInClassish => {
536                 let name = if name.starts_with(':') {
537                     prefix_slash(arena, name)
538                 } else {
539                     name
540                 };
541                 *self = InClassish(arena.alloc((name, pos, token_kind)))
542             }
543             InClassish(_) => {}
544         }
545     }
547     fn parsed_classish_declaration(&mut self) {
548         *self = ClassishNameBuilder::NotInClassish;
549     }
551     fn get_current_classish_name(&self) -> Option<(&'a str, &'a Pos<'a>)> {
552         use ClassishNameBuilder::*;
553         match self {
554             NotInClassish => None,
555             InClassish((name, pos, _)) => Some((name, pos)),
556         }
557     }
559     fn in_interface(&self) -> bool {
560         use ClassishNameBuilder::*;
561         match self {
562             InClassish((_, _, TokenKind::Interface)) => true,
563             InClassish((_, _, _)) | NotInClassish => false,
564         }
565     }
568 #[derive(Debug)]
569 pub struct FunParamDecl<'a> {
570     attributes: Node<'a>,
571     visibility: Node<'a>,
572     kind: ParamMode,
573     hint: Node<'a>,
574     pos: &'a Pos<'a>,
575     name: Option<&'a str>,
576     variadic: bool,
577     initializer: Node<'a>,
580 #[derive(Debug)]
581 pub struct FunctionHeader<'a> {
582     name: Node<'a>,
583     modifiers: Node<'a>,
584     type_params: Node<'a>,
585     param_list: Node<'a>,
586     capability: Node<'a>,
587     ret_hint: Node<'a>,
588     where_constraints: Node<'a>,
591 #[derive(Debug)]
592 pub struct RequireClause<'a> {
593     require_type: Node<'a>,
594     name: Node<'a>,
597 #[derive(Debug)]
598 pub struct TypeParameterDecl<'a> {
599     name: Node<'a>,
600     reified: aast::ReifyKind,
601     variance: Variance,
602     constraints: &'a [(ConstraintKind, Node<'a>)],
603     tparam_params: &'a [&'a Tparam<'a>],
604     user_attributes: &'a [&'a UserAttributeNode<'a>],
607 #[derive(Debug)]
608 pub struct ClosureTypeHint<'a> {
609     args: Node<'a>,
610     ret_hint: Node<'a>,
613 #[derive(Debug)]
614 pub struct NamespaceUseClause<'a> {
615     kind: TokenKind,
616     id: Id<'a>,
617     as_: Option<&'a str>,
620 #[derive(Debug)]
621 pub struct ConstructorNode<'a> {
622     method: &'a ShallowMethod<'a>,
623     properties: &'a [ShallowProp<'a>],
626 #[derive(Debug)]
627 pub struct MethodNode<'a> {
628     method: &'a ShallowMethod<'a>,
629     is_static: bool,
632 #[derive(Debug)]
633 pub struct PropertyNode<'a> {
634     decls: &'a [ShallowProp<'a>],
635     is_static: bool,
638 #[derive(Debug)]
639 pub struct XhpClassAttributeDeclarationNode<'a> {
640     xhp_attr_decls: &'a [ShallowProp<'a>],
641     xhp_attr_uses_decls: &'a [Node<'a>],
644 #[derive(Debug)]
645 pub struct XhpClassAttributeNode<'a> {
646     name: Id<'a>,
647     tag: Option<XhpAttrTag>,
648     needs_init: bool,
649     nullable: bool,
650     hint: Node<'a>,
653 #[derive(Debug)]
654 pub struct ShapeFieldNode<'a> {
655     name: &'a ShapeField<'a>,
656     type_: &'a ShapeFieldType<'a>,
659 #[derive(Copy, Clone, Debug)]
660 struct ClassNameParam<'a> {
661     name: Id<'a>,
662     full_pos: &'a Pos<'a>, // Position of the full expression `Foo::class`
665 #[derive(Debug)]
666 pub struct UserAttributeNode<'a> {
667     name: Id<'a>,
668     classname_params: &'a [ClassNameParam<'a>],
669     string_literal_params: &'a [&'a BStr], // this is only used for __Deprecated attribute message and Cipp parameters
672 mod fixed_width_token {
673     use parser_core_types::token_kind::TokenKind;
674     use std::convert::TryInto;
676     #[derive(Copy, Clone)]
677     pub struct FixedWidthToken(u64); // { offset: u56, kind: TokenKind }
679     const KIND_BITS: u8 = 8;
680     const KIND_MASK: u64 = u8::MAX as u64;
681     const MAX_OFFSET: u64 = !(KIND_MASK << (64 - KIND_BITS));
683     impl FixedWidthToken {
684         pub fn new(kind: TokenKind, offset: usize) -> Self {
685             // We don't want to spend bits tracking the width of fixed-width
686             // tokens. Since we don't track width, verify that this token kind
687             // is in fact a fixed-width kind.
688             debug_assert!(kind.fixed_width().is_some());
690             let offset: u64 = offset.try_into().unwrap();
691             if offset > MAX_OFFSET {
692                 panic!("FixedWidthToken: offset too large");
693             }
694             Self(offset << KIND_BITS | kind as u8 as u64)
695         }
697         pub fn offset(self) -> usize {
698             (self.0 >> KIND_BITS).try_into().unwrap()
699         }
701         pub fn kind(self) -> TokenKind {
702             TokenKind::try_from_u8(self.0 as u8).unwrap()
703         }
705         pub fn width(self) -> usize {
706             self.kind().fixed_width().unwrap().get()
707         }
708     }
710     impl std::fmt::Debug for FixedWidthToken {
711         fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
712             fmt.debug_struct("FixedWidthToken")
713                 .field("kind", &self.kind())
714                 .field("offset", &self.offset())
715                 .finish()
716         }
717     }
719 use fixed_width_token::FixedWidthToken;
721 #[derive(Copy, Clone, Debug)]
722 pub enum Node<'a> {
723     // Nodes which are not useful in constructing a decl are ignored. We keep
724     // track of the SyntaxKind for two reasons.
725     //
726     // One is that the parser needs to know the SyntaxKind of a parsed node in
727     // some circumstances (this information is exposed to the parser via an
728     // implementation of `smart_constructors::NodeType`). An adapter called
729     // WithKind exists to provide a `NodeType` implementation for arbitrary
730     // nodes by pairing each node with a SyntaxKind, but in the direct decl
731     // parser, we want to avoid the extra 8 bytes of overhead on each node.
732     //
733     // The second reason is that debugging is difficult when nodes are silently
734     // ignored, and providing at least the SyntaxKind of an ignored node helps
735     // in tracking down the reason it was ignored.
736     Ignored(SyntaxKind),
738     List(&'a &'a [Node<'a>]),
739     BracketedList(&'a (&'a Pos<'a>, &'a [Node<'a>], &'a Pos<'a>)),
740     Name(&'a (&'a str, &'a Pos<'a>)),
741     XhpName(&'a (&'a str, &'a Pos<'a>)),
742     QualifiedName(&'a (&'a [Node<'a>], &'a Pos<'a>)),
743     StringLiteral(&'a (&'a BStr, &'a Pos<'a>)), // For shape keys and const expressions.
744     IntLiteral(&'a (&'a str, &'a Pos<'a>)),     // For const expressions.
745     FloatingLiteral(&'a (&'a str, &'a Pos<'a>)), // For const expressions.
746     BooleanLiteral(&'a (&'a str, &'a Pos<'a>)), // For const expressions.
747     Ty(&'a Ty<'a>),
748     ListItem(&'a (Node<'a>, Node<'a>)),
749     Const(&'a ShallowClassConst<'a>),
750     ConstInitializer(&'a (Node<'a>, Node<'a>)), // Name, initializer expression
751     FunParam(&'a FunParamDecl<'a>),
752     Attribute(&'a UserAttributeNode<'a>),
753     FunctionHeader(&'a FunctionHeader<'a>),
754     Constructor(&'a ConstructorNode<'a>),
755     Method(&'a MethodNode<'a>),
756     Property(&'a PropertyNode<'a>),
757     TraitUse(&'a Node<'a>),
758     XhpClassAttributeDeclaration(&'a XhpClassAttributeDeclarationNode<'a>),
759     XhpClassAttribute(&'a XhpClassAttributeNode<'a>),
760     XhpAttributeUse(&'a Node<'a>),
761     TypeConstant(&'a ShallowTypeconst<'a>),
762     RequireClause(&'a RequireClause<'a>),
763     ClassishBody(&'a &'a [Node<'a>]),
764     TypeParameter(&'a TypeParameterDecl<'a>),
765     TypeConstraint(&'a (ConstraintKind, Node<'a>)),
766     ShapeFieldSpecifier(&'a ShapeFieldNode<'a>),
767     NamespaceUseClause(&'a NamespaceUseClause<'a>),
768     Expr(&'a nast::Expr<'a>),
769     TypeParameters(&'a &'a [&'a Tparam<'a>]),
770     WhereConstraint(&'a WhereConstraint<'a>),
771     RecordField(&'a (Id<'a>, RecordFieldReq)),
773     // Non-ignored, fixed-width tokens (e.g., keywords, operators, braces, etc.).
774     Token(FixedWidthToken),
777 impl<'a> smart_constructors::NodeType for Node<'a> {
778     type R = Node<'a>;
780     fn extract(self) -> Self::R {
781         self
782     }
784     fn is_abstract(&self) -> bool {
785         self.is_token(TokenKind::Abstract)
786             || matches!(self, Node::Ignored(SK::Token(TokenKind::Abstract)))
787     }
788     fn is_name(&self) -> bool {
789         matches!(self, Node::Name(..)) || matches!(self, Node::Ignored(SK::Token(TokenKind::Name)))
790     }
791     fn is_qualified_name(&self) -> bool {
792         matches!(self, Node::QualifiedName(..)) || matches!(self, Node::Ignored(SK::QualifiedName))
793     }
794     fn is_prefix_unary_expression(&self) -> bool {
795         matches!(self, Node::Expr(aast::Expr(_, aast::Expr_::Unop(..))))
796             || matches!(self, Node::Ignored(SK::PrefixUnaryExpression))
797     }
798     fn is_scope_resolution_expression(&self) -> bool {
799         matches!(self, Node::Expr(aast::Expr(_, aast::Expr_::ClassConst(..))))
800             || matches!(self, Node::Ignored(SK::ScopeResolutionExpression))
801     }
802     fn is_missing(&self) -> bool {
803         matches!(self, Node::Ignored(SK::Missing))
804     }
805     fn is_variable_expression(&self) -> bool {
806         matches!(self, Node::Ignored(SK::VariableExpression))
807     }
808     fn is_subscript_expression(&self) -> bool {
809         matches!(self, Node::Ignored(SK::SubscriptExpression))
810     }
811     fn is_member_selection_expression(&self) -> bool {
812         matches!(self, Node::Ignored(SK::MemberSelectionExpression))
813     }
814     fn is_object_creation_expression(&self) -> bool {
815         matches!(self, Node::Ignored(SK::ObjectCreationExpression))
816     }
817     fn is_safe_member_selection_expression(&self) -> bool {
818         matches!(self, Node::Ignored(SK::SafeMemberSelectionExpression))
819     }
820     fn is_function_call_expression(&self) -> bool {
821         matches!(self, Node::Ignored(SK::FunctionCallExpression))
822     }
823     fn is_list_expression(&self) -> bool {
824         matches!(self, Node::Ignored(SK::ListExpression))
825     }
828 impl<'a> Node<'a> {
829     fn is_token(self, kind: TokenKind) -> bool {
830         self.token_kind() == Some(kind)
831     }
833     fn token_kind(self) -> Option<TokenKind> {
834         match self {
835             Node::Token(token) => Some(token.kind()),
836             _ => None,
837         }
838     }
840     fn as_slice(self, b: &'a Bump) -> &'a [Self] {
841         match self {
842             Node::List(&items) | Node::BracketedList(&(_, items, _)) => items,
843             n if n.is_ignored() => &[],
844             n => std::slice::from_ref(b.alloc(n)),
845         }
846     }
848     fn iter<'b>(&'b self) -> NodeIterHelper<'a, 'b>
849     where
850         'a: 'b,
851     {
852         match self {
853             &Node::List(&items) | Node::BracketedList(&(_, items, _)) => {
854                 NodeIterHelper::Vec(items.iter())
855             }
856             n if n.is_ignored() => NodeIterHelper::Empty,
857             n => NodeIterHelper::Single(n),
858         }
859     }
861     // The number of elements which would be yielded by `self.iter()`.
862     // Must return the upper bound returned by NodeIterHelper::size_hint.
863     fn len(&self) -> usize {
864         match self {
865             &Node::List(&items) | Node::BracketedList(&(_, items, _)) => items.len(),
866             n if n.is_ignored() => 0,
867             _ => 1,
868         }
869     }
871     fn as_visibility(&self) -> Option<aast::Visibility> {
872         match self.token_kind() {
873             Some(TokenKind::Private) => Some(aast::Visibility::Private),
874             Some(TokenKind::Protected) => Some(aast::Visibility::Protected),
875             Some(TokenKind::Public) => Some(aast::Visibility::Public),
876             _ => None,
877         }
878     }
880     // If this node is a simple unqualified identifier, return its position and text.
881     fn as_id(&self) -> Option<Id<'a>> {
882         match self {
883             Node::Name(&(name, pos)) | Node::XhpName(&(name, pos)) => Some(Id(pos, name)),
884             _ => None,
885         }
886     }
888     fn is_ignored(&self) -> bool {
889         matches!(self, Node::Ignored(..))
890     }
892     fn is_present(&self) -> bool {
893         !self.is_ignored()
894     }
897 struct Attributes<'a> {
898     reactivity: Reactivity<'a>,
899     reactivity_condition_type: Option<&'a Ty<'a>>,
900     param_mutability: Option<ParamMutability>,
901     deprecated: Option<&'a str>,
902     reifiable: Option<&'a Pos<'a>>,
903     returns_mutable: bool,
904     late_init: bool,
905     const_: bool,
906     lsb: bool,
907     memoizelsb: bool,
908     override_: bool,
909     at_most_rx_as_func: bool,
910     enforceable: Option<&'a Pos<'a>>,
911     returns_void_to_rx: bool,
912     accept_disposable: bool,
913     dynamically_callable: bool,
914     returns_disposable: bool,
915     php_std_lib: bool,
916     ifc_attribute: IfcFunDecl<'a>,
917     external: bool,
918     can_call: bool,
919     atom: bool,
922 impl<'a> DirectDeclSmartConstructors<'a> {
923     fn add_class(&mut self, name: &'a str, decl: &'a shallow_decl_defs::ShallowClass<'a>) {
924         self.decls.add(name, Decl::Class(decl), self.arena);
925     }
926     fn add_fun(&mut self, name: &'a str, decl: &'a typing_defs::FunElt<'a>) {
927         self.decls.add(name, Decl::Fun(decl), self.arena);
928     }
929     fn add_typedef(&mut self, name: &'a str, decl: &'a typing_defs::TypedefType<'a>) {
930         self.decls.add(name, Decl::Typedef(decl), self.arena);
931     }
932     fn add_const(&mut self, name: &'a str, decl: &'a typing_defs::ConstDecl<'a>) {
933         self.decls.add(name, Decl::Const(decl), self.arena);
934     }
935     fn add_record(&mut self, name: &'a str, decl: &'a typing_defs::RecordDefType<'a>) {
936         self.decls.add(name, Decl::Record(decl), self.arena);
937     }
939     fn token_bytes(&self, token: &CompactToken) -> &'a [u8] {
940         self.source_text
941             .source_text()
942             .sub(token.start_offset(), token.width())
943     }
945     // Check that the slice is valid UTF-8. If it is, return a &str referencing
946     // the same data. Otherwise, copy the slice into our arena using
947     // String::from_utf8_lossy_in, and return a reference to the arena str.
948     fn str_from_utf8(&self, slice: &'a [u8]) -> &'a str {
949         str_from_utf8(self.arena, slice)
950     }
952     fn merge(
953         &self,
954         pos1: impl Into<Option<&'a Pos<'a>>>,
955         pos2: impl Into<Option<&'a Pos<'a>>>,
956     ) -> &'a Pos<'a> {
957         match (pos1.into(), pos2.into()) {
958             (None, None) => Pos::none(),
959             (Some(pos), None) | (None, Some(pos)) => pos,
960             (Some(pos1), Some(pos2)) => match (pos1.is_none(), pos2.is_none()) {
961                 (true, true) => Pos::none(),
962                 (true, false) => pos2,
963                 (false, true) => pos1,
964                 (false, false) => Pos::merge_without_checking_filename(self.arena, pos1, pos2),
965             },
966         }
967     }
969     fn merge_positions(&self, node1: Node<'a>, node2: Node<'a>) -> &'a Pos<'a> {
970         self.merge(self.get_pos(node1), self.get_pos(node2))
971     }
973     fn pos_from_slice(&self, nodes: &[Node<'a>]) -> &'a Pos<'a> {
974         nodes.iter().fold(Pos::none(), |acc, &node| {
975             self.merge(acc, self.get_pos(node))
976         })
977     }
979     fn get_pos(&self, node: Node<'a>) -> &'a Pos<'a> {
980         self.get_pos_opt(node).unwrap_or(Pos::none())
981     }
983     fn get_pos_opt(&self, node: Node<'a>) -> Option<&'a Pos<'a>> {
984         let pos = match node {
985             Node::Name(&(_, pos)) => pos,
986             Node::Ty(ty) => return ty.get_pos(),
987             Node::XhpName(&(_, pos)) => pos,
988             Node::QualifiedName(&(_, pos)) => pos,
989             Node::IntLiteral(&(_, pos))
990             | Node::FloatingLiteral(&(_, pos))
991             | Node::StringLiteral(&(_, pos))
992             | Node::BooleanLiteral(&(_, pos)) => pos,
993             Node::ListItem(&(fst, snd)) => self.merge_positions(fst, snd),
994             Node::List(items) => self.pos_from_slice(&items),
995             Node::BracketedList(&(first_pos, inner_list, second_pos)) => self.merge(
996                 first_pos,
997                 self.merge(self.pos_from_slice(inner_list), second_pos),
998             ),
999             Node::Expr(&aast::Expr(pos, _)) => pos,
1000             Node::Token(token) => self.token_pos(token),
1001             _ => return None,
1002         };
1003         if pos.is_none() { None } else { Some(pos) }
1004     }
1006     fn token_pos(&self, token: FixedWidthToken) -> &'a Pos<'a> {
1007         let start = token.offset();
1008         let end = start + token.width();
1009         let start = self.source_text.offset_to_file_pos_triple(start);
1010         let end = self.source_text.offset_to_file_pos_triple(end);
1011         Pos::from_lnum_bol_cnum(self.arena, self.filename, start, end)
1012     }
1014     fn node_to_expr(&self, node: Node<'a>) -> Option<&'a nast::Expr<'a>> {
1015         let expr_ = match node {
1016             Node::Expr(expr) => return Some(expr),
1017             Node::IntLiteral(&(s, _)) => aast::Expr_::Int(s),
1018             Node::FloatingLiteral(&(s, _)) => aast::Expr_::Float(s),
1019             Node::StringLiteral(&(s, _)) => aast::Expr_::String(s),
1020             Node::BooleanLiteral((s, _)) => {
1021                 if s.eq_ignore_ascii_case("true") {
1022                     aast::Expr_::True
1023                 } else {
1024                     aast::Expr_::False
1025                 }
1026             }
1027             Node::Token(t) if t.kind() == TokenKind::NullLiteral => aast::Expr_::Null,
1028             Node::Name(..) | Node::QualifiedName(..) => {
1029                 aast::Expr_::Id(self.alloc(self.elaborate_const_id(self.expect_name(node)?)))
1030             }
1031             _ => return None,
1032         };
1033         let pos = self.get_pos(node);
1034         Some(self.alloc(aast::Expr(pos, expr_)))
1035     }
1037     fn node_to_non_ret_ty(&self, node: Node<'a>) -> Option<&'a Ty<'a>> {
1038         self.node_to_ty_(node, false)
1039     }
1041     fn node_to_ty(&self, node: Node<'a>) -> Option<&'a Ty<'a>> {
1042         self.node_to_ty_(node, true)
1043     }
1045     fn node_to_ty_(&self, node: Node<'a>, allow_non_ret_ty: bool) -> Option<&'a Ty<'a>> {
1046         match node {
1047             Node::Ty(Ty(reason, Ty_::Tprim(aast::Tprim::Tvoid))) if !allow_non_ret_ty => {
1048                 Some(self.alloc(Ty(reason, Ty_::Terr)))
1049             }
1050             Node::Ty(Ty(reason, Ty_::Tprim(aast::Tprim::Tnoreturn))) if !allow_non_ret_ty => {
1051                 Some(self.alloc(Ty(reason, Ty_::Terr)))
1052             }
1053             Node::Ty(ty) => Some(ty),
1054             Node::Expr(expr) => {
1055                 fn expr_to_ty<'a>(arena: &'a Bump, expr: &'a nast::Expr<'a>) -> Option<Ty_<'a>> {
1056                     use aast::Expr_::*;
1057                     match expr.1 {
1058                         Null => Some(Ty_::Tprim(arena.alloc(aast::Tprim::Tnull))),
1059                         This => Some(Ty_::Tthis),
1060                         True | False => Some(Ty_::Tprim(arena.alloc(aast::Tprim::Tbool))),
1061                         Int(_) => Some(Ty_::Tprim(arena.alloc(aast::Tprim::Tint))),
1062                         Float(_) => Some(Ty_::Tprim(arena.alloc(aast::Tprim::Tfloat))),
1063                         String(_) => Some(Ty_::Tprim(arena.alloc(aast::Tprim::Tstring))),
1064                         String2(_) => Some(Ty_::Tprim(arena.alloc(aast::Tprim::Tstring))),
1065                         PrefixedString(_) => Some(Ty_::Tprim(arena.alloc(aast::Tprim::Tstring))),
1066                         Unop(&(_op, expr)) => expr_to_ty(arena, expr),
1067                         Any => Some(TANY_),
1069                         ArrayGet(_) | As(_) | Await(_) | Binop(_) | Call(_) | Callconv(_)
1070                         | Cast(_) | ClassConst(_) | ClassGet(_) | Clone(_) | Collection(_)
1071                         | Darray(_) | Dollardollar(_) | Efun(_) | Eif(_) | EnumAtom(_)
1072                         | ETSplice(_) | ExpressionTree(_) | FunctionPointer(_) | FunId(_)
1073                         | Id(_) | Import(_) | Is(_) | KeyValCollection(_) | Lfun(_) | List(_)
1074                         | Lplaceholder(_) | Lvar(_) | MethodCaller(_) | MethodId(_) | New(_)
1075                         | ObjGet(_) | Omitted | Pair(_) | Pipe(_) | Record(_) | Shape(_)
1076                         | SmethodId(_) | ValCollection(_) | Varray(_) | Xml(_) | Yield(_) => None,
1077                     }
1078                 }
1080                 Some(self.alloc(Ty(
1081                     self.alloc(Reason::witness(expr.0)),
1082                     expr_to_ty(self.arena, expr)?,
1083                 )))
1084             }
1085             Node::IntLiteral((_, pos)) => Some(self.alloc(Ty(
1086                 self.alloc(Reason::witness(pos)),
1087                 Ty_::Tprim(self.alloc(aast::Tprim::Tint)),
1088             ))),
1089             Node::FloatingLiteral((_, pos)) => Some(self.alloc(Ty(
1090                 self.alloc(Reason::witness(pos)),
1091                 Ty_::Tprim(self.alloc(aast::Tprim::Tfloat)),
1092             ))),
1093             Node::StringLiteral((_, pos)) => Some(self.alloc(Ty(
1094                 self.alloc(Reason::witness(pos)),
1095                 Ty_::Tprim(self.alloc(aast::Tprim::Tstring)),
1096             ))),
1097             Node::BooleanLiteral((_, pos)) => Some(self.alloc(Ty(
1098                 self.alloc(Reason::witness(pos)),
1099                 Ty_::Tprim(self.alloc(aast::Tprim::Tbool)),
1100             ))),
1101             Node::Token(t) if t.kind() == TokenKind::Varray => {
1102                 let pos = self.token_pos(t);
1103                 let tany = self.alloc(Ty(self.alloc(Reason::hint(pos)), TANY_));
1104                 Some(self.alloc(Ty(self.alloc(Reason::hint(pos)), Ty_::Tvarray(tany))))
1105             }
1106             Node::Token(t) if t.kind() == TokenKind::Darray => {
1107                 let pos = self.token_pos(t);
1108                 let tany = self.alloc(Ty(self.alloc(Reason::hint(pos)), TANY_));
1109                 Some(self.alloc(Ty(
1110                     self.alloc(Reason::hint(pos)),
1111                     Ty_::Tdarray(self.alloc((tany, tany))),
1112                 )))
1113             }
1114             Node::Token(t) if t.kind() == TokenKind::This => {
1115                 Some(self.alloc(Ty(self.alloc(Reason::hint(self.token_pos(t))), Ty_::Tthis)))
1116             }
1117             Node::Token(t) if t.kind() == TokenKind::NullLiteral => {
1118                 let pos = self.token_pos(t);
1119                 Some(self.alloc(Ty(
1120                     self.alloc(Reason::hint(pos)),
1121                     Ty_::Tprim(self.alloc(aast::Tprim::Tnull)),
1122                 )))
1123             }
1124             node => {
1125                 let Id(pos, name) = self.expect_name(node)?;
1126                 let reason = self.alloc(Reason::hint(pos));
1127                 let ty_ = if self.is_type_param_in_scope(name) {
1128                     // TODO (T69662957) must fill type args of Tgeneric
1129                     Ty_::Tgeneric(self.alloc((name, &[])))
1130                 } else {
1131                     match name.as_ref() {
1132                         "nothing" => Ty_::Tunion(&[]),
1133                         "nonnull" => Ty_::Tnonnull,
1134                         "dynamic" => Ty_::Tdynamic,
1135                         "varray_or_darray" => {
1136                             let key_type = self.varray_or_darray_key(pos);
1137                             let value_type = self.alloc(Ty(self.alloc(Reason::hint(pos)), TANY_));
1138                             Ty_::TvarrayOrDarray(self.alloc((key_type, value_type)))
1139                         }
1140                         "_" => Ty_::Terr,
1141                         _ => {
1142                             let name = self.elaborate_raw_id(name);
1143                             Ty_::Tapply(self.alloc((Id(pos, name), &[][..])))
1144                         }
1145                     }
1146                 };
1147                 Some(self.alloc(Ty(reason, ty_)))
1148             }
1149         }
1150     }
1152     fn to_attributes(&self, node: Node<'a>) -> Attributes<'a> {
1153         let mut attributes = Attributes {
1154             reactivity: Reactivity::Nonreactive,
1155             reactivity_condition_type: None,
1156             param_mutability: None,
1157             deprecated: None,
1158             reifiable: None,
1159             returns_mutable: false,
1160             late_init: false,
1161             const_: false,
1162             lsb: false,
1163             memoizelsb: false,
1164             override_: false,
1165             at_most_rx_as_func: false,
1166             enforceable: None,
1167             returns_void_to_rx: false,
1168             accept_disposable: false,
1169             dynamically_callable: false,
1170             returns_disposable: false,
1171             php_std_lib: false,
1172             ifc_attribute: default_ifc_fun_decl(),
1173             external: false,
1174             can_call: false,
1175             atom: false,
1176         };
1178         let nodes = match node {
1179             Node::List(&nodes) | Node::BracketedList(&(_, nodes, _)) => nodes,
1180             _ => return attributes,
1181         };
1183         // If we see the attribute `__OnlyRxIfImpl(Foo::class)`, set
1184         // `reactivity_condition_type` to `Foo`.
1185         attributes.reactivity_condition_type = nodes.iter().find_map(|attr| match attr {
1186             Node::Attribute(UserAttributeNode {
1187                 name: Id(_, "__OnlyRxIfImpl"),
1188                 classname_params: &[param],
1189                 ..
1190             }) => Some(self.alloc(Ty(
1191                 self.alloc(Reason::hint(param.full_pos)),
1192                 Ty_::Tapply(self.alloc((param.name, &[][..]))),
1193             ))),
1194             _ => None,
1195         });
1197         let string_or_classname_arg = |attribute: &'a UserAttributeNode| {
1198             attribute
1199                 .string_literal_params
1200                 .first()
1201                 .map(|&x| self.str_from_utf8(x))
1202                 .or_else(|| attribute.classname_params.first().map(|x| x.name.1))
1203         };
1204         let mut ifc_already_policied = false;
1206         // Iterate in reverse, to match the behavior of OCaml decl in error conditions.
1207         for attribute in nodes.iter().rev() {
1208             if let Node::Attribute(attribute) = attribute {
1209                 match attribute.name.1.as_ref() {
1210                     // NB: It is an error to specify more than one of __Rx,
1211                     // __RxShallow, and __RxLocal, so to avoid cloning the
1212                     // condition type, we use Option::take here.
1213                     "__Rx" => {
1214                         attributes.reactivity =
1215                             Reactivity::Reactive(attributes.reactivity_condition_type)
1216                     }
1217                     "__RxShallow" => {
1218                         attributes.reactivity =
1219                             Reactivity::Shallow(attributes.reactivity_condition_type)
1220                     }
1221                     "__RxLocal" => {
1222                         attributes.reactivity =
1223                             Reactivity::Local(attributes.reactivity_condition_type)
1224                     }
1225                     "__Pure" => {
1226                         attributes.reactivity =
1227                             Reactivity::Pure(attributes.reactivity_condition_type);
1228                     }
1229                     "__Cipp" => {
1230                         attributes.reactivity = Reactivity::Cipp(string_or_classname_arg(attribute))
1231                     }
1232                     "__CippGlobal" => {
1233                         attributes.reactivity = Reactivity::CippGlobal;
1234                     }
1235                     "__CippLocal" => {
1236                         attributes.reactivity =
1237                             Reactivity::CippLocal(string_or_classname_arg(attribute))
1238                     }
1239                     "__CippRx" => {
1240                         attributes.reactivity = Reactivity::CippRx;
1241                     }
1242                     "__Mutable" => {
1243                         attributes.param_mutability = Some(ParamMutability::ParamBorrowedMutable)
1244                     }
1245                     "__MaybeMutable" => {
1246                         attributes.param_mutability = Some(ParamMutability::ParamMaybeMutable)
1247                     }
1248                     "__OwnedMutable" => {
1249                         attributes.param_mutability = Some(ParamMutability::ParamOwnedMutable)
1250                     }
1251                     "__MutableReturn" => attributes.returns_mutable = true,
1252                     "__ReturnsVoidToRx" => attributes.returns_void_to_rx = true,
1253                     "__Deprecated" => {
1254                         attributes.deprecated = attribute
1255                             .string_literal_params
1256                             .first()
1257                             .map(|&x| self.str_from_utf8(x));
1258                     }
1259                     "__Reifiable" => attributes.reifiable = Some(attribute.name.0),
1260                     "__LateInit" => {
1261                         attributes.late_init = true;
1262                     }
1263                     "__Const" => {
1264                         attributes.const_ = true;
1265                     }
1266                     "__LSB" => {
1267                         attributes.lsb = true;
1268                     }
1269                     "__MemoizeLSB" => {
1270                         attributes.memoizelsb = true;
1271                     }
1272                     "__Override" => {
1273                         attributes.override_ = true;
1274                     }
1275                     "__AtMostRxAsFunc" => {
1276                         attributes.at_most_rx_as_func = true;
1277                     }
1278                     "__Enforceable" => {
1279                         attributes.enforceable = Some(attribute.name.0);
1280                     }
1281                     "__AcceptDisposable" => {
1282                         attributes.accept_disposable = true;
1283                     }
1284                     "__DynamicallyCallable" => {
1285                         attributes.dynamically_callable = true;
1286                     }
1287                     "__ReturnDisposable" => {
1288                         attributes.returns_disposable = true;
1289                     }
1290                     "__PHPStdLib" => {
1291                         attributes.php_std_lib = true;
1292                     }
1293                     "__Policied" => {
1294                         let string_literal_params = || {
1295                             attribute
1296                                 .string_literal_params
1297                                 .first()
1298                                 .map(|&x| self.str_from_utf8(x))
1299                         };
1300                         // Take the classname param by default
1301                         attributes.ifc_attribute =
1302                             IfcFunDecl::FDPolicied(attribute.classname_params.first().map_or_else(
1303                                 string_literal_params, // default
1304                                 |&x| Some(x.name.1),   // f
1305                             ));
1306                         ifc_already_policied = true;
1307                     }
1308                     "__InferFlows" => {
1309                         if !ifc_already_policied {
1310                             attributes.ifc_attribute = IfcFunDecl::FDInferFlows;
1311                         }
1312                     }
1313                     "__External" => {
1314                         attributes.external = true;
1315                     }
1316                     "__CanCall" => {
1317                         attributes.can_call = true;
1318                     }
1319                     "__Atom" => {
1320                         attributes.atom = true;
1321                     }
1322                     _ => {}
1323                 }
1324             } else {
1325                 panic!("Expected an attribute, but was {:?}", node);
1326             }
1327         }
1329         attributes
1330     }
1332     // Limited version of node_to_ty that matches behavior of Decl_utils.infer_const
1333     fn infer_const(&self, name: Node<'a>, node: Node<'a>) -> Option<&'a Ty<'a>> {
1334         match node {
1335             Node::StringLiteral(_)
1336             | Node::BooleanLiteral(_)
1337             | Node::IntLiteral(_)
1338             | Node::FloatingLiteral(_)
1339             | Node::Expr(aast::Expr(_, aast::Expr_::Unop(&(Uop::Uminus, _))))
1340             | Node::Expr(aast::Expr(_, aast::Expr_::Unop(&(Uop::Uplus, _))))
1341             | Node::Expr(aast::Expr(_, aast::Expr_::String(..))) => self.node_to_ty(node),
1342             Node::Token(t) if t.kind() == TokenKind::NullLiteral => {
1343                 let pos = self.token_pos(t);
1344                 Some(self.alloc(Ty(
1345                     self.alloc(Reason::witness(pos)),
1346                     Ty_::Tprim(self.alloc(aast::Tprim::Tnull)),
1347                 )))
1348             }
1349             _ => Some(self.tany_with_pos(self.get_pos(name))),
1350         }
1351     }
1353     fn pop_type_params(&mut self, node: Node<'a>) -> &'a [&'a Tparam<'a>] {
1354         match node {
1355             Node::TypeParameters(tparams) => {
1356                 Rc::make_mut(&mut self.type_parameters).pop().unwrap();
1357                 tparams
1358             }
1359             _ => &[],
1360         }
1361     }
1363     fn ret_from_fun_kind(&self, kind: FunKind, type_: &'a Ty<'a>) -> &'a Ty<'a> {
1364         let pos = type_.get_pos().unwrap_or_else(|| Pos::none());
1365         match kind {
1366             FunKind::FAsyncGenerator => self.alloc(Ty(
1367                 self.alloc(Reason::RretFunKind(self.alloc((pos, kind)))),
1368                 Ty_::Tapply(self.alloc((
1369                     Id(pos, naming_special_names::classes::ASYNC_GENERATOR),
1370                     self.alloc([type_, type_, type_]),
1371                 ))),
1372             )),
1373             FunKind::FGenerator => self.alloc(Ty(
1374                 self.alloc(Reason::RretFunKind(self.alloc((pos, kind)))),
1375                 Ty_::Tapply(self.alloc((
1376                     Id(pos, naming_special_names::classes::GENERATOR),
1377                     self.alloc([type_, type_, type_]),
1378                 ))),
1379             )),
1380             FunKind::FAsync => self.alloc(Ty(
1381                 self.alloc(Reason::RretFunKind(self.alloc((pos, kind)))),
1382                 Ty_::Tapply(self.alloc((
1383                     Id(pos, naming_special_names::classes::AWAITABLE),
1384                     self.alloc([type_]),
1385                 ))),
1386             )),
1387             _ => type_,
1388         }
1389     }
1391     fn is_type_param_in_scope(&self, name: &str) -> bool {
1392         self.type_parameters.iter().any(|tps| tps.contains(name))
1393     }
1395     fn param_mutability_to_fun_type_flags(
1396         param_mutability: Option<ParamMutability>,
1397     ) -> FunTypeFlags {
1398         match param_mutability {
1399             Some(ParamMutability::ParamBorrowedMutable) => FunTypeFlags::MUTABLE_FLAGS_BORROWED,
1400             Some(ParamMutability::ParamOwnedMutable) => FunTypeFlags::MUTABLE_FLAGS_OWNED,
1401             Some(ParamMutability::ParamMaybeMutable) => FunTypeFlags::MUTABLE_FLAGS_MAYBE,
1402             None => FunTypeFlags::empty(),
1403         }
1404     }
1406     fn param_mutability_to_fun_param_flags(
1407         param_mutability: Option<ParamMutability>,
1408     ) -> FunParamFlags {
1409         match param_mutability {
1410             Some(ParamMutability::ParamBorrowedMutable) => FunParamFlags::MUTABLE_FLAGS_BORROWED,
1411             Some(ParamMutability::ParamOwnedMutable) => FunParamFlags::MUTABLE_FLAGS_OWNED,
1412             Some(ParamMutability::ParamMaybeMutable) => FunParamFlags::MUTABLE_FLAGS_MAYBE,
1413             None => FunParamFlags::empty(),
1414         }
1415     }
1417     fn as_fun_implicit_params(
1418         &mut self,
1419         capability: Node<'a>,
1420         default_pos: &'a Pos<'a>,
1421     ) -> &'a FunImplicitParams<'a> {
1422         let capability = match self.node_to_ty(capability) {
1423             Some(ty) => CapTy(ty),
1424             None => CapDefaults(default_pos),
1425         };
1426         self.alloc(FunImplicitParams { capability })
1427     }
1429     fn function_to_ty(
1430         &mut self,
1431         is_method: bool,
1432         attributes: Node<'a>,
1433         header: &'a FunctionHeader<'a>,
1434         body: Node,
1435     ) -> Option<(Id<'a>, &'a Ty<'a>, &'a [ShallowProp<'a>])> {
1436         let id_opt = match (is_method, header.name) {
1437             (true, Node::Token(t)) if t.kind() == TokenKind::Construct => {
1438                 let pos = self.token_pos(t);
1439                 Some(Id(pos, naming_special_names::members::__CONSTRUCT))
1440             }
1441             (true, _) => self.expect_name(header.name),
1442             (false, _) => self.elaborate_defined_id(header.name),
1443         };
1444         let id = id_opt.unwrap_or(Id(self.get_pos(header.name), ""));
1445         let (params, properties, arity) = self.as_fun_params(header.param_list)?;
1446         let f_pos = self.get_pos(header.name);
1447         let implicit_params = self.as_fun_implicit_params(header.capability, f_pos);
1449         let type_ = match header.name {
1450             Node::Token(t) if t.kind() == TokenKind::Construct => {
1451                 let pos = self.token_pos(t);
1452                 self.alloc(Ty(
1453                     self.alloc(Reason::witness(pos)),
1454                     Ty_::Tprim(self.alloc(aast::Tprim::Tvoid)),
1455                 ))
1456             }
1457             _ => self
1458                 .node_to_ty(header.ret_hint)
1459                 .unwrap_or_else(|| self.tany_with_pos(f_pos)),
1460         };
1461         let async_ = header
1462             .modifiers
1463             .iter()
1464             .any(|n| n.is_token(TokenKind::Async));
1465         let fun_kind = if body.iter().any(|node| node.is_token(TokenKind::Yield)) {
1466             if async_ {
1467                 FunKind::FAsyncGenerator
1468             } else {
1469                 FunKind::FGenerator
1470             }
1471         } else {
1472             if async_ {
1473                 FunKind::FAsync
1474             } else {
1475                 FunKind::FSync
1476             }
1477         };
1478         let type_ = if !header.ret_hint.is_present() {
1479             self.ret_from_fun_kind(fun_kind, type_)
1480         } else {
1481             type_
1482         };
1483         let attributes = self.to_attributes(attributes);
1484         // TODO(hrust) Put this in a helper. Possibly do this for all flags.
1485         let mut flags = match fun_kind {
1486             FunKind::FSync => FunTypeFlags::empty(),
1487             FunKind::FAsync => FunTypeFlags::ASYNC,
1488             FunKind::FGenerator => FunTypeFlags::GENERATOR,
1489             FunKind::FAsyncGenerator => FunTypeFlags::ASYNC | FunTypeFlags::GENERATOR,
1490         };
1491         if attributes.returns_mutable {
1492             flags |= FunTypeFlags::RETURNS_MUTABLE;
1493         }
1494         if attributes.returns_disposable {
1495             flags |= FunTypeFlags::RETURN_DISPOSABLE;
1496         }
1497         if attributes.returns_void_to_rx {
1498             flags |= FunTypeFlags::RETURNS_VOID_TO_RX;
1499         }
1500         let ifc_decl = attributes.ifc_attribute;
1502         flags |= Self::param_mutability_to_fun_type_flags(attributes.param_mutability);
1503         // Pop the type params stack only after creating all inner types.
1504         let tparams = self.pop_type_params(header.type_params);
1506         let where_constraints =
1507             self.slice(header.where_constraints.iter().filter_map(|&x| match x {
1508                 Node::WhereConstraint(x) => Some(x),
1509                 _ => None,
1510             }));
1512         let ft = self.alloc(FunType {
1513             arity,
1514             tparams,
1515             where_constraints,
1516             params,
1517             implicit_params,
1518             ret: self.alloc(PossiblyEnforcedTy {
1519                 enforced: false,
1520                 type_,
1521             }),
1522             reactive: attributes.reactivity,
1523             flags,
1524             ifc_decl,
1525         });
1527         let ty = self.alloc(Ty(self.alloc(Reason::witness(id.0)), Ty_::Tfun(ft)));
1528         Some((id, ty, properties))
1529     }
1531     fn as_fun_params(
1532         &self,
1533         list: Node<'a>,
1534     ) -> Option<(&'a FunParams<'a>, &'a [ShallowProp<'a>], FunArity<'a>)> {
1535         match list {
1536             Node::List(nodes) => {
1537                 let mut params = Vec::with_capacity_in(nodes.len(), self.arena);
1538                 let mut properties = Vec::new_in(self.arena);
1539                 let mut arity = FunArity::Fstandard;
1540                 for node in nodes.iter() {
1541                     match node {
1542                         Node::FunParam(&FunParamDecl {
1543                             attributes,
1544                             visibility,
1545                             kind,
1546                             hint,
1547                             pos,
1548                             name,
1549                             variadic,
1550                             initializer,
1551                         }) => {
1552                             let attributes = self.to_attributes(attributes);
1554                             if let Some(visibility) = visibility.as_visibility() {
1555                                 let name = name.unwrap_or("");
1556                                 let name = strip_dollar_prefix(name);
1557                                 let mut flags = PropFlags::empty();
1558                                 flags.set(PropFlags::CONST, attributes.const_);
1559                                 flags.set(PropFlags::NEEDS_INIT, self.file_mode != Mode::Mdecl);
1560                                 flags.set(PropFlags::PHP_STD_LIB, attributes.php_std_lib);
1561                                 properties.push(ShallowProp {
1562                                     xhp_attr: None,
1563                                     name: Id(pos, name),
1564                                     type_: self.node_to_ty(hint),
1565                                     visibility,
1566                                     flags,
1567                                 });
1568                             }
1570                             let type_ = if hint.is_ignored() {
1571                                 self.tany_with_pos(pos)
1572                             } else {
1573                                 self.node_to_ty(hint).map(|ty| match ty {
1574                                     &Ty(r, Ty_::Tfun(fun_type))
1575                                         if attributes.at_most_rx_as_func =>
1576                                     {
1577                                         let fun_type = self.alloc(FunType {
1578                                             reactive: Reactivity::RxVar(None),
1579                                             ..*fun_type
1580                                         });
1581                                         self.alloc(Ty(r, Ty_::Tfun(fun_type)))
1582                                     }
1583                                     &Ty(r, Ty_::Toption(&Ty(r1, Ty_::Tfun(fun_type))))
1584                                         if attributes.at_most_rx_as_func =>
1585                                     {
1586                                         let fun_type = self.alloc(FunType {
1587                                             reactive: Reactivity::RxVar(None),
1588                                             ..*fun_type
1589                                         });
1590                                         self.alloc(Ty(
1591                                             r,
1592                                             Ty_::Toption(self.alloc(Ty(r1, Ty_::Tfun(fun_type)))),
1593                                         ))
1594                                     }
1595                                     ty => ty,
1596                                 })?
1597                             };
1598                             // These are illegal here--they can only be used on
1599                             // parameters in a function type hint (see
1600                             // make_closure_type_specifier and unwrap_mutability).
1601                             // Unwrap them here anyway for better error recovery.
1602                             let type_ = match type_ {
1603                                 Ty(_, Ty_::Tapply((Id(_, "\\Mutable"), [t]))) => t,
1604                                 Ty(_, Ty_::Tapply((Id(_, "\\OwnedMutable"), [t]))) => t,
1605                                 Ty(_, Ty_::Tapply((Id(_, "\\MaybeMutable"), [t]))) => t,
1606                                 _ => type_,
1607                             };
1608                             let mut flags = match attributes.param_mutability {
1609                                 Some(ParamMutability::ParamBorrowedMutable) => {
1610                                     FunParamFlags::MUTABLE_FLAGS_BORROWED
1611                                 }
1612                                 Some(ParamMutability::ParamOwnedMutable) => {
1613                                     FunParamFlags::MUTABLE_FLAGS_OWNED
1614                                 }
1615                                 Some(ParamMutability::ParamMaybeMutable) => {
1616                                     FunParamFlags::MUTABLE_FLAGS_MAYBE
1617                                 }
1618                                 None => FunParamFlags::empty(),
1619                             };
1620                             if attributes.accept_disposable {
1621                                 flags |= FunParamFlags::ACCEPT_DISPOSABLE
1622                             }
1623                             if attributes.external {
1624                                 flags |= FunParamFlags::IFC_EXTERNAL
1625                             }
1626                             if attributes.can_call {
1627                                 flags |= FunParamFlags::IFC_CAN_CALL
1628                             }
1629                             if attributes.atom {
1630                                 flags |= FunParamFlags::ATOM
1631                             }
1632                             match kind {
1633                                 ParamMode::FPinout => {
1634                                     flags |= FunParamFlags::INOUT;
1635                                 }
1636                                 ParamMode::FPnormal => {}
1637                             };
1638                             if initializer.is_present() {
1639                                 flags |= FunParamFlags::HAS_DEFAULT;
1640                             }
1641                             let variadic = initializer.is_ignored() && variadic;
1642                             let type_ = if variadic {
1643                                 self.alloc(Ty(
1644                                     self.alloc(if name.is_some() {
1645                                         Reason::RvarParam(pos)
1646                                     } else {
1647                                         Reason::witness(pos)
1648                                     }),
1649                                     type_.1,
1650                                 ))
1651                             } else {
1652                                 type_
1653                             };
1654                             let rx_annotation = if attributes.at_most_rx_as_func {
1655                                 Some(ParamRxAnnotation::ParamRxVar)
1656                             } else {
1657                                 attributes
1658                                     .reactivity_condition_type
1659                                     .map(|ty| ParamRxAnnotation::ParamRxIfImpl(ty))
1660                             };
1661                             let param = self.alloc(FunParam {
1662                                 pos,
1663                                 name,
1664                                 type_: self.alloc(PossiblyEnforcedTy {
1665                                     enforced: false,
1666                                     type_,
1667                                 }),
1668                                 flags,
1669                                 rx_annotation,
1670                             });
1671                             arity = match arity {
1672                                 FunArity::Fstandard if variadic => FunArity::Fvariadic(param),
1673                                 arity => {
1674                                     params.push(param);
1675                                     arity
1676                                 }
1677                             };
1678                         }
1679                         n => panic!("Expected a function parameter, but got {:?}", n),
1680                     }
1681                 }
1682                 Some((
1683                     params.into_bump_slice(),
1684                     properties.into_bump_slice(),
1685                     arity,
1686                 ))
1687             }
1688             n if n.is_ignored() => Some((&[], &[], FunArity::Fstandard)),
1689             n => panic!("Expected a list of function parameters, but got {:?}", n),
1690         }
1691     }
1693     fn make_shape_field_name(&self, name: Node<'a>) -> Option<ShapeFieldName<'a>> {
1694         Some(match name {
1695             Node::StringLiteral(&(s, pos)) => ShapeFieldName::SFlitStr(self.alloc((pos, s))),
1696             // TODO: OCaml decl produces SFlitStr here instead of SFlitInt, so
1697             // we must also. Looks like int literal keys have become a parse
1698             // error--perhaps that's why.
1699             Node::IntLiteral(&(s, pos)) => ShapeFieldName::SFlitStr(self.alloc((pos, s.into()))),
1700             Node::Expr(aast::Expr(
1701                 _,
1702                 aast::Expr_::ClassConst(&(
1703                     aast::ClassId(_, aast::ClassId_::CI(&class_name)),
1704                     const_name,
1705                 )),
1706             )) => ShapeFieldName::SFclassConst(self.alloc((class_name, const_name))),
1707             Node::Expr(aast::Expr(
1708                 _,
1709                 aast::Expr_::ClassConst(&(aast::ClassId(pos, aast::ClassId_::CIself), const_name)),
1710             )) => ShapeFieldName::SFclassConst(self.alloc((
1711                 Id(
1712                     pos,
1713                     self.classish_name_builder.get_current_classish_name()?.0,
1714                 ),
1715                 const_name,
1716             ))),
1717             _ => return None,
1718         })
1719     }
1721     fn make_apply(
1722         &self,
1723         base_ty: Id<'a>,
1724         type_arguments: Node<'a>,
1725         pos_to_merge: &'a Pos<'a>,
1726     ) -> Node<'a> {
1727         let type_arguments = self.slice(
1728             type_arguments
1729                 .iter()
1730                 .filter_map(|&node| self.node_to_ty(node)),
1731         );
1733         let pos = self.merge(base_ty.0, pos_to_merge);
1735         // OCaml decl creates a capability with a hint pointing to the entire
1736         // type (i.e., pointing to `Rx<(function(): void)>` rather than just
1737         // `(function(): void)`), so we extend the hint position similarly here.
1738         let extend_capability_pos = |implicit_params: &'a FunImplicitParams| {
1739             let capability = match implicit_params.capability {
1740                 CapTy(ty) => {
1741                     let ty = self.alloc(Ty(self.alloc(Reason::hint(pos)), ty.1));
1742                     CapTy(ty)
1743                 }
1744                 CapDefaults(_) => CapDefaults(pos),
1745             };
1746             self.alloc(FunImplicitParams {
1747                 capability,
1748                 ..*implicit_params
1749             })
1750         };
1752         let ty_ = match (base_ty, type_arguments) {
1753             (Id(_, name), &[&Ty(_, Ty_::Tfun(f))]) if name == "\\Pure" => {
1754                 Ty_::Tfun(self.alloc(FunType {
1755                     reactive: Reactivity::Pure(None),
1756                     implicit_params: extend_capability_pos(f.implicit_params),
1757                     ..*f
1758                 }))
1759             }
1760             (Id(_, name), &[&Ty(_, Ty_::Tfun(f))]) if name == "\\Rx" => {
1761                 Ty_::Tfun(self.alloc(FunType {
1762                     reactive: Reactivity::Reactive(None),
1763                     implicit_params: extend_capability_pos(f.implicit_params),
1764                     ..*f
1765                 }))
1766             }
1767             (Id(_, name), &[&Ty(_, Ty_::Tfun(f))]) if name == "\\RxShallow" => {
1768                 Ty_::Tfun(self.alloc(FunType {
1769                     reactive: Reactivity::Shallow(None),
1770                     implicit_params: extend_capability_pos(f.implicit_params),
1771                     ..*f
1772                 }))
1773             }
1774             (Id(_, name), &[&Ty(_, Ty_::Tfun(f))]) if name == "\\RxLocal" => {
1775                 Ty_::Tfun(self.alloc(FunType {
1776                     reactive: Reactivity::Local(None),
1777                     implicit_params: extend_capability_pos(f.implicit_params),
1778                     ..*f
1779                 }))
1780             }
1781             _ => Ty_::Tapply(self.alloc((base_ty, type_arguments))),
1782         };
1784         self.hint_ty(pos, ty_)
1785     }
1787     fn hint_ty(&self, pos: &'a Pos<'a>, ty_: Ty_<'a>) -> Node<'a> {
1788         Node::Ty(self.alloc(Ty(self.alloc(Reason::hint(pos)), ty_)))
1789     }
1791     fn prim_ty(&self, tprim: aast::Tprim, pos: &'a Pos<'a>) -> Node<'a> {
1792         self.hint_ty(pos, Ty_::Tprim(self.alloc(tprim)))
1793     }
1795     fn tany_with_pos(&self, pos: &'a Pos<'a>) -> &'a Ty<'a> {
1796         self.alloc(Ty(self.alloc(Reason::witness(pos)), TANY_))
1797     }
1799     /// The type used when a `varray_or_darray` typehint is missing its key type argument.
1800     fn varray_or_darray_key(&self, pos: &'a Pos<'a>) -> &'a Ty<'a> {
1801         self.alloc(Ty(
1802             self.alloc(Reason::RvarrayOrDarrayKey(pos)),
1803             Ty_::Tprim(self.alloc(aast::Tprim::Tarraykey)),
1804         ))
1805     }
1807     fn source_text_at_pos(&self, pos: &'a Pos<'a>) -> &'a [u8] {
1808         let start = pos.start_cnum();
1809         let end = pos.end_cnum();
1810         self.source_text.source_text().sub(start, end - start)
1811     }
1813     // While we usually can tell whether to allocate a Tapply or Tgeneric based
1814     // on our type_parameters stack, *constraints* on type parameters may
1815     // reference type parameters which we have not parsed yet. When constructing
1816     // a type parameter list, we use this function to rewrite the type of each
1817     // constraint, considering the full list of type parameters to be in scope.
1818     fn convert_tapply_to_tgeneric(&self, ty: &'a Ty<'a>) -> &'a Ty<'a> {
1819         let ty_ = match ty.1 {
1820             Ty_::Tapply(&(id, targs)) => {
1821                 let converted_targs = self.slice(
1822                     targs
1823                         .iter()
1824                         .map(|&targ| self.convert_tapply_to_tgeneric(targ)),
1825                 );
1826                 match self.tapply_should_be_tgeneric(ty.0, id) {
1827                     Some(name) => Ty_::Tgeneric(self.alloc((name, converted_targs))),
1828                     None => Ty_::Tapply(self.alloc((id, converted_targs))),
1829                 }
1830             }
1831             Ty_::Tlike(ty) => Ty_::Tlike(self.convert_tapply_to_tgeneric(ty)),
1832             Ty_::Toption(ty) => Ty_::Toption(self.convert_tapply_to_tgeneric(ty)),
1833             Ty_::Tfun(fun_type) => {
1834                 let convert_param = |param: &'a FunParam<'a>| {
1835                     self.alloc(FunParam {
1836                         type_: self.alloc(PossiblyEnforcedTy {
1837                             enforced: param.type_.enforced,
1838                             type_: self.convert_tapply_to_tgeneric(param.type_.type_),
1839                         }),
1840                         ..*param
1841                     })
1842                 };
1843                 let arity = match fun_type.arity {
1844                     FunArity::Fstandard => FunArity::Fstandard,
1845                     FunArity::Fvariadic(param) => FunArity::Fvariadic(convert_param(param)),
1846                 };
1847                 let params = self.slice(fun_type.params.iter().copied().map(convert_param));
1848                 let implicit_params = fun_type.implicit_params;
1849                 let ret = self.alloc(PossiblyEnforcedTy {
1850                     enforced: fun_type.ret.enforced,
1851                     type_: self.convert_tapply_to_tgeneric(fun_type.ret.type_),
1852                 });
1853                 Ty_::Tfun(self.alloc(FunType {
1854                     arity,
1855                     params,
1856                     implicit_params,
1857                     ret,
1858                     ..*fun_type
1859                 }))
1860             }
1861             Ty_::Tshape(&(kind, fields)) => {
1862                 let mut converted_fields = AssocListMut::with_capacity_in(fields.len(), self.arena);
1863                 for (&name, ty) in fields.iter() {
1864                     converted_fields.insert(
1865                         name,
1866                         self.alloc(ShapeFieldType {
1867                             optional: ty.optional,
1868                             ty: self.convert_tapply_to_tgeneric(ty.ty),
1869                         }),
1870                     );
1871                 }
1872                 Ty_::Tshape(self.alloc((kind, converted_fields.into())))
1873             }
1874             Ty_::Tdarray(&(tk, tv)) => Ty_::Tdarray(self.alloc((
1875                 self.convert_tapply_to_tgeneric(tk),
1876                 self.convert_tapply_to_tgeneric(tv),
1877             ))),
1878             Ty_::Tvarray(ty) => Ty_::Tvarray(self.convert_tapply_to_tgeneric(ty)),
1879             Ty_::TvarrayOrDarray(&(tk, tv)) => Ty_::TvarrayOrDarray(self.alloc((
1880                 self.convert_tapply_to_tgeneric(tk),
1881                 self.convert_tapply_to_tgeneric(tv),
1882             ))),
1883             Ty_::Ttuple(tys) => Ty_::Ttuple(
1884                 self.slice(
1885                     tys.iter()
1886                         .map(|&targ| self.convert_tapply_to_tgeneric(targ)),
1887                 ),
1888             ),
1889             _ => return ty,
1890         };
1891         self.alloc(Ty(ty.0, ty_))
1892     }
1894     // This is the logic for determining if convert_tapply_to_tgeneric should turn
1895     // a Tapply into a Tgeneric
1896     fn tapply_should_be_tgeneric(
1897         &self,
1898         reason: &'a Reason<'a>,
1899         id: nast::Sid<'a>,
1900     ) -> Option<&'a str> {
1901         match reason.pos() {
1902             // If the name contained a namespace delimiter in the original
1903             // source text, then it can't have referred to a type parameter
1904             // (since type parameters cannot be namespaced).
1905             Some(pos) => {
1906                 if self.source_text_at_pos(pos).contains(&b'\\') {
1907                     return None;
1908                 }
1909             }
1910             None => return None,
1911         }
1912         // However, the direct decl parser will unconditionally prefix
1913         // the name with the current namespace (as it does for any
1914         // Tapply). We need to remove it.
1915         match id.1.rsplit('\\').next() {
1916             Some(name) if self.is_type_param_in_scope(name) => return Some(name),
1917             _ => return None,
1918         }
1919     }
1921     fn rewrite_taccess_reasons(&self, ty: &'a Ty<'a>, r: &'a Reason<'a>) -> &'a Ty<'a> {
1922         let ty_ = match ty.1 {
1923             Ty_::Taccess(&TaccessType(ty, id)) => {
1924                 Ty_::Taccess(self.alloc(TaccessType(self.rewrite_taccess_reasons(ty, r), id)))
1925             }
1926             ty_ => ty_,
1927         };
1928         self.alloc(Ty(r, ty_))
1929     }
1931     fn user_attribute_to_decl(
1932         &self,
1933         attr: &UserAttributeNode<'a>,
1934     ) -> &'a shallow_decl_defs::UserAttribute<'a> {
1935         self.alloc(shallow_decl_defs::UserAttribute {
1936             name: attr.name,
1937             classname_params: self.slice(attr.classname_params.iter().map(|p| p.name.1)),
1938         })
1939     }
1941     fn namespace_use_kind(use_kind: &Node) -> Option<TokenKind> {
1942         match use_kind.token_kind() {
1943             Some(TokenKind::Const) => None,
1944             Some(TokenKind::Function) => None,
1945             Some(TokenKind::Type) => Some(TokenKind::Type),
1946             Some(TokenKind::Namespace) => Some(TokenKind::Namespace),
1947             _ if !use_kind.is_present() => Some(TokenKind::Mixed),
1948             x => panic!("Unexpected namespace use kind: {:?}", x),
1949         }
1950     }
1953 enum NodeIterHelper<'a: 'b, 'b> {
1954     Empty,
1955     Single(&'b Node<'a>),
1956     Vec(std::slice::Iter<'b, Node<'a>>),
1959 impl<'a, 'b> Iterator for NodeIterHelper<'a, 'b> {
1960     type Item = &'b Node<'a>;
1962     fn next(&mut self) -> Option<Self::Item> {
1963         match self {
1964             NodeIterHelper::Empty => None,
1965             NodeIterHelper::Single(node) => {
1966                 let node = *node;
1967                 *self = NodeIterHelper::Empty;
1968                 Some(node)
1969             }
1970             NodeIterHelper::Vec(ref mut iter) => iter.next(),
1971         }
1972     }
1974     // Must return the upper bound returned by Node::len.
1975     fn size_hint(&self) -> (usize, Option<usize>) {
1976         match self {
1977             NodeIterHelper::Empty => (0, Some(0)),
1978             NodeIterHelper::Single(_) => (1, Some(1)),
1979             NodeIterHelper::Vec(iter) => iter.size_hint(),
1980         }
1981     }
1984 impl<'a, 'b> DoubleEndedIterator for NodeIterHelper<'a, 'b> {
1985     fn next_back(&mut self) -> Option<Self::Item> {
1986         match self {
1987             NodeIterHelper::Empty => None,
1988             NodeIterHelper::Single(_) => self.next(),
1989             NodeIterHelper::Vec(ref mut iter) => iter.next_back(),
1990         }
1991     }
1994 impl<'a> FlattenOp for DirectDeclSmartConstructors<'a> {
1995     type S = Node<'a>;
1997     fn flatten(&self, kind: SyntaxKind, lst: std::vec::Vec<Self::S>) -> Self::S {
1998         let size = lst
1999             .iter()
2000             .map(|s| match s {
2001                 Node::List(children) => children.len(),
2002                 x => {
2003                     if Self::is_zero(x) {
2004                         0
2005                     } else {
2006                         1
2007                     }
2008                 }
2009             })
2010             .sum();
2011         let mut r = Vec::with_capacity_in(size, self.arena);
2012         for s in lst.into_iter() {
2013             match s {
2014                 Node::List(children) => r.extend(children.iter().copied()),
2015                 x => {
2016                     if !Self::is_zero(&x) {
2017                         r.push(x)
2018                     }
2019                 }
2020             }
2021         }
2022         match r.into_bump_slice() {
2023             [] => Node::Ignored(kind),
2024             [node] => *node,
2025             slice => Node::List(self.alloc(slice)),
2026         }
2027     }
2029     fn zero(kind: SyntaxKind) -> Self::S {
2030         Node::Ignored(kind)
2031     }
2033     fn is_zero(s: &Self::S) -> bool {
2034         match s {
2035             Node::Token(token) => match token.kind() {
2036                 TokenKind::Yield | TokenKind::Required | TokenKind::Lateinit => false,
2037                 _ => true,
2038             },
2039             Node::List(inner) => inner.iter().all(Self::is_zero),
2040             _ => true,
2041         }
2042     }
2045 impl<'a> FlattenSmartConstructors<'a, DirectDeclSmartConstructors<'a>>
2046     for DirectDeclSmartConstructors<'a>
2048     fn make_token(&mut self, token: CompactToken) -> Self::R {
2049         let token_text = |this: &Self| this.str_from_utf8(this.token_bytes(&token));
2050         let token_pos = |this: &Self| {
2051             let start = this
2052                 .source_text
2053                 .offset_to_file_pos_triple(token.start_offset());
2054             let end = this
2055                 .source_text
2056                 .offset_to_file_pos_triple(token.end_offset());
2057             Pos::from_lnum_bol_cnum(this.arena, this.filename, start, end)
2058         };
2059         let kind = token.kind();
2061         let result = match kind {
2062             TokenKind::Name | TokenKind::XHPClassName => {
2063                 let text = token_text(self);
2064                 let pos = token_pos(self);
2066                 let name = if kind == TokenKind::XHPClassName {
2067                     Node::XhpName(self.alloc((text, pos)))
2068                 } else {
2069                     Node::Name(self.alloc((text, pos)))
2070                 };
2072                 if self.previous_token_kind == TokenKind::Class
2073                     || self.previous_token_kind == TokenKind::Trait
2074                     || self.previous_token_kind == TokenKind::Interface
2075                 {
2076                     if let Some(current_class_name) = self.elaborate_defined_id(name) {
2077                         self.classish_name_builder
2078                             .lexed_name_after_classish_keyword(
2079                                 self.arena,
2080                                 current_class_name.1,
2081                                 pos,
2082                                 self.previous_token_kind,
2083                             );
2084                     }
2085                 }
2086                 name
2087             }
2088             TokenKind::Class => Node::Name(self.alloc((token_text(self), token_pos(self)))),
2089             // There are a few types whose string representations we have to
2090             // grab anyway, so just go ahead and treat them as generic names.
2091             TokenKind::Variable
2092             | TokenKind::Vec
2093             | TokenKind::Dict
2094             | TokenKind::Keyset
2095             | TokenKind::Tuple
2096             | TokenKind::Classname
2097             | TokenKind::SelfToken => Node::Name(self.alloc((token_text(self), token_pos(self)))),
2098             TokenKind::XHPElementName => {
2099                 Node::XhpName(self.alloc((token_text(self), token_pos(self))))
2100             }
2101             TokenKind::SingleQuotedStringLiteral => match escaper::unescape_single_in(
2102                 self.str_from_utf8(escaper::unquote_slice(self.token_bytes(&token))),
2103                 self.arena,
2104             ) {
2105                 Ok(text) => Node::StringLiteral(self.alloc((text.into(), token_pos(self)))),
2106                 Err(_) => Node::Ignored(SK::Token(kind)),
2107             },
2108             TokenKind::DoubleQuotedStringLiteral => match escaper::unescape_double_in(
2109                 self.str_from_utf8(escaper::unquote_slice(self.token_bytes(&token))),
2110                 self.arena,
2111             ) {
2112                 Ok(text) => Node::StringLiteral(self.alloc((text.into(), token_pos(self)))),
2113                 Err(_) => Node::Ignored(SK::Token(kind)),
2114             },
2115             TokenKind::HeredocStringLiteral => match escaper::unescape_heredoc_in(
2116                 self.str_from_utf8(escaper::unquote_slice(self.token_bytes(&token))),
2117                 self.arena,
2118             ) {
2119                 Ok(text) => Node::StringLiteral(self.alloc((text.into(), token_pos(self)))),
2120                 Err(_) => Node::Ignored(SK::Token(kind)),
2121             },
2122             TokenKind::NowdocStringLiteral => match escaper::unescape_nowdoc_in(
2123                 self.str_from_utf8(escaper::unquote_slice(self.token_bytes(&token))),
2124                 self.arena,
2125             ) {
2126                 Ok(text) => Node::StringLiteral(self.alloc((text.into(), token_pos(self)))),
2127                 Err(_) => Node::Ignored(SK::Token(kind)),
2128             },
2129             TokenKind::DecimalLiteral
2130             | TokenKind::OctalLiteral
2131             | TokenKind::HexadecimalLiteral
2132             | TokenKind::BinaryLiteral => {
2133                 Node::IntLiteral(self.alloc((token_text(self), token_pos(self))))
2134             }
2135             TokenKind::FloatingLiteral => {
2136                 Node::FloatingLiteral(self.alloc((token_text(self), token_pos(self))))
2137             }
2138             TokenKind::BooleanLiteral => {
2139                 Node::BooleanLiteral(self.alloc((token_text(self), token_pos(self))))
2140             }
2141             TokenKind::String => self.prim_ty(aast::Tprim::Tstring, token_pos(self)),
2142             TokenKind::Int => self.prim_ty(aast::Tprim::Tint, token_pos(self)),
2143             TokenKind::Float => self.prim_ty(aast::Tprim::Tfloat, token_pos(self)),
2144             // "double" and "boolean" are parse errors--they should be written
2145             // "float" and "bool". The decl-parser treats the incorrect names as
2146             // type names rather than primitives.
2147             TokenKind::Double | TokenKind::Boolean => self.hint_ty(
2148                 token_pos(self),
2149                 Ty_::Tapply(self.alloc((Id(token_pos(self), token_text(self)), &[][..]))),
2150             ),
2151             TokenKind::Num => self.prim_ty(aast::Tprim::Tnum, token_pos(self)),
2152             TokenKind::Bool => self.prim_ty(aast::Tprim::Tbool, token_pos(self)),
2153             TokenKind::Mixed => {
2154                 Node::Ty(self.alloc(Ty(self.alloc(Reason::hint(token_pos(self))), Ty_::Tmixed)))
2155             }
2156             TokenKind::Void => self.prim_ty(aast::Tprim::Tvoid, token_pos(self)),
2157             TokenKind::Arraykey => self.prim_ty(aast::Tprim::Tarraykey, token_pos(self)),
2158             TokenKind::Noreturn => self.prim_ty(aast::Tprim::Tnoreturn, token_pos(self)),
2159             TokenKind::Resource => self.prim_ty(aast::Tprim::Tresource, token_pos(self)),
2160             TokenKind::NullLiteral
2161             | TokenKind::Darray
2162             | TokenKind::Varray
2163             | TokenKind::Backslash
2164             | TokenKind::Construct
2165             | TokenKind::LeftParen
2166             | TokenKind::RightParen
2167             | TokenKind::LeftBracket
2168             | TokenKind::RightBracket
2169             | TokenKind::Shape
2170             | TokenKind::Question
2171             | TokenKind::This
2172             | TokenKind::Tilde
2173             | TokenKind::Exclamation
2174             | TokenKind::Plus
2175             | TokenKind::Minus
2176             | TokenKind::PlusPlus
2177             | TokenKind::MinusMinus
2178             | TokenKind::At
2179             | TokenKind::Star
2180             | TokenKind::Slash
2181             | TokenKind::EqualEqual
2182             | TokenKind::EqualEqualEqual
2183             | TokenKind::StarStar
2184             | TokenKind::AmpersandAmpersand
2185             | TokenKind::BarBar
2186             | TokenKind::LessThan
2187             | TokenKind::LessThanEqual
2188             | TokenKind::GreaterThan
2189             | TokenKind::GreaterThanEqual
2190             | TokenKind::Dot
2191             | TokenKind::Ampersand
2192             | TokenKind::Bar
2193             | TokenKind::LessThanLessThan
2194             | TokenKind::GreaterThanGreaterThan
2195             | TokenKind::Percent
2196             | TokenKind::QuestionQuestion
2197             | TokenKind::Equal
2198             | TokenKind::Abstract
2199             | TokenKind::As
2200             | TokenKind::Super
2201             | TokenKind::Async
2202             | TokenKind::DotDotDot
2203             | TokenKind::Extends
2204             | TokenKind::Final
2205             | TokenKind::Implements
2206             | TokenKind::Inout
2207             | TokenKind::Interface
2208             | TokenKind::Newtype
2209             | TokenKind::Type
2210             | TokenKind::Yield
2211             | TokenKind::Semicolon
2212             | TokenKind::Private
2213             | TokenKind::Protected
2214             | TokenKind::Public
2215             | TokenKind::Reify
2216             | TokenKind::Static
2217             | TokenKind::Trait
2218             | TokenKind::Lateinit
2219             | TokenKind::RecordDec
2220             | TokenKind::RightBrace
2221             | TokenKind::Enum
2222             | TokenKind::Const
2223             | TokenKind::Function
2224             | TokenKind::Namespace
2225             | TokenKind::XHP
2226             | TokenKind::Required
2227             | TokenKind::Ctx => Node::Token(FixedWidthToken::new(kind, token.start_offset())),
2228             TokenKind::EndOfFile
2229             | TokenKind::Attribute
2230             | TokenKind::Await
2231             | TokenKind::Binary
2232             | TokenKind::Break
2233             | TokenKind::Case
2234             | TokenKind::Catch
2235             | TokenKind::Category
2236             | TokenKind::Children
2237             | TokenKind::Clone
2238             | TokenKind::Continue
2239             | TokenKind::Default
2240             | TokenKind::Define
2241             | TokenKind::Do
2242             | TokenKind::Echo
2243             | TokenKind::Else
2244             | TokenKind::Elseif
2245             | TokenKind::Empty
2246             | TokenKind::Endfor
2247             | TokenKind::Endforeach
2248             | TokenKind::Endif
2249             | TokenKind::Endswitch
2250             | TokenKind::Endwhile
2251             | TokenKind::Eval
2252             | TokenKind::Fallthrough
2253             | TokenKind::File
2254             | TokenKind::Finally
2255             | TokenKind::For
2256             | TokenKind::Foreach
2257             | TokenKind::From
2258             | TokenKind::Global
2259             | TokenKind::Concurrent
2260             | TokenKind::If
2261             | TokenKind::Include
2262             | TokenKind::Include_once
2263             | TokenKind::Instanceof
2264             | TokenKind::Insteadof
2265             | TokenKind::Integer
2266             | TokenKind::Is
2267             | TokenKind::Isset
2268             | TokenKind::List
2269             | TokenKind::New
2270             | TokenKind::Object
2271             | TokenKind::Parent
2272             | TokenKind::Print
2273             | TokenKind::Real
2274             | TokenKind::Record
2275             | TokenKind::Require
2276             | TokenKind::Require_once
2277             | TokenKind::Return
2278             | TokenKind::Switch
2279             | TokenKind::Throw
2280             | TokenKind::Try
2281             | TokenKind::Unset
2282             | TokenKind::Use
2283             | TokenKind::Using
2284             | TokenKind::Var
2285             | TokenKind::Where
2286             | TokenKind::While
2287             | TokenKind::LeftBrace
2288             | TokenKind::MinusGreaterThan
2289             | TokenKind::Dollar
2290             | TokenKind::LessThanEqualGreaterThan
2291             | TokenKind::ExclamationEqual
2292             | TokenKind::ExclamationEqualEqual
2293             | TokenKind::Carat
2294             | TokenKind::QuestionAs
2295             | TokenKind::QuestionColon
2296             | TokenKind::QuestionQuestionEqual
2297             | TokenKind::Colon
2298             | TokenKind::StarStarEqual
2299             | TokenKind::StarEqual
2300             | TokenKind::SlashEqual
2301             | TokenKind::PercentEqual
2302             | TokenKind::PlusEqual
2303             | TokenKind::MinusEqual
2304             | TokenKind::DotEqual
2305             | TokenKind::LessThanLessThanEqual
2306             | TokenKind::GreaterThanGreaterThanEqual
2307             | TokenKind::AmpersandEqual
2308             | TokenKind::CaratEqual
2309             | TokenKind::BarEqual
2310             | TokenKind::Comma
2311             | TokenKind::ColonColon
2312             | TokenKind::EqualGreaterThan
2313             | TokenKind::EqualEqualGreaterThan
2314             | TokenKind::QuestionMinusGreaterThan
2315             | TokenKind::DollarDollar
2316             | TokenKind::BarGreaterThan
2317             | TokenKind::SlashGreaterThan
2318             | TokenKind::LessThanSlash
2319             | TokenKind::LessThanQuestion
2320             | TokenKind::Backtick
2321             | TokenKind::ErrorToken
2322             | TokenKind::DoubleQuotedStringLiteralHead
2323             | TokenKind::StringLiteralBody
2324             | TokenKind::DoubleQuotedStringLiteralTail
2325             | TokenKind::HeredocStringLiteralHead
2326             | TokenKind::HeredocStringLiteralTail
2327             | TokenKind::XHPCategoryName
2328             | TokenKind::XHPStringLiteral
2329             | TokenKind::XHPBody
2330             | TokenKind::XHPComment
2331             | TokenKind::Hash
2332             | TokenKind::Hashbang => Node::Ignored(SK::Token(kind)),
2333         };
2334         self.previous_token_kind = kind;
2335         result
2336     }
2338     fn make_missing(&mut self, _: usize) -> Self::R {
2339         Node::Ignored(SK::Missing)
2340     }
2342     fn make_list(&mut self, items: std::vec::Vec<Self::R>, _: usize) -> Self::R {
2343         if let Some(&yield_) = items
2344             .iter()
2345             .flat_map(|node| node.iter())
2346             .find(|node| node.is_token(TokenKind::Yield))
2347         {
2348             yield_
2349         } else {
2350             let size = items.iter().filter(|node| node.is_present()).count();
2351             let items_iter = items.into_iter();
2352             let mut items = Vec::with_capacity_in(size, self.arena);
2353             for node in items_iter {
2354                 if node.is_present() {
2355                     items.push(node);
2356                 }
2357             }
2358             let items = items.into_bump_slice();
2359             if items.is_empty() {
2360                 Node::Ignored(SK::SyntaxList)
2361             } else {
2362                 Node::List(self.alloc(items))
2363             }
2364         }
2365     }
2367     fn make_qualified_name(&mut self, parts: Self::R) -> Self::R {
2368         let pos = self.get_pos(parts);
2369         match parts {
2370             Node::List(nodes) => Node::QualifiedName(self.alloc((nodes, pos))),
2371             node if node.is_ignored() => Node::Ignored(SK::QualifiedName),
2372             node => Node::QualifiedName(
2373                 self.alloc((bumpalo::vec![in self.arena; node].into_bump_slice(), pos)),
2374             ),
2375         }
2376     }
2378     fn make_simple_type_specifier(&mut self, specifier: Self::R) -> Self::R {
2379         // Return this explicitly because flatten filters out zero nodes, and
2380         // we treat most non-error nodes as zeroes.
2381         specifier
2382     }
2384     fn make_literal_expression(&mut self, expression: Self::R) -> Self::R {
2385         expression
2386     }
2388     fn make_simple_initializer(&mut self, equals: Self::R, expr: Self::R) -> Self::R {
2389         // If the expr is Ignored, bubble up the assignment operator so that we
2390         // can tell that *some* initializer was here. Useful for class
2391         // properties, where we need to enforce that properties without default
2392         // values are initialized in the constructor.
2393         if expr.is_ignored() { equals } else { expr }
2394     }
2396     fn make_anonymous_function(
2397         &mut self,
2398         _attribute_spec: Self::R,
2399         _static_keyword: Self::R,
2400         _async_keyword: Self::R,
2401         _function_keyword: Self::R,
2402         _left_paren: Self::R,
2403         _parameters: Self::R,
2404         _right_paren: Self::R,
2405         _ctx_list: Self::R,
2406         _colon: Self::R,
2407         _type_: Self::R,
2408         _use_: Self::R,
2409         _body: Self::R,
2410     ) -> Self::R {
2411         // do not allow Yield to bubble up
2412         Node::Ignored(SK::AnonymousFunction)
2413     }
2415     fn make_lambda_expression(
2416         &mut self,
2417         _attribute_spec: Self::R,
2418         _async_: Self::R,
2419         _signature: Self::R,
2420         _arrow: Self::R,
2421         _body: Self::R,
2422     ) -> Self::R {
2423         // do not allow Yield to bubble up
2424         Node::Ignored(SK::LambdaExpression)
2425     }
2427     fn make_awaitable_creation_expression(
2428         &mut self,
2429         _attribute_spec: Self::R,
2430         _async_: Self::R,
2431         _compound_statement: Self::R,
2432     ) -> Self::R {
2433         // do not allow Yield to bubble up
2434         Node::Ignored(SK::AwaitableCreationExpression)
2435     }
2437     fn make_darray_intrinsic_expression(
2438         &mut self,
2439         darray: Self::R,
2440         _explicit_type: Self::R,
2441         _left_bracket: Self::R,
2442         fields: Self::R,
2443         right_bracket: Self::R,
2444     ) -> Self::R {
2445         let fields = self.slice(fields.iter().filter_map(|node| match node {
2446             Node::ListItem(&(key, value)) => {
2447                 let key = self.node_to_expr(key)?;
2448                 let value = self.node_to_expr(value)?;
2449                 Some((key, value))
2450             }
2451             n => panic!("Expected a ListItem but was {:?}", n),
2452         }));
2453         Node::Expr(self.alloc(aast::Expr(
2454             self.merge_positions(darray, right_bracket),
2455             nast::Expr_::Darray(self.alloc((None, fields))),
2456         )))
2457     }
2459     fn make_dictionary_intrinsic_expression(
2460         &mut self,
2461         dict: Self::R,
2462         _explicit_type: Self::R,
2463         _left_bracket: Self::R,
2464         fields: Self::R,
2465         right_bracket: Self::R,
2466     ) -> Self::R {
2467         let fields = self.slice(fields.iter().filter_map(|node| match node {
2468             Node::ListItem(&(key, value)) => {
2469                 let key = self.node_to_expr(key)?;
2470                 let value = self.node_to_expr(value)?;
2471                 Some(self.alloc(aast::Field(key, value)))
2472             }
2473             n => panic!("Expected a ListItem but was {:?}", n),
2474         }));
2475         Node::Expr(self.alloc(aast::Expr(
2476             self.merge_positions(dict, right_bracket),
2477             nast::Expr_::KeyValCollection(self.alloc((aast_defs::KvcKind::Dict, None, fields))),
2478         )))
2479     }
2481     fn make_keyset_intrinsic_expression(
2482         &mut self,
2483         keyset: Self::R,
2484         _explicit_type: Self::R,
2485         _left_bracket: Self::R,
2486         fields: Self::R,
2487         right_bracket: Self::R,
2488     ) -> Self::R {
2489         let fields = self.slice(fields.iter().filter_map(|&node| self.node_to_expr(node)));
2490         Node::Expr(self.alloc(aast::Expr(
2491             self.merge_positions(keyset, right_bracket),
2492             nast::Expr_::ValCollection(self.alloc((aast_defs::VcKind::Keyset, None, fields))),
2493         )))
2494     }
2496     fn make_varray_intrinsic_expression(
2497         &mut self,
2498         varray: Self::R,
2499         _explicit_type: Self::R,
2500         _left_bracket: Self::R,
2501         fields: Self::R,
2502         right_bracket: Self::R,
2503     ) -> Self::R {
2504         let fields = self.slice(fields.iter().filter_map(|&node| self.node_to_expr(node)));
2505         Node::Expr(self.alloc(aast::Expr(
2506             self.merge_positions(varray, right_bracket),
2507             nast::Expr_::Varray(self.alloc((None, fields))),
2508         )))
2509     }
2511     fn make_vector_intrinsic_expression(
2512         &mut self,
2513         vec: Self::R,
2514         _explicit_type: Self::R,
2515         _left_bracket: Self::R,
2516         fields: Self::R,
2517         right_bracket: Self::R,
2518     ) -> Self::R {
2519         let fields = self.slice(fields.iter().filter_map(|&node| self.node_to_expr(node)));
2520         Node::Expr(self.alloc(aast::Expr(
2521             self.merge_positions(vec, right_bracket),
2522             nast::Expr_::ValCollection(self.alloc((aast_defs::VcKind::Vec, None, fields))),
2523         )))
2524     }
2526     fn make_element_initializer(
2527         &mut self,
2528         key: Self::R,
2529         _arrow: Self::R,
2530         value: Self::R,
2531     ) -> Self::R {
2532         Node::ListItem(self.alloc((key, value)))
2533     }
2535     fn make_prefix_unary_expression(&mut self, op: Self::R, value: Self::R) -> Self::R {
2536         let pos = self.merge_positions(op, value);
2537         let op = match op.token_kind() {
2538             Some(TokenKind::Tilde) => Uop::Utild,
2539             Some(TokenKind::Exclamation) => Uop::Unot,
2540             Some(TokenKind::Plus) => Uop::Uplus,
2541             Some(TokenKind::Minus) => Uop::Uminus,
2542             Some(TokenKind::PlusPlus) => Uop::Uincr,
2543             Some(TokenKind::MinusMinus) => Uop::Udecr,
2544             Some(TokenKind::At) => Uop::Usilence,
2545             _ => return Node::Ignored(SK::PrefixUnaryExpression),
2546         };
2547         let value = match self.node_to_expr(value) {
2548             Some(value) => value,
2549             None => return Node::Ignored(SK::PrefixUnaryExpression),
2550         };
2551         Node::Expr(self.alloc(aast::Expr(pos, aast::Expr_::Unop(self.alloc((op, value))))))
2552     }
2554     fn make_postfix_unary_expression(&mut self, value: Self::R, op: Self::R) -> Self::R {
2555         let pos = self.merge_positions(value, op);
2556         let op = match op.token_kind() {
2557             Some(TokenKind::PlusPlus) => Uop::Upincr,
2558             Some(TokenKind::MinusMinus) => Uop::Updecr,
2559             _ => return Node::Ignored(SK::PostfixUnaryExpression),
2560         };
2561         let value = match self.node_to_expr(value) {
2562             Some(value) => value,
2563             None => return Node::Ignored(SK::PostfixUnaryExpression),
2564         };
2565         Node::Expr(self.alloc(aast::Expr(pos, aast::Expr_::Unop(self.alloc((op, value))))))
2566     }
2568     fn make_binary_expression(&mut self, lhs: Self::R, op_node: Self::R, rhs: Self::R) -> Self::R {
2569         let op = match op_node.token_kind() {
2570             Some(TokenKind::Plus) => Bop::Plus,
2571             Some(TokenKind::Minus) => Bop::Minus,
2572             Some(TokenKind::Star) => Bop::Star,
2573             Some(TokenKind::Slash) => Bop::Slash,
2574             Some(TokenKind::Equal) => Bop::Eq(None),
2575             Some(TokenKind::EqualEqual) => Bop::Eqeq,
2576             Some(TokenKind::EqualEqualEqual) => Bop::Eqeqeq,
2577             Some(TokenKind::StarStar) => Bop::Starstar,
2578             Some(TokenKind::AmpersandAmpersand) => Bop::Ampamp,
2579             Some(TokenKind::BarBar) => Bop::Barbar,
2580             Some(TokenKind::LessThan) => Bop::Lt,
2581             Some(TokenKind::LessThanEqual) => Bop::Lte,
2582             Some(TokenKind::LessThanLessThan) => Bop::Ltlt,
2583             Some(TokenKind::GreaterThan) => Bop::Gt,
2584             Some(TokenKind::GreaterThanEqual) => Bop::Gte,
2585             Some(TokenKind::GreaterThanGreaterThan) => Bop::Gtgt,
2586             Some(TokenKind::Dot) => Bop::Dot,
2587             Some(TokenKind::Ampersand) => Bop::Amp,
2588             Some(TokenKind::Bar) => Bop::Bar,
2589             Some(TokenKind::Percent) => Bop::Percent,
2590             Some(TokenKind::QuestionQuestion) => Bop::QuestionQuestion,
2591             _ => return Node::Ignored(SK::BinaryExpression),
2592         };
2594         match (&op, rhs.is_token(TokenKind::Yield)) {
2595             (Bop::Eq(_), true) => return rhs,
2596             _ => {}
2597         }
2599         let pos = self.merge(self.merge_positions(lhs, op_node), self.get_pos(rhs));
2601         let lhs = match self.node_to_expr(lhs) {
2602             Some(lhs) => lhs,
2603             None => return Node::Ignored(SK::BinaryExpression),
2604         };
2605         let rhs = match self.node_to_expr(rhs) {
2606             Some(rhs) => rhs,
2607             None => return Node::Ignored(SK::BinaryExpression),
2608         };
2610         Node::Expr(self.alloc(aast::Expr(
2611             pos,
2612             aast::Expr_::Binop(self.alloc((op, lhs, rhs))),
2613         )))
2614     }
2616     fn make_parenthesized_expression(
2617         &mut self,
2618         _lparen: Self::R,
2619         expr: Self::R,
2620         _rparen: Self::R,
2621     ) -> Self::R {
2622         expr
2623     }
2625     fn make_list_item(&mut self, item: Self::R, sep: Self::R) -> Self::R {
2626         match (item.is_ignored(), sep.is_ignored()) {
2627             (true, true) => Node::Ignored(SK::ListItem),
2628             (false, true) => item,
2629             (true, false) => sep,
2630             (false, false) => Node::ListItem(self.alloc((item, sep))),
2631         }
2632     }
2634     fn make_type_arguments(
2635         &mut self,
2636         less_than: Self::R,
2637         arguments: Self::R,
2638         greater_than: Self::R,
2639     ) -> Self::R {
2640         Node::BracketedList(self.alloc((
2641             self.get_pos(less_than),
2642             arguments.as_slice(self.arena),
2643             self.get_pos(greater_than),
2644         )))
2645     }
2647     fn make_generic_type_specifier(
2648         &mut self,
2649         class_type: Self::R,
2650         type_arguments: Self::R,
2651     ) -> Self::R {
2652         let class_id = match self.expect_name(class_type) {
2653             Some(id) => id,
2654             None => return Node::Ignored(SK::GenericTypeSpecifier),
2655         };
2656         if class_id.1.trim_start_matches("\\") == "varray_or_darray" {
2657             let id_pos = class_id.0;
2658             let pos = self.merge(id_pos, self.get_pos(type_arguments));
2659             let type_arguments = type_arguments.as_slice(self.arena);
2660             let ty_ = match type_arguments {
2661                 [tk, tv] => Ty_::TvarrayOrDarray(
2662                     self.alloc((
2663                         self.node_to_ty(*tk)
2664                             .unwrap_or_else(|| self.tany_with_pos(id_pos)),
2665                         self.node_to_ty(*tv)
2666                             .unwrap_or_else(|| self.tany_with_pos(id_pos)),
2667                     )),
2668                 ),
2669                 [tv] => Ty_::TvarrayOrDarray(
2670                     self.alloc((
2671                         self.varray_or_darray_key(pos),
2672                         self.node_to_ty(*tv)
2673                             .unwrap_or_else(|| self.tany_with_pos(id_pos)),
2674                     )),
2675                 ),
2676                 _ => TANY_,
2677             };
2678             self.hint_ty(pos, ty_)
2679         } else {
2680             let Id(pos, class_type) = class_id;
2681             match class_type.rsplit('\\').next() {
2682                 Some(name) if self.is_type_param_in_scope(name) => {
2683                     let pos = self.merge(pos, self.get_pos(type_arguments));
2684                     let type_arguments = self.slice(
2685                         type_arguments
2686                             .iter()
2687                             .filter_map(|&node| self.node_to_ty(node)),
2688                     );
2689                     let ty_ = Ty_::Tgeneric(self.alloc((name, type_arguments)));
2690                     self.hint_ty(pos, ty_)
2691                 }
2692                 _ => {
2693                     let class_type = self.elaborate_raw_id(class_type);
2694                     self.make_apply(
2695                         Id(pos, class_type),
2696                         type_arguments,
2697                         self.get_pos(type_arguments),
2698                     )
2699                 }
2700             }
2701         }
2702     }
2704     fn make_record_declaration(
2705         &mut self,
2706         attribute_spec: Self::R,
2707         modifier: Self::R,
2708         record_keyword: Self::R,
2709         name: Self::R,
2710         _extends_keyword: Self::R,
2711         extends_opt: Self::R,
2712         _left_brace: Self::R,
2713         fields: Self::R,
2714         right_brace: Self::R,
2715     ) -> Self::R {
2716         let name = match self.elaborate_defined_id(name) {
2717             Some(name) => name,
2718             None => return Node::Ignored(SK::RecordDeclaration),
2719         };
2720         self.add_record(
2721             name.1,
2722             self.alloc(typing_defs::RecordDefType {
2723                 name,
2724                 extends: self
2725                     .expect_name(extends_opt)
2726                     .map(|id| self.elaborate_id(id)),
2727                 fields: self.slice(fields.iter().filter_map(|node| match node {
2728                     Node::RecordField(&field) => Some(field),
2729                     _ => None,
2730                 })),
2731                 abstract_: modifier.is_token(TokenKind::Abstract),
2732                 pos: self.pos_from_slice(&[attribute_spec, modifier, record_keyword, right_brace]),
2733             }),
2734         );
2735         Node::Ignored(SK::RecordDeclaration)
2736     }
2738     fn make_record_field(
2739         &mut self,
2740         _type_: Self::R,
2741         name: Self::R,
2742         initializer: Self::R,
2743         _semicolon: Self::R,
2744     ) -> Self::R {
2745         let name = match self.expect_name(name) {
2746             Some(name) => name,
2747             None => return Node::Ignored(SK::RecordField),
2748         };
2749         let field_req = if initializer.is_ignored() {
2750             RecordFieldReq::ValueRequired
2751         } else {
2752             RecordFieldReq::HasDefaultValue
2753         };
2754         Node::RecordField(self.alloc((name, field_req)))
2755     }
2757     fn make_alias_declaration(
2758         &mut self,
2759         _attributes: Self::R,
2760         keyword: Self::R,
2761         name: Self::R,
2762         generic_params: Self::R,
2763         constraint: Self::R,
2764         _equal: Self::R,
2765         aliased_type: Self::R,
2766         _semicolon: Self::R,
2767     ) -> Self::R {
2768         if name.is_ignored() {
2769             return Node::Ignored(SK::AliasDeclaration);
2770         }
2771         let Id(pos, name) = match self.elaborate_defined_id(name) {
2772             Some(id) => id,
2773             None => return Node::Ignored(SK::AliasDeclaration),
2774         };
2775         let ty = match self.node_to_ty(aliased_type) {
2776             Some(ty) => ty,
2777             None => return Node::Ignored(SK::AliasDeclaration),
2778         };
2779         let constraint = match constraint {
2780             Node::TypeConstraint(&(_kind, hint)) => self.node_to_ty(hint),
2781             _ => None,
2782         };
2783         // Pop the type params stack only after creating all inner types.
2784         let tparams = self.pop_type_params(generic_params);
2785         let typedef = self.alloc(TypedefType {
2786             pos,
2787             vis: match keyword.token_kind() {
2788                 Some(TokenKind::Type) => aast::TypedefVisibility::Transparent,
2789                 Some(TokenKind::Newtype) => aast::TypedefVisibility::Opaque,
2790                 _ => aast::TypedefVisibility::Transparent,
2791             },
2792             tparams,
2793             constraint,
2794             type_: ty,
2795         });
2797         self.add_typedef(name, typedef);
2799         Node::Ignored(SK::AliasDeclaration)
2800     }
2802     fn make_type_constraint(&mut self, kind: Self::R, value: Self::R) -> Self::R {
2803         let kind = match kind.token_kind() {
2804             Some(TokenKind::As) => ConstraintKind::ConstraintAs,
2805             Some(TokenKind::Super) => ConstraintKind::ConstraintSuper,
2806             n => panic!("Expected either As or Super, but was {:?}", n),
2807         };
2808         Node::TypeConstraint(self.alloc((kind, value)))
2809     }
2811     fn make_type_parameter(
2812         &mut self,
2813         user_attributes: Self::R,
2814         reify: Self::R,
2815         variance: Self::R,
2816         name: Self::R,
2817         tparam_params: Self::R,
2818         constraints: Self::R,
2819     ) -> Self::R {
2820         let user_attributes = match user_attributes {
2821             Node::BracketedList((_, attributes, _)) => {
2822                 self.slice(attributes.into_iter().filter_map(|x| match x {
2823                     Node::Attribute(a) => Some(*a),
2824                     _ => None,
2825                 }))
2826             }
2827             _ => &[][..],
2828         };
2830         let constraints = self.slice(constraints.iter().filter_map(|node| match node {
2831             Node::TypeConstraint(&constraint) => Some(constraint),
2832             n if n.is_ignored() => None,
2833             n => panic!("Expected a type constraint, but was {:?}", n),
2834         }));
2836         // TODO(T70068435) Once we add support for constraints on higher-kinded types
2837         // (in particular, constraints on nested type parameters), we need to ensure
2838         // that we correctly handle the scoping of nested type parameters.
2839         // This includes making sure that the call to convert_type_appl_to_generic
2840         // in make_type_parameters handles nested constraints.
2841         // For now, we just make sure that the nested type parameters that make_type_parameters
2842         // added to the global list of in-scope type parameters are removed immediately:
2843         self.pop_type_params(tparam_params);
2845         let tparam_params = match tparam_params {
2846             Node::TypeParameters(&params) => params,
2847             _ => &[],
2848         };
2850         Node::TypeParameter(self.alloc(TypeParameterDecl {
2851             name,
2852             variance: match variance.token_kind() {
2853                 Some(TokenKind::Minus) => Variance::Contravariant,
2854                 Some(TokenKind::Plus) => Variance::Covariant,
2855                 _ => Variance::Invariant,
2856             },
2857             reified: if reify.is_token(TokenKind::Reify) {
2858                 if user_attributes.iter().any(|node| node.name.1 == "__Soft") {
2859                     aast::ReifyKind::SoftReified
2860                 } else {
2861                     aast::ReifyKind::Reified
2862                 }
2863             } else {
2864                 aast::ReifyKind::Erased
2865             },
2866             constraints,
2867             tparam_params,
2868             user_attributes,
2869         }))
2870     }
2872     fn make_type_parameters(&mut self, _lt: Self::R, tparams: Self::R, _gt: Self::R) -> Self::R {
2873         let size = tparams.len();
2874         let mut tparams_with_name = Vec::with_capacity_in(size, self.arena);
2875         let mut tparam_names = MultiSetMut::with_capacity_in(size, self.arena);
2876         for node in tparams.iter() {
2877             match node {
2878                 &Node::TypeParameter(decl) => {
2879                     let name = match decl.name.as_id() {
2880                         Some(name) => name,
2881                         None => return Node::Ignored(SK::TypeParameters),
2882                     };
2883                     tparam_names.insert(name.1);
2884                     tparams_with_name.push((decl, name));
2885                 }
2886                 n => panic!("Expected a type parameter, but got {:?}", n),
2887             }
2888         }
2889         Rc::make_mut(&mut self.type_parameters).push(tparam_names.into());
2890         let mut tparams = Vec::with_capacity_in(tparams_with_name.len(), self.arena);
2891         for (decl, name) in tparams_with_name.into_iter() {
2892             let &TypeParameterDecl {
2893                 name: _,
2894                 variance,
2895                 reified,
2896                 constraints,
2897                 tparam_params,
2898                 user_attributes,
2899             } = decl;
2900             let constraints = self.slice(constraints.iter().filter_map(|constraint| {
2901                 let &(kind, ty) = constraint;
2902                 let ty = self.node_to_ty(ty)?;
2903                 let ty = self.convert_tapply_to_tgeneric(ty);
2904                 Some((kind, ty))
2905             }));
2907             let user_attributes = self.slice(
2908                 user_attributes
2909                     .iter()
2910                     .rev()
2911                     .map(|x| self.user_attribute_to_decl(x)),
2912             );
2913             tparams.push(self.alloc(Tparam {
2914                 variance,
2915                 name,
2916                 constraints,
2917                 reified,
2918                 user_attributes,
2919                 tparams: tparam_params,
2920             }));
2921         }
2922         Node::TypeParameters(self.alloc(tparams.into_bump_slice()))
2923     }
2925     fn make_parameter_declaration(
2926         &mut self,
2927         attributes: Self::R,
2928         visibility: Self::R,
2929         inout: Self::R,
2930         hint: Self::R,
2931         name: Self::R,
2932         initializer: Self::R,
2933     ) -> Self::R {
2934         let (variadic, pos, name) = match name {
2935             Node::ListItem(&(ellipsis, id)) => {
2936                 let Id(pos, name) = match id.as_id() {
2937                     Some(id) => id,
2938                     None => return Node::Ignored(SK::ParameterDeclaration),
2939                 };
2940                 let variadic = ellipsis.is_token(TokenKind::DotDotDot);
2941                 (variadic, pos, Some(name))
2942             }
2943             name => {
2944                 let Id(pos, name) = match name.as_id() {
2945                     Some(id) => id,
2946                     None => return Node::Ignored(SK::ParameterDeclaration),
2947                 };
2948                 (false, pos, Some(name))
2949             }
2950         };
2951         let kind = if inout.is_token(TokenKind::Inout) {
2952             ParamMode::FPinout
2953         } else {
2954             ParamMode::FPnormal
2955         };
2956         Node::FunParam(self.alloc(FunParamDecl {
2957             attributes,
2958             visibility,
2959             kind,
2960             hint,
2961             pos,
2962             name,
2963             variadic,
2964             initializer,
2965         }))
2966     }
2968     fn make_variadic_parameter(&mut self, _: Self::R, hint: Self::R, ellipsis: Self::R) -> Self::R {
2969         Node::FunParam(
2970             self.alloc(FunParamDecl {
2971                 attributes: Node::Ignored(SK::Missing),
2972                 visibility: Node::Ignored(SK::Missing),
2973                 kind: ParamMode::FPnormal,
2974                 hint,
2975                 pos: self
2976                     .get_pos_opt(hint)
2977                     .unwrap_or_else(|| self.get_pos(ellipsis)),
2978                 name: None,
2979                 variadic: true,
2980                 initializer: Node::Ignored(SK::Missing),
2981             }),
2982         )
2983     }
2985     fn make_function_declaration(
2986         &mut self,
2987         attributes: Self::R,
2988         header: Self::R,
2989         body: Self::R,
2990     ) -> Self::R {
2991         let parsed_attributes = self.to_attributes(attributes);
2992         match header {
2993             Node::FunctionHeader(header) => {
2994                 let is_method = false;
2995                 let (Id(pos, name), type_, _) =
2996                     match self.function_to_ty(is_method, attributes, header, body) {
2997                         Some(x) => x,
2998                         None => return Node::Ignored(SK::FunctionDeclaration),
2999                     };
3000                 let deprecated = parsed_attributes.deprecated.map(|msg| {
3001                     let mut s = String::new_in(self.arena);
3002                     s.push_str("The function ");
3003                     s.push_str(name.trim_start_matches("\\"));
3004                     s.push_str(" is deprecated: ");
3005                     s.push_str(msg);
3006                     s.into_bump_str()
3007                 });
3008                 let fun_elt = self.alloc(FunElt {
3009                     deprecated,
3010                     type_,
3011                     pos,
3012                     php_std_lib: parsed_attributes.php_std_lib,
3013                 });
3014                 self.add_fun(name, fun_elt);
3015                 Node::Ignored(SK::FunctionDeclaration)
3016             }
3017             _ => Node::Ignored(SK::FunctionDeclaration),
3018         }
3019     }
3021     fn make_contexts(&mut self, lb: Self::R, tys: Self::R, rb: Self::R) -> Self::R {
3022         let mut namespace_builder = NamespaceBuilder::empty_with_ns_in("HH\\Contexts", self.arena);
3023         std::mem::swap(
3024             &mut namespace_builder,
3025             Rc::make_mut(&mut self.namespace_builder),
3026         );
3027         // Simulating Typing_make_type.intersection here
3028         let make_mixed = || {
3029             let pos = Reason::hint(self.merge_positions(lb, rb));
3030             Node::Ty(self.alloc(Ty(
3031                 self.alloc(pos),
3032                 Ty_::Toption(self.alloc(Ty(self.alloc(pos), Ty_::Tnonnull))),
3033             )))
3034         };
3035         let cap = match tys {
3036             Node::Ignored(_) => make_mixed(),
3037             Node::List(tys_list) => {
3038                 if tys_list.is_empty() {
3039                     make_mixed()
3040                 } else if tys_list.len() == 1 {
3041                     Node::Ty(self.node_to_ty(tys_list[0]).unwrap())
3042                 } else {
3043                     self.make_intersection_type_specifier(lb, tys, rb)
3044                 }
3045             }
3046             _ => self.make_intersection_type_specifier(lb, tys, rb),
3047         };
3048         std::mem::swap(
3049             &mut namespace_builder,
3050             Rc::make_mut(&mut self.namespace_builder),
3051         );
3052         cap
3053     }
3055     fn make_function_declaration_header(
3056         &mut self,
3057         modifiers: Self::R,
3058         _keyword: Self::R,
3059         name: Self::R,
3060         type_params: Self::R,
3061         left_paren: Self::R,
3062         param_list: Self::R,
3063         _right_paren: Self::R,
3064         capability: Self::R,
3065         _colon: Self::R,
3066         ret_hint: Self::R,
3067         where_constraints: Self::R,
3068     ) -> Self::R {
3069         // Use the position of the left paren if the name is missing.
3070         let name = if name.is_ignored() { left_paren } else { name };
3071         Node::FunctionHeader(self.alloc(FunctionHeader {
3072             name,
3073             modifiers,
3074             type_params,
3075             param_list,
3076             capability,
3077             ret_hint,
3078             where_constraints,
3079         }))
3080     }
3082     fn make_yield_expression(&mut self, keyword: Self::R, _operand: Self::R) -> Self::R {
3083         assert!(keyword.token_kind() == Some(TokenKind::Yield));
3084         keyword
3085     }
3087     fn make_const_declaration(
3088         &mut self,
3089         modifiers: Self::R,
3090         _const_keyword: Self::R,
3091         hint: Self::R,
3092         decls: Self::R,
3093         _semicolon: Self::R,
3094     ) -> Self::R {
3095         match decls {
3096             // Class consts.
3097             Node::List(consts)
3098                 if self
3099                     .classish_name_builder
3100                     .get_current_classish_name()
3101                     .is_some() =>
3102             {
3103                 let ty = self.node_to_ty(hint);
3104                 Node::List(
3105                     self.alloc(self.slice(consts.iter().filter_map(|cst| match cst {
3106                         Node::ConstInitializer(&(name, initializer)) => {
3107                             let id = name.as_id()?;
3108                             let ty = ty
3109                                 .or_else(|| self.infer_const(name, initializer))
3110                                 .unwrap_or_else(|| tany());
3111                             let modifiers = read_member_modifiers(modifiers.iter());
3112                             Some(Node::Const(self.alloc(
3113                                 shallow_decl_defs::ShallowClassConst {
3114                                     abstract_: modifiers.is_abstract,
3115                                     name: id,
3116                                     type_: ty,
3117                                 },
3118                             )))
3119                         }
3120                         _ => None,
3121                     }))),
3122                 )
3123             }
3124             // Global consts.
3125             Node::List([Node::ConstInitializer(&(name, initializer))]) => {
3126                 let Id(pos, id) = match self.elaborate_defined_id(name) {
3127                     Some(id) => id,
3128                     None => return Node::Ignored(SK::ConstDeclaration),
3129                 };
3130                 let ty = self
3131                     .node_to_ty(hint)
3132                     .or_else(|| self.infer_const(name, initializer))
3133                     .unwrap_or_else(|| self.tany_with_pos(pos));
3134                 self.add_const(id, self.alloc(ConstDecl { pos, type_: ty }));
3135                 Node::Ignored(SK::ConstDeclaration)
3136             }
3137             _ => Node::Ignored(SK::ConstDeclaration),
3138         }
3139     }
3141     fn make_constant_declarator(&mut self, name: Self::R, initializer: Self::R) -> Self::R {
3142         if name.is_ignored() {
3143             Node::Ignored(SK::ConstantDeclarator)
3144         } else {
3145             Node::ConstInitializer(self.alloc((name, initializer)))
3146         }
3147     }
3149     fn make_namespace_declaration(&mut self, _name: Self::R, body: Self::R) -> Self::R {
3150         if let Node::Ignored(SK::NamespaceBody) = body {
3151             Rc::make_mut(&mut self.namespace_builder).pop_namespace();
3152         }
3153         Node::Ignored(SK::NamespaceDeclaration)
3154     }
3156     fn make_namespace_declaration_header(&mut self, _keyword: Self::R, name: Self::R) -> Self::R {
3157         let name = self.expect_name(name).map(|Id(_, name)| name);
3158         // if this is header of semicolon-style (one with NamespaceEmptyBody) namespace, we should pop
3159         // the previous namespace first, but we don't have the body yet. We'll fix it retroactively in
3160         // make_namespace_empty_body
3161         Rc::make_mut(&mut self.namespace_builder).push_namespace(name);
3162         Node::Ignored(SK::NamespaceDeclarationHeader)
3163     }
3165     fn make_namespace_body(
3166         &mut self,
3167         _left_brace: Self::R,
3168         _declarations: Self::R,
3169         _right_brace: Self::R,
3170     ) -> Self::R {
3171         Node::Ignored(SK::NamespaceBody)
3172     }
3174     fn make_namespace_empty_body(&mut self, _semicolon: Self::R) -> Self::R {
3175         Rc::make_mut(&mut self.namespace_builder).pop_previous_namespace();
3176         Node::Ignored(SK::NamespaceEmptyBody)
3177     }
3179     fn make_namespace_use_declaration(
3180         &mut self,
3181         _keyword: Self::R,
3182         namespace_use_kind: Self::R,
3183         clauses: Self::R,
3184         _semicolon: Self::R,
3185     ) -> Self::R {
3186         if let Some(import_kind) = Self::namespace_use_kind(&namespace_use_kind) {
3187             for clause in clauses.iter() {
3188                 if let Node::NamespaceUseClause(nuc) = clause {
3189                     Rc::make_mut(&mut self.namespace_builder).add_import(
3190                         import_kind,
3191                         nuc.id.1,
3192                         nuc.as_,
3193                     );
3194                 }
3195             }
3196         }
3197         Node::Ignored(SK::NamespaceUseDeclaration)
3198     }
3200     fn make_namespace_group_use_declaration(
3201         &mut self,
3202         _keyword: Self::R,
3203         _kind: Self::R,
3204         prefix: Self::R,
3205         _left_brace: Self::R,
3206         clauses: Self::R,
3207         _right_brace: Self::R,
3208         _semicolon: Self::R,
3209     ) -> Self::R {
3210         let Id(_, prefix) = match self.expect_name(prefix) {
3211             Some(id) => id,
3212             None => return Node::Ignored(SK::NamespaceGroupUseDeclaration),
3213         };
3214         for clause in clauses.iter() {
3215             if let Node::NamespaceUseClause(nuc) = clause {
3216                 let mut id = String::new_in(self.arena);
3217                 id.push_str(prefix);
3218                 id.push_str(nuc.id.1);
3219                 Rc::make_mut(&mut self.namespace_builder).add_import(
3220                     nuc.kind,
3221                     id.into_bump_str(),
3222                     nuc.as_,
3223                 );
3224             }
3225         }
3226         Node::Ignored(SK::NamespaceGroupUseDeclaration)
3227     }
3229     fn make_namespace_use_clause(
3230         &mut self,
3231         clause_kind: Self::R,
3232         name: Self::R,
3233         as_: Self::R,
3234         aliased_name: Self::R,
3235     ) -> Self::R {
3236         let id = match self.expect_name(name) {
3237             Some(id) => id,
3238             None => return Node::Ignored(SK::NamespaceUseClause),
3239         };
3240         let as_ = if as_.is_token(TokenKind::As) {
3241             match aliased_name.as_id() {
3242                 Some(name) => Some(name.1),
3243                 None => return Node::Ignored(SK::NamespaceUseClause),
3244             }
3245         } else {
3246             None
3247         };
3248         if let Some(kind) = Self::namespace_use_kind(&clause_kind) {
3249             Node::NamespaceUseClause(self.alloc(NamespaceUseClause { kind, id, as_ }))
3250         } else {
3251             Node::Ignored(SK::NamespaceUseClause)
3252         }
3253     }
3255     fn make_where_clause(&mut self, _: Self::R, where_constraints: Self::R) -> Self::R {
3256         where_constraints
3257     }
3259     fn make_where_constraint(
3260         &mut self,
3261         left_type: Self::R,
3262         operator: Self::R,
3263         right_type: Self::R,
3264     ) -> Self::R {
3265         Node::WhereConstraint(self.alloc(WhereConstraint(
3266             self.node_to_ty(left_type).unwrap_or_else(|| tany()),
3267             match operator.token_kind() {
3268                 Some(TokenKind::Equal) => ConstraintKind::ConstraintEq,
3269                 Some(TokenKind::Super) => ConstraintKind::ConstraintSuper,
3270                 _ => ConstraintKind::ConstraintAs,
3271             },
3272             self.node_to_ty(right_type).unwrap_or_else(|| tany()),
3273         )))
3274     }
3276     fn make_classish_declaration(
3277         &mut self,
3278         attributes: Self::R,
3279         modifiers: Self::R,
3280         xhp_keyword: Self::R,
3281         class_keyword: Self::R,
3282         name: Self::R,
3283         tparams: Self::R,
3284         _extends_keyword: Self::R,
3285         extends: Self::R,
3286         _implements_keyword: Self::R,
3287         implements: Self::R,
3288         where_clause: Self::R,
3289         body: Self::R,
3290     ) -> Self::R {
3291         let raw_name = match self.expect_name(name) {
3292             Some(Id(_, name)) => name,
3293             None => return Node::Ignored(SK::ClassishDeclaration),
3294         };
3295         let Id(pos, name) = match self.elaborate_defined_id(name) {
3296             Some(id) => id,
3297             None => return Node::Ignored(SK::ClassishDeclaration),
3298         };
3299         let is_xhp = raw_name.starts_with(':') || xhp_keyword.is_present();
3301         let mut class_kind = match class_keyword.token_kind() {
3302             Some(TokenKind::Interface) => ClassKind::Cinterface,
3303             Some(TokenKind::Trait) => ClassKind::Ctrait,
3304             _ => ClassKind::Cnormal,
3305         };
3306         let mut final_ = false;
3308         for modifier in modifiers.iter() {
3309             match modifier.token_kind() {
3310                 Some(TokenKind::Abstract) => class_kind = ClassKind::Cabstract,
3311                 Some(TokenKind::Final) => final_ = true,
3312                 _ => {}
3313             }
3314         }
3316         let where_constraints = self.slice(where_clause.iter().filter_map(|&x| match x {
3317             Node::WhereConstraint(x) => Some(x),
3318             _ => None,
3319         }));
3321         let body = match body {
3322             Node::ClassishBody(body) => body,
3323             body => panic!("Expected a classish body, but was {:?}", body),
3324         };
3326         let mut uses_len = 0;
3327         let mut xhp_attr_uses_len = 0;
3328         let mut req_extends_len = 0;
3329         let mut req_implements_len = 0;
3330         let mut consts_len = 0;
3331         let mut typeconsts_len = 0;
3332         let mut props_len = 0;
3333         let mut sprops_len = 0;
3334         let mut static_methods_len = 0;
3335         let mut methods_len = 0;
3337         let mut user_attributes_len = 0;
3338         for attribute in attributes.iter() {
3339             match attribute {
3340                 &Node::Attribute(..) => user_attributes_len += 1,
3341                 _ => {}
3342             }
3343         }
3345         for element in body.iter().copied() {
3346             match element {
3347                 Node::TraitUse(names) => uses_len += names.len(),
3348                 Node::XhpClassAttributeDeclaration(&XhpClassAttributeDeclarationNode {
3349                     xhp_attr_decls,
3350                     xhp_attr_uses_decls,
3351                 }) => {
3352                     props_len += xhp_attr_decls.len();
3353                     xhp_attr_uses_len += xhp_attr_uses_decls.len();
3354                 }
3355                 Node::TypeConstant(..) => typeconsts_len += 1,
3356                 Node::RequireClause(require) => match require.require_type.token_kind() {
3357                     Some(TokenKind::Extends) => req_extends_len += 1,
3358                     Some(TokenKind::Implements) => req_implements_len += 1,
3359                     _ => {}
3360                 },
3361                 Node::List(consts @ [Node::Const(..), ..]) => consts_len += consts.len(),
3362                 Node::Property(&PropertyNode { decls, is_static }) => {
3363                     if is_static {
3364                         sprops_len += decls.len()
3365                     } else {
3366                         props_len += decls.len()
3367                     }
3368                 }
3369                 Node::Constructor(&ConstructorNode { properties, .. }) => {
3370                     props_len += properties.len()
3371                 }
3372                 Node::Method(&MethodNode { is_static, .. }) => {
3373                     if is_static {
3374                         static_methods_len += 1
3375                     } else {
3376                         methods_len += 1
3377                     }
3378                 }
3379                 _ => {}
3380             }
3381         }
3383         let mut constructor = None;
3385         let mut uses = Vec::with_capacity_in(uses_len, self.arena);
3386         let mut xhp_attr_uses = Vec::with_capacity_in(xhp_attr_uses_len, self.arena);
3387         let mut req_extends = Vec::with_capacity_in(req_extends_len, self.arena);
3388         let mut req_implements = Vec::with_capacity_in(req_implements_len, self.arena);
3389         let mut consts = Vec::with_capacity_in(consts_len, self.arena);
3390         let mut typeconsts = Vec::with_capacity_in(typeconsts_len, self.arena);
3391         let mut props = Vec::with_capacity_in(props_len, self.arena);
3392         let mut sprops = Vec::with_capacity_in(sprops_len, self.arena);
3393         let mut static_methods = Vec::with_capacity_in(static_methods_len, self.arena);
3394         let mut methods = Vec::with_capacity_in(methods_len, self.arena);
3396         let mut user_attributes = Vec::with_capacity_in(user_attributes_len, self.arena);
3397         for attribute in attributes.iter() {
3398             match attribute {
3399                 Node::Attribute(attr) => user_attributes.push(self.user_attribute_to_decl(&attr)),
3400                 _ => {}
3401             }
3402         }
3403         // Match ordering of attributes produced by the OCaml decl parser (even
3404         // though it's the reverse of the syntactic ordering).
3405         user_attributes.reverse();
3407         // xhp props go after regular props, regardless of their order in file
3408         let mut xhp_props = vec![];
3410         for element in body.iter().copied() {
3411             match element {
3412                 Node::TraitUse(names) => {
3413                     uses.extend(names.iter().filter_map(|&name| self.node_to_ty(name)))
3414                 }
3415                 Node::XhpClassAttributeDeclaration(&XhpClassAttributeDeclarationNode {
3416                     xhp_attr_decls,
3417                     xhp_attr_uses_decls,
3418                 }) => {
3419                     xhp_props.extend(xhp_attr_decls);
3420                     xhp_attr_uses.extend(
3421                         xhp_attr_uses_decls
3422                             .iter()
3423                             .filter_map(|&node| self.node_to_ty(node)),
3424                     )
3425                 }
3426                 Node::TypeConstant(constant) => typeconsts.push(constant),
3427                 Node::RequireClause(require) => match require.require_type.token_kind() {
3428                     Some(TokenKind::Extends) => {
3429                         req_extends.extend(self.node_to_ty(require.name).iter())
3430                     }
3431                     Some(TokenKind::Implements) => {
3432                         req_implements.extend(self.node_to_ty(require.name).iter())
3433                     }
3434                     _ => {}
3435                 },
3436                 Node::List(&const_nodes @ [Node::Const(..), ..]) => {
3437                     for node in const_nodes {
3438                         if let &Node::Const(decl) = node {
3439                             consts.push(decl)
3440                         }
3441                     }
3442                 }
3443                 Node::Property(&PropertyNode { decls, is_static }) => {
3444                     for property in decls {
3445                         if is_static {
3446                             sprops.push(property)
3447                         } else {
3448                             props.push(property)
3449                         }
3450                     }
3451                 }
3452                 Node::Constructor(&ConstructorNode { method, properties }) => {
3453                     constructor = Some(method);
3454                     for property in properties {
3455                         props.push(property)
3456                     }
3457                 }
3458                 Node::Method(&MethodNode { method, is_static }) => {
3459                     if is_static {
3460                         static_methods.push(method);
3461                     } else {
3462                         methods.push(method);
3463                     }
3464                 }
3465                 _ => {} // It's not our job to report errors here.
3466             }
3467         }
3469         props.extend(xhp_props.into_iter());
3471         let class_attributes = self.to_attributes(attributes);
3472         if class_attributes.const_ {
3473             for prop in props.iter_mut() {
3474                 if !prop.flags.contains(PropFlags::CONST) {
3475                     *prop = self.alloc(ShallowProp {
3476                         flags: prop.flags | PropFlags::CONST,
3477                         ..**prop
3478                     })
3479                 }
3480             }
3481         }
3483         let uses = uses.into_bump_slice();
3484         let xhp_attr_uses = xhp_attr_uses.into_bump_slice();
3485         let req_extends = req_extends.into_bump_slice();
3486         let req_implements = req_implements.into_bump_slice();
3487         let consts = consts.into_bump_slice();
3488         let typeconsts = typeconsts.into_bump_slice();
3489         let props = props.into_bump_slice();
3490         let sprops = sprops.into_bump_slice();
3491         let static_methods = static_methods.into_bump_slice();
3492         let methods = methods.into_bump_slice();
3493         let user_attributes = user_attributes.into_bump_slice();
3495         let extends = self.slice(extends.iter().filter_map(|&node| self.node_to_ty(node)));
3497         let mut implements_dynamic = false;
3498         let implements = self.slice(implements.iter().filter_map(
3499             |&node| match self.node_to_ty(node) {
3500                 Some(Ty(_, Ty_::Tdynamic)) => {
3501                     implements_dynamic = true;
3502                     None
3503                 }
3504                 x => x,
3505             },
3506         ));
3508         // Pop the type params stack only after creating all inner types.
3509         let tparams = self.pop_type_params(tparams);
3511         let cls = self.alloc(shallow_decl_defs::ShallowClass {
3512             mode: self.file_mode,
3513             final_,
3514             is_xhp,
3515             has_xhp_keyword: xhp_keyword.is_token(TokenKind::XHP),
3516             kind: class_kind,
3517             name: Id(pos, name),
3518             tparams,
3519             where_constraints,
3520             extends,
3521             uses,
3522             xhp_attr_uses,
3523             req_extends,
3524             req_implements,
3525             implements,
3526             implements_dynamic,
3527             consts,
3528             typeconsts,
3529             props,
3530             sprops,
3531             constructor,
3532             static_methods,
3533             methods,
3534             user_attributes,
3535             enum_type: None,
3536         });
3537         self.add_class(name, cls);
3539         self.classish_name_builder.parsed_classish_declaration();
3541         Node::Ignored(SK::ClassishDeclaration)
3542     }
3544     fn make_property_declaration(
3545         &mut self,
3546         attrs: Self::R,
3547         modifiers: Self::R,
3548         hint: Self::R,
3549         declarators: Self::R,
3550         _semicolon: Self::R,
3551     ) -> Self::R {
3552         let (attrs, modifiers, hint) = (attrs, modifiers, hint);
3553         let modifiers = read_member_modifiers(modifiers.iter());
3554         let declarators = self.slice(declarators.iter().filter_map(
3555             |declarator| match declarator {
3556                 Node::ListItem(&(name, initializer)) => {
3557                     let attributes = self.to_attributes(attrs);
3558                     let Id(pos, name) = name.as_id()?;
3559                     let name = if modifiers.is_static {
3560                         name
3561                     } else {
3562                         strip_dollar_prefix(name)
3563                     };
3564                     let ty = self.node_to_non_ret_ty(hint);
3565                     let needs_init = if self.file_mode == Mode::Mdecl {
3566                         false
3567                     } else {
3568                         initializer.is_ignored()
3569                     };
3570                     let mut flags = PropFlags::empty();
3571                     flags.set(PropFlags::CONST, attributes.const_);
3572                     flags.set(PropFlags::LATEINIT, attributes.late_init);
3573                     flags.set(PropFlags::LSB, attributes.lsb);
3574                     flags.set(PropFlags::NEEDS_INIT, needs_init);
3575                     flags.set(PropFlags::ABSTRACT, modifiers.is_abstract);
3576                     flags.set(PropFlags::PHP_STD_LIB, attributes.php_std_lib);
3577                     Some(ShallowProp {
3578                         xhp_attr: None,
3579                         name: Id(pos, name),
3580                         type_: ty,
3581                         visibility: modifiers.visibility,
3582                         flags,
3583                     })
3584                 }
3585                 n => panic!("Expected a ListItem, but was {:?}", n),
3586             },
3587         ));
3588         Node::Property(self.alloc(PropertyNode {
3589             decls: declarators,
3590             is_static: modifiers.is_static,
3591         }))
3592     }
3594     fn make_xhp_class_attribute_declaration(
3595         &mut self,
3596         _keyword: Self::R,
3597         attributes: Self::R,
3598         _semicolon: Self::R,
3599     ) -> Self::R {
3600         let xhp_attr_decls = self.slice(attributes.iter().filter_map(|node| {
3601             let node = match node {
3602                 Node::XhpClassAttribute(x) => x,
3603                 _ => return None,
3604             };
3605             let Id(pos, name) = node.name;
3606             let name = prefix_colon(self.arena, name);
3608             let type_ = self.node_to_ty(node.hint);
3609             let type_ = if node.nullable && node.tag.is_none() {
3610                 type_.and_then(|x| match x {
3611                     // already nullable
3612                     Ty(_, Ty_::Toption(_)) | Ty(_, Ty_::Tmixed) => type_,
3613                     // make nullable
3614                     _ => self.node_to_ty(self.hint_ty(x.get_pos()?, Ty_::Toption(x))),
3615                 })
3616             } else {
3617                 type_
3618             };
3619             let mut flags = PropFlags::empty();
3620             flags.set(PropFlags::NEEDS_INIT, node.needs_init);
3621             Some(ShallowProp {
3622                 name: Id(pos, name),
3623                 visibility: aast::Visibility::Public,
3624                 type_,
3625                 xhp_attr: Some(shallow_decl_defs::XhpAttr {
3626                     tag: node.tag,
3627                     has_default: !node.needs_init,
3628                 }),
3629                 flags,
3630             })
3631         }));
3633         let xhp_attr_uses_decls = self.slice(attributes.iter().filter_map(|x| match x {
3634             Node::XhpAttributeUse(&name) => Some(name),
3635             _ => None,
3636         }));
3638         Node::XhpClassAttributeDeclaration(self.alloc(XhpClassAttributeDeclarationNode {
3639             xhp_attr_decls,
3640             xhp_attr_uses_decls,
3641         }))
3642     }
3644     fn make_xhp_enum_type(
3645         &mut self,
3646         enum_keyword: Self::R,
3647         _left_brace: Self::R,
3648         xhp_enum_values: Self::R,
3649         right_brace: Self::R,
3650     ) -> Self::R {
3651         let ty_opt = xhp_enum_values
3652             .iter()
3653             .next()
3654             .and_then(|x| self.node_to_ty(*x));
3655         match ty_opt {
3656             Some(ty) => self.hint_ty(self.merge_positions(enum_keyword, right_brace), ty.1),
3657             None => Node::Ignored(SK::XHPEnumType),
3658         }
3659     }
3661     fn make_xhp_class_attribute(
3662         &mut self,
3663         type_: Self::R,
3664         name: Self::R,
3665         initializer: Self::R,
3666         tag: Self::R,
3667     ) -> Self::R {
3668         let name = match name.as_id() {
3669             Some(name) => name,
3670             None => return Node::Ignored(SK::XHPClassAttribute),
3671         };
3672         Node::XhpClassAttribute(self.alloc(XhpClassAttributeNode {
3673             name,
3674             hint: type_,
3675             needs_init: !initializer.is_present(),
3676             tag: match tag.token_kind() {
3677                 Some(TokenKind::Required) => Some(XhpAttrTag::Required),
3678                 Some(TokenKind::Lateinit) => Some(XhpAttrTag::Lateinit),
3679                 _ => None,
3680             },
3681             nullable: initializer.is_token(TokenKind::NullLiteral) || !initializer.is_present(),
3682         }))
3683     }
3685     fn make_xhp_simple_class_attribute(&mut self, name: Self::R) -> Self::R {
3686         Node::XhpAttributeUse(self.alloc(name))
3687     }
3689     fn make_property_declarator(&mut self, name: Self::R, initializer: Self::R) -> Self::R {
3690         Node::ListItem(self.alloc((name, initializer)))
3691     }
3693     fn make_methodish_declaration(
3694         &mut self,
3695         attributes: Self::R,
3696         header: Self::R,
3697         body: Self::R,
3698         closer: Self::R,
3699     ) -> Self::R {
3700         let header = match header {
3701             Node::FunctionHeader(header) => header,
3702             n => panic!("Expected a FunctionDecl header, but was {:?}", n),
3703         };
3704         // If we don't have a body, use the closing token. A closing token of
3705         // '}' indicates a regular function, while a closing token of ';'
3706         // indicates an abstract function.
3707         let body = if body.is_ignored() { closer } else { body };
3708         let modifiers = read_member_modifiers(header.modifiers.iter());
3709         let is_constructor = header.name.is_token(TokenKind::Construct);
3710         let is_method = true;
3711         let (id, ty, properties) = match self.function_to_ty(is_method, attributes, header, body) {
3712             Some(tuple) => tuple,
3713             None => return Node::Ignored(SK::MethodishDeclaration),
3714         };
3715         let attributes = self.to_attributes(attributes);
3716         let deprecated = attributes.deprecated.map(|msg| {
3717             let mut s = String::new_in(self.arena);
3718             s.push_str("The method ");
3719             s.push_str(id.1);
3720             s.push_str(" is deprecated: ");
3721             s.push_str(msg);
3722             s.into_bump_str()
3723         });
3724         fn get_condition_type_name<'a>(ty_opt: Option<&'a Ty<'a>>) -> Option<&'a str> {
3725             ty_opt.and_then(|ty| {
3726                 let Ty(_, ty_) = ty;
3727                 match *ty_ {
3728                     Ty_::Tapply(&(Id(_, class_name), _)) => Some(class_name),
3729                     _ => None,
3730                 }
3731             })
3732         }
3733         let mut flags = MethodFlags::empty();
3734         flags.set(
3735             MethodFlags::ABSTRACT,
3736             self.classish_name_builder.in_interface() || modifiers.is_abstract,
3737         );
3738         flags.set(MethodFlags::FINAL, modifiers.is_final);
3739         flags.set(MethodFlags::OVERRIDE, attributes.override_);
3740         flags.set(
3741             MethodFlags::DYNAMICALLYCALLABLE,
3742             attributes.dynamically_callable,
3743         );
3744         flags.set(MethodFlags::PHP_STD_LIB, attributes.php_std_lib);
3745         let method = self.alloc(ShallowMethod {
3746             name: id,
3747             reactivity: match attributes.reactivity {
3748                 Reactivity::Local(condition_type) => Some(MethodReactivity::MethodLocal(
3749                     get_condition_type_name(condition_type),
3750                 )),
3751                 Reactivity::Shallow(condition_type) => Some(MethodReactivity::MethodShallow(
3752                     get_condition_type_name(condition_type),
3753                 )),
3754                 Reactivity::Reactive(condition_type) => Some(MethodReactivity::MethodReactive(
3755                     get_condition_type_name(condition_type),
3756                 )),
3757                 Reactivity::Pure(condition_type) => Some(MethodReactivity::MethodPure(
3758                     get_condition_type_name(condition_type),
3759                 )),
3760                 Reactivity::Nonreactive
3761                 | Reactivity::MaybeReactive(_)
3762                 | Reactivity::RxVar(_)
3763                 | Reactivity::Cipp(_)
3764                 | Reactivity::CippLocal(_)
3765                 | Reactivity::CippGlobal
3766                 | Reactivity::CippRx => None,
3767             },
3768             type_: ty,
3769             visibility: modifiers.visibility,
3770             deprecated,
3771             flags,
3772         });
3773         if is_constructor {
3774             Node::Constructor(self.alloc(ConstructorNode { method, properties }))
3775         } else {
3776             Node::Method(self.alloc(MethodNode {
3777                 method,
3778                 is_static: modifiers.is_static,
3779             }))
3780         }
3781     }
3783     fn make_classish_body(
3784         &mut self,
3785         _left_brace: Self::R,
3786         elements: Self::R,
3787         _right_brace: Self::R,
3788     ) -> Self::R {
3789         Node::ClassishBody(self.alloc(elements.as_slice(self.arena)))
3790     }
3792     fn make_enum_declaration(
3793         &mut self,
3794         attributes: Self::R,
3795         _keyword: Self::R,
3796         name: Self::R,
3797         _colon: Self::R,
3798         extends: Self::R,
3799         constraint: Self::R,
3800         _left_brace: Self::R,
3801         use_clauses: Self::R,
3802         enumerators: Self::R,
3803         _right_brace: Self::R,
3804     ) -> Self::R {
3805         let id = match self.elaborate_defined_id(name) {
3806             Some(id) => id,
3807             None => return Node::Ignored(SK::EnumDeclaration),
3808         };
3809         let hint = match self.node_to_ty(extends) {
3810             Some(ty) => ty,
3811             None => return Node::Ignored(SK::EnumDeclaration),
3812         };
3813         let extends = match self.node_to_ty(self.make_apply(
3814             Id(self.get_pos(name), "\\HH\\BuiltinEnum"),
3815             name,
3816             Pos::none(),
3817         )) {
3818             Some(ty) => ty,
3819             None => return Node::Ignored(SK::EnumDeclaration),
3820         };
3821         let key = id.1;
3822         let consts = self.slice(enumerators.iter().filter_map(|node| match node {
3823             Node::ListItem(&(name, value)) => {
3824                 let id = name.as_id()?;
3825                 Some(
3826                     self.alloc(shallow_decl_defs::ShallowClassConst {
3827                         abstract_: false,
3828                         name: id,
3829                         type_: self
3830                             .infer_const(name, value)
3831                             .unwrap_or_else(|| self.tany_with_pos(id.0)),
3832                     }),
3833                 )
3834             }
3835             n => panic!("Expected an enum case, got {:?}", n),
3836         }));
3838         let mut user_attributes = Vec::with_capacity_in(attributes.len(), self.arena);
3839         for attribute in attributes.iter() {
3840             match attribute {
3841                 Node::Attribute(attr) => user_attributes.push(self.user_attribute_to_decl(attr)),
3842                 _ => {}
3843             }
3844         }
3845         // Match ordering of attributes produced by the OCaml decl parser (even
3846         // though it's the reverse of the syntactic ordering).
3847         user_attributes.reverse();
3848         let user_attributes = user_attributes.into_bump_slice();
3850         let constraint = match constraint {
3851             Node::TypeConstraint(&(_kind, ty)) => self.node_to_ty(ty),
3852             _ => None,
3853         };
3855         let includes = self.slice(use_clauses.iter().filter_map(|&node| self.node_to_ty(node)));
3857         let cls = self.alloc(shallow_decl_defs::ShallowClass {
3858             mode: self.file_mode,
3859             final_: false,
3860             is_xhp: false,
3861             has_xhp_keyword: false,
3862             kind: ClassKind::Cenum,
3863             name: id,
3864             tparams: &[],
3865             where_constraints: &[],
3866             extends: bumpalo::vec![in self.arena; extends].into_bump_slice(),
3867             uses: &[],
3868             xhp_attr_uses: &[],
3869             req_extends: &[],
3870             req_implements: &[],
3871             implements: &[],
3872             implements_dynamic: false,
3873             consts,
3874             typeconsts: &[],
3875             props: &[],
3876             sprops: &[],
3877             constructor: None,
3878             static_methods: &[],
3879             methods: &[],
3880             user_attributes,
3881             enum_type: Some(self.alloc(EnumType {
3882                 base: hint,
3883                 constraint,
3884                 includes,
3885                 enum_class: false,
3886             })),
3887         });
3888         self.add_class(key, cls);
3890         self.classish_name_builder.parsed_classish_declaration();
3892         Node::Ignored(SK::EnumDeclaration)
3893     }
3895     fn make_enumerator(
3896         &mut self,
3897         name: Self::R,
3898         _equal: Self::R,
3899         value: Self::R,
3900         _semicolon: Self::R,
3901     ) -> Self::R {
3902         Node::ListItem(self.alloc((name, value)))
3903     }
3905     fn make_enum_class_declaration(
3906         &mut self,
3907         attributes: Self::R,
3908         _enum_keyword: Self::R,
3909         _class_keyword: Self::R,
3910         name: Self::R,
3911         _colon: Self::R,
3912         base: Self::R,
3913         _extends_keyword: Self::R,
3914         extends_list: Self::R,
3915         _left_brace: Self::R,
3916         elements: Self::R,
3917         _right_brace: Self::R,
3918     ) -> Self::R {
3919         let name = match self.elaborate_defined_id(name) {
3920             Some(name) => name,
3921             None => return Node::Ignored(SyntaxKind::EnumClassDeclaration),
3922         };
3923         let base = self
3924             .node_to_ty(base)
3925             .unwrap_or_else(|| self.tany_with_pos(name.0));
3927         let builtin_enum_class_ty = {
3928             let pos = name.0;
3929             let enum_class_ty_ = Ty_::Tapply(self.alloc((name, &[])));
3930             let enum_class_ty = self.alloc(Ty(self.alloc(Reason::hint(pos)), enum_class_ty_));
3931             let elt_ty_ = Ty_::Tapply(self.alloc((
3932                 Id(pos, "\\HH\\MemberOf"),
3933                 bumpalo::vec![in self.arena; enum_class_ty, base].into_bump_slice(),
3934             )));
3935             let elt_ty = self.alloc(Ty(self.alloc(Reason::hint(pos)), elt_ty_));
3936             let builtin_enum_ty_ = Ty_::Tapply(self.alloc((
3937                 Id(pos, "\\HH\\BuiltinEnumClass"),
3938                 std::slice::from_ref(self.alloc(elt_ty)),
3939             )));
3940             self.alloc(Ty(self.alloc(Reason::hint(pos)), builtin_enum_ty_))
3941         };
3943         let consts = self.slice(elements.iter().filter_map(|node| match node {
3944             &Node::Const(const_) => Some(const_),
3945             _ => None,
3946         }));
3948         let mut extends = Vec::with_capacity_in(extends_list.len() + 1, self.arena);
3949         extends.push(builtin_enum_class_ty);
3950         extends.extend(extends_list.iter().filter_map(|&n| self.node_to_ty(n)));
3951         let extends = extends.into_bump_slice();
3952         let includes = &extends[1..];
3954         let mut user_attributes = Vec::with_capacity_in(attributes.len() + 1, self.arena);
3955         user_attributes.push(self.alloc(shallow_decl_defs::UserAttribute {
3956             name: Id(name.0, "__EnumClass"),
3957             classname_params: &[],
3958         }));
3959         for attribute in attributes.iter() {
3960             match attribute {
3961                 Node::Attribute(attr) => user_attributes.push(self.user_attribute_to_decl(attr)),
3962                 _ => {}
3963             }
3964         }
3965         // Match ordering of attributes produced by the OCaml decl parser (even
3966         // though it's the reverse of the syntactic ordering).
3967         user_attributes.reverse();
3968         let user_attributes = user_attributes.into_bump_slice();
3970         let cls = self.alloc(shallow_decl_defs::ShallowClass {
3971             mode: self.file_mode,
3972             final_: false,
3973             is_xhp: false,
3974             has_xhp_keyword: false,
3975             kind: ClassKind::Cenum,
3976             name,
3977             tparams: &[],
3978             where_constraints: &[],
3979             extends,
3980             uses: &[],
3981             xhp_attr_uses: &[],
3982             req_extends: &[],
3983             req_implements: &[],
3984             implements: &[],
3985             implements_dynamic: false,
3986             consts,
3987             typeconsts: &[],
3988             props: &[],
3989             sprops: &[],
3990             constructor: None,
3991             static_methods: &[],
3992             methods: &[],
3993             user_attributes,
3994             enum_type: Some(self.alloc(EnumType {
3995                 base,
3996                 constraint: None,
3997                 includes,
3998                 enum_class: true,
3999             })),
4000         });
4001         self.add_class(name.1, cls);
4003         self.classish_name_builder.parsed_classish_declaration();
4005         Node::Ignored(SyntaxKind::EnumClassDeclaration)
4006     }
4008     fn make_enum_class_enumerator(
4009         &mut self,
4010         type_: Self::R,
4011         name: Self::R,
4012         _equal: Self::R,
4013         _initial_value: Self::R,
4014         _semicolon: Self::R,
4015     ) -> Self::R {
4016         let name = match self.expect_name(name) {
4017             Some(name) => name,
4018             None => return Node::Ignored(SyntaxKind::EnumClassEnumerator),
4019         };
4020         let pos = name.0;
4021         let type_ = self
4022             .node_to_ty(type_)
4023             .unwrap_or_else(|| self.tany_with_pos(name.0));
4024         let class_name = match self.classish_name_builder.get_current_classish_name() {
4025             Some(name) => name,
4026             None => return Node::Ignored(SyntaxKind::EnumClassEnumerator),
4027         };
4028         let enum_class_ty_ = Ty_::Tapply(self.alloc((Id(pos, class_name.0), &[])));
4029         let enum_class_ty = self.alloc(Ty(self.alloc(Reason::hint(pos)), enum_class_ty_));
4030         let type_ = Ty_::Tapply(self.alloc((
4031             Id(pos, "\\HH\\MemberOf"),
4032             bumpalo::vec![in self.arena; enum_class_ty, type_].into_bump_slice(),
4033         )));
4034         let type_ = self.alloc(Ty(self.alloc(Reason::hint(pos)), type_));
4035         Node::Const(self.alloc(ShallowClassConst {
4036             abstract_: false,
4037             name,
4038             type_,
4039         }))
4040     }
4042     fn make_tuple_type_specifier(
4043         &mut self,
4044         left_paren: Self::R,
4045         tys: Self::R,
4046         right_paren: Self::R,
4047     ) -> Self::R {
4048         // We don't need to include the tys list in this position merging
4049         // because by definition it's already contained by the two brackets.
4050         let pos = self.merge_positions(left_paren, right_paren);
4051         let tys = self.slice(tys.iter().filter_map(|&node| self.node_to_ty(node)));
4052         self.hint_ty(pos, Ty_::Ttuple(tys))
4053     }
4055     fn make_tuple_type_explicit_specifier(
4056         &mut self,
4057         keyword: Self::R,
4058         _left_angle: Self::R,
4059         types: Self::R,
4060         right_angle: Self::R,
4061     ) -> Self::R {
4062         let id = Id(self.get_pos(keyword), "\\tuple");
4063         // This is an error--tuple syntax is (A, B), not tuple<A, B>.
4064         // OCaml decl makes a Tapply rather than a Ttuple here.
4065         self.make_apply(id, types, self.get_pos(right_angle))
4066     }
4068     fn make_intersection_type_specifier(
4069         &mut self,
4070         left_paren: Self::R,
4071         tys: Self::R,
4072         right_paren: Self::R,
4073     ) -> Self::R {
4074         let pos = self.merge_positions(left_paren, right_paren);
4075         let tys = self.slice(tys.iter().filter_map(|x| match x {
4076             Node::ListItem(&(ty, _ampersand)) => self.node_to_ty(ty),
4077             &x => self.node_to_ty(x),
4078         }));
4079         self.hint_ty(pos, Ty_::Tintersection(tys))
4080     }
4082     fn make_union_type_specifier(
4083         &mut self,
4084         left_paren: Self::R,
4085         tys: Self::R,
4086         right_paren: Self::R,
4087     ) -> Self::R {
4088         let pos = self.merge_positions(left_paren, right_paren);
4089         let tys = self.slice(tys.iter().filter_map(|x| match x {
4090             Node::ListItem(&(ty, _bar)) => self.node_to_ty(ty),
4091             &x => self.node_to_ty(x),
4092         }));
4093         self.hint_ty(pos, Ty_::Tunion(tys))
4094     }
4096     fn make_shape_type_specifier(
4097         &mut self,
4098         shape: Self::R,
4099         _lparen: Self::R,
4100         fields: Self::R,
4101         open: Self::R,
4102         rparen: Self::R,
4103     ) -> Self::R {
4104         let fields = fields;
4105         let fields_iter = fields.iter();
4106         let mut fields = AssocListMut::new_in(self.arena);
4107         for node in fields_iter {
4108             match node {
4109                 &Node::ShapeFieldSpecifier(&ShapeFieldNode { name, type_ }) => {
4110                     fields.insert(*name, type_)
4111                 }
4112                 n => panic!("Expected a shape field specifier, but was {:?}", n),
4113             }
4114         }
4115         let kind = match open.token_kind() {
4116             Some(TokenKind::DotDotDot) => ShapeKind::OpenShape,
4117             _ => ShapeKind::ClosedShape,
4118         };
4119         let pos = self.merge_positions(shape, rparen);
4120         self.hint_ty(pos, Ty_::Tshape(self.alloc((kind, fields.into()))))
4121     }
4123     fn make_shape_expression(
4124         &mut self,
4125         shape: Self::R,
4126         _left_paren: Self::R,
4127         fields: Self::R,
4128         right_paren: Self::R,
4129     ) -> Self::R {
4130         let fields = self.slice(fields.iter().filter_map(|node| match node {
4131             Node::ListItem(&(key, value)) => {
4132                 let key = self.make_shape_field_name(key)?;
4133                 let value = self.node_to_expr(value)?;
4134                 Some((key, value))
4135             }
4136             n => panic!("Expected a ListItem but was {:?}", n),
4137         }));
4138         Node::Expr(self.alloc(aast::Expr(
4139             self.merge_positions(shape, right_paren),
4140             nast::Expr_::Shape(fields),
4141         )))
4142     }
4144     fn make_tuple_expression(
4145         &mut self,
4146         tuple: Self::R,
4147         _left_paren: Self::R,
4148         fields: Self::R,
4149         right_paren: Self::R,
4150     ) -> Self::R {
4151         let fields = self.slice(fields.iter().filter_map(|&field| self.node_to_expr(field)));
4152         Node::Expr(self.alloc(aast::Expr(
4153             self.merge_positions(tuple, right_paren),
4154             nast::Expr_::List(fields),
4155         )))
4156     }
4158     fn make_classname_type_specifier(
4159         &mut self,
4160         classname: Self::R,
4161         _lt: Self::R,
4162         targ: Self::R,
4163         _trailing_comma: Self::R,
4164         gt: Self::R,
4165     ) -> Self::R {
4166         let id = match classname.as_id() {
4167             Some(id) => id,
4168             None => return Node::Ignored(SK::ClassnameTypeSpecifier),
4169         };
4170         if gt.is_ignored() {
4171             self.prim_ty(aast::Tprim::Tstring, id.0)
4172         } else {
4173             self.make_apply(
4174                 Id(id.0, self.elaborate_raw_id(id.1)),
4175                 targ,
4176                 self.merge_positions(classname, gt),
4177             )
4178         }
4179     }
4181     fn make_scope_resolution_expression(
4182         &mut self,
4183         class_name: Self::R,
4184         _operator: Self::R,
4185         value: Self::R,
4186     ) -> Self::R {
4187         let pos = self.merge_positions(class_name, value);
4188         let Id(class_name_pos, class_name_str) = match self.expect_name(class_name) {
4189             Some(id) => self.elaborate_id(id),
4190             None => return Node::Ignored(SK::ScopeResolutionExpression),
4191         };
4192         let class_id = self.alloc(aast::ClassId(
4193             class_name_pos,
4194             match class_name {
4195                 Node::Name(("self", _)) => aast::ClassId_::CIself,
4196                 _ => aast::ClassId_::CI(self.alloc(Id(class_name_pos, class_name_str))),
4197             },
4198         ));
4199         let value_id = match self.expect_name(value) {
4200             Some(id) => id,
4201             None => return Node::Ignored(SK::ScopeResolutionExpression),
4202         };
4203         Node::Expr(self.alloc(aast::Expr(
4204             pos,
4205             nast::Expr_::ClassConst(self.alloc((class_id, self.alloc((value_id.0, value_id.1))))),
4206         )))
4207     }
4209     fn make_field_specifier(
4210         &mut self,
4211         question_token: Self::R,
4212         name: Self::R,
4213         _arrow: Self::R,
4214         type_: Self::R,
4215     ) -> Self::R {
4216         let optional = question_token.is_present();
4217         let ty = match self.node_to_ty(type_) {
4218             Some(ty) => ty,
4219             None => return Node::Ignored(SK::FieldSpecifier),
4220         };
4221         let name = match self.make_shape_field_name(name) {
4222             Some(name) => name,
4223             None => return Node::Ignored(SK::FieldSpecifier),
4224         };
4225         Node::ShapeFieldSpecifier(self.alloc(ShapeFieldNode {
4226             name: self.alloc(ShapeField(name)),
4227             type_: self.alloc(ShapeFieldType { optional, ty }),
4228         }))
4229     }
4231     fn make_field_initializer(&mut self, key: Self::R, _arrow: Self::R, value: Self::R) -> Self::R {
4232         Node::ListItem(self.alloc((key, value)))
4233     }
4235     fn make_varray_type_specifier(
4236         &mut self,
4237         varray_keyword: Self::R,
4238         _less_than: Self::R,
4239         tparam: Self::R,
4240         _trailing_comma: Self::R,
4241         greater_than: Self::R,
4242     ) -> Self::R {
4243         let tparam = match self.node_to_ty(tparam) {
4244             Some(ty) => ty,
4245             None => self.tany_with_pos(self.get_pos(varray_keyword)),
4246         };
4247         self.hint_ty(
4248             self.merge_positions(varray_keyword, greater_than),
4249             Ty_::Tvarray(tparam),
4250         )
4251     }
4253     fn make_darray_type_specifier(
4254         &mut self,
4255         darray: Self::R,
4256         _less_than: Self::R,
4257         key_type: Self::R,
4258         _comma: Self::R,
4259         value_type: Self::R,
4260         _trailing_comma: Self::R,
4261         greater_than: Self::R,
4262     ) -> Self::R {
4263         let pos = self.merge_positions(darray, greater_than);
4264         let key_type = self.node_to_ty(key_type).unwrap_or(TANY);
4265         let value_type = self.node_to_ty(value_type).unwrap_or(TANY);
4266         self.hint_ty(pos, Ty_::Tdarray(self.alloc((key_type, value_type))))
4267     }
4269     fn make_old_attribute_specification(
4270         &mut self,
4271         ltlt: Self::R,
4272         attrs: Self::R,
4273         gtgt: Self::R,
4274     ) -> Self::R {
4275         match attrs {
4276             Node::List(nodes) => {
4277                 Node::BracketedList(self.alloc((self.get_pos(ltlt), nodes, self.get_pos(gtgt))))
4278             }
4279             node => panic!(
4280                 "Expected List in old_attribute_specification, but got {:?}",
4281                 node
4282             ),
4283         }
4284     }
4286     fn make_constructor_call(
4287         &mut self,
4288         name: Self::R,
4289         _left_paren: Self::R,
4290         args: Self::R,
4291         _right_paren: Self::R,
4292     ) -> Self::R {
4293         let unqualified_name = match self.expect_name(name) {
4294             Some(name) => name,
4295             None => return Node::Ignored(SK::ConstructorCall),
4296         };
4297         let name = if unqualified_name.1.starts_with("__") {
4298             unqualified_name
4299         } else {
4300             match self.expect_name(name) {
4301                 Some(name) => self.elaborate_id(name),
4302                 None => return Node::Ignored(SK::ConstructorCall),
4303             }
4304         };
4305         let classname_params = self.slice(args.iter().filter_map(|node| match node {
4306             Node::Expr(aast::Expr(
4307                 full_pos,
4308                 aast::Expr_::ClassConst(&(
4309                     aast::ClassId(_, aast::ClassId_::CI(&Id(pos, class_name))),
4310                     (_, "class"),
4311                 )),
4312             )) => {
4313                 let name = self.elaborate_id(Id(pos, class_name));
4314                 Some(ClassNameParam { name, full_pos })
4315             }
4316             _ => None,
4317         }));
4319         let string_literal_params = if match name.1 {
4320             "__Deprecated" | "__Cipp" | "__CippLocal" | "__Policied" => true,
4321             _ => false,
4322         } {
4323             fn fold_string_concat<'a>(expr: &nast::Expr<'a>, acc: &mut Vec<'a, u8>) {
4324                 match expr {
4325                     &aast::Expr(_, aast::Expr_::String(val)) => acc.extend_from_slice(val),
4326                     &aast::Expr(_, aast::Expr_::Binop(&(Bop::Dot, e1, e2))) => {
4327                         fold_string_concat(&e1, acc);
4328                         fold_string_concat(&e2, acc);
4329                     }
4330                     _ => {}
4331                 }
4332             }
4334             self.slice(args.iter().filter_map(|expr| match expr {
4335                 Node::StringLiteral((x, _)) => Some(*x),
4336                 Node::Expr(e @ aast::Expr(_, aast::Expr_::Binop(_))) => {
4337                     let mut acc = Vec::new_in(self.arena);
4338                     fold_string_concat(e, &mut acc);
4339                     Some(acc.into_bump_slice().into())
4340                 }
4341                 _ => None,
4342             }))
4343         } else {
4344             &[]
4345         };
4347         Node::Attribute(self.alloc(UserAttributeNode {
4348             name,
4349             classname_params,
4350             string_literal_params,
4351         }))
4352     }
4354     fn make_trait_use(
4355         &mut self,
4356         _keyword: Self::R,
4357         names: Self::R,
4358         _semicolon: Self::R,
4359     ) -> Self::R {
4360         Node::TraitUse(self.alloc(names))
4361     }
4363     fn make_trait_use_conflict_resolution(
4364         &mut self,
4365         _keyword: Self::R,
4366         names: Self::R,
4367         _left_brace: Self::R,
4368         _clauses: Self::R,
4369         _right_brace: Self::R,
4370     ) -> Self::R {
4371         Node::TraitUse(self.alloc(names))
4372     }
4374     fn make_require_clause(
4375         &mut self,
4376         _keyword: Self::R,
4377         require_type: Self::R,
4378         name: Self::R,
4379         _semicolon: Self::R,
4380     ) -> Self::R {
4381         Node::RequireClause(self.alloc(RequireClause { require_type, name }))
4382     }
4384     fn make_nullable_type_specifier(&mut self, question_mark: Self::R, hint: Self::R) -> Self::R {
4385         let pos = self.merge_positions(question_mark, hint);
4386         let ty = match self.node_to_ty(hint) {
4387             Some(ty) => ty,
4388             None => return Node::Ignored(SK::NullableTypeSpecifier),
4389         };
4390         self.hint_ty(pos, Ty_::Toption(ty))
4391     }
4393     fn make_like_type_specifier(&mut self, tilde: Self::R, hint: Self::R) -> Self::R {
4394         let pos = self.merge_positions(tilde, hint);
4395         let ty = match self.node_to_ty(hint) {
4396             Some(ty) => ty,
4397             None => return Node::Ignored(SK::LikeTypeSpecifier),
4398         };
4399         self.hint_ty(pos, Ty_::Tlike(ty))
4400     }
4402     fn make_closure_type_specifier(
4403         &mut self,
4404         outer_left_paren: Self::R,
4405         _function_keyword: Self::R,
4406         _inner_left_paren: Self::R,
4407         parameter_list: Self::R,
4408         _inner_right_paren: Self::R,
4409         capability: Self::R,
4410         _colon: Self::R,
4411         return_type: Self::R,
4412         outer_right_paren: Self::R,
4413     ) -> Self::R {
4414         let make_param = |fp: &'a FunParamDecl<'a>| -> &'a FunParam<'a> {
4415             let mut flags = FunParamFlags::empty();
4416             let (hint, mutability) = Self::unwrap_mutability(fp.hint);
4417             flags |= Self::param_mutability_to_fun_param_flags(mutability);
4419             match fp.kind {
4420                 ParamMode::FPinout => {
4421                     flags |= FunParamFlags::INOUT;
4422                 }
4423                 ParamMode::FPnormal => {}
4424             };
4426             self.alloc(FunParam {
4427                 pos: self.get_pos(hint),
4428                 name: None,
4429                 type_: self.alloc(PossiblyEnforcedTy {
4430                     enforced: false,
4431                     type_: self.node_to_ty(hint).unwrap_or_else(|| tany()),
4432                 }),
4433                 flags,
4434                 rx_annotation: None,
4435             })
4436         };
4438         let arity = parameter_list
4439             .iter()
4440             .find_map(|&node| match node {
4441                 Node::FunParam(fp) if fp.variadic => Some(FunArity::Fvariadic(make_param(fp))),
4442                 _ => None,
4443             })
4444             .unwrap_or(FunArity::Fstandard);
4446         let params = self.slice(parameter_list.iter().filter_map(|&node| match node {
4447             Node::FunParam(fp) if !fp.variadic => Some(make_param(fp)),
4448             _ => None,
4449         }));
4451         let (hint, mutability) = Self::unwrap_mutability(return_type);
4452         let ret = match self.node_to_ty(hint) {
4453             Some(ty) => ty,
4454             None => return Node::Ignored(SK::ClosureTypeSpecifier),
4455         };
4456         let pos = self.merge_positions(outer_left_paren, outer_right_paren);
4457         let implicit_params = self.as_fun_implicit_params(capability, pos);
4459         let mut flags = FunTypeFlags::empty();
4460         if mutability.is_some() {
4461             flags |= FunTypeFlags::RETURNS_MUTABLE;
4462         }
4464         self.hint_ty(
4465             pos,
4466             Ty_::Tfun(self.alloc(FunType {
4467                 arity,
4468                 tparams: &[],
4469                 where_constraints: &[],
4470                 params,
4471                 implicit_params,
4472                 ret: self.alloc(PossiblyEnforcedTy {
4473                     enforced: false,
4474                     type_: ret,
4475                 }),
4476                 reactive: Reactivity::Nonreactive,
4477                 flags,
4478                 ifc_decl: default_ifc_fun_decl(),
4479             })),
4480         )
4481     }
4483     fn make_closure_parameter_type_specifier(&mut self, inout: Self::R, hint: Self::R) -> Self::R {
4484         let kind = if inout.is_token(TokenKind::Inout) {
4485             ParamMode::FPinout
4486         } else {
4487             ParamMode::FPnormal
4488         };
4489         Node::FunParam(self.alloc(FunParamDecl {
4490             attributes: Node::Ignored(SK::Missing),
4491             visibility: Node::Ignored(SK::Missing),
4492             kind,
4493             hint,
4494             pos: self.get_pos(hint),
4495             name: Some(""),
4496             variadic: false,
4497             initializer: Node::Ignored(SK::Missing),
4498         }))
4499     }
4501     fn make_type_const_declaration(
4502         &mut self,
4503         attributes: Self::R,
4504         modifiers: Self::R,
4505         _const_keyword: Self::R,
4506         _type_keyword: Self::R,
4507         name: Self::R,
4508         _type_parameters: Self::R,
4509         constraint: Self::R,
4510         _equal: Self::R,
4511         type_: Self::R,
4512         _semicolon: Self::R,
4513     ) -> Self::R {
4514         let attributes = self.to_attributes(attributes);
4515         let has_abstract_keyword = modifiers
4516             .iter()
4517             .any(|node| node.is_token(TokenKind::Abstract));
4518         let constraint = match constraint {
4519             Node::TypeConstraint(innards) => self.node_to_ty(innards.1),
4520             _ => None,
4521         };
4522         let type_ = self.node_to_ty(type_);
4523         let has_constraint = constraint.is_some();
4524         let has_type = type_.is_some();
4525         let (type_, abstract_) = match (has_abstract_keyword, has_constraint, has_type) {
4526             // Has no assigned type. Technically illegal, so if the constraint
4527             // is present, proceed as if the constraint was the assigned type.
4528             //     const type TFoo;
4529             //     const type TFoo as OtherType;
4530             (false, _, false) => (constraint, TypeconstAbstractKind::TCConcrete),
4531             // Has no constraint, but does have an assigned type.
4532             //     const type TFoo = SomeType;
4533             (false, false, true) => (type_, TypeconstAbstractKind::TCConcrete),
4534             // Has both a constraint and an assigned type.
4535             //     const type TFoo as OtherType = SomeType;
4536             (false, true, true) => (type_, TypeconstAbstractKind::TCPartiallyAbstract),
4537             // Has no default type.
4538             //     abstract const type TFoo;
4539             //     abstract const type TFoo as OtherType;
4540             (true, _, false) => (type_, TypeconstAbstractKind::TCAbstract(None)),
4541             // Has a default type.
4542             //     abstract const Type TFoo = SomeType;
4543             //     abstract const Type TFoo as OtherType = SomeType;
4544             (true, _, true) => (None, TypeconstAbstractKind::TCAbstract(type_)),
4545         };
4546         let name = match name.as_id() {
4547             Some(name) => name,
4548             None => return Node::Ignored(SK::TypeConstDeclaration),
4549         };
4550         Node::TypeConstant(self.alloc(ShallowTypeconst {
4551             abstract_,
4552             constraint,
4553             name,
4554             type_,
4555             enforceable: match attributes.enforceable {
4556                 Some(pos) => (pos, true),
4557                 None => (Pos::none(), false),
4558             },
4559             reifiable: attributes.reifiable,
4560         }))
4561     }
4563     fn make_decorated_expression(&mut self, decorator: Self::R, expr: Self::R) -> Self::R {
4564         Node::ListItem(self.alloc((decorator, expr)))
4565     }
4567     fn make_type_constant(
4568         &mut self,
4569         ty: Self::R,
4570         _coloncolon: Self::R,
4571         constant_name: Self::R,
4572     ) -> Self::R {
4573         let id = match self.expect_name(constant_name) {
4574             Some(id) => id,
4575             None => return Node::Ignored(SK::TypeConstant),
4576         };
4577         let pos = self.merge_positions(ty, constant_name);
4578         let ty = match (ty, self.classish_name_builder.get_current_classish_name()) {
4579             (Node::Name(("self", self_pos)), Some((name, class_name_pos))) => {
4580                 // In classes, we modify the position when rewriting the
4581                 // `self` keyword to point to the class name. In traits,
4582                 // we don't (because traits are not types). We indicate
4583                 // that the position shouldn't be rewritten with the
4584                 // none Pos.
4585                 let id_pos = if class_name_pos.is_none() {
4586                     self_pos
4587                 } else {
4588                     class_name_pos
4589                 };
4590                 let reason = self.alloc(Reason::hint(self_pos));
4591                 let ty_ = Ty_::Tapply(self.alloc((Id(id_pos, name), &[][..])));
4592                 self.alloc(Ty(reason, ty_))
4593             }
4594             _ => match self.node_to_ty(ty) {
4595                 Some(ty) => ty,
4596                 None => return Node::Ignored(SK::TypeConstant),
4597             },
4598         };
4599         let reason = self.alloc(Reason::hint(pos));
4600         // The reason-rewriting here is only necessary to match the
4601         // behavior of OCaml decl (which flattens and then unflattens
4602         // Haccess hints, losing some position information).
4603         let ty = self.rewrite_taccess_reasons(ty, reason);
4604         Node::Ty(self.alloc(Ty(reason, Ty_::Taccess(self.alloc(TaccessType(ty, id))))))
4605     }
4607     fn make_soft_type_specifier(&mut self, at_token: Self::R, hint: Self::R) -> Self::R {
4608         let pos = self.merge_positions(at_token, hint);
4609         let hint = match self.node_to_ty(hint) {
4610             Some(ty) => ty,
4611             None => return Node::Ignored(SK::SoftTypeSpecifier),
4612         };
4613         // Use the type of the hint as-is (i.e., throw away the knowledge that
4614         // we had a soft type specifier here--the typechecker does not use it).
4615         // Replace its Reason with one including the position of the `@` token.
4616         self.hint_ty(pos, hint.1)
4617     }
4619     // A type specifier preceded by an attribute list. At the time of writing,
4620     // only the <<__Soft>> attribute is permitted here.
4621     fn make_attributized_specifier(&mut self, attributes: Self::R, hint: Self::R) -> Self::R {
4622         match attributes {
4623             Node::BracketedList((
4624                 ltlt_pos,
4625                 [Node::Attribute(UserAttributeNode {
4626                     name: Id(_, "__Soft"),
4627                     ..
4628                 })],
4629                 gtgt_pos,
4630             )) => {
4631                 let attributes_pos = self.merge(*ltlt_pos, *gtgt_pos);
4632                 let hint_pos = self.get_pos(hint);
4633                 // Use the type of the hint as-is (i.e., throw away the
4634                 // knowledge that we had a soft type specifier here--the
4635                 // typechecker does not use it). Replace its Reason with one
4636                 // including the position of the attribute list.
4637                 let hint = match self.node_to_ty(hint) {
4638                     Some(ty) => ty,
4639                     None => return Node::Ignored(SK::AttributizedSpecifier),
4640                 };
4641                 self.hint_ty(self.merge(attributes_pos, hint_pos), hint.1)
4642             }
4643             _ => hint,
4644         }
4645     }
4647     fn make_vector_type_specifier(
4648         &mut self,
4649         vec: Self::R,
4650         _left_angle: Self::R,
4651         hint: Self::R,
4652         _trailing_comma: Self::R,
4653         right_angle: Self::R,
4654     ) -> Self::R {
4655         let id = match self.expect_name(vec) {
4656             Some(id) => id,
4657             None => return Node::Ignored(SK::VectorTypeSpecifier),
4658         };
4659         let id = Id(id.0, self.elaborate_raw_id(id.1));
4660         self.make_apply(id, hint, self.get_pos(right_angle))
4661     }
4663     fn make_dictionary_type_specifier(
4664         &mut self,
4665         dict: Self::R,
4666         _left_angle: Self::R,
4667         type_arguments: Self::R,
4668         right_angle: Self::R,
4669     ) -> Self::R {
4670         let id = match self.expect_name(dict) {
4671             Some(id) => id,
4672             None => return Node::Ignored(SK::DictionaryTypeSpecifier),
4673         };
4674         let id = Id(id.0, self.elaborate_raw_id(id.1));
4675         self.make_apply(id, type_arguments, self.get_pos(right_angle))
4676     }
4678     fn make_keyset_type_specifier(
4679         &mut self,
4680         keyset: Self::R,
4681         _left_angle: Self::R,
4682         hint: Self::R,
4683         _trailing_comma: Self::R,
4684         right_angle: Self::R,
4685     ) -> Self::R {
4686         let id = match self.expect_name(keyset) {
4687             Some(id) => id,
4688             None => return Node::Ignored(SK::KeysetTypeSpecifier),
4689         };
4690         let id = Id(id.0, self.elaborate_raw_id(id.1));
4691         self.make_apply(id, hint, self.get_pos(right_angle))
4692     }
4694     fn make_variable_expression(&mut self, _expression: Self::R) -> Self::R {
4695         Node::Ignored(SK::VariableExpression)
4696     }
4698     fn make_subscript_expression(
4699         &mut self,
4700         _receiver: Self::R,
4701         _left_bracket: Self::R,
4702         _index: Self::R,
4703         _right_bracket: Self::R,
4704     ) -> Self::R {
4705         Node::Ignored(SK::SubscriptExpression)
4706     }
4708     fn make_member_selection_expression(
4709         &mut self,
4710         _object: Self::R,
4711         _operator: Self::R,
4712         _name: Self::R,
4713     ) -> Self::R {
4714         Node::Ignored(SK::MemberSelectionExpression)
4715     }
4717     fn make_object_creation_expression(
4718         &mut self,
4719         _new_keyword: Self::R,
4720         _object: Self::R,
4721     ) -> Self::R {
4722         Node::Ignored(SK::ObjectCreationExpression)
4723     }
4725     fn make_safe_member_selection_expression(
4726         &mut self,
4727         _object: Self::R,
4728         _operator: Self::R,
4729         _name: Self::R,
4730     ) -> Self::R {
4731         Node::Ignored(SK::SafeMemberSelectionExpression)
4732     }
4734     fn make_function_call_expression(
4735         &mut self,
4736         _receiver: Self::R,
4737         _type_args: Self::R,
4738         _left_paren: Self::R,
4739         _argument_list: Self::R,
4740         _right_paren: Self::R,
4741     ) -> Self::R {
4742         Node::Ignored(SK::FunctionCallExpression)
4743     }
4745     fn make_list_expression(
4746         &mut self,
4747         _keyword: Self::R,
4748         _left_paren: Self::R,
4749         _members: Self::R,
4750         _right_paren: Self::R,
4751     ) -> Self::R {
4752         Node::Ignored(SK::ListExpression)
4753     }