1use crate::types::{
14 CallSignature, CallableShape, FunctionShape, LiteralValue, ObjectShape, ObjectShapeId,
15 ParamInfo, PropertyInfo, TupleElement, TypeData, TypeId,
16};
17use crate::utils;
18use crate::visitor;
19use rustc_hash::FxHashSet;
20use tsz_common::interner::Atom;
21
22use super::InferenceContext;
23
24struct TupleRestExpansion {
25 fixed: Vec<TupleElement>,
27 variadic: Option<TypeId>,
29 tail: Vec<TupleElement>,
31}
32
33impl<'a> InferenceContext<'a> {
34 pub fn best_common_type(&self, types: &[TypeId]) -> TypeId {
47 if types.is_empty() {
48 return TypeId::UNKNOWN;
49 }
50 if types.len() == 1 {
51 return types[0];
52 }
53
54 let first = types[0];
57 if types.iter().all(|&t| t == first) {
58 return first;
59 }
60
61 let mut seen = FxHashSet::default();
63 let mut unique: Vec<TypeId> = Vec::new();
64 let mut has_any = false;
65 for &ty in types {
66 if ty == TypeId::ANY {
67 has_any = true;
68 }
69 if ty == TypeId::NEVER {
70 continue; }
72 if seen.insert(ty) {
73 unique.push(ty);
74 }
75 }
76
77 if has_any {
79 return TypeId::ANY;
80 }
81
82 if unique.is_empty() {
83 return TypeId::NEVER;
84 }
85 if unique.len() == 1 {
86 return unique[0];
87 }
88
89 let common_base = self.find_common_base_type(&unique);
92 if let Some(base) = common_base {
93 if unique.len() > 1 {
97 return base;
98 }
99 }
100
101 let mut best = unique[0];
105 for &candidate in &unique[1..] {
106 if self.is_subtype(best, candidate) {
107 best = candidate;
108 }
109 }
110 if self.is_suitable_common_type(best, &unique) {
111 return best;
112 }
113
114 if let Some(common_class) = self.find_common_base_class(&unique) {
117 return common_class;
118 }
119
120 self.interner.union(unique)
122 }
123
124 fn find_common_base_type(&self, types: &[TypeId]) -> Option<TypeId> {
127 if types.is_empty() {
128 return None;
129 }
130
131 let first_base = self.get_base_type(types[0])?;
133
134 for &ty in types.iter().skip(1) {
136 let base = self.get_base_type(ty)?;
137 if base != first_base {
138 return None;
139 }
140 }
141
142 Some(first_base)
143 }
144
145 pub(crate) fn get_base_type(&self, ty: TypeId) -> Option<TypeId> {
151 match self.interner.lookup(ty) {
152 Some(TypeData::Literal(_)) => {
154 match ty {
155 TypeId::STRING | TypeId::NUMBER | TypeId::BOOLEAN | TypeId::BIGINT => Some(ty),
156 _ => {
157 if let Some(TypeData::Literal(lit)) = self.interner.lookup(ty) {
159 match lit {
160 LiteralValue::String(_) => Some(TypeId::STRING),
161 LiteralValue::Number(_) => Some(TypeId::NUMBER),
162 LiteralValue::Boolean(_) => Some(TypeId::BOOLEAN),
163 LiteralValue::BigInt(_) => Some(TypeId::BIGINT),
164 }
165 } else {
166 Some(ty)
167 }
168 }
169 }
170 }
171 Some(TypeData::Lazy(_)) => {
173 if let Some(resolver) = self.resolver {
175 resolver.get_base_type(ty, self.interner)
176 } else {
177 Some(ty)
179 }
180 }
181 _ => Some(ty),
182 }
183 }
184
185 fn find_common_base_class(&self, types: &[TypeId]) -> Option<TypeId> {
191 if types.len() < 2 {
192 return None;
193 }
194
195 let mut base_candidates = self.get_class_hierarchy(types[0])?;
198
199 for &ty in types.iter().skip(1) {
203 if base_candidates.is_empty() {
205 return None;
206 }
207
208 base_candidates.retain(|&base| self.is_subtype(ty, base));
211 }
212
213 base_candidates.first().copied()
215 }
216
217 fn get_class_hierarchy(&self, ty: TypeId) -> Option<Vec<TypeId>> {
220 let mut hierarchy = Vec::new();
221 self.collect_class_hierarchy(ty, &mut hierarchy);
222 if hierarchy.is_empty() {
223 None
224 } else {
225 Some(hierarchy)
226 }
227 }
228
229 fn collect_class_hierarchy(&self, ty: TypeId, hierarchy: &mut Vec<TypeId>) {
231 if hierarchy.contains(&ty) {
233 return;
234 }
235
236 hierarchy.push(ty);
238
239 let Some(type_key) = self.interner.lookup(ty) else {
241 return;
242 };
243
244 match type_key {
245 TypeData::Intersection(members_id) => {
249 let members = self.interner.type_list(members_id);
250 for &member in members.iter() {
251 self.collect_class_hierarchy(member, hierarchy);
252 }
253 }
254 TypeData::Lazy(_) => {
257 if let Some(base_type) = self.get_extends_clause(ty) {
258 self.collect_class_hierarchy(base_type, hierarchy);
259 }
260 }
261 TypeData::Callable(shape_id) => {
263 let _shape = self.interner.callable_shape(shape_id);
264
265 if let Some(base_type) = self.get_extends_clause(ty) {
268 self.collect_class_hierarchy(base_type, hierarchy);
269 }
270 }
271 TypeData::Object(shape_id) => {
272 let _shape = self.interner.object_shape(shape_id);
273
274 if let Some(base_type) = self.get_extends_clause(ty) {
276 self.collect_class_hierarchy(base_type, hierarchy);
277 }
278 }
279 _ => {
280 }
282 }
283 }
284
285 fn get_extends_clause(&self, ty: TypeId) -> Option<TypeId> {
290 if let Some(resolver) = self.resolver {
292 resolver.get_base_type(ty, self.interner)
293 } else {
294 None
296 }
297 }
298
299 fn is_suitable_common_type(&self, candidate: TypeId, types: &[TypeId]) -> bool {
302 types.iter().all(|&ty| self.is_subtype(ty, candidate))
303 }
304
305 pub(crate) fn is_subtype(&self, source: TypeId, target: TypeId) -> bool {
308 let key = (source, target);
309 if let Some(&cached) = self.subtype_cache.borrow().get(&key) {
310 return cached;
311 }
312
313 let result = self.is_subtype_uncached(source, target);
314 self.subtype_cache.borrow_mut().insert(key, result);
315 result
316 }
317
318 fn is_subtype_uncached(&self, source: TypeId, target: TypeId) -> bool {
319 if source == target {
321 return true;
322 }
323
324 if source == TypeId::NEVER {
326 return true;
327 }
328
329 if target == TypeId::UNKNOWN {
331 return true;
332 }
333
334 if source == TypeId::ANY || target == TypeId::ANY {
336 return source == target;
337 }
338
339 if source == TypeId::STRICT_ANY || target == TypeId::STRICT_ANY {
341 return source == target
342 || target == TypeId::UNKNOWN
343 || target == TypeId::ANY
344 || source == TypeId::ANY;
345 }
346
347 if target == TypeId::OBJECT {
349 return self.is_object_keyword_type(source);
350 }
351
352 let source_key = self.interner.lookup(source);
353 let target_key = self.interner.lookup(target);
354
355 if let (Some(TypeData::Enum(..)), Some(TypeData::Enum(..))) =
360 (source_key.as_ref(), target_key.as_ref())
361 {
362 return false;
364 }
365
366 if let Some(TypeData::Literal(lit)) = source_key.as_ref() {
368 match (lit, target) {
369 (LiteralValue::String(_), t) if t == TypeId::STRING => return true,
370 (LiteralValue::Number(_), t) if t == TypeId::NUMBER => return true,
371 (LiteralValue::Boolean(_), t) if t == TypeId::BOOLEAN => return true,
372 (LiteralValue::BigInt(_), t) if t == TypeId::BIGINT => return true,
373 _ => {}
374 }
375 }
376
377 if let (Some(TypeData::Array(s_elem)), Some(TypeData::Array(t_elem))) =
379 (source_key.as_ref(), target_key.as_ref())
380 {
381 return self.is_subtype(*s_elem, *t_elem);
382 }
383
384 if let (Some(TypeData::Tuple(_)), Some(TypeData::Tuple(_))) =
385 (source_key.as_ref(), target_key.as_ref())
386 {
387 if visitor::is_unit_type(self.interner, source)
393 && visitor::is_unit_type(self.interner, target)
394 {
395 return false;
396 }
397 let (Some(TypeData::Tuple(s_elems)), Some(TypeData::Tuple(t_elems))) =
399 (source_key.as_ref(), target_key.as_ref())
400 else {
401 panic!("invariant violation: tuple subtype check expected tuple operands")
402 };
403 let s_elems = self.interner.tuple_list(*s_elems);
404 let t_elems = self.interner.tuple_list(*t_elems);
405 return self.tuple_subtype_of(&s_elems, &t_elems);
406 }
407
408 if let (Some(TypeData::Tuple(s_elems)), Some(TypeData::Array(t_elem))) =
409 (source_key.as_ref(), target_key.as_ref())
410 {
411 let s_elems = self.interner.tuple_list(*s_elems);
412 return self.tuple_subtype_array(&s_elems, *t_elem);
413 }
414
415 if let (Some(TypeData::Object(s_props)), Some(TypeData::Object(t_props))) =
416 (source_key.as_ref(), target_key.as_ref())
417 {
418 let s_shape = self.interner.object_shape(*s_props);
419 let t_shape = self.interner.object_shape(*t_props);
420 return self.object_subtype_of(
421 &s_shape.properties,
422 Some(*s_props),
423 &t_shape.properties,
424 );
425 }
426
427 if let (
428 Some(TypeData::ObjectWithIndex(s_shape_id)),
429 Some(TypeData::ObjectWithIndex(t_shape_id)),
430 ) = (source_key.as_ref(), target_key.as_ref())
431 {
432 let s_shape = self.interner.object_shape(*s_shape_id);
433 let t_shape = self.interner.object_shape(*t_shape_id);
434 return self.object_with_index_subtype_of(&s_shape, Some(*s_shape_id), &t_shape);
435 }
436
437 if let (Some(TypeData::Object(s_props)), Some(TypeData::ObjectWithIndex(t_shape))) =
438 (source_key.as_ref(), target_key.as_ref())
439 {
440 let s_shape = self.interner.object_shape(*s_props);
441 let t_shape = self.interner.object_shape(*t_shape);
442 return self.object_props_subtype_index(&s_shape.properties, Some(*s_props), &t_shape);
443 }
444
445 if let (Some(TypeData::ObjectWithIndex(s_shape_id)), Some(TypeData::Object(t_props))) =
446 (source_key.as_ref(), target_key.as_ref())
447 {
448 let s_shape = self.interner.object_shape(*s_shape_id);
449 let t_shape = self.interner.object_shape(*t_props);
450 return self.object_subtype_of(
451 &s_shape.properties,
452 Some(*s_shape_id),
453 &t_shape.properties,
454 );
455 }
456
457 if let (Some(TypeData::Function(s_fn)), Some(TypeData::Function(t_fn))) =
458 (source_key.as_ref(), target_key.as_ref())
459 {
460 let s_fn = self.interner.function_shape(*s_fn);
461 let t_fn = self.interner.function_shape(*t_fn);
462 return self.function_subtype_of(&s_fn, &t_fn);
463 }
464
465 if let (Some(TypeData::Callable(s_callable)), Some(TypeData::Callable(t_callable))) =
466 (source_key.as_ref(), target_key.as_ref())
467 {
468 let s_callable = self.interner.callable_shape(*s_callable);
469 let t_callable = self.interner.callable_shape(*t_callable);
470 return self.callable_subtype_of(&s_callable, &t_callable);
471 }
472
473 if let (Some(TypeData::Function(s_fn)), Some(TypeData::Callable(t_callable))) =
474 (source_key.as_ref(), target_key.as_ref())
475 {
476 let s_fn = self.interner.function_shape(*s_fn);
477 let t_callable = self.interner.callable_shape(*t_callable);
478 return self.function_subtype_callable(&s_fn, &t_callable);
479 }
480
481 if let (Some(TypeData::Callable(s_callable)), Some(TypeData::Function(t_fn))) =
482 (source_key.as_ref(), target_key.as_ref())
483 {
484 let s_callable = self.interner.callable_shape(*s_callable);
485 let t_fn = self.interner.function_shape(*t_fn);
486 return self.callable_subtype_function(&s_callable, &t_fn);
487 }
488
489 if let (Some(TypeData::Application(s_app)), Some(TypeData::Application(t_app))) =
490 (source_key.as_ref(), target_key.as_ref())
491 {
492 let s_app = self.interner.type_application(*s_app);
493 let t_app = self.interner.type_application(*t_app);
494 if s_app.args.len() != t_app.args.len() {
495 return false;
496 }
497 if !self.is_subtype(s_app.base, t_app.base) {
498 return false;
499 }
500 for (s_arg, t_arg) in s_app.args.iter().zip(t_app.args.iter()) {
501 if !self.is_subtype(*s_arg, *t_arg) {
502 return false;
503 }
504 }
505 return true;
506 }
507
508 if let Some(TypeData::Intersection(members)) = source_key.as_ref() {
510 let members = self.interner.type_list(*members);
511 return members
512 .iter()
513 .any(|&member| self.is_subtype(member, target));
514 }
515
516 if let Some(TypeData::Union(members)) = source_key.as_ref() {
518 let members = self.interner.type_list(*members);
519 return members
520 .iter()
521 .all(|&member| self.is_subtype(member, target));
522 }
523
524 if let Some(TypeData::Intersection(members)) = target_key.as_ref() {
526 let members = self.interner.type_list(*members);
527 return members
528 .iter()
529 .all(|&member| self.is_subtype(source, member));
530 }
531
532 if let Some(TypeData::Union(members)) = target_key.as_ref() {
534 let members = self.interner.type_list(*members);
535 return members
536 .iter()
537 .any(|&member| self.is_subtype(source, member));
538 }
539
540 if let (Some(TypeData::Object(s_props)), Some(TypeData::Object(t_props))) =
542 (source_key.as_ref(), target_key.as_ref())
543 {
544 let s_shape = self.interner.object_shape(*s_props);
545 let t_shape = self.interner.object_shape(*t_props);
546 return self.object_subtype_of(
547 &s_shape.properties,
548 Some(*s_props),
549 &t_shape.properties,
550 );
551 }
552
553 false
554 }
555
556 fn is_object_keyword_type(&self, source: TypeId) -> bool {
557 match source {
558 TypeId::NEVER | TypeId::ERROR | TypeId::OBJECT => return true,
559 TypeId::ANY => {
560 return false;
562 }
563 TypeId::UNKNOWN
564 | TypeId::VOID
565 | TypeId::NULL
566 | TypeId::UNDEFINED
567 | TypeId::BOOLEAN
568 | TypeId::NUMBER
569 | TypeId::STRING
570 | TypeId::BIGINT
571 | TypeId::SYMBOL => return false,
572 _ => {}
573 }
574
575 let key = match self.interner.lookup(source) {
576 Some(key) => key,
577 None => return false,
578 };
579
580 match key {
581 TypeData::Object(_)
582 | TypeData::ObjectWithIndex(_)
583 | TypeData::Array(_)
584 | TypeData::Tuple(_)
585 | TypeData::Function(_)
586 | TypeData::Callable(_)
587 | TypeData::Mapped(_)
588 | TypeData::Application(_)
589 | TypeData::ThisType => true,
590 TypeData::ReadonlyType(inner) => self.is_subtype(inner, TypeId::OBJECT),
591 TypeData::TypeParameter(info) | TypeData::Infer(info) => info
592 .constraint
593 .is_some_and(|constraint| self.is_subtype(constraint, TypeId::OBJECT)),
594 _ => false,
595 }
596 }
597
598 fn optional_property_type(&self, prop: &PropertyInfo) -> TypeId {
599 if prop.optional {
600 self.interner.union2(prop.type_id, TypeId::UNDEFINED)
601 } else {
602 prop.type_id
603 }
604 }
605
606 fn optional_property_write_type(&self, prop: &PropertyInfo) -> TypeId {
607 if prop.optional {
608 self.interner.union2(prop.write_type, TypeId::UNDEFINED)
609 } else {
610 prop.write_type
611 }
612 }
613
614 fn is_subtype_with_method_variance(
615 &self,
616 source: TypeId,
617 target: TypeId,
618 allow_bivariant: bool,
619 ) -> bool {
620 if !allow_bivariant {
621 return self.is_subtype(source, target);
622 }
623
624 let source_key = self.interner.lookup(source);
625 let target_key = self.interner.lookup(target);
626
627 match (source_key.as_ref(), target_key.as_ref()) {
628 (Some(TypeData::Function(s_fn)), Some(TypeData::Function(t_fn))) => {
629 let s_fn = self.interner.function_shape(*s_fn);
630 let t_fn = self.interner.function_shape(*t_fn);
631 return self.function_like_subtype_of_with_variance(
632 &s_fn.params,
633 s_fn.return_type,
634 &t_fn.params,
635 t_fn.return_type,
636 true,
637 );
638 }
639 (Some(TypeData::Callable(s_callable)), Some(TypeData::Callable(t_callable))) => {
640 let s_callable = self.interner.callable_shape(*s_callable);
641 let t_callable = self.interner.callable_shape(*t_callable);
642 return self.callable_subtype_of_with_variance(&s_callable, &t_callable, true);
643 }
644 (Some(TypeData::Function(s_fn)), Some(TypeData::Callable(t_callable))) => {
645 let s_fn = self.interner.function_shape(*s_fn);
646 let t_callable = self.interner.callable_shape(*t_callable);
647 return self.function_subtype_callable_with_variance(&s_fn, &t_callable, true);
648 }
649 (Some(TypeData::Callable(s_callable)), Some(TypeData::Function(t_fn))) => {
650 let s_callable = self.interner.callable_shape(*s_callable);
651 let t_fn = self.interner.function_shape(*t_fn);
652 return self.callable_subtype_function_with_variance(&s_callable, &t_fn, true);
653 }
654 _ => {}
655 }
656
657 self.is_subtype(source, target)
658 }
659
660 fn lookup_property<'props>(
661 &self,
662 props: &'props [PropertyInfo],
663 shape_id: Option<ObjectShapeId>,
664 name: Atom,
665 ) -> Option<&'props PropertyInfo> {
666 crate::utils::lookup_property(self.interner, props, shape_id, name)
667 }
668
669 fn object_subtype_of(
670 &self,
671 source: &[PropertyInfo],
672 source_shape_id: Option<ObjectShapeId>,
673 target: &[PropertyInfo],
674 ) -> bool {
675 for t_prop in target {
676 let s_prop = self.lookup_property(source, source_shape_id, t_prop.name);
677 match s_prop {
678 Some(sp) => {
679 if sp.optional && !t_prop.optional {
680 return false;
681 }
682 let source_type = self.optional_property_type(sp);
685 let target_type = self.optional_property_type(t_prop);
686 if !self.is_subtype_with_method_variance(
687 source_type,
688 target_type,
689 t_prop.is_method,
690 ) {
691 return false;
692 }
693 if !t_prop.readonly {
696 if sp.readonly {
698 return false;
699 }
700 if !sp.optional && t_prop.optional {
703 } else {
705 let source_write = self.optional_property_write_type(sp);
706 let target_write = self.optional_property_write_type(t_prop);
707 if !self.is_subtype_with_method_variance(
708 target_write,
709 source_write,
710 t_prop.is_method,
711 ) {
712 return false;
713 }
714 }
715 }
716 }
717 None => {
718 if !t_prop.optional {
719 return false;
720 }
721 }
722 }
723 }
724 true
725 }
726
727 fn object_props_subtype_index(
728 &self,
729 source: &[PropertyInfo],
730 source_shape_id: Option<ObjectShapeId>,
731 target: &ObjectShape,
732 ) -> bool {
733 if !self.object_subtype_of(source, source_shape_id, &target.properties) {
734 return false;
735 }
736 self.check_properties_against_index_signatures(source, target)
737 }
738
739 fn object_with_index_subtype_of(
740 &self,
741 source: &ObjectShape,
742 source_shape_id: Option<ObjectShapeId>,
743 target: &ObjectShape,
744 ) -> bool {
745 if !self.object_subtype_of(&source.properties, source_shape_id, &target.properties) {
746 return false;
747 }
748
749 if let Some(t_string_idx) = &target.string_index
750 && let Some(s_string_idx) = &source.string_index
751 {
752 if s_string_idx.readonly && !t_string_idx.readonly {
753 return false;
754 }
755 if !self.is_subtype(s_string_idx.value_type, t_string_idx.value_type) {
756 return false;
757 }
758 }
759
760 if let Some(t_number_idx) = &target.number_index
761 && let Some(s_number_idx) = &source.number_index
762 {
763 if s_number_idx.readonly && !t_number_idx.readonly {
764 return false;
765 }
766 if !self.is_subtype(s_number_idx.value_type, t_number_idx.value_type) {
767 return false;
768 }
769 }
770
771 if let (Some(s_string_idx), Some(s_number_idx)) =
772 (&source.string_index, &source.number_index)
773 && !self.is_subtype(s_number_idx.value_type, s_string_idx.value_type)
774 {
775 return false;
776 }
777
778 self.check_properties_against_index_signatures(&source.properties, target)
779 }
780
781 fn check_properties_against_index_signatures(
782 &self,
783 source: &[PropertyInfo],
784 target: &ObjectShape,
785 ) -> bool {
786 let string_index = target.string_index.as_ref();
787 let number_index = target.number_index.as_ref();
788
789 if string_index.is_none() && number_index.is_none() {
790 return true;
791 }
792
793 for prop in source {
794 let prop_type = self.optional_property_type(prop);
795
796 if let Some(number_idx) = number_index
797 && utils::is_numeric_property_name(self.interner, prop.name)
798 {
799 if !number_idx.readonly && prop.readonly {
800 return false;
801 }
802 if !self.is_subtype(prop_type, number_idx.value_type) {
803 return false;
804 }
805 }
806
807 if let Some(string_idx) = string_index {
808 if !string_idx.readonly && prop.readonly {
809 return false;
810 }
811 if !self.is_subtype(prop_type, string_idx.value_type) {
812 return false;
813 }
814 }
815 }
816
817 true
818 }
819
820 fn rest_element_type(&self, type_id: TypeId) -> TypeId {
821 if type_id == TypeId::ANY {
822 return TypeId::ANY;
823 }
824 match self.interner.lookup(type_id) {
825 Some(TypeData::Array(elem)) => elem,
826 _ => type_id,
827 }
828 }
829
830 fn are_parameters_compatible(&self, source: TypeId, target: TypeId, bivariant: bool) -> bool {
831 if bivariant {
832 self.is_subtype(target, source) || self.is_subtype(source, target)
833 } else {
834 self.is_subtype(target, source)
835 }
836 }
837
838 fn are_this_parameters_compatible(
839 &self,
840 source: Option<TypeId>,
841 target: Option<TypeId>,
842 bivariant: bool,
843 ) -> bool {
844 if source.is_none() && target.is_none() {
845 return true;
846 }
847 if target.is_none() {
850 return true;
851 }
852 let source = source.unwrap_or(TypeId::UNKNOWN);
853 let target = target.unwrap();
854 self.are_parameters_compatible(source, target, bivariant)
855 }
856
857 fn function_like_subtype_of(
858 &self,
859 source_params: &[ParamInfo],
860 source_return: TypeId,
861 target_params: &[ParamInfo],
862 target_return: TypeId,
863 ) -> bool {
864 self.function_like_subtype_of_with_variance(
865 source_params,
866 source_return,
867 target_params,
868 target_return,
869 false,
870 )
871 }
872
873 fn function_like_subtype_of_with_variance(
874 &self,
875 source_params: &[ParamInfo],
876 source_return: TypeId,
877 target_params: &[ParamInfo],
878 target_return: TypeId,
879 bivariant: bool,
880 ) -> bool {
881 if !self.is_subtype(source_return, target_return) {
882 return false;
883 }
884
885 let target_has_rest = target_params.last().is_some_and(|p| p.rest);
886 let source_has_rest = source_params.last().is_some_and(|p| p.rest);
887 let target_fixed = if target_has_rest {
888 target_params.len().saturating_sub(1)
889 } else {
890 target_params.len()
891 };
892 let source_fixed = if source_has_rest {
893 source_params.len().saturating_sub(1)
894 } else {
895 source_params.len()
896 };
897
898 if !target_has_rest && source_params.len() > target_params.len() {
899 return false;
900 }
901
902 let fixed_compare = std::cmp::min(source_fixed, target_fixed);
903 for i in 0..fixed_compare {
904 let s_param = &source_params[i];
905 let t_param = &target_params[i];
906 if !self.are_parameters_compatible(s_param.type_id, t_param.type_id, bivariant) {
907 return false;
908 }
909 }
910
911 if target_has_rest {
912 let rest_param = match target_params.last() {
913 Some(param) => param,
914 None => return false,
915 };
916 let rest_elem = self.rest_element_type(rest_param.type_id);
917
918 for s_param in source_params
919 .iter()
920 .skip(target_fixed)
921 .take(source_fixed - target_fixed)
922 {
923 if !self.are_parameters_compatible(s_param.type_id, rest_elem, bivariant) {
924 return false;
925 }
926 }
927
928 if source_has_rest {
929 let s_rest = match source_params.last() {
930 Some(param) => param,
931 None => return false,
932 };
933 let s_rest_elem = self.rest_element_type(s_rest.type_id);
934 if !self.are_parameters_compatible(s_rest_elem, rest_elem, bivariant) {
935 return false;
936 }
937 }
938 }
939
940 true
941 }
942
943 fn function_subtype_of(&self, source: &FunctionShape, target: &FunctionShape) -> bool {
944 if source.is_constructor != target.is_constructor {
945 return false;
946 }
947 if !self.are_this_parameters_compatible(source.this_type, target.this_type, false) {
948 return false;
949 }
950
951 self.function_like_subtype_of(
952 &source.params,
953 source.return_type,
954 &target.params,
955 target.return_type,
956 )
957 }
958
959 fn call_signature_subtype_of(
960 &self,
961 source: &CallSignature,
962 target: &CallSignature,
963 bivariant: bool,
964 ) -> bool {
965 if !self.are_this_parameters_compatible(source.this_type, target.this_type, bivariant) {
966 return false;
967 }
968 self.function_like_subtype_of_with_variance(
969 &source.params,
970 source.return_type,
971 &target.params,
972 target.return_type,
973 bivariant,
974 )
975 }
976
977 fn callable_subtype_of(&self, source: &CallableShape, target: &CallableShape) -> bool {
978 self.callable_subtype_of_with_variance(source, target, false)
979 }
980
981 fn callable_subtype_of_with_variance(
982 &self,
983 source: &CallableShape,
984 target: &CallableShape,
985 bivariant: bool,
986 ) -> bool {
987 for t_sig in &target.call_signatures {
988 let mut found = false;
989 for s_sig in &source.call_signatures {
990 if self.call_signature_subtype_of(s_sig, t_sig, bivariant) {
991 found = true;
992 break;
993 }
994 }
995 if !found {
996 return false;
997 }
998 }
999
1000 for t_sig in &target.construct_signatures {
1001 let mut found = false;
1002 for s_sig in &source.construct_signatures {
1003 if self.call_signature_subtype_of(s_sig, t_sig, bivariant) {
1004 found = true;
1005 break;
1006 }
1007 }
1008 if !found {
1009 return false;
1010 }
1011 }
1012
1013 self.object_subtype_of(&source.properties, None, &target.properties)
1014 }
1015
1016 fn function_subtype_callable(&self, source: &FunctionShape, target: &CallableShape) -> bool {
1017 self.function_subtype_callable_with_variance(source, target, false)
1018 }
1019
1020 fn function_subtype_callable_with_variance(
1021 &self,
1022 source: &FunctionShape,
1023 target: &CallableShape,
1024 bivariant: bool,
1025 ) -> bool {
1026 for t_sig in &target.call_signatures {
1027 if !self.function_like_subtype_of_with_variance(
1028 &source.params,
1029 source.return_type,
1030 &t_sig.params,
1031 t_sig.return_type,
1032 bivariant,
1033 ) {
1034 return false;
1035 }
1036 }
1037 true
1038 }
1039
1040 fn callable_subtype_function(&self, source: &CallableShape, target: &FunctionShape) -> bool {
1041 self.callable_subtype_function_with_variance(source, target, false)
1042 }
1043
1044 fn callable_subtype_function_with_variance(
1045 &self,
1046 source: &CallableShape,
1047 target: &FunctionShape,
1048 bivariant: bool,
1049 ) -> bool {
1050 for s_sig in &source.call_signatures {
1051 if self.function_like_subtype_of_with_variance(
1052 &s_sig.params,
1053 s_sig.return_type,
1054 &target.params,
1055 target.return_type,
1056 bivariant,
1057 ) {
1058 return true;
1059 }
1060 }
1061 false
1062 }
1063
1064 fn tuple_subtype_array(&self, source: &[TupleElement], target_elem: TypeId) -> bool {
1065 for elem in source {
1066 if elem.rest {
1067 let expansion = self.expand_tuple_rest(elem.type_id);
1068 for fixed in expansion.fixed {
1069 if !self.is_subtype(fixed.type_id, target_elem) {
1070 return false;
1071 }
1072 }
1073 if let Some(variadic) = expansion.variadic
1074 && !self.is_subtype(variadic, target_elem)
1075 {
1076 return false;
1077 }
1078 for tail_elem in expansion.tail {
1080 if !self.is_subtype(tail_elem.type_id, target_elem) {
1081 return false;
1082 }
1083 }
1084 } else if !self.is_subtype(elem.type_id, target_elem) {
1085 return false;
1086 }
1087 }
1088 true
1089 }
1090
1091 fn tuple_subtype_of(&self, source: &[TupleElement], target: &[TupleElement]) -> bool {
1092 let source_required = source.iter().filter(|e| !e.optional && !e.rest).count();
1093 let target_required = target.iter().filter(|e| !e.optional && !e.rest).count();
1094
1095 if source_required < target_required {
1096 return false;
1097 }
1098
1099 for (i, t_elem) in target.iter().enumerate() {
1100 if t_elem.rest {
1101 let expansion = self.expand_tuple_rest(t_elem.type_id);
1102 let outer_tail = &target[i + 1..];
1103 let combined_suffix: Vec<_> = expansion
1105 .tail
1106 .iter()
1107 .chain(outer_tail.iter())
1108 .cloned()
1109 .collect();
1110
1111 let mut source_end = source.len();
1113 for tail_elem in combined_suffix.iter().rev() {
1114 if source_end <= i {
1115 if !tail_elem.optional {
1116 return false;
1117 }
1118 break;
1119 }
1120 let s_elem = &source[source_end - 1];
1121 if s_elem.rest {
1122 if !tail_elem.optional {
1123 return false;
1124 }
1125 break;
1126 }
1127 if !self.is_subtype(s_elem.type_id, tail_elem.type_id) {
1128 if tail_elem.optional {
1129 break;
1130 }
1131 return false;
1132 }
1133 source_end -= 1;
1134 }
1135
1136 let mut source_iter = source.iter().take(source_end).skip(i);
1137
1138 for t_fixed in &expansion.fixed {
1139 match source_iter.next() {
1140 Some(s_elem) => {
1141 if s_elem.rest {
1142 return false;
1143 }
1144 if !self.is_subtype(s_elem.type_id, t_fixed.type_id) {
1145 return false;
1146 }
1147 }
1148 None => {
1149 if !t_fixed.optional {
1150 return false;
1151 }
1152 }
1153 }
1154 }
1155
1156 if let Some(variadic) = expansion.variadic {
1157 let variadic_array = self.interner.array(variadic);
1158 for s_elem in source_iter {
1159 if s_elem.rest {
1160 if !self.is_subtype(s_elem.type_id, variadic_array) {
1161 return false;
1162 }
1163 } else if !self.is_subtype(s_elem.type_id, variadic) {
1164 return false;
1165 }
1166 }
1167 return true;
1168 }
1169
1170 if source_iter.next().is_some() {
1171 return false;
1172 }
1173 return true;
1174 }
1175
1176 if let Some(s_elem) = source.get(i) {
1177 if s_elem.rest {
1178 return false;
1179 }
1180 if !self.is_subtype(s_elem.type_id, t_elem.type_id) {
1181 return false;
1182 }
1183 } else if !t_elem.optional {
1184 return false;
1185 }
1186 }
1187
1188 if source.len() > target.len() {
1189 return false;
1190 }
1191
1192 if source.iter().any(|elem| elem.rest) {
1193 return false;
1194 }
1195
1196 true
1197 }
1198
1199 fn expand_tuple_rest(&self, type_id: TypeId) -> TupleRestExpansion {
1200 match self.interner.lookup(type_id) {
1201 Some(TypeData::Array(elem)) => TupleRestExpansion {
1202 fixed: Vec::new(),
1203 variadic: Some(elem),
1204 tail: Vec::new(),
1205 },
1206 Some(TypeData::Tuple(elements)) => {
1207 let elements = self.interner.tuple_list(elements);
1208 let mut fixed = Vec::new();
1209 for (i, elem) in elements.iter().enumerate() {
1210 if elem.rest {
1211 let inner = self.expand_tuple_rest(elem.type_id);
1212 fixed.extend(inner.fixed);
1213 let mut tail = inner.tail;
1215 tail.extend(elements[i + 1..].iter().cloned());
1216 return TupleRestExpansion {
1217 fixed,
1218 variadic: inner.variadic,
1219 tail,
1220 };
1221 }
1222 fixed.push(elem.clone());
1223 }
1224 TupleRestExpansion {
1225 fixed,
1226 variadic: None,
1227 tail: Vec::new(),
1228 }
1229 }
1230 _ => TupleRestExpansion {
1231 fixed: Vec::new(),
1232 variadic: Some(type_id),
1233 tail: Vec::new(),
1234 },
1235 }
1236 }
1237}