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