1use super::*;
2use crate::allocator::AstArena;
3use std::fmt;
4use std::marker::PhantomData;
5use std::ptr::NonNull;
6
7#[repr(u8)]
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum TypeTag {
10 Reference,
11 Table,
12 Function,
13 Typeof,
14 SingletonBool,
15 SingletonString,
16 Group,
17 Optional,
18 Union,
19 Intersection,
20 Error,
21}
22
23#[repr(C)]
24#[derive(Debug, PartialEq)]
25pub struct TypeHeader<'ast> {
26 pub tag: TypeTag,
27 pub location: Location,
28 _marker: PhantomData<&'ast ()>,
29}
30
31#[derive(Clone, Copy)]
32pub struct Type<'ast> {
33 ptr: NonNull<TypeHeader<'ast>>,
34 _marker: PhantomData<&'ast TypeHeader<'ast>>,
35}
36
37impl<'ast> std::ops::Deref for Type<'ast> {
38 type Target = TypeHeader<'ast>;
39
40 fn deref(&self) -> &Self::Target {
41 self.header()
42 }
43}
44
45impl fmt::Debug for Type<'_> {
46 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
47 formatter
48 .debug_struct("Type")
49 .field("location", &self.location())
50 .field("kind", &self.kind())
51 .finish()
52 }
53}
54
55impl PartialEq for Type<'_> {
56 fn eq(&self, other: &Self) -> bool {
57 self.location() == other.location() && self.kind() == other.kind()
58 }
59}
60
61#[derive(Debug, Clone, Copy, PartialEq)]
62pub enum TypeKind<'ast> {
63 Reference {
64 prefix: Option<AstName<'ast>>,
65 prefix_location: Option<Location>,
66 prefix_local: Option<&'ast Local<'ast>>,
67 name: AstName<'ast>,
68 location: Location,
69 name_location: Location,
70 has_parameter_list: bool,
71 parameters: &'ast [TypeOrPack<'ast>],
72 },
73 Table {
74 props: &'ast [TableTypeProp<'ast>],
75 indexer: Option<&'ast TableTypeIndexer<'ast>>,
76 },
77 Function {
78 attributes: &'ast [&'ast Attribute<'ast>],
79 generics: &'ast [&'ast GenericType<'ast>],
80 generic_packs: &'ast [&'ast GenericTypePack<'ast>],
81 arg_types: TypeList<'ast>,
82 arg_names: &'ast [Option<ArgumentName<'ast>>],
83 return_types: TypePack<'ast>,
84 },
85 Typeof {
86 expr: Expression<'ast>,
87 },
88 SingletonBool {
89 value: bool,
90 },
91 SingletonString {
92 value: AstString<'ast>,
93 },
94 Group {
95 ty: Type<'ast>,
96 },
97 Optional,
98 Union {
99 types: &'ast [Type<'ast>],
100 },
101 Intersection {
102 types: &'ast [Type<'ast>],
103 },
104 Error {
105 types: &'ast [Type<'ast>],
106 missing: bool,
107 message_index: usize,
108 },
109}
110
111#[derive(Debug, Clone, Copy, PartialEq)]
112pub enum TypeOrPack<'ast> {
113 Type(Type<'ast>),
114 Pack(TypePack<'ast>),
115}
116
117macro_rules! type_node {
118 ($name:ident { $($field:ident : $ty:ty),* $(,)? }, $tag:ident) => {
119 #[repr(C)]
120 #[derive(Debug, PartialEq)]
121 pub struct $name<'ast> {
122 pub base: TypeHeader<'ast>,
123 $(pub $field: $ty),*
124 }
125 };
126}
127
128#[repr(C)]
129#[derive(Debug, PartialEq)]
130pub struct TypeUnit<'ast> {
131 pub base: TypeHeader<'ast>,
132}
133
134type_node!(
135 TypeReference {
136 has_parameter_list: bool,
137 prefix: Option<AstName<'ast>>,
138 prefix_location: Option<Location>,
139 prefix_local: Option<&'ast Local<'ast>>,
140 name: AstName<'ast>,
141 name_location: Location,
142 parameters: &'ast [TypeOrPack<'ast>]
143 },
144 Reference
145);
146type_node!(
147 TypeTable {
148 props: &'ast [TableTypeProp<'ast>],
149 indexer: Option<&'ast TableTypeIndexer<'ast>>
150 },
151 Table
152);
153type_node!(
154 TypeFunction {
155 attributes: &'ast [&'ast Attribute<'ast>],
156 generics: &'ast [&'ast GenericType<'ast>],
157 generic_packs: &'ast [&'ast GenericTypePack<'ast>],
158 arg_types: TypeList<'ast>,
159 arg_names: &'ast [Option<ArgumentName<'ast>>],
160 return_types: TypePack<'ast>
161 },
162 Function
163);
164type_node!(TypeTypeof { expr: Expression<'ast> }, Typeof);
165type_node!(TypeSingletonBool { value: bool }, SingletonBool);
166type_node!(TypeSingletonString { value: AstString<'ast> }, SingletonString);
167type_node!(TypeGroup { ty: Type<'ast> }, Group);
168type_node!(TypeUnion { types: &'ast [Type<'ast>] }, Union);
169type_node!(TypeIntersection { types: &'ast [Type<'ast>] }, Intersection);
170type_node!(
171 TypeError {
172 types: &'ast [Type<'ast>],
173 missing: bool,
174 message_index: usize
175 },
176 Error
177);
178
179impl<'ast> Type<'ast> {
180 const fn new_header(tag: TypeTag, location: Location) -> TypeHeader<'ast> {
181 TypeHeader {
182 tag,
183 location,
184 _marker: PhantomData,
185 }
186 }
187
188 pub(crate) fn from_node<T>(node: &'ast mut T) -> Self {
189 Self {
190 ptr: NonNull::from(node).cast(),
191 _marker: PhantomData,
192 }
193 }
194
195 pub fn as_ptr(self) -> *const () {
196 self.ptr.as_ptr().cast()
197 }
198
199 #[inline(always)]
200 fn header(&self) -> &TypeHeader<'ast> {
201 unsafe { self.ptr.as_ref() }
202 }
203
204 #[inline(always)]
205 pub fn location(self) -> Location {
206 self.header().location
207 }
208
209 #[inline(always)]
210 pub fn kind(&self) -> TypeKind<'ast> {
211 match self.tag {
212 TypeTag::Reference => {
213 let node = self.cast_ref::<TypeReference>();
214 TypeKind::Reference {
215 prefix: node.prefix,
216 prefix_location: node.prefix_location,
217 prefix_local: node.prefix_local,
218 name: node.name,
219 location: self.location,
220 name_location: node.name_location,
221 has_parameter_list: node.has_parameter_list,
222 parameters: node.parameters,
223 }
224 }
225 TypeTag::Table => {
226 let node = self.cast_ref::<TypeTable>();
227 TypeKind::Table {
228 props: node.props,
229 indexer: node.indexer,
230 }
231 }
232 TypeTag::Function => {
233 let node = self.cast_ref::<TypeFunction>();
234 TypeKind::Function {
235 attributes: node.attributes,
236 generics: node.generics,
237 generic_packs: node.generic_packs,
238 arg_types: node.arg_types,
239 arg_names: node.arg_names,
240 return_types: node.return_types,
241 }
242 }
243 TypeTag::Typeof => TypeKind::Typeof {
244 expr: self.cast_ref::<TypeTypeof>().expr,
245 },
246 TypeTag::SingletonBool => TypeKind::SingletonBool {
247 value: self.cast_ref::<TypeSingletonBool>().value,
248 },
249 TypeTag::SingletonString => TypeKind::SingletonString {
250 value: self.cast_ref::<TypeSingletonString>().value,
251 },
252 TypeTag::Group => TypeKind::Group {
253 ty: self.cast_ref::<TypeGroup>().ty,
254 },
255 TypeTag::Optional => TypeKind::Optional,
256 TypeTag::Union => TypeKind::Union {
257 types: self.cast_ref::<TypeUnion>().types,
258 },
259 TypeTag::Intersection => TypeKind::Intersection {
260 types: self.cast_ref::<TypeIntersection>().types,
261 },
262 TypeTag::Error => {
263 let node = self.cast_ref::<TypeError>();
264 TypeKind::Error {
265 types: node.types,
266 missing: node.missing,
267 message_index: node.message_index,
268 }
269 }
270 }
271 }
272
273 pub fn visit<V: AstVisitor>(self, visitor: &mut V) {
274 let should_visit = match self.tag {
275 TypeTag::Reference => visitor.visit_reference_type(self),
276 TypeTag::Table => visitor.visit_table_type(self),
277 TypeTag::Function => visitor.visit_function_type(self),
278 TypeTag::Typeof => visitor.visit_typeof_type(self),
279 TypeTag::SingletonBool => visitor.visit_singleton_bool_type(self),
280 TypeTag::SingletonString => visitor.visit_singleton_string_type(self),
281 TypeTag::Group => visitor.visit_group_type(self),
282 TypeTag::Optional => visitor.visit_optional_type(self),
283 TypeTag::Union => visitor.visit_union_type(self),
284 TypeTag::Intersection => visitor.visit_intersection_type(self),
285 TypeTag::Error => visitor.visit_error_type(self),
286 };
287
288 if !should_visit {
289 return;
290 }
291
292 match self.kind() {
293 TypeKind::Reference { parameters, .. } => {
294 for parameter in parameters {
295 match parameter {
296 TypeOrPack::Type(annotation) => annotation.visit(visitor),
297 TypeOrPack::Pack(pack) => pack.visit(visitor),
298 }
299 }
300 }
301 TypeKind::Union { types, .. } | TypeKind::Intersection { types, .. } => {
302 for annotation in types {
303 annotation.visit(visitor);
304 }
305 }
306 TypeKind::Table { props, indexer, .. } => {
307 for prop in props {
308 prop.ty.visit(visitor);
309 }
310 if let Some(indexer) = indexer {
311 indexer.index_type.visit(visitor);
312 indexer.result_type.visit(visitor);
313 }
314 }
315 TypeKind::Function {
316 arg_types,
317 return_types,
318 ..
319 } => {
320 arg_types.visit(visitor);
321 return_types.visit(visitor);
322 }
323 TypeKind::Typeof { expr, .. } => expr.visit(visitor),
324 TypeKind::Group { ty, .. } => ty.visit(visitor),
325 TypeKind::Error { types, .. } => {
326 for annotation in types {
327 annotation.visit(visitor);
328 }
329 }
330 TypeKind::Optional
331 | TypeKind::SingletonBool { .. }
332 | TypeKind::SingletonString { .. } => {}
333 }
334 }
335
336 #[inline(always)]
337 fn cast_ref<T>(self) -> &'ast T {
338 unsafe { self.ptr.cast::<T>().as_ref() }
339 }
340
341 #[inline(always)]
342 fn cast_if_tag<T>(self, tag: TypeTag) -> Option<&'ast T> {
343 (self.tag == tag).then(|| self.cast_ref())
344 }
345
346 #[inline(always)]
347 pub fn as_reference(self) -> Option<&'ast TypeReference<'ast>> {
348 self.cast_if_tag(TypeTag::Reference)
349 }
350
351 #[inline(always)]
352 pub fn as_table(self) -> Option<&'ast TypeTable<'ast>> {
353 self.cast_if_tag(TypeTag::Table)
354 }
355
356 #[inline(always)]
357 pub fn as_function(self) -> Option<&'ast TypeFunction<'ast>> {
358 self.cast_if_tag(TypeTag::Function)
359 }
360
361 #[inline(always)]
362 pub fn as_typeof(self) -> Option<&'ast TypeTypeof<'ast>> {
363 self.cast_if_tag(TypeTag::Typeof)
364 }
365
366 #[inline(always)]
367 pub fn as_singleton_bool(self) -> Option<&'ast TypeSingletonBool<'ast>> {
368 self.cast_if_tag(TypeTag::SingletonBool)
369 }
370
371 #[inline(always)]
372 pub fn as_singleton_string(self) -> Option<&'ast TypeSingletonString<'ast>> {
373 self.cast_if_tag(TypeTag::SingletonString)
374 }
375
376 #[inline(always)]
377 pub fn as_group(self) -> Option<&'ast TypeGroup<'ast>> {
378 self.cast_if_tag(TypeTag::Group)
379 }
380
381 #[inline(always)]
382 pub fn as_union(self) -> Option<&'ast TypeUnion<'ast>> {
383 self.cast_if_tag(TypeTag::Union)
384 }
385
386 #[inline(always)]
387 pub fn as_intersection(self) -> Option<&'ast TypeIntersection<'ast>> {
388 self.cast_if_tag(TypeTag::Intersection)
389 }
390
391 #[inline(always)]
392 pub fn as_error(self) -> Option<&'ast TypeError<'ast>> {
393 self.cast_if_tag(TypeTag::Error)
394 }
395}
396
397impl<'ast> TypeKind<'ast> {
398 pub fn is_checked_function(&self) -> bool {
399 self.has_function_attribute(AttributeKind::Checked)
400 }
401
402 pub fn has_function_attribute(&self, kind: AttributeKind) -> bool {
403 self.get_function_attribute(kind).is_some()
404 }
405
406 pub fn get_function_attribute(&self, kind: AttributeKind) -> Option<&'ast Attribute<'ast>> {
407 match self {
408 Self::Function { attributes, .. } => find_attribute(attributes, kind),
409 _ => None,
410 }
411 }
412}
413
414#[repr(u8)]
415#[derive(Debug, Clone, Copy, PartialEq, Eq)]
416pub enum TypePackTag {
417 Explicit,
418 Variadic,
419 Generic,
420}
421
422#[repr(C)]
423#[derive(Debug, PartialEq)]
424pub struct TypePackHeader<'ast> {
425 pub tag: TypePackTag,
426 pub location: Location,
427 _marker: PhantomData<&'ast ()>,
428}
429
430#[derive(Clone, Copy)]
431pub struct TypePack<'ast> {
432 ptr: NonNull<TypePackHeader<'ast>>,
433 _marker: PhantomData<&'ast TypePackHeader<'ast>>,
434}
435
436impl<'ast> std::ops::Deref for TypePack<'ast> {
437 type Target = TypePackHeader<'ast>;
438
439 fn deref(&self) -> &Self::Target {
440 self.header()
441 }
442}
443
444impl fmt::Debug for TypePack<'_> {
445 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
446 formatter
447 .debug_struct("TypePack")
448 .field("location", &self.location())
449 .field("kind", &self.kind())
450 .finish()
451 }
452}
453
454impl PartialEq for TypePack<'_> {
455 fn eq(&self, other: &Self) -> bool {
456 self.location() == other.location() && self.kind() == other.kind()
457 }
458}
459
460#[derive(Debug, Clone, Copy, PartialEq)]
461pub struct TypeList<'ast> {
462 pub types: &'ast [Type<'ast>],
463 pub tail_type: Option<TypePack<'ast>>,
464}
465
466#[derive(Debug, Clone, Copy, PartialEq)]
467pub enum TypePackKind<'ast> {
468 Explicit { type_list: TypeList<'ast> },
469 Variadic { variadic_type: Type<'ast> },
470 Generic { generic_name: AstName<'ast> },
471}
472
473macro_rules! type_pack_node {
474 ($name:ident { $($field:ident : $ty:ty),* $(,)? }, $tag:ident) => {
475 #[repr(C)]
476 #[derive(Debug, PartialEq)]
477 pub struct $name<'ast> {
478 pub base: TypePackHeader<'ast>,
479 $(pub $field: $ty),*
480 }
481 };
482}
483
484type_pack_node!(TypePackExplicitNode { type_list: TypeList<'ast> }, Explicit);
485type_pack_node!(TypePackVariadicNode { variadic_type: Type<'ast> }, Variadic);
486type_pack_node!(TypePackGenericNode { generic_name: AstName<'ast> }, Generic);
487
488impl TypeList<'_> {
489 pub fn visit<V: AstVisitor>(&self, visitor: &mut V) {
490 for annotation in self.types {
491 annotation.visit(visitor);
492 }
493 if let Some(tail_type) = self.tail_type {
494 tail_type.visit(visitor);
495 }
496 }
497}
498
499impl<'ast> TypePack<'ast> {
500 const fn new_header(tag: TypePackTag, location: Location) -> TypePackHeader<'ast> {
501 TypePackHeader {
502 tag,
503 location,
504 _marker: PhantomData,
505 }
506 }
507
508 pub(crate) fn from_node<T>(node: &'ast mut T) -> Self {
509 Self {
510 ptr: NonNull::from(node).cast(),
511 _marker: PhantomData,
512 }
513 }
514
515 pub fn as_ptr(self) -> *const () {
516 self.ptr.as_ptr().cast()
517 }
518
519 #[inline(always)]
520 fn header(&self) -> &TypePackHeader<'ast> {
521 unsafe { self.ptr.as_ref() }
522 }
523
524 #[inline(always)]
525 pub fn location(self) -> Location {
526 self.header().location
527 }
528
529 #[inline(always)]
530 pub fn kind(&self) -> TypePackKind<'ast> {
531 match self.tag {
532 TypePackTag::Explicit => TypePackKind::Explicit {
533 type_list: self.cast_ref::<TypePackExplicitNode>().type_list,
534 },
535 TypePackTag::Variadic => TypePackKind::Variadic {
536 variadic_type: self.cast_ref::<TypePackVariadicNode>().variadic_type,
537 },
538 TypePackTag::Generic => TypePackKind::Generic {
539 generic_name: self.cast_ref::<TypePackGenericNode>().generic_name,
540 },
541 }
542 }
543
544 pub fn explicit_type_list(&self) -> Option<TypeList<'ast>> {
545 match self.kind() {
546 TypePackKind::Explicit { type_list } => Some(type_list),
547 _ => None,
548 }
549 }
550
551 pub fn visit<V: AstVisitor>(self, visitor: &mut V) {
552 let should_visit = match self.tag {
553 TypePackTag::Explicit => visitor.visit_explicit_type_pack(self),
554 TypePackTag::Variadic => visitor.visit_variadic_type_pack(self),
555 TypePackTag::Generic => visitor.visit_generic_type_pack_type(self),
556 };
557
558 if !should_visit {
559 return;
560 }
561
562 match self.kind() {
563 TypePackKind::Explicit { type_list } => type_list.visit(visitor),
564 TypePackKind::Variadic { variadic_type } => variadic_type.visit(visitor),
565 TypePackKind::Generic { .. } => {}
566 }
567 }
568
569 #[inline(always)]
570 fn cast_ref<T>(self) -> &'ast T {
571 unsafe { self.ptr.cast::<T>().as_ref() }
572 }
573
574 #[inline(always)]
575 fn cast_if_tag<T>(self, tag: TypePackTag) -> Option<&'ast T> {
576 (self.tag == tag).then(|| self.cast_ref())
577 }
578
579 #[inline(always)]
580 pub fn as_explicit(self) -> Option<&'ast TypePackExplicitNode<'ast>> {
581 self.cast_if_tag(TypePackTag::Explicit)
582 }
583
584 #[inline(always)]
585 pub fn as_variadic(self) -> Option<&'ast TypePackVariadicNode<'ast>> {
586 self.cast_if_tag(TypePackTag::Variadic)
587 }
588
589 #[inline(always)]
590 pub fn as_generic(self) -> Option<&'ast TypePackGenericNode<'ast>> {
591 self.cast_if_tag(TypePackTag::Generic)
592 }
593}
594
595#[derive(Debug, Clone, Copy, PartialEq)]
596pub struct Attribute<'ast> {
597 pub location: Location,
598 pub kind: AttributeKind,
599 pub args: &'ast [Expression<'ast>],
600 pub name: AstName<'ast>,
601}
602
603#[derive(Debug, Clone, Copy, PartialEq, Eq)]
604pub enum AttributeKind {
605 Checked,
606 Native,
607 Deprecated,
608 DebugNoinline,
609 Unknown,
610}
611
612#[derive(Debug, Clone, PartialEq, Eq)]
613pub struct DeprecatedInfo {
614 pub deprecated: bool,
615 pub use_replacement: Option<Vec<u8>>,
616 pub reason: Option<Vec<u8>>,
617}
618
619impl Attribute<'_> {
620 pub fn kind(&self) -> AttributeKind {
621 self.kind
622 }
623
624 pub fn visit<V: AstVisitor>(&self, visitor: &mut V) {
625 let _ = visitor.visit_attribute(self);
626 }
627
628 pub fn deprecated_info(&self) -> DeprecatedInfo {
629 let mut info = DeprecatedInfo {
630 deprecated: self.kind == AttributeKind::Deprecated,
631 use_replacement: None,
632 reason: None,
633 };
634
635 if !info.deprecated {
636 return info;
637 }
638
639 let Some(argument) = self.args.first() else {
640 return info;
641 };
642 let ExpressionKind::Table { items } = argument.kind() else {
643 return info;
644 };
645
646 for item in items {
647 let TableItem::Record { key, value } = item else {
648 continue;
649 };
650 let ExpressionKind::String {
651 value: key_value, ..
652 } = key.kind()
653 else {
654 continue;
655 };
656 let ExpressionKind::String { value, .. } = value.kind() else {
657 continue;
658 };
659
660 match key_value.as_bytes() {
661 b"use" => info.use_replacement = Some(value.as_bytes().to_vec()),
662 b"reason" => info.reason = Some(value.as_bytes().to_vec()),
663 _ => {}
664 }
665 }
666
667 info
668 }
669}
670
671#[derive(Debug, Clone, Copy, PartialEq)]
672pub struct TableTypeProp<'ast> {
673 pub name: AstName<'ast>,
674 pub location: Location,
675 pub ty: Type<'ast>,
676 pub access: TableAccess,
677 pub access_location: Option<Location>,
678}
679
680#[derive(Debug, Clone, Copy, PartialEq)]
681pub struct TableTypeIndexer<'ast> {
682 pub index_type: Type<'ast>,
683 pub result_type: Type<'ast>,
684 pub location: Location,
685 pub access: TableAccess,
686 pub access_location: Option<Location>,
687}
688
689#[derive(Debug, Clone, Copy, PartialEq)]
690pub struct DeclaredExternTypeProperty<'ast> {
691 pub name: AstName<'ast>,
692 pub name_location: Location,
693 pub ty: Type<'ast>,
694 pub is_method: bool,
695 pub location: Location,
696 pub access: TableAccess,
697}
698
699#[derive(Debug, Clone, Copy, PartialEq, Eq)]
700pub enum TableAccess {
701 Read,
702 Write,
703 ReadWrite,
704}
705
706impl AstArena {
707 fn alloc_type_node<'ast, T: 'ast>(&'ast self, node: T) -> Type<'ast> {
708 Type::from_node(self.alloc(node))
709 }
710
711 fn alloc_type_pack_node<'ast, T: 'ast>(&'ast self, node: T) -> TypePack<'ast> {
712 TypePack::from_node(self.alloc(node))
713 }
714
715 pub fn alloc_type_kind<'ast>(
716 &'ast self,
717 location: Location,
718 kind: TypeKind<'ast>,
719 ) -> Type<'ast> {
720 match kind {
721 TypeKind::Reference {
722 prefix,
723 prefix_location,
724 prefix_local,
725 name,
726 name_location,
727 has_parameter_list,
728 parameters,
729 ..
730 } => self.alloc_type_node(TypeReference {
731 base: Type::new_header(TypeTag::Reference, location),
732 has_parameter_list,
733 prefix,
734 prefix_location,
735 prefix_local,
736 name,
737 name_location,
738 parameters,
739 }),
740 TypeKind::Table { props, indexer } => self.alloc_type_node(TypeTable {
741 base: Type::new_header(TypeTag::Table, location),
742 props,
743 indexer,
744 }),
745 TypeKind::Function {
746 attributes,
747 generics,
748 generic_packs,
749 arg_types,
750 arg_names,
751 return_types,
752 } => self.alloc_type_node(TypeFunction {
753 base: Type::new_header(TypeTag::Function, location),
754 attributes,
755 generics,
756 generic_packs,
757 arg_types,
758 arg_names,
759 return_types,
760 }),
761 TypeKind::Typeof { expr } => self.alloc_type_node(TypeTypeof {
762 base: Type::new_header(TypeTag::Typeof, location),
763 expr,
764 }),
765 TypeKind::SingletonBool { value } => self.alloc_type_node(TypeSingletonBool {
766 base: Type::new_header(TypeTag::SingletonBool, location),
767 value,
768 }),
769 TypeKind::SingletonString { value } => self.alloc_type_node(TypeSingletonString {
770 base: Type::new_header(TypeTag::SingletonString, location),
771 value,
772 }),
773 TypeKind::Group { ty } => self.alloc_type_node(TypeGroup {
774 base: Type::new_header(TypeTag::Group, location),
775 ty,
776 }),
777 TypeKind::Optional => self.alloc_type_node(TypeUnit {
778 base: Type::new_header(TypeTag::Optional, location),
779 }),
780 TypeKind::Union { types } => self.alloc_type_node(TypeUnion {
781 base: Type::new_header(TypeTag::Union, location),
782 types,
783 }),
784 TypeKind::Intersection { types } => self.alloc_type_node(TypeIntersection {
785 base: Type::new_header(TypeTag::Intersection, location),
786 types,
787 }),
788 TypeKind::Error {
789 types,
790 missing,
791 message_index,
792 } => self.alloc_type_node(TypeError {
793 base: Type::new_header(TypeTag::Error, location),
794 types,
795 missing,
796 message_index,
797 }),
798 }
799 }
800
801 pub fn alloc_type_pack_kind<'ast>(
802 &'ast self,
803 location: Location,
804 kind: TypePackKind<'ast>,
805 ) -> TypePack<'ast> {
806 match kind {
807 TypePackKind::Explicit { type_list } => {
808 self.alloc_type_pack_node(TypePackExplicitNode {
809 base: TypePack::new_header(TypePackTag::Explicit, location),
810 type_list,
811 })
812 }
813 TypePackKind::Variadic { variadic_type } => {
814 self.alloc_type_pack_node(TypePackVariadicNode {
815 base: TypePack::new_header(TypePackTag::Variadic, location),
816 variadic_type,
817 })
818 }
819 TypePackKind::Generic { generic_name } => {
820 self.alloc_type_pack_node(TypePackGenericNode {
821 base: TypePack::new_header(TypePackTag::Generic, location),
822 generic_name,
823 })
824 }
825 }
826 }
827}