1use crate::AssignabilityChecker;
14use crate::TypeDatabase;
15use crate::caches::db::QueryDatabase;
16use crate::def::DefId;
17use crate::diagnostics::{DynSubtypeTracer, SubtypeFailureReason};
18#[cfg(test)]
19use crate::types::*;
20use crate::types::{
21 IntrinsicKind, LiteralValue, ObjectFlags, ObjectShape, SymbolRef, TypeData, TypeId, TypeListId,
22};
23use crate::visitor::{
24 TypeVisitor, application_id, array_element_type, callable_shape_id, conditional_type_id,
25 enum_components, function_shape_id, intersection_list_id, intrinsic_kind, is_this_type,
26 keyof_inner_type, lazy_def_id, literal_value, mapped_type_id, object_shape_id,
27 object_with_index_shape_id, readonly_inner_type, ref_symbol, template_literal_id,
28 tuple_list_id, type_param_info, type_query_symbol, union_list_id, unique_symbol_ref,
29};
30use rustc_hash::{FxHashMap, FxHashSet};
31use tsz_common::limits;
32
33pub(crate) const MAX_SUBTYPE_DEPTH: u32 = limits::MAX_SUBTYPE_DEPTH;
37pub(crate) const INTERSECTION_OBJECT_FAST_PATH_THRESHOLD: usize = 8;
38
39#[derive(Copy, Clone, Debug, PartialEq, Eq)]
41pub enum SubtypeResult {
42 True,
44 False,
46 CycleDetected,
51 DepthExceeded,
59}
60
61impl SubtypeResult {
62 pub const fn is_true(self) -> bool {
63 matches!(self, Self::True | Self::CycleDetected)
64 }
65
66 pub const fn is_false(self) -> bool {
67 matches!(self, Self::False)
68 }
69}
70
71pub(crate) fn is_disjoint_unit_type(types: &dyn TypeDatabase, ty: TypeId) -> bool {
79 match types.lookup(ty) {
80 Some(TypeData::Literal(_) | TypeData::UniqueSymbol(_)) => true,
81 _ => false,
84 }
85}
86
87#[derive(Copy, Clone, Debug, PartialEq, Eq)]
89pub enum AnyPropagationMode {
90 All,
92 TopLevelOnly,
94}
95
96impl AnyPropagationMode {
97 #[inline]
98 pub(crate) const fn allows_any_at_depth(self, depth: u32) -> bool {
99 match self {
100 Self::All => true,
101 Self::TopLevelOnly => depth == 0,
102 }
103 }
104}
105
106pub use crate::type_resolver::{NoopResolver, TypeEnvironment, TypeResolver};
108
109pub use crate::relations::subtype_visitor::SubtypeVisitor;
111
112pub struct SubtypeChecker<'a, R: TypeResolver = NoopResolver> {
115 pub(crate) interner: &'a dyn TypeDatabase,
116 pub(crate) query_db: Option<&'a dyn QueryDatabase>,
119 pub(crate) resolver: &'a R,
120 pub(crate) guard: crate::recursion::RecursionGuard<(TypeId, TypeId)>,
122 pub(crate) seen_refs: FxHashSet<(SymbolRef, SymbolRef)>,
126 pub(crate) def_guard: crate::recursion::RecursionGuard<(DefId, DefId)>,
129 sym_visiting: FxHashSet<(tsz_binder::SymbolId, tsz_binder::SymbolId)>,
135 pub strict_function_types: bool,
138 pub allow_void_return: bool,
140 pub allow_bivariant_rest: bool,
143 pub bypass_evaluation: bool,
147 pub max_depth: u32,
151 pub allow_bivariant_param_count: bool,
153 pub exact_optional_property_types: bool,
156 pub strict_null_checks: bool,
159 pub no_unchecked_indexed_access: bool,
162 pub disable_method_bivariance: bool,
165 pub inheritance_graph: Option<&'a crate::classes::inheritance::InheritanceGraph>,
168 pub is_class_symbol: Option<&'a dyn Fn(SymbolRef) -> bool>,
171 pub any_propagation: AnyPropagationMode,
173 pub(crate) eval_cache: FxHashMap<(TypeId, bool), TypeId>,
178 pub tracer: Option<&'a mut dyn DynSubtypeTracer>,
182}
183
184impl<'a> SubtypeChecker<'a, NoopResolver> {
185 pub fn new(interner: &'a dyn TypeDatabase) -> Self {
187 static NOOP: NoopResolver = NoopResolver;
188 SubtypeChecker {
189 interner,
190 query_db: None,
191 resolver: &NOOP,
192 guard: crate::recursion::RecursionGuard::with_profile(
193 crate::recursion::RecursionProfile::SubtypeCheck,
194 ),
195 seen_refs: FxHashSet::default(),
196 def_guard: crate::recursion::RecursionGuard::with_profile(
197 crate::recursion::RecursionProfile::SubtypeCheck,
198 ),
199 sym_visiting: FxHashSet::default(),
200 strict_function_types: true, allow_void_return: false,
202 allow_bivariant_rest: false,
203 allow_bivariant_param_count: false,
204 exact_optional_property_types: false,
205 strict_null_checks: true,
206 no_unchecked_indexed_access: false,
207 disable_method_bivariance: false,
208 inheritance_graph: None,
209 is_class_symbol: None,
210 any_propagation: AnyPropagationMode::All,
211 bypass_evaluation: false,
212 max_depth: MAX_SUBTYPE_DEPTH,
213 eval_cache: FxHashMap::default(),
214 tracer: None,
215 }
216 }
217}
218
219impl<'a, R: TypeResolver> SubtypeChecker<'a, R> {
220 pub fn with_resolver(interner: &'a dyn TypeDatabase, resolver: &'a R) -> Self {
222 SubtypeChecker {
223 interner,
224 query_db: None,
225 resolver,
226 guard: crate::recursion::RecursionGuard::with_profile(
227 crate::recursion::RecursionProfile::SubtypeCheck,
228 ),
229 seen_refs: FxHashSet::default(),
230 def_guard: crate::recursion::RecursionGuard::with_profile(
231 crate::recursion::RecursionProfile::SubtypeCheck,
232 ),
233 sym_visiting: FxHashSet::default(),
234 strict_function_types: true,
235 allow_void_return: false,
236 allow_bivariant_rest: false,
237 allow_bivariant_param_count: false,
238 exact_optional_property_types: false,
239 strict_null_checks: true,
240 no_unchecked_indexed_access: false,
241 disable_method_bivariance: false,
242 inheritance_graph: None,
243 is_class_symbol: None,
244 any_propagation: AnyPropagationMode::All,
245 bypass_evaluation: false,
246 max_depth: MAX_SUBTYPE_DEPTH,
247 eval_cache: FxHashMap::default(),
248 tracer: None,
249 }
250 }
251
252 pub const fn with_inheritance_graph(
254 mut self,
255 graph: &'a crate::classes::inheritance::InheritanceGraph,
256 ) -> Self {
257 self.inheritance_graph = Some(graph);
258 self
259 }
260
261 pub fn with_class_check(mut self, check: &'a dyn Fn(SymbolRef) -> bool) -> Self {
263 self.is_class_symbol = Some(check);
264 self
265 }
266
267 pub const fn with_any_propagation_mode(mut self, mode: AnyPropagationMode) -> Self {
269 self.any_propagation = mode;
270 self
271 }
272
273 pub fn with_tracer(mut self, tracer: &'a mut dyn DynSubtypeTracer) -> Self {
276 self.tracer = Some(tracer);
277 self
278 }
279
280 pub fn with_query_db(mut self, db: &'a dyn QueryDatabase) -> Self {
283 self.query_db = Some(db);
284 self
285 }
286
287 pub const fn with_strict_null_checks(mut self, strict_null_checks: bool) -> Self {
290 self.strict_null_checks = strict_null_checks;
291 self
292 }
293
294 #[inline]
302 pub fn reset(&mut self) {
303 self.guard.reset();
304 self.seen_refs.clear();
305 self.def_guard.reset();
306 self.sym_visiting.clear();
307 self.eval_cache.clear();
308 }
309
310 pub const fn depth_exceeded(&self) -> bool {
312 self.guard.is_exceeded()
313 }
314
315 pub(crate) const fn apply_flags(mut self, flags: u16) -> Self {
328 self.strict_null_checks = (flags & (1 << 0)) != 0;
329 self.strict_function_types = (flags & (1 << 1)) != 0;
330 self.exact_optional_property_types = (flags & (1 << 2)) != 0;
331 self.no_unchecked_indexed_access = (flags & (1 << 3)) != 0;
332 self.disable_method_bivariance = (flags & (1 << 4)) != 0;
333 self.allow_void_return = (flags & (1 << 5)) != 0;
334 self.allow_bivariant_rest = (flags & (1 << 6)) != 0;
335 self.allow_bivariant_param_count = (flags & (1 << 7)) != 0;
336 self
337 }
338
339 pub(crate) fn resolve_ref_type(&self, type_id: TypeId) -> TypeId {
340 if let Some(def_id) = lazy_def_id(self.interner, type_id) {
342 return self
343 .resolver
344 .resolve_lazy(def_id, self.interner)
345 .unwrap_or(type_id);
346 }
347
348 if let Some(symbol) = ref_symbol(self.interner, type_id) {
350 self.resolver
351 .resolve_symbol_ref(symbol, self.interner)
352 .unwrap_or(type_id)
353 } else {
354 type_id
355 }
356 }
357
358 pub(crate) fn resolve_lazy_type(&self, type_id: TypeId) -> TypeId {
359 if let Some(def_id) = lazy_def_id(self.interner, type_id) {
360 self.resolver
361 .resolve_lazy(def_id, self.interner)
362 .unwrap_or(type_id)
363 } else {
364 type_id
365 }
366 }
367
368 pub(crate) fn check_subtype_inner(&mut self, source: TypeId, target: TypeId) -> SubtypeResult {
370 if !self.strict_null_checks && source.is_nullish() {
373 return SubtypeResult::True;
374 }
375
376 if let Some(shape) = self.apparent_primitive_shape_for_type(source) {
389 if let Some(t_shape_id) = object_shape_id(self.interner, target) {
390 let t_shape = self.interner.object_shape(t_shape_id);
391 return self.check_object_subtype(&shape, None, &t_shape);
392 }
393 if let Some(t_shape_id) = object_with_index_shape_id(self.interner, target) {
394 let t_shape = self.interner.object_shape(t_shape_id);
395 return self.check_object_with_index_subtype(&shape, None, &t_shape);
396 }
397 }
398
399 if let Some(source_cond_id) = conditional_type_id(self.interner, source) {
400 if let Some(target_cond_id) = conditional_type_id(self.interner, target) {
401 let source_cond = self.interner.conditional_type(source_cond_id);
402 let target_cond = self.interner.conditional_type(target_cond_id);
403 return self.check_conditional_subtype(source_cond.as_ref(), target_cond.as_ref());
404 }
405
406 let source_cond = self.interner.conditional_type(source_cond_id);
407 return self.conditional_branches_subtype(source_cond.as_ref(), target);
408 }
409
410 if let Some(target_cond_id) = conditional_type_id(self.interner, target) {
411 let target_cond = self.interner.conditional_type(target_cond_id);
412 return self.subtype_of_conditional_target(source, target_cond.as_ref());
413 }
414
415 if let Some(members) = union_list_id(self.interner, source) {
430 let member_list = self.interner.type_list(members);
431 for &member in member_list.iter() {
432 if !self.check_subtype(member, target).is_true() {
433 if let Some(tracer) = &mut self.tracer
435 && !tracer.on_mismatch_dyn(SubtypeFailureReason::NoUnionMemberMatches {
436 source_type: source,
437 target_union_members: vec![target],
438 })
439 {
440 return SubtypeResult::False;
441 }
442 return SubtypeResult::False;
443 }
444 }
445 return SubtypeResult::True;
446 }
447
448 if let Some(members) = union_list_id(self.interner, target) {
449 if keyof_inner_type(self.interner, source).is_some()
450 && self.is_keyof_subtype_of_string_number_symbol_union(members)
451 {
452 return SubtypeResult::True;
453 }
454
455 if source == TypeId::NUMBER {
457 let member_list = self.interner.type_list(members);
458 for &member in member_list.iter() {
459 let def_id = lazy_def_id(self.interner, member)
460 .or_else(|| enum_components(self.interner, member).map(|(d, _)| d));
461 if let Some(def_id) = def_id
462 && self.resolver.is_numeric_enum(def_id)
463 {
464 return SubtypeResult::True;
465 }
466 }
467 }
468
469 let member_list = self.interner.type_list(members);
470
471 for &member in member_list.iter() {
475 if source == member {
476 return SubtypeResult::True;
477 }
478 }
479
480 for &member in member_list.iter() {
481 if self.check_subtype(source, member).is_true() {
482 return SubtypeResult::True;
483 }
484 }
485
486 if let Some(s_info) = type_param_info(self.interner, source)
490 && let Some(constraint) = s_info.constraint
491 && self.check_subtype(constraint, target).is_true()
492 {
493 return SubtypeResult::True;
494 }
495
496 let s_arc;
499 let source_members: &[TypeId] =
500 if let Some(s_list) = intersection_list_id(self.interner, source) {
501 s_arc = self.interner.type_list(s_list);
502 &s_arc
503 } else {
504 std::slice::from_ref(&source)
505 };
506
507 let mut factored_members = Vec::new();
508 let mut all_contain_source = true;
509 for &member in member_list.iter() {
510 let i_arc;
511 let i_list: &[TypeId] =
512 if let Some(i_members) = intersection_list_id(self.interner, member) {
513 i_arc = self.interner.type_list(i_members);
514 &i_arc
515 } else {
516 std::slice::from_ref(&member)
517 };
518
519 let mut contains_all = true;
520 for &s_m in source_members.iter() {
521 if !i_list.contains(&s_m) {
522 contains_all = false;
523 break;
524 }
525 }
526
527 if contains_all {
528 let mut rem = Vec::new();
529 for &i_m in i_list.iter() {
530 if !source_members.contains(&i_m) {
531 rem.push(i_m);
532 }
533 }
534 factored_members.push(self.interner.intersection(rem));
535 } else {
536 all_contain_source = false;
537 break;
538 }
539 }
540
541 if all_contain_source && !factored_members.is_empty() {
542 let factored_target = self.interner.union(factored_members);
543 if self.check_subtype(source, factored_target).is_true() {
544 return SubtypeResult::True;
545 }
546 }
547
548 if self
553 .type_related_to_discriminated_type(source, &member_list)
554 .is_true()
555 {
556 return SubtypeResult::True;
557 }
558
559 if let Some(s_list) = intersection_list_id(self.interner, source) {
563 let s_member_list = self.interner.type_list(s_list);
564 for &s_member in s_member_list.iter() {
565 if self.check_subtype(s_member, target).is_true() {
566 return SubtypeResult::True;
567 }
568 }
569 }
570
571 if let Some(tracer) = &mut self.tracer
573 && !tracer.on_mismatch_dyn(SubtypeFailureReason::NoUnionMemberMatches {
574 source_type: source,
575 target_union_members: member_list.iter().copied().collect(),
576 })
577 {
578 return SubtypeResult::False;
579 }
580 return SubtypeResult::False;
581 }
582
583 if let Some(members) = intersection_list_id(self.interner, target) {
587 let member_list = self.interner.type_list(members);
588
589 if self.tracer.is_none()
591 && self.can_use_object_intersection_fast_path(&member_list)
592 && let Some(merged_target) = self.build_object_intersection_target(target)
593 {
594 return self.check_subtype(source, merged_target);
595 }
596
597 for &member in member_list.iter() {
598 if !self.check_subtype(source, member).is_true() {
599 return SubtypeResult::False;
600 }
601 }
602 return SubtypeResult::True;
603 }
604
605 if let (Some(s_kind), Some(t_kind)) = (
606 intrinsic_kind(self.interner, source),
607 intrinsic_kind(self.interner, target),
608 ) {
609 return self.check_intrinsic_subtype(s_kind, t_kind);
610 }
611
612 if let Some(s_info) = type_param_info(self.interner, source) {
615 return self.check_type_parameter_subtype(&s_info, target);
616 }
617
618 if let Some(_t_info) = type_param_info(self.interner, target) {
619 if let Some(members) = intersection_list_id(self.interner, source) {
624 let member_list = self.interner.type_list(members);
625 for &member in member_list.iter() {
626 if member == target {
627 return SubtypeResult::True;
628 }
629 }
630 }
631
632 if let Some(tracer) = &mut self.tracer
645 && !tracer.on_mismatch_dyn(SubtypeFailureReason::TypeMismatch {
646 source_type: source,
647 target_type: target,
648 })
649 {
650 return SubtypeResult::False;
651 }
652 return SubtypeResult::False;
653 }
654
655 if let Some(s_kind) = intrinsic_kind(self.interner, source) {
656 if self.is_boxed_primitive_subtype(s_kind, target) {
657 return SubtypeResult::True;
658 }
659 if s_kind == IntrinsicKind::Object {
663 let target_shape = object_shape_id(self.interner, target)
664 .or_else(|| object_with_index_shape_id(self.interner, target));
665 if let Some(t_shape_id) = target_shape {
666 let t_shape = self.interner.object_shape(t_shape_id);
667 if t_shape.properties.iter().all(|p| p.optional) {
668 return SubtypeResult::True;
669 }
670 }
671 }
672 if let Some(tracer) = &mut self.tracer
674 && !tracer.on_mismatch_dyn(SubtypeFailureReason::TypeMismatch {
675 source_type: source,
676 target_type: target,
677 })
678 {
679 return SubtypeResult::False;
680 }
681 return SubtypeResult::False;
682 }
683
684 if let (Some(lit), Some(t_kind)) = (
685 literal_value(self.interner, source),
686 intrinsic_kind(self.interner, target),
687 ) {
688 return self.check_literal_to_intrinsic(&lit, t_kind);
689 }
690
691 if let (Some(s_lit), Some(t_lit)) = (
692 literal_value(self.interner, source),
693 literal_value(self.interner, target),
694 ) {
695 if s_lit == t_lit {
696 return SubtypeResult::True;
697 }
698 if let Some(tracer) = &mut self.tracer
700 && !tracer.on_mismatch_dyn(SubtypeFailureReason::LiteralTypeMismatch {
701 source_type: source,
702 target_type: target,
703 })
704 {
705 return SubtypeResult::False;
706 }
707 return SubtypeResult::False;
708 }
709
710 if let (Some(LiteralValue::String(s_lit)), Some(t_spans)) = (
711 literal_value(self.interner, source),
712 template_literal_id(self.interner, target),
713 ) {
714 return self.check_literal_matches_template_literal(s_lit, t_spans);
715 }
716
717 if intrinsic_kind(self.interner, target) == Some(IntrinsicKind::Object) {
718 if self.is_object_keyword_type(source) {
719 return SubtypeResult::True;
720 }
721 if let Some(tracer) = &mut self.tracer
723 && !tracer.on_mismatch_dyn(SubtypeFailureReason::TypeMismatch {
724 source_type: source,
725 target_type: target,
726 })
727 {
728 return SubtypeResult::False;
729 }
730 return SubtypeResult::False;
731 }
732
733 let is_function_target = intrinsic_kind(self.interner, target)
741 == Some(IntrinsicKind::Function)
742 || self
743 .resolver
744 .is_boxed_type_id(target, IntrinsicKind::Function)
745 || self
746 .resolver
747 .get_boxed_type(IntrinsicKind::Function)
748 .is_some_and(|boxed| boxed == target)
749 || lazy_def_id(self.interner, target).is_some_and(|def_id| {
750 self.resolver
751 .is_boxed_def_id(def_id, IntrinsicKind::Function)
752 });
753 if is_function_target {
754 if self.is_callable_type(source) {
755 return SubtypeResult::True;
756 }
757 if let Some(tracer) = &mut self.tracer
759 && !tracer.on_mismatch_dyn(SubtypeFailureReason::TypeMismatch {
760 source_type: source,
761 target_type: target,
762 })
763 {
764 return SubtypeResult::False;
765 }
766 return SubtypeResult::False;
767 }
768
769 let is_global_object_target = self
775 .resolver
776 .is_boxed_type_id(target, IntrinsicKind::Object)
777 || self
778 .resolver
779 .get_boxed_type(IntrinsicKind::Object)
780 .is_some_and(|boxed| boxed == target)
781 || lazy_def_id(self.interner, target)
782 .is_some_and(|t_def| self.resolver.is_boxed_def_id(t_def, IntrinsicKind::Object));
783 if is_global_object_target {
784 let source_eval = self.evaluate_type(source);
785 if self.is_global_object_interface_type(source_eval) {
786 return SubtypeResult::True;
787 }
788
789 if let Some(tracer) = &mut self.tracer
790 && !tracer.on_mismatch_dyn(SubtypeFailureReason::TypeMismatch {
791 source_type: source,
792 target_type: target,
793 })
794 {
795 return SubtypeResult::False;
796 }
797 return SubtypeResult::False;
798 }
799
800 if let (Some(s_elem), Some(t_elem)) = (
801 array_element_type(self.interner, source),
802 array_element_type(self.interner, target),
803 ) {
804 return self.check_subtype(s_elem, t_elem);
805 }
806
807 if let (Some(s_elems), Some(t_elems)) = (
808 tuple_list_id(self.interner, source),
809 tuple_list_id(self.interner, target),
810 ) {
811 if self.interner.is_identity_comparable_type(source)
817 && self.interner.is_identity_comparable_type(target)
818 {
819 return SubtypeResult::False;
820 }
821 let s_elems = self.interner.tuple_list(s_elems);
822 let t_elems = self.interner.tuple_list(t_elems);
823 return self.check_tuple_subtype(&s_elems, &t_elems);
824 }
825
826 if let (Some(s_elems), Some(t_elem)) = (
827 tuple_list_id(self.interner, source),
828 array_element_type(self.interner, target),
829 ) {
830 return self.check_tuple_to_array_subtype(s_elems, t_elem);
831 }
832
833 if let (Some(s_elem), Some(t_elems)) = (
834 array_element_type(self.interner, source),
835 tuple_list_id(self.interner, target),
836 ) {
837 let t_elems = self.interner.tuple_list(t_elems);
838 return self.check_array_to_tuple_subtype(s_elem, &t_elems);
839 }
840
841 if let (Some(s_shape_id), Some(t_shape_id)) = (
842 object_shape_id(self.interner, source),
843 object_shape_id(self.interner, target),
844 ) {
845 let s_shape = self.interner.object_shape(s_shape_id);
846 let t_shape = self.interner.object_shape(t_shape_id);
847
848 if let (Some(s_sym), Some(t_sym)) = (s_shape.symbol, t_shape.symbol)
856 && s_sym != t_sym
857 {
858 let sym_pair = (s_sym, t_sym);
859 if !self.sym_visiting.insert(sym_pair) {
860 return SubtypeResult::CycleDetected;
862 }
863 let result = self.check_object_subtype(&s_shape, Some(s_shape_id), &t_shape);
864 self.sym_visiting.remove(&sym_pair);
865 return result;
866 }
867
868 return self.check_object_subtype(&s_shape, Some(s_shape_id), &t_shape);
869 }
870
871 if let (Some(s_shape_id), Some(t_shape_id)) = (
872 object_with_index_shape_id(self.interner, source),
873 object_with_index_shape_id(self.interner, target),
874 ) {
875 let s_shape = self.interner.object_shape(s_shape_id);
876 let t_shape = self.interner.object_shape(t_shape_id);
877 return self.check_object_with_index_subtype(&s_shape, Some(s_shape_id), &t_shape);
878 }
879
880 if let (Some(s_shape_id), Some(t_shape_id)) = (
881 object_with_index_shape_id(self.interner, source),
882 object_shape_id(self.interner, target),
883 ) {
884 let s_shape = self.interner.object_shape(s_shape_id);
885 let t_shape = self.interner.object_shape(t_shape_id);
886 return self.check_object_with_index_to_object(
887 &s_shape,
888 s_shape_id,
889 &t_shape.properties,
890 );
891 }
892
893 if let (Some(s_shape_id), Some(t_shape_id)) = (
894 object_shape_id(self.interner, source),
895 object_with_index_shape_id(self.interner, target),
896 ) {
897 let s_shape = self.interner.object_shape(s_shape_id);
898 let t_shape = self.interner.object_shape(t_shape_id);
899 return self.check_object_to_indexed(&s_shape.properties, Some(s_shape_id), &t_shape);
900 }
901
902 if let (Some(s_fn_id), Some(t_fn_id)) = (
903 function_shape_id(self.interner, source),
904 function_shape_id(self.interner, target),
905 ) {
906 let s_fn = self.interner.function_shape(s_fn_id);
907 let t_fn = self.interner.function_shape(t_fn_id);
908 return self.check_function_subtype(&s_fn, &t_fn);
909 }
910
911 let source_function_like = function_shape_id(self.interner, source).is_some()
917 || callable_shape_id(self.interner, source).is_some_and(|sid| {
918 let shape = self.interner.callable_shape(sid);
919 !shape.call_signatures.is_empty()
920 })
921 || source == TypeId::FUNCTION;
922 if source_function_like {
923 if let Some(t_callable_id) = callable_shape_id(self.interner, target) {
924 let t_shape = self.interner.callable_shape(t_callable_id);
925 if t_shape.call_signatures.is_empty() && t_shape.construct_signatures.is_empty() {
926 let required_props: Vec<_> =
927 t_shape.properties.iter().filter(|p| !p.optional).collect();
928 if required_props.len() == 1 {
929 let name = self.interner.resolve_atom(required_props[0].name);
930 if name == "call" || name == "apply" {
931 return SubtypeResult::True;
932 }
933 }
934 }
935 }
936 if let Some(t_shape_id) = object_shape_id(self.interner, target)
937 .or_else(|| object_with_index_shape_id(self.interner, target))
938 {
939 let t_shape = self.interner.object_shape(t_shape_id);
940 let required_props: Vec<_> =
941 t_shape.properties.iter().filter(|p| !p.optional).collect();
942 if required_props.len() == 1 {
943 let name = self.interner.resolve_atom(required_props[0].name);
944 if name == "call" || name == "apply" {
945 return SubtypeResult::True;
946 }
947 }
948 }
949 }
950
951 if let (Some(s_callable_id), Some(t_callable_id)) = (
952 callable_shape_id(self.interner, source),
953 callable_shape_id(self.interner, target),
954 ) {
955 let s_callable = self.interner.callable_shape(s_callable_id);
956 let t_callable = self.interner.callable_shape(t_callable_id);
957 return self.check_callable_subtype(&s_callable, &t_callable);
958 }
959
960 if let (Some(s_fn_id), Some(t_callable_id)) = (
961 function_shape_id(self.interner, source),
962 callable_shape_id(self.interner, target),
963 ) {
964 return self.check_function_to_callable_subtype(s_fn_id, t_callable_id);
965 }
966
967 if let (Some(s_callable_id), Some(t_fn_id)) = (
968 callable_shape_id(self.interner, source),
969 function_shape_id(self.interner, target),
970 ) {
971 return self.check_callable_to_function_subtype(s_callable_id, t_fn_id);
972 }
973
974 if let (Some(s_app_id), Some(t_app_id)) = (
975 application_id(self.interner, source),
976 application_id(self.interner, target),
977 ) {
978 return self.check_application_to_application_subtype(s_app_id, t_app_id);
979 }
980
981 if let (Some(s_app_id), Some(t_app_id)) = (
986 application_id(self.interner, source),
987 application_id(self.interner, target),
988 ) {
989 let result = self.check_application_to_application(source, target, s_app_id, t_app_id);
990 if result != SubtypeResult::False {
991 return result;
992 }
993 }
995
996 if let Some(app_id) = application_id(self.interner, source) {
997 return self.check_application_expansion_target(source, target, app_id);
998 }
999
1000 if let Some(app_id) = application_id(self.interner, target) {
1001 return self.check_source_to_application_expansion(source, target, app_id);
1002 }
1003
1004 if let (Some(source_mapped_id), Some(target_mapped_id)) = (
1006 mapped_type_id(self.interner, source),
1007 mapped_type_id(self.interner, target),
1008 ) {
1009 let result =
1010 self.check_mapped_to_mapped(source, target, source_mapped_id, target_mapped_id);
1011 if result != SubtypeResult::False {
1012 return result;
1013 }
1014 }
1015
1016 if let Some(mapped_id) = mapped_type_id(self.interner, source) {
1017 return self.check_mapped_expansion_target(source, target, mapped_id);
1018 }
1019
1020 if let Some(mapped_id) = mapped_type_id(self.interner, target) {
1021 return self.check_source_to_mapped_expansion(source, target, mapped_id);
1022 }
1023
1024 if let (Some((s_def_id, _s_members)), Some((t_def_id, _t_members))) = (
1034 enum_components(self.interner, source),
1035 enum_components(self.interner, target),
1036 ) {
1037 if s_def_id == t_def_id {
1039 return SubtypeResult::True;
1040 }
1041
1042 if self.resolver.get_enum_parent_def_id(s_def_id) == Some(t_def_id) {
1045 if self.resolver.is_enum_type(target, self.interner) {
1048 return SubtypeResult::True;
1049 }
1050 }
1051
1052 if let Some(tracer) = &mut self.tracer
1055 && !tracer.on_mismatch_dyn(SubtypeFailureReason::TypeMismatch {
1056 source_type: source,
1057 target_type: target,
1058 })
1059 {
1060 return SubtypeResult::False;
1061 }
1062 return SubtypeResult::False;
1063 }
1064
1065 if let Some((_s_def_id, s_members)) = enum_components(self.interner, source) {
1067 return self.check_subtype(s_members, target);
1068 }
1069
1070 if let Some((t_def_id, t_members)) = enum_components(self.interner, target) {
1072 if source == TypeId::NUMBER && self.resolver.is_numeric_enum(t_def_id) {
1074 return SubtypeResult::True;
1075 }
1076 return self.check_subtype(source, t_members);
1079 }
1080
1081 if let (Some(s_def), Some(t_def)) = (
1090 lazy_def_id(self.interner, source),
1091 lazy_def_id(self.interner, target),
1092 ) {
1093 return self.check_lazy_lazy_subtype(source, target, s_def, t_def);
1095 }
1096
1097 let get_enum_def_id = |type_id: TypeId| -> Option<DefId> {
1106 match self.interner.lookup(type_id) {
1107 Some(TypeData::Enum(def_id, _)) | Some(TypeData::Lazy(def_id)) => Some(def_id),
1108 _ => None,
1109 }
1110 };
1111
1112 if let Some(s_def) = get_enum_def_id(source)
1114 && target == TypeId::NUMBER
1115 && self.resolver.is_numeric_enum(s_def)
1116 {
1117 return SubtypeResult::True;
1118 }
1119
1120 if let Some(t_def) = get_enum_def_id(target) {
1122 if source == TypeId::NUMBER && self.resolver.is_numeric_enum(t_def) {
1123 return SubtypeResult::True;
1124 }
1125 if matches!(
1127 self.interner.lookup(source),
1128 Some(TypeData::Literal(LiteralValue::Number(_)))
1129 ) && self.resolver.is_numeric_enum(t_def)
1130 {
1131 return self.check_subtype(source, self.resolve_lazy_type(target));
1134 }
1135 }
1136
1137 if lazy_def_id(self.interner, source).is_some() {
1138 let resolved = self.resolve_lazy_type(source);
1139 return if resolved != source {
1140 self.check_subtype(resolved, target)
1141 } else {
1142 SubtypeResult::False
1143 };
1144 }
1145
1146 if lazy_def_id(self.interner, target).is_some() {
1147 let resolved = self.resolve_lazy_type(target);
1148 return if resolved != target {
1149 self.check_subtype(source, resolved)
1150 } else {
1151 SubtypeResult::False
1152 };
1153 }
1154
1155 if let (Some(s_sym), Some(t_sym)) = (
1160 ref_symbol(self.interner, source),
1161 ref_symbol(self.interner, target),
1162 ) {
1163 return self.check_ref_ref_subtype(source, target, s_sym, t_sym);
1164 }
1165
1166 if let Some(s_sym) = ref_symbol(self.interner, source) {
1167 return self.check_ref_subtype(source, target, s_sym);
1168 }
1169
1170 if let Some(t_sym) = ref_symbol(self.interner, target) {
1171 return self.check_to_ref_subtype(source, target, t_sym);
1172 }
1173
1174 if let (Some(s_sym), Some(t_sym)) = (
1175 type_query_symbol(self.interner, source),
1176 type_query_symbol(self.interner, target),
1177 ) {
1178 return self.check_typequery_typequery_subtype(source, target, s_sym, t_sym);
1179 }
1180
1181 if let Some(s_sym) = type_query_symbol(self.interner, source) {
1182 return self.check_typequery_subtype(source, target, s_sym);
1183 }
1184
1185 if let Some(t_sym) = type_query_symbol(self.interner, target) {
1186 return self.check_to_typequery_subtype(source, target, t_sym);
1187 }
1188
1189 if let (Some(s_inner), Some(t_inner)) = (
1190 keyof_inner_type(self.interner, source),
1191 keyof_inner_type(self.interner, target),
1192 ) {
1193 return self.check_subtype(t_inner, s_inner);
1194 }
1195
1196 if let (Some(s_inner), Some(t_inner)) = (
1197 readonly_inner_type(self.interner, source),
1198 readonly_inner_type(self.interner, target),
1199 ) {
1200 return self.check_subtype(s_inner, t_inner);
1201 }
1202
1203 if let Some(t_inner) = readonly_inner_type(self.interner, target)
1208 && readonly_inner_type(self.interner, source).is_none()
1209 {
1210 return self.check_subtype(source, t_inner);
1211 }
1212
1213 if let (Some(s_sym), Some(t_sym)) = (
1217 unique_symbol_ref(self.interner, source),
1218 unique_symbol_ref(self.interner, target),
1219 ) {
1220 return if s_sym == t_sym {
1221 SubtypeResult::True
1222 } else {
1223 SubtypeResult::False
1224 };
1225 }
1226
1227 if unique_symbol_ref(self.interner, source).is_some()
1228 && intrinsic_kind(self.interner, target) == Some(IntrinsicKind::Symbol)
1229 {
1230 return SubtypeResult::True;
1231 }
1232
1233 if is_this_type(self.interner, source) && is_this_type(self.interner, target) {
1234 return SubtypeResult::True;
1235 }
1236
1237 if let (Some(s_spans), Some(t_spans)) = (
1238 template_literal_id(self.interner, source),
1239 template_literal_id(self.interner, target),
1240 ) {
1241 return self.check_template_assignable_to_template(s_spans, t_spans);
1242 }
1243
1244 if template_literal_id(self.interner, source).is_some()
1245 && intrinsic_kind(self.interner, target) == Some(IntrinsicKind::String)
1246 {
1247 return SubtypeResult::True;
1248 }
1249
1250 let source_is_callable = function_shape_id(self.interner, source).is_some()
1251 || callable_shape_id(self.interner, source).is_some();
1252 if source_is_callable {
1253 let source_props = if let Some(callable_id) = callable_shape_id(self.interner, source) {
1256 let callable = self.interner.callable_shape(callable_id);
1257 let mut props = callable.properties.clone();
1258 props.sort_by_key(|a| a.name);
1259 Some(ObjectShape {
1260 flags: ObjectFlags::empty(),
1261 properties: props,
1262 string_index: callable.string_index.clone(),
1263 number_index: callable.number_index.clone(),
1264 symbol: callable.symbol,
1265 })
1266 } else {
1267 None
1268 };
1269
1270 if let Some(t_shape_id) = object_shape_id(self.interner, target) {
1271 let t_shape = self.interner.object_shape(t_shape_id);
1272 if t_shape.properties.is_empty() {
1273 return SubtypeResult::True;
1274 }
1275 if let Some(ref s_shape) = source_props {
1277 return self.check_object_subtype(s_shape, None, &t_shape);
1278 }
1279 if let Some(tracer) = &mut self.tracer
1281 && !tracer.on_mismatch_dyn(SubtypeFailureReason::TypeMismatch {
1282 source_type: source,
1283 target_type: target,
1284 })
1285 {
1286 return SubtypeResult::False;
1287 }
1288 return SubtypeResult::False;
1289 }
1290 if let Some(t_shape_id) = object_with_index_shape_id(self.interner, target) {
1291 let t_shape = self.interner.object_shape(t_shape_id);
1292 if t_shape.properties.is_empty() && t_shape.string_index.is_none() {
1293 return SubtypeResult::True;
1294 }
1295 if let Some(ref s_shape) = source_props {
1297 return self.check_object_subtype(s_shape, None, &t_shape);
1298 }
1299 if let Some(tracer) = &mut self.tracer
1301 && !tracer.on_mismatch_dyn(SubtypeFailureReason::TypeMismatch {
1302 source_type: source,
1303 target_type: target,
1304 })
1305 {
1306 return SubtypeResult::False;
1307 }
1308 return SubtypeResult::False;
1309 }
1310 }
1311
1312 let source_is_array_or_tuple = array_element_type(self.interner, source).is_some()
1313 || tuple_list_id(self.interner, source).is_some();
1314 if source_is_array_or_tuple {
1315 if let Some(t_shape_id) = object_shape_id(self.interner, target) {
1316 let t_shape = self.interner.object_shape(t_shape_id);
1317 if t_shape.properties.is_empty() {
1318 return SubtypeResult::True;
1319 }
1320 let only_length = t_shape
1323 .properties
1324 .iter()
1325 .all(|p| self.interner.resolve_atom(p.name) == "length");
1326 if only_length {
1327 let all_ok = t_shape
1328 .properties
1329 .iter()
1330 .all(|p| self.check_subtype(TypeId::NUMBER, p.type_id).is_true());
1331 if all_ok {
1332 return SubtypeResult::True;
1333 }
1334 }
1335 if let Some(elem) = array_element_type(self.interner, source)
1338 && let Some(result) = self.check_array_interface_subtype(elem, target)
1339 {
1340 return result;
1341 }
1342 if let Some(tracer) = &mut self.tracer
1344 && !tracer.on_mismatch_dyn(SubtypeFailureReason::TypeMismatch {
1345 source_type: source,
1346 target_type: target,
1347 })
1348 {
1349 return SubtypeResult::False;
1350 }
1351 return SubtypeResult::False;
1352 }
1353 if let Some(t_shape_id) = object_with_index_shape_id(self.interner, target) {
1354 let t_shape = self.interner.object_shape(t_shape_id);
1355 if t_shape.properties.is_empty() && t_shape.string_index.is_none() {
1356 if let Some(ref num_idx) = t_shape.number_index {
1357 let elem_type =
1358 array_element_type(self.interner, source).unwrap_or(TypeId::ANY);
1359 if !self.check_subtype(elem_type, num_idx.value_type).is_true() {
1360 if let Some(tracer) = &mut self.tracer
1362 && !tracer.on_mismatch_dyn(
1363 SubtypeFailureReason::IndexSignatureMismatch {
1364 index_kind: "number",
1365 source_value_type: elem_type,
1366 target_value_type: num_idx.value_type,
1367 },
1368 )
1369 {
1370 return SubtypeResult::False;
1371 }
1372 return SubtypeResult::False;
1373 }
1374 }
1375 return SubtypeResult::True;
1376 }
1377 if let Some(elem) = array_element_type(self.interner, source)
1380 && let Some(result) = self.check_array_interface_subtype(elem, target)
1381 {
1382 return result;
1383 }
1384 if let Some(tracer) = &mut self.tracer
1386 && !tracer.on_mismatch_dyn(SubtypeFailureReason::TypeMismatch {
1387 source_type: source,
1388 target_type: target,
1389 })
1390 {
1391 return SubtypeResult::False;
1392 }
1393 return SubtypeResult::False;
1394 }
1395 }
1396
1397 let interner = self.interner;
1409
1410 let mut visitor = SubtypeVisitor {
1412 checker: self,
1413 source,
1414 target,
1415 };
1416
1417 let result = visitor.visit_type(interner, source);
1419
1420 if result == SubtypeResult::False && self.check_generic_index_access_subtype(source, target)
1421 {
1422 return SubtypeResult::True;
1423 }
1424
1425 if result == SubtypeResult::False
1427 && let Some(tracer) = &mut self.tracer
1428 && !tracer.on_mismatch_dyn(SubtypeFailureReason::TypeMismatch {
1429 source_type: source,
1430 target_type: target,
1431 })
1432 {
1433 return SubtypeResult::False;
1434 }
1435
1436 result
1437 }
1438
1439 fn is_keyof_subtype_of_string_number_symbol_union(&self, members: TypeListId) -> bool {
1444 let member_list = self.interner.type_list(members);
1445 let mut has_string = false;
1447 let mut has_number = false;
1448 let mut has_symbol = false;
1449 for &member in member_list.iter() {
1450 if member == TypeId::STRING {
1451 has_string = true;
1452 } else if member == TypeId::NUMBER {
1453 has_number = true;
1454 } else if member == TypeId::SYMBOL {
1455 has_symbol = true;
1456 }
1457 }
1458 has_string && has_number && has_symbol
1459 }
1460}
1461
1462pub fn is_subtype_of(interner: &dyn TypeDatabase, source: TypeId, target: TypeId) -> bool {
1464 let mut checker = SubtypeChecker::new(interner);
1465 checker.is_subtype_of(source, target)
1466}
1467
1468impl<'a, R: TypeResolver> AssignabilityChecker for SubtypeChecker<'a, R> {
1469 fn is_assignable_to(&mut self, source: TypeId, target: TypeId) -> bool {
1470 SubtypeChecker::is_assignable_to(self, source, target)
1471 }
1472
1473 fn is_assignable_to_bivariant_callback(&mut self, source: TypeId, target: TypeId) -> bool {
1474 let prev_strict = self.strict_function_types;
1475 let prev_param_count = self.allow_bivariant_param_count;
1476 self.strict_function_types = false;
1477 self.allow_bivariant_param_count = true;
1478 let result = SubtypeChecker::is_assignable_to(self, source, target);
1479 self.allow_bivariant_param_count = prev_param_count;
1480 self.strict_function_types = prev_strict;
1481 result
1482 }
1483
1484 fn evaluate_type(&mut self, type_id: TypeId) -> TypeId {
1485 SubtypeChecker::evaluate_type(self, type_id)
1486 }
1487}
1488
1489pub fn are_types_structurally_identical<R: TypeResolver>(
1494 interner: &dyn TypeDatabase,
1495 resolver: &R,
1496 a: TypeId,
1497 b: TypeId,
1498) -> bool {
1499 if a == b {
1500 return true;
1501 }
1502 let mut canonicalizer = crate::canonicalize::Canonicalizer::new(interner, resolver);
1503 let canon_a = canonicalizer.canonicalize(a);
1504 let canon_b = canonicalizer.canonicalize(b);
1505
1506 canon_a == canon_b
1508}
1509
1510pub fn is_subtype_of_with_db(db: &dyn QueryDatabase, source: TypeId, target: TypeId) -> bool {
1513 let mut checker = SubtypeChecker::new(db.as_type_database()).with_query_db(db);
1514 checker.is_subtype_of(source, target)
1515}
1516
1517pub fn is_subtype_of_with_flags(
1520 interner: &dyn TypeDatabase,
1521 source: TypeId,
1522 target: TypeId,
1523 flags: u16,
1524) -> bool {
1525 let mut checker = SubtypeChecker::new(interner).apply_flags(flags);
1526 checker.is_subtype_of(source, target)
1527}
1528
1529#[cfg(test)]
1531#[path = "../../tests/subtype_tests.rs"]
1532mod tests;
1533
1534#[cfg(test)]
1535#[path = "../../tests/index_signature_tests.rs"]
1536mod index_signature_tests;
1537
1538#[cfg(test)]
1539#[path = "../../tests/generics_rules_tests.rs"]
1540mod generics_rules_tests;
1541
1542#[cfg(test)]
1543#[path = "../../tests/callable_tests.rs"]
1544mod callable_tests;
1545
1546#[cfg(test)]
1547#[path = "../../tests/union_tests.rs"]
1548mod union_tests;
1549
1550#[cfg(test)]
1551#[path = "../../tests/typescript_quirks_tests.rs"]
1552mod typescript_quirks_tests;
1553
1554#[cfg(test)]
1555#[path = "../../tests/type_predicate_tests.rs"]
1556mod type_predicate_tests;
1557
1558#[cfg(test)]
1559#[path = "../../tests/overlap_tests.rs"]
1560mod overlap_tests;