1use crate::ObjectLiteralBuilder;
7use crate::def::DefId;
8use crate::element_access::{ElementAccessEvaluator, ElementAccessResult};
9use crate::intern::TypeInterner;
10use crate::narrowing;
11use crate::operations_property::PropertyAccessResult;
12use crate::subtype::TypeResolver;
13use crate::type_factory::TypeFactory;
14use crate::types::{
15 CallableShape, CallableShapeId, ConditionalType, ConditionalTypeId, FunctionShape,
16 FunctionShapeId, IndexInfo, IntrinsicKind, MappedType, MappedTypeId, ObjectFlags, ObjectShape,
17 ObjectShapeId, PropertyInfo, PropertyLookup, RelationCacheKey, StringIntrinsicKind, SymbolRef,
18 TemplateLiteralId, TemplateSpan, TupleElement, TupleListId, TypeApplication, TypeApplicationId,
19 TypeData, TypeId, TypeListId, TypeParamInfo, Variance,
20};
21use rustc_hash::{FxHashMap, FxHashSet};
22use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
23use std::sync::{Arc, RwLock};
24use tsz_binder::SymbolId;
25use tsz_common::interner::Atom;
26
27pub trait TypeDatabase {
32 fn intern(&self, key: TypeData) -> TypeId;
33 fn lookup(&self, id: TypeId) -> Option<TypeData>;
34 fn intern_string(&self, s: &str) -> Atom;
35 fn resolve_atom(&self, atom: Atom) -> String;
36 fn resolve_atom_ref(&self, atom: Atom) -> Arc<str>;
37 fn type_list(&self, id: TypeListId) -> Arc<[TypeId]>;
38 fn tuple_list(&self, id: TupleListId) -> Arc<[TupleElement]>;
39 fn template_list(&self, id: TemplateLiteralId) -> Arc<[TemplateSpan]>;
40 fn object_shape(&self, id: ObjectShapeId) -> Arc<ObjectShape>;
41 fn object_property_index(&self, shape_id: ObjectShapeId, name: Atom) -> PropertyLookup;
42 fn function_shape(&self, id: FunctionShapeId) -> Arc<FunctionShape>;
43 fn callable_shape(&self, id: CallableShapeId) -> Arc<CallableShape>;
44 fn conditional_type(&self, id: ConditionalTypeId) -> Arc<ConditionalType>;
45 fn mapped_type(&self, id: MappedTypeId) -> Arc<MappedType>;
46 fn type_application(&self, id: TypeApplicationId) -> Arc<TypeApplication>;
47
48 fn literal_string(&self, value: &str) -> TypeId;
49 fn literal_number(&self, value: f64) -> TypeId;
50 fn literal_boolean(&self, value: bool) -> TypeId;
51 fn literal_bigint(&self, value: &str) -> TypeId;
52 fn literal_bigint_with_sign(&self, negative: bool, digits: &str) -> TypeId;
53
54 fn union(&self, members: Vec<TypeId>) -> TypeId;
55 fn union_from_sorted_vec(&self, flat: Vec<TypeId>) -> TypeId;
56 fn union2(&self, left: TypeId, right: TypeId) -> TypeId;
57 fn union3(&self, first: TypeId, second: TypeId, third: TypeId) -> TypeId;
58 fn intersection(&self, members: Vec<TypeId>) -> TypeId;
59 fn intersection2(&self, left: TypeId, right: TypeId) -> TypeId;
60 fn intersect_types_raw2(&self, left: TypeId, right: TypeId) -> TypeId;
62 fn array(&self, element: TypeId) -> TypeId;
63 fn tuple(&self, elements: Vec<TupleElement>) -> TypeId;
64 fn object(&self, properties: Vec<PropertyInfo>) -> TypeId;
65 fn object_with_flags(&self, properties: Vec<PropertyInfo>, flags: ObjectFlags) -> TypeId;
66 fn object_with_flags_and_symbol(
67 &self,
68 properties: Vec<PropertyInfo>,
69 flags: ObjectFlags,
70 symbol: Option<SymbolId>,
71 ) -> TypeId;
72 fn object_fresh(&self, properties: Vec<PropertyInfo>) -> TypeId {
73 self.object_with_flags(properties, ObjectFlags::FRESH_LITERAL)
74 }
75 fn object_with_index(&self, shape: ObjectShape) -> TypeId;
76 fn function(&self, shape: FunctionShape) -> TypeId;
77 fn callable(&self, shape: CallableShape) -> TypeId;
78 fn template_literal(&self, spans: Vec<TemplateSpan>) -> TypeId;
79 fn conditional(&self, conditional: ConditionalType) -> TypeId;
80 fn mapped(&self, mapped: MappedType) -> TypeId;
81 fn reference(&self, symbol: SymbolRef) -> TypeId;
82 fn lazy(&self, def_id: DefId) -> TypeId;
83 fn bound_parameter(&self, index: u32) -> TypeId;
84 fn recursive(&self, depth: u32) -> TypeId;
85 fn type_param(&self, info: TypeParamInfo) -> TypeId;
86 fn type_query(&self, symbol: SymbolRef) -> TypeId;
87 fn enum_type(&self, def_id: DefId, structural_type: TypeId) -> TypeId;
88 fn application(&self, base: TypeId, args: Vec<TypeId>) -> TypeId;
89
90 fn literal_string_atom(&self, atom: Atom) -> TypeId;
91 fn union_preserve_members(&self, members: Vec<TypeId>) -> TypeId;
92 fn readonly_type(&self, inner: TypeId) -> TypeId;
93 fn keyof(&self, inner: TypeId) -> TypeId;
94 fn index_access(&self, object_type: TypeId, index_type: TypeId) -> TypeId;
95 fn this_type(&self) -> TypeId;
96 fn no_infer(&self, inner: TypeId) -> TypeId;
97 fn unique_symbol(&self, symbol: SymbolRef) -> TypeId;
98 fn infer(&self, info: TypeParamInfo) -> TypeId;
99 fn string_intrinsic(&self, kind: StringIntrinsicKind, type_arg: TypeId) -> TypeId;
100
101 fn get_class_base_type(&self, symbol_id: SymbolId) -> Option<TypeId>;
105
106 fn is_unit_type(&self, type_id: TypeId) -> bool;
111}
112
113impl TypeDatabase for TypeInterner {
114 fn intern(&self, key: TypeData) -> TypeId {
115 Self::intern(self, key)
116 }
117
118 fn lookup(&self, id: TypeId) -> Option<TypeData> {
119 Self::lookup(self, id)
120 }
121
122 fn intern_string(&self, s: &str) -> Atom {
123 Self::intern_string(self, s)
124 }
125
126 fn resolve_atom(&self, atom: Atom) -> String {
127 Self::resolve_atom(self, atom)
128 }
129
130 fn resolve_atom_ref(&self, atom: Atom) -> Arc<str> {
131 Self::resolve_atom_ref(self, atom)
132 }
133
134 fn type_list(&self, id: TypeListId) -> Arc<[TypeId]> {
135 Self::type_list(self, id)
136 }
137
138 fn tuple_list(&self, id: TupleListId) -> Arc<[TupleElement]> {
139 Self::tuple_list(self, id)
140 }
141
142 fn template_list(&self, id: TemplateLiteralId) -> Arc<[TemplateSpan]> {
143 Self::template_list(self, id)
144 }
145
146 fn object_shape(&self, id: ObjectShapeId) -> Arc<ObjectShape> {
147 Self::object_shape(self, id)
148 }
149
150 fn object_property_index(&self, shape_id: ObjectShapeId, name: Atom) -> PropertyLookup {
151 Self::object_property_index(self, shape_id, name)
152 }
153
154 fn function_shape(&self, id: FunctionShapeId) -> Arc<FunctionShape> {
155 Self::function_shape(self, id)
156 }
157
158 fn callable_shape(&self, id: CallableShapeId) -> Arc<CallableShape> {
159 Self::callable_shape(self, id)
160 }
161
162 fn conditional_type(&self, id: ConditionalTypeId) -> Arc<ConditionalType> {
163 Self::conditional_type(self, id)
164 }
165
166 fn mapped_type(&self, id: MappedTypeId) -> Arc<MappedType> {
167 Self::mapped_type(self, id)
168 }
169
170 fn type_application(&self, id: TypeApplicationId) -> Arc<TypeApplication> {
171 Self::type_application(self, id)
172 }
173
174 fn literal_string(&self, value: &str) -> TypeId {
175 Self::literal_string(self, value)
176 }
177
178 fn literal_number(&self, value: f64) -> TypeId {
179 Self::literal_number(self, value)
180 }
181
182 fn literal_boolean(&self, value: bool) -> TypeId {
183 Self::literal_boolean(self, value)
184 }
185
186 fn literal_bigint(&self, value: &str) -> TypeId {
187 Self::literal_bigint(self, value)
188 }
189
190 fn literal_bigint_with_sign(&self, negative: bool, digits: &str) -> TypeId {
191 Self::literal_bigint_with_sign(self, negative, digits)
192 }
193
194 fn union(&self, members: Vec<TypeId>) -> TypeId {
195 Self::union(self, members)
196 }
197
198 fn union_from_sorted_vec(&self, flat: Vec<TypeId>) -> TypeId {
199 Self::union_from_sorted_vec(self, flat)
200 }
201
202 fn union2(&self, left: TypeId, right: TypeId) -> TypeId {
203 Self::union2(self, left, right)
204 }
205
206 fn union3(&self, first: TypeId, second: TypeId, third: TypeId) -> TypeId {
207 Self::union3(self, first, second, third)
208 }
209
210 fn intersection(&self, members: Vec<TypeId>) -> TypeId {
211 Self::intersection(self, members)
212 }
213
214 fn intersection2(&self, left: TypeId, right: TypeId) -> TypeId {
215 Self::intersection2(self, left, right)
216 }
217
218 fn intersect_types_raw2(&self, left: TypeId, right: TypeId) -> TypeId {
219 Self::intersect_types_raw2(self, left, right)
220 }
221
222 fn array(&self, element: TypeId) -> TypeId {
223 Self::array(self, element)
224 }
225
226 fn tuple(&self, elements: Vec<TupleElement>) -> TypeId {
227 Self::tuple(self, elements)
228 }
229
230 fn object(&self, properties: Vec<PropertyInfo>) -> TypeId {
231 Self::object(self, properties)
232 }
233
234 fn object_with_flags(&self, properties: Vec<PropertyInfo>, flags: ObjectFlags) -> TypeId {
235 Self::object_with_flags(self, properties, flags)
236 }
237
238 fn object_with_flags_and_symbol(
239 &self,
240 properties: Vec<PropertyInfo>,
241 flags: ObjectFlags,
242 symbol: Option<SymbolId>,
243 ) -> TypeId {
244 Self::object_with_flags_and_symbol(self, properties, flags, symbol)
245 }
246
247 fn object_with_index(&self, shape: ObjectShape) -> TypeId {
248 Self::object_with_index(self, shape)
249 }
250
251 fn function(&self, shape: FunctionShape) -> TypeId {
252 Self::function(self, shape)
253 }
254
255 fn callable(&self, shape: CallableShape) -> TypeId {
256 Self::callable(self, shape)
257 }
258
259 fn template_literal(&self, spans: Vec<TemplateSpan>) -> TypeId {
260 Self::template_literal(self, spans)
261 }
262
263 fn conditional(&self, conditional: ConditionalType) -> TypeId {
264 Self::conditional(self, conditional)
265 }
266
267 fn mapped(&self, mapped: MappedType) -> TypeId {
268 Self::mapped(self, mapped)
269 }
270
271 fn reference(&self, symbol: SymbolRef) -> TypeId {
272 Self::reference(self, symbol)
273 }
274
275 fn lazy(&self, def_id: DefId) -> TypeId {
276 Self::lazy(self, def_id)
277 }
278
279 fn bound_parameter(&self, index: u32) -> TypeId {
280 Self::bound_parameter(self, index)
281 }
282
283 fn recursive(&self, depth: u32) -> TypeId {
284 Self::recursive(self, depth)
285 }
286
287 fn type_param(&self, info: TypeParamInfo) -> TypeId {
288 Self::type_param(self, info)
289 }
290
291 fn type_query(&self, symbol: SymbolRef) -> TypeId {
292 Self::type_query(self, symbol)
293 }
294
295 fn enum_type(&self, def_id: DefId, structural_type: TypeId) -> TypeId {
296 Self::enum_type(self, def_id, structural_type)
297 }
298
299 fn application(&self, base: TypeId, args: Vec<TypeId>) -> TypeId {
300 Self::application(self, base, args)
301 }
302
303 fn literal_string_atom(&self, atom: Atom) -> TypeId {
304 Self::literal_string_atom(self, atom)
305 }
306
307 fn union_preserve_members(&self, members: Vec<TypeId>) -> TypeId {
308 Self::union_preserve_members(self, members)
309 }
310
311 fn readonly_type(&self, inner: TypeId) -> TypeId {
312 Self::readonly_type(self, inner)
313 }
314
315 fn keyof(&self, inner: TypeId) -> TypeId {
316 Self::keyof(self, inner)
317 }
318
319 fn index_access(&self, object_type: TypeId, index_type: TypeId) -> TypeId {
320 Self::index_access(self, object_type, index_type)
321 }
322
323 fn this_type(&self) -> TypeId {
324 Self::this_type(self)
325 }
326
327 fn no_infer(&self, inner: TypeId) -> TypeId {
328 Self::no_infer(self, inner)
329 }
330
331 fn unique_symbol(&self, symbol: SymbolRef) -> TypeId {
332 Self::unique_symbol(self, symbol)
333 }
334
335 fn infer(&self, info: TypeParamInfo) -> TypeId {
336 Self::infer(self, info)
337 }
338
339 fn string_intrinsic(&self, kind: StringIntrinsicKind, type_arg: TypeId) -> TypeId {
340 Self::string_intrinsic(self, kind, type_arg)
341 }
342
343 fn get_class_base_type(&self, _symbol_id: SymbolId) -> Option<TypeId> {
344 None
347 }
348
349 fn is_unit_type(&self, type_id: TypeId) -> bool {
350 Self::is_unit_type(self, type_id)
351 }
352}
353
354impl TypeResolver for TypeInterner {
361 fn resolve_ref(&self, _symbol: SymbolRef, _interner: &dyn TypeDatabase) -> Option<TypeId> {
362 None
363 }
364
365 fn resolve_lazy(&self, _def_id: DefId, _interner: &dyn TypeDatabase) -> Option<TypeId> {
366 None
367 }
368
369 fn get_type_params(&self, _symbol: SymbolRef) -> Option<Vec<TypeParamInfo>> {
370 None
371 }
372
373 fn get_lazy_type_params(&self, _def_id: DefId) -> Option<Vec<TypeParamInfo>> {
374 None
375 }
376
377 fn def_to_symbol_id(&self, _def_id: DefId) -> Option<SymbolId> {
378 None
379 }
380
381 fn symbol_to_def_id(&self, _symbol: SymbolRef) -> Option<DefId> {
382 None
383 }
384
385 fn get_boxed_type(&self, kind: IntrinsicKind) -> Option<TypeId> {
386 TypeInterner::get_boxed_type(self, kind)
387 }
388
389 fn get_array_base_type(&self) -> Option<TypeId> {
390 self.get_array_base_type()
391 }
392
393 fn get_array_base_type_params(&self) -> &[TypeParamInfo] {
394 self.get_array_base_type_params()
395 }
396}
397
398pub trait QueryDatabase: TypeDatabase + TypeResolver {
403 fn as_type_database(&self) -> &dyn TypeDatabase;
405
406 #[inline]
408 fn factory(&self) -> TypeFactory<'_> {
409 TypeFactory::new(self.as_type_database())
410 }
411
412 fn register_array_base_type(&self, _type_id: TypeId, _type_params: Vec<TypeParamInfo>) {}
419
420 fn register_boxed_type(&self, _kind: IntrinsicKind, _type_id: TypeId) {}
426
427 fn evaluate_conditional(&self, cond: &ConditionalType) -> TypeId {
428 crate::evaluate::evaluate_conditional(self.as_type_database(), cond)
429 }
430
431 fn evaluate_index_access(&self, object_type: TypeId, index_type: TypeId) -> TypeId {
432 self.evaluate_index_access_with_options(
433 object_type,
434 index_type,
435 self.no_unchecked_indexed_access(),
436 )
437 }
438
439 fn evaluate_index_access_with_options(
440 &self,
441 object_type: TypeId,
442 index_type: TypeId,
443 no_unchecked_indexed_access: bool,
444 ) -> TypeId {
445 crate::evaluate::evaluate_index_access_with_options(
446 self.as_type_database(),
447 object_type,
448 index_type,
449 no_unchecked_indexed_access,
450 )
451 }
452
453 fn evaluate_type(&self, type_id: TypeId) -> TypeId {
454 crate::evaluate::evaluate_type(self.as_type_database(), type_id)
455 }
456
457 fn evaluate_type_with_options(
458 &self,
459 type_id: TypeId,
460 no_unchecked_indexed_access: bool,
461 ) -> TypeId {
462 if !no_unchecked_indexed_access {
463 return self.evaluate_type(type_id);
464 }
465
466 let mut evaluator = crate::evaluate::TypeEvaluator::new(self.as_type_database());
467 evaluator.set_no_unchecked_indexed_access(no_unchecked_indexed_access);
468 evaluator.evaluate(type_id)
469 }
470
471 fn evaluate_mapped(&self, mapped: &MappedType) -> TypeId {
472 crate::evaluate::evaluate_mapped(self.as_type_database(), mapped)
473 }
474
475 fn lookup_application_eval_cache(
477 &self,
478 _def_id: DefId,
479 _args: &[TypeId],
480 _no_unchecked_indexed_access: bool,
481 ) -> Option<TypeId> {
482 None
483 }
484
485 fn insert_application_eval_cache(
487 &self,
488 _def_id: DefId,
489 _args: &[TypeId],
490 _no_unchecked_indexed_access: bool,
491 _result: TypeId,
492 ) {
493 }
494
495 fn evaluate_keyof(&self, operand: TypeId) -> TypeId {
496 crate::evaluate::evaluate_keyof(self.as_type_database(), operand)
497 }
498
499 fn narrow(&self, type_id: TypeId, narrower: TypeId) -> TypeId
500 where
501 Self: Sized,
502 {
503 crate::narrowing::NarrowingContext::new(self).narrow(type_id, narrower)
504 }
505
506 fn resolve_property_access(
507 &self,
508 object_type: TypeId,
509 prop_name: &str,
510 ) -> crate::operations_property::PropertyAccessResult;
511
512 fn resolve_property_access_with_options(
513 &self,
514 object_type: TypeId,
515 prop_name: &str,
516 no_unchecked_indexed_access: bool,
517 ) -> crate::operations_property::PropertyAccessResult;
518
519 fn property_access_type(
520 &self,
521 object_type: TypeId,
522 prop_name: &str,
523 ) -> crate::operations_property::PropertyAccessResult {
524 self.resolve_property_access_with_options(
525 object_type,
526 prop_name,
527 self.no_unchecked_indexed_access(),
528 )
529 }
530
531 fn no_unchecked_indexed_access(&self) -> bool {
532 false
533 }
534
535 fn set_no_unchecked_indexed_access(&self, _enabled: bool) {}
536
537 fn contextual_property_type(&self, expected: TypeId, prop_name: &str) -> Option<TypeId> {
538 let ctx = crate::ContextualTypeContext::with_expected(self.as_type_database(), expected);
539 ctx.get_property_type(prop_name)
540 }
541
542 fn is_property_readonly(&self, object_type: TypeId, prop_name: &str) -> bool {
543 crate::operations_property::property_is_readonly(
544 self.as_type_database(),
545 object_type,
546 prop_name,
547 )
548 }
549
550 fn is_readonly_index_signature(
551 &self,
552 object_type: TypeId,
553 wants_string: bool,
554 wants_number: bool,
555 ) -> bool {
556 crate::operations_property::is_readonly_index_signature(
557 self.as_type_database(),
558 object_type,
559 wants_string,
560 wants_number,
561 )
562 }
563
564 fn resolve_element_access(
566 &self,
567 object_type: TypeId,
568 index_type: TypeId,
569 literal_index: Option<usize>,
570 ) -> ElementAccessResult {
571 let evaluator = ElementAccessEvaluator::new(self.as_type_database());
572 evaluator.resolve_element_access(object_type, index_type, literal_index)
573 }
574
575 fn resolve_element_access_type(
577 &self,
578 object_type: TypeId,
579 index_type: TypeId,
580 literal_index: Option<usize>,
581 ) -> TypeId {
582 match self.resolve_element_access(object_type, index_type, literal_index) {
583 crate::element_access::ElementAccessResult::Success(type_id) => type_id,
584 _ => TypeId::ERROR,
585 }
586 }
587
588 fn collect_object_spread_properties(&self, spread_type: TypeId) -> Vec<PropertyInfo> {
590 let builder = ObjectLiteralBuilder::new(self.as_type_database());
591 builder.collect_spread_properties(spread_type)
592 }
593
594 fn get_index_signatures(&self, type_id: TypeId) -> IndexInfo;
596
597 fn is_nullish_type(&self, type_id: TypeId) -> bool;
599
600 fn remove_nullish(&self, type_id: TypeId) -> TypeId;
602
603 fn canonical_id(&self, type_id: TypeId) -> TypeId;
616
617 fn is_subtype_of(&self, source: TypeId, target: TypeId) -> bool {
629 self.is_subtype_of_with_flags(source, target, 0)
632 }
633
634 fn is_subtype_of_with_flags(&self, source: TypeId, target: TypeId, flags: u16) -> bool {
638 crate::subtype::is_subtype_of_with_flags(self.as_type_database(), source, target, flags)
641 }
642
643 fn is_assignable_to(&self, source: TypeId, target: TypeId) -> bool {
658 self.is_assignable_to_with_flags(source, target, 0)
661 }
662
663 fn is_assignable_to_with_flags(&self, source: TypeId, target: TypeId, flags: u16) -> bool;
667
668 fn lookup_subtype_cache(&self, _key: RelationCacheKey) -> Option<bool> {
672 None
673 }
674
675 fn insert_subtype_cache(&self, _key: RelationCacheKey, _result: bool) {}
678
679 fn lookup_assignability_cache(&self, _key: RelationCacheKey) -> Option<bool> {
683 None
684 }
685
686 fn insert_assignability_cache(&self, _key: RelationCacheKey, _result: bool) {}
689
690 fn new_inference_context(&self) -> crate::infer::InferenceContext<'_> {
691 crate::infer::InferenceContext::new(self.as_type_database())
692 }
693
694 fn get_type_param_variance(&self, def_id: DefId) -> Option<Arc<[Variance]>>;
699}
700
701impl QueryDatabase for TypeInterner {
702 fn as_type_database(&self) -> &dyn TypeDatabase {
703 self
704 }
705
706 fn register_array_base_type(&self, type_id: TypeId, type_params: Vec<TypeParamInfo>) {
707 self.set_array_base_type(type_id, type_params);
708 }
709
710 fn register_boxed_type(&self, kind: IntrinsicKind, type_id: TypeId) {
711 TypeInterner::set_boxed_type(self, kind, type_id);
712 }
713
714 fn get_index_signatures(&self, type_id: TypeId) -> IndexInfo {
715 match self.lookup(type_id) {
716 Some(TypeData::ObjectWithIndex(shape_id)) => {
717 let shape = self.object_shape(shape_id);
718 IndexInfo {
719 string_index: shape.string_index.clone(),
720 number_index: shape.number_index.clone(),
721 }
722 }
723 Some(TypeData::Array(element)) => {
724 IndexInfo {
726 string_index: None,
727 number_index: Some(crate::types::IndexSignature {
728 key_type: TypeId::NUMBER,
729 value_type: element,
730 readonly: false,
731 }),
732 }
733 }
734 Some(TypeData::Tuple(elements_id)) => {
735 let elements = self.tuple_list(elements_id);
737 let element_types: Vec<TypeId> = elements.iter().map(|e| e.type_id).collect();
738 let value_type = if element_types.is_empty() {
739 TypeId::UNDEFINED
740 } else if element_types.len() == 1 {
741 element_types[0]
742 } else {
743 self.union(element_types)
744 };
745 IndexInfo {
746 string_index: None,
747 number_index: Some(crate::types::IndexSignature {
748 key_type: TypeId::NUMBER,
749 value_type,
750 readonly: false,
751 }),
752 }
753 }
754 Some(TypeData::Union(members_id)) => {
755 let members = self.type_list(members_id);
757 let mut string_indices = Vec::new();
758 let mut number_indices = Vec::new();
759
760 for &member in members.iter() {
761 let info = self.get_index_signatures(member);
762 if let Some(sig) = info.string_index {
763 string_indices.push(sig);
764 }
765 if let Some(sig) = info.number_index {
766 number_indices.push(sig);
767 }
768 }
769
770 let string_index = if string_indices.is_empty() {
772 None
773 } else {
774 Some(crate::types::IndexSignature {
775 key_type: TypeId::STRING,
776 value_type: self
777 .union(string_indices.iter().map(|s| s.value_type).collect()),
778 readonly: string_indices.iter().all(|s| s.readonly),
779 })
780 };
781
782 let number_index = if number_indices.is_empty() {
783 None
784 } else {
785 Some(crate::types::IndexSignature {
786 key_type: TypeId::NUMBER,
787 value_type: self
788 .union(number_indices.iter().map(|s| s.value_type).collect()),
789 readonly: number_indices.iter().all(|s| s.readonly),
790 })
791 };
792
793 IndexInfo {
794 string_index,
795 number_index,
796 }
797 }
798 Some(TypeData::Intersection(members_id)) => {
799 let members = self.type_list(members_id);
801 let mut string_index = None;
802 let mut number_index = None;
803
804 for &member in members.iter() {
805 let info = self.get_index_signatures(member);
806 if let Some(sig) = info.string_index {
807 string_index = Some(sig);
808 }
809 if let Some(sig) = info.number_index {
810 number_index = Some(sig);
811 }
812 }
813
814 IndexInfo {
815 string_index,
816 number_index,
817 }
818 }
819 _ => IndexInfo::default(),
820 }
821 }
822
823 fn is_nullish_type(&self, type_id: TypeId) -> bool {
824 narrowing::is_nullish_type(self, type_id)
825 }
826
827 fn remove_nullish(&self, type_id: TypeId) -> TypeId {
828 narrowing::remove_nullish(self, type_id)
829 }
830
831 fn is_assignable_to(&self, source: TypeId, target: TypeId) -> bool {
832 self.is_assignable_to_with_flags(source, target, 0)
834 }
835
836 fn is_assignable_to_with_flags(&self, source: TypeId, target: TypeId, flags: u16) -> bool {
837 use crate::compat::CompatChecker;
838 let mut checker = CompatChecker::new(self);
839 if flags != 0 {
840 checker.apply_flags(flags);
841 }
842 checker.is_assignable(source, target)
843 }
844
845 fn resolve_property_access(
846 &self,
847 object_type: TypeId,
848 prop_name: &str,
849 ) -> crate::operations_property::PropertyAccessResult {
850 let evaluator = crate::operations_property::PropertyAccessEvaluator::new(self);
853 evaluator.resolve_property_access(object_type, prop_name)
854 }
855
856 fn resolve_property_access_with_options(
857 &self,
858 object_type: TypeId,
859 prop_name: &str,
860 no_unchecked_indexed_access: bool,
861 ) -> crate::operations_property::PropertyAccessResult {
862 let mut evaluator = crate::operations_property::PropertyAccessEvaluator::new(self);
863 evaluator.set_no_unchecked_indexed_access(no_unchecked_indexed_access);
864 evaluator.resolve_property_access(object_type, prop_name)
865 }
866
867 fn get_type_param_variance(&self, _def_id: DefId) -> Option<Arc<[Variance]>> {
868 None
871 }
872
873 fn canonical_id(&self, type_id: TypeId) -> TypeId {
874 use crate::canonicalize::Canonicalizer;
876 let mut canon = Canonicalizer::new(self, self);
877 canon.canonicalize(type_id)
878 }
879}
880
881type EvalCacheKey = (TypeId, bool);
882type ApplicationEvalCacheKey = (DefId, Vec<TypeId>, bool);
883type ElementAccessTypeCacheKey = (TypeId, TypeId, Option<u32>, bool);
884type PropertyAccessCacheKey = (TypeId, Atom, bool);
885
886#[derive(Debug, Clone, Copy, PartialEq, Eq)]
887pub enum RelationCacheProbe {
888 Hit(bool),
889 MissNotCached,
890}
891
892#[derive(Debug, Clone, Copy, PartialEq, Eq)]
893pub struct RelationCacheStats {
894 pub subtype_hits: u64,
895 pub subtype_misses: u64,
896 pub subtype_entries: usize,
897 pub assignability_hits: u64,
898 pub assignability_misses: u64,
899 pub assignability_entries: usize,
900}
901
902pub struct QueryCache<'a> {
904 interner: &'a TypeInterner,
905 eval_cache: RwLock<FxHashMap<EvalCacheKey, TypeId>>,
906 application_eval_cache: RwLock<FxHashMap<ApplicationEvalCacheKey, TypeId>>,
907 element_access_cache: RwLock<FxHashMap<ElementAccessTypeCacheKey, TypeId>>,
908 object_spread_properties_cache: RwLock<FxHashMap<TypeId, Vec<PropertyInfo>>>,
909 subtype_cache: RwLock<FxHashMap<RelationCacheKey, bool>>,
910 assignability_cache: RwLock<FxHashMap<RelationCacheKey, bool>>,
914 property_cache: RwLock<FxHashMap<PropertyAccessCacheKey, PropertyAccessResult>>,
915 variance_cache: RwLock<FxHashMap<DefId, Arc<[Variance]>>>,
918 canonical_cache: RwLock<FxHashMap<TypeId, TypeId>>,
921 subtype_cache_hits: AtomicU64,
922 subtype_cache_misses: AtomicU64,
923 assignability_cache_hits: AtomicU64,
924 assignability_cache_misses: AtomicU64,
925 no_unchecked_indexed_access: AtomicBool,
926}
927
928impl<'a> QueryCache<'a> {
929 pub fn new(interner: &'a TypeInterner) -> Self {
930 QueryCache {
931 interner,
932 eval_cache: RwLock::new(FxHashMap::default()),
933 application_eval_cache: RwLock::new(FxHashMap::default()),
934 element_access_cache: RwLock::new(FxHashMap::default()),
935 object_spread_properties_cache: RwLock::new(FxHashMap::default()),
936 subtype_cache: RwLock::new(FxHashMap::default()),
937 assignability_cache: RwLock::new(FxHashMap::default()),
938 property_cache: RwLock::new(FxHashMap::default()),
939 variance_cache: RwLock::new(FxHashMap::default()),
940 canonical_cache: RwLock::new(FxHashMap::default()),
941 subtype_cache_hits: AtomicU64::new(0),
942 subtype_cache_misses: AtomicU64::new(0),
943 assignability_cache_hits: AtomicU64::new(0),
944 assignability_cache_misses: AtomicU64::new(0),
945 no_unchecked_indexed_access: AtomicBool::new(false),
946 }
947 }
948
949 pub fn clear(&self) {
950 match self.eval_cache.write() {
952 Ok(mut cache) => cache.clear(),
953 Err(e) => e.into_inner().clear(),
954 }
955 match self.element_access_cache.write() {
956 Ok(mut cache) => cache.clear(),
957 Err(e) => e.into_inner().clear(),
958 }
959 match self.application_eval_cache.write() {
960 Ok(mut cache) => cache.clear(),
961 Err(e) => e.into_inner().clear(),
962 }
963 match self.object_spread_properties_cache.write() {
964 Ok(mut cache) => cache.clear(),
965 Err(e) => e.into_inner().clear(),
966 }
967 match self.subtype_cache.write() {
968 Ok(mut cache) => cache.clear(),
969 Err(e) => e.into_inner().clear(),
970 }
971 match self.assignability_cache.write() {
972 Ok(mut cache) => cache.clear(),
973 Err(e) => e.into_inner().clear(),
974 }
975 match self.property_cache.write() {
976 Ok(mut cache) => cache.clear(),
977 Err(e) => e.into_inner().clear(),
978 }
979 match self.variance_cache.write() {
980 Ok(mut cache) => cache.clear(),
981 Err(e) => e.into_inner().clear(),
982 }
983 match self.canonical_cache.write() {
984 Ok(mut cache) => cache.clear(),
985 Err(e) => e.into_inner().clear(),
986 }
987 self.reset_relation_cache_stats();
988 }
989
990 pub fn relation_cache_stats(&self) -> RelationCacheStats {
991 let subtype_entries = match self.subtype_cache.read() {
992 Ok(cache) => cache.len(),
993 Err(e) => e.into_inner().len(),
994 };
995 let assignability_entries = match self.assignability_cache.read() {
996 Ok(cache) => cache.len(),
997 Err(e) => e.into_inner().len(),
998 };
999 RelationCacheStats {
1000 subtype_hits: self.subtype_cache_hits.load(Ordering::Relaxed),
1001 subtype_misses: self.subtype_cache_misses.load(Ordering::Relaxed),
1002 subtype_entries,
1003 assignability_hits: self.assignability_cache_hits.load(Ordering::Relaxed),
1004 assignability_misses: self.assignability_cache_misses.load(Ordering::Relaxed),
1005 assignability_entries,
1006 }
1007 }
1008
1009 pub fn reset_relation_cache_stats(&self) {
1010 self.subtype_cache_hits.store(0, Ordering::Relaxed);
1011 self.subtype_cache_misses.store(0, Ordering::Relaxed);
1012 self.assignability_cache_hits.store(0, Ordering::Relaxed);
1013 self.assignability_cache_misses.store(0, Ordering::Relaxed);
1014 }
1015
1016 pub fn probe_subtype_cache(&self, key: RelationCacheKey) -> RelationCacheProbe {
1017 match self.lookup_subtype_cache(key) {
1018 Some(result) => RelationCacheProbe::Hit(result),
1019 None => RelationCacheProbe::MissNotCached,
1020 }
1021 }
1022
1023 pub fn probe_assignability_cache(&self, key: RelationCacheKey) -> RelationCacheProbe {
1024 match self.lookup_assignability_cache(key) {
1025 Some(result) => RelationCacheProbe::Hit(result),
1026 None => RelationCacheProbe::MissNotCached,
1027 }
1028 }
1029
1030 fn check_cache(
1032 &self,
1033 cache: &RwLock<FxHashMap<RelationCacheKey, bool>>,
1034 key: RelationCacheKey,
1035 ) -> Option<bool> {
1036 match cache.read() {
1037 Ok(cached) => cached.get(&key).copied(),
1038 Err(e) => e.into_inner().get(&key).copied(),
1039 }
1040 }
1041
1042 fn insert_cache(
1044 &self,
1045 cache: &RwLock<FxHashMap<RelationCacheKey, bool>>,
1046 key: RelationCacheKey,
1047 result: bool,
1048 ) {
1049 match cache.write() {
1050 Ok(mut c) => {
1051 c.insert(key, result);
1052 }
1053 Err(e) => {
1054 e.into_inner().insert(key, result);
1055 }
1056 }
1057 }
1058
1059 fn check_property_cache(&self, key: PropertyAccessCacheKey) -> Option<PropertyAccessResult> {
1060 match self.property_cache.read() {
1061 Ok(cache) => cache.get(&key).cloned(),
1062 Err(e) => e.into_inner().get(&key).cloned(),
1063 }
1064 }
1065
1066 fn insert_property_cache(&self, key: PropertyAccessCacheKey, result: PropertyAccessResult) {
1067 match self.property_cache.write() {
1068 Ok(mut cache) => {
1069 cache.insert(key, result);
1070 }
1071 Err(e) => {
1072 e.into_inner().insert(key, result);
1073 }
1074 }
1075 }
1076
1077 fn check_element_access_cache(&self, key: ElementAccessTypeCacheKey) -> Option<TypeId> {
1078 match self.element_access_cache.read() {
1079 Ok(cache) => cache.get(&key).copied(),
1080 Err(e) => e.into_inner().get(&key).copied(),
1081 }
1082 }
1083
1084 fn insert_element_access_cache(&self, key: ElementAccessTypeCacheKey, result: TypeId) {
1085 match self.element_access_cache.write() {
1086 Ok(mut cache) => {
1087 cache.insert(key, result);
1088 }
1089 Err(e) => {
1090 e.into_inner().insert(key, result);
1091 }
1092 }
1093 }
1094
1095 fn check_application_eval_cache(&self, key: ApplicationEvalCacheKey) -> Option<TypeId> {
1096 match self.application_eval_cache.read() {
1097 Ok(cache) => cache.get(&key).copied(),
1098 Err(e) => e.into_inner().get(&key).copied(),
1099 }
1100 }
1101
1102 fn insert_application_eval_cache(&self, key: ApplicationEvalCacheKey, result: TypeId) {
1103 match self.application_eval_cache.write() {
1104 Ok(mut cache) => {
1105 cache.insert(key, result);
1106 }
1107 Err(e) => {
1108 e.into_inner().insert(key, result);
1109 }
1110 }
1111 }
1112
1113 fn check_object_spread_properties_cache(&self, key: TypeId) -> Option<Vec<PropertyInfo>> {
1114 match self.object_spread_properties_cache.read() {
1115 Ok(cache) => cache.get(&key).cloned(),
1116 Err(e) => e.into_inner().get(&key).cloned(),
1117 }
1118 }
1119
1120 fn insert_object_spread_properties_cache(&self, key: TypeId, value: Vec<PropertyInfo>) {
1121 match self.object_spread_properties_cache.write() {
1122 Ok(mut cache) => {
1123 cache.insert(key, value);
1124 }
1125 Err(e) => {
1126 e.into_inner().insert(key, value);
1127 }
1128 }
1129 }
1130
1131 fn collect_object_spread_properties_inner(
1132 &self,
1133 spread_type: TypeId,
1134 visited: &mut FxHashSet<TypeId>,
1135 ) -> Vec<PropertyInfo> {
1136 let normalized =
1137 self.evaluate_type_with_options(spread_type, self.no_unchecked_indexed_access());
1138
1139 if !visited.insert(normalized) {
1140 return Vec::new();
1141 }
1142
1143 if normalized != spread_type {
1144 return self.collect_object_spread_properties_inner(normalized, visited);
1145 }
1146
1147 let Some(key) = self.interner.lookup(normalized) else {
1148 return Vec::new();
1149 };
1150
1151 match key {
1152 TypeData::Object(shape_id) | TypeData::ObjectWithIndex(shape_id) => {
1153 self.interner.object_shape(shape_id).properties.to_vec()
1154 }
1155 TypeData::Callable(shape_id) => {
1156 self.interner.callable_shape(shape_id).properties.to_vec()
1157 }
1158 TypeData::Intersection(members_id) => {
1159 let members = self.interner.type_list(members_id);
1160 let mut merged: FxHashMap<Atom, PropertyInfo> = FxHashMap::default();
1161
1162 for &member in members.iter() {
1163 for prop in self.collect_object_spread_properties_inner(member, visited) {
1164 merged.insert(prop.name, prop);
1165 }
1166 }
1167
1168 merged.into_values().collect()
1169 }
1170 _ => Vec::new(),
1171 }
1172 }
1173}
1174
1175impl TypeDatabase for QueryCache<'_> {
1176 fn intern(&self, key: TypeData) -> TypeId {
1177 self.interner.intern(key)
1178 }
1179
1180 fn lookup(&self, id: TypeId) -> Option<TypeData> {
1181 self.interner.lookup(id)
1182 }
1183
1184 fn intern_string(&self, s: &str) -> Atom {
1185 self.interner.intern_string(s)
1186 }
1187
1188 fn resolve_atom(&self, atom: Atom) -> String {
1189 self.interner.resolve_atom(atom)
1190 }
1191
1192 fn resolve_atom_ref(&self, atom: Atom) -> Arc<str> {
1193 self.interner.resolve_atom_ref(atom)
1194 }
1195
1196 fn type_list(&self, id: TypeListId) -> Arc<[TypeId]> {
1197 self.interner.type_list(id)
1198 }
1199
1200 fn tuple_list(&self, id: TupleListId) -> Arc<[TupleElement]> {
1201 self.interner.tuple_list(id)
1202 }
1203
1204 fn template_list(&self, id: TemplateLiteralId) -> Arc<[TemplateSpan]> {
1205 self.interner.template_list(id)
1206 }
1207
1208 fn object_shape(&self, id: ObjectShapeId) -> Arc<ObjectShape> {
1209 self.interner.object_shape(id)
1210 }
1211
1212 fn object_property_index(&self, shape_id: ObjectShapeId, name: Atom) -> PropertyLookup {
1213 self.interner.object_property_index(shape_id, name)
1214 }
1215
1216 fn function_shape(&self, id: FunctionShapeId) -> Arc<FunctionShape> {
1217 self.interner.function_shape(id)
1218 }
1219
1220 fn callable_shape(&self, id: CallableShapeId) -> Arc<CallableShape> {
1221 self.interner.callable_shape(id)
1222 }
1223
1224 fn conditional_type(&self, id: ConditionalTypeId) -> Arc<ConditionalType> {
1225 self.interner.conditional_type(id)
1226 }
1227
1228 fn mapped_type(&self, id: MappedTypeId) -> Arc<MappedType> {
1229 self.interner.mapped_type(id)
1230 }
1231
1232 fn type_application(&self, id: TypeApplicationId) -> Arc<TypeApplication> {
1233 self.interner.type_application(id)
1234 }
1235
1236 fn literal_string(&self, value: &str) -> TypeId {
1237 self.interner.literal_string(value)
1238 }
1239
1240 fn literal_number(&self, value: f64) -> TypeId {
1241 self.interner.literal_number(value)
1242 }
1243
1244 fn literal_boolean(&self, value: bool) -> TypeId {
1245 self.interner.literal_boolean(value)
1246 }
1247
1248 fn literal_bigint(&self, value: &str) -> TypeId {
1249 self.interner.literal_bigint(value)
1250 }
1251
1252 fn literal_bigint_with_sign(&self, negative: bool, digits: &str) -> TypeId {
1253 self.interner.literal_bigint_with_sign(negative, digits)
1254 }
1255
1256 fn union(&self, members: Vec<TypeId>) -> TypeId {
1257 self.interner.union(members)
1258 }
1259
1260 fn union_from_sorted_vec(&self, flat: Vec<TypeId>) -> TypeId {
1261 self.interner.union_from_sorted_vec(flat)
1262 }
1263
1264 fn union2(&self, left: TypeId, right: TypeId) -> TypeId {
1265 self.interner.union2(left, right)
1266 }
1267
1268 fn union3(&self, first: TypeId, second: TypeId, third: TypeId) -> TypeId {
1269 self.interner.union3(first, second, third)
1270 }
1271
1272 fn intersection(&self, members: Vec<TypeId>) -> TypeId {
1273 self.interner.intersection(members)
1274 }
1275
1276 fn intersection2(&self, left: TypeId, right: TypeId) -> TypeId {
1277 self.interner.intersection2(left, right)
1278 }
1279
1280 fn intersect_types_raw2(&self, left: TypeId, right: TypeId) -> TypeId {
1281 self.interner.intersect_types_raw2(left, right)
1282 }
1283
1284 fn array(&self, element: TypeId) -> TypeId {
1285 self.interner.array(element)
1286 }
1287
1288 fn tuple(&self, elements: Vec<TupleElement>) -> TypeId {
1289 self.interner.tuple(elements)
1290 }
1291
1292 fn object(&self, properties: Vec<PropertyInfo>) -> TypeId {
1293 self.interner.object(properties)
1294 }
1295
1296 fn object_with_flags(&self, properties: Vec<PropertyInfo>, flags: ObjectFlags) -> TypeId {
1297 self.interner.object_with_flags(properties, flags)
1298 }
1299
1300 fn object_with_flags_and_symbol(
1301 &self,
1302 properties: Vec<PropertyInfo>,
1303 flags: ObjectFlags,
1304 symbol: Option<SymbolId>,
1305 ) -> TypeId {
1306 self.interner
1307 .object_with_flags_and_symbol(properties, flags, symbol)
1308 }
1309
1310 fn object_with_index(&self, shape: ObjectShape) -> TypeId {
1311 self.interner.object_with_index(shape)
1312 }
1313
1314 fn function(&self, shape: FunctionShape) -> TypeId {
1315 self.interner.function(shape)
1316 }
1317
1318 fn callable(&self, shape: CallableShape) -> TypeId {
1319 self.interner.callable(shape)
1320 }
1321
1322 fn template_literal(&self, spans: Vec<TemplateSpan>) -> TypeId {
1323 self.interner.template_literal(spans)
1324 }
1325
1326 fn conditional(&self, conditional: ConditionalType) -> TypeId {
1327 self.interner.conditional(conditional)
1328 }
1329
1330 fn mapped(&self, mapped: MappedType) -> TypeId {
1331 self.interner.mapped(mapped)
1332 }
1333
1334 fn reference(&self, symbol: SymbolRef) -> TypeId {
1335 self.interner.reference(symbol)
1336 }
1337
1338 fn lazy(&self, def_id: DefId) -> TypeId {
1339 self.interner.lazy(def_id)
1340 }
1341
1342 fn bound_parameter(&self, index: u32) -> TypeId {
1343 self.interner.bound_parameter(index)
1344 }
1345
1346 fn recursive(&self, depth: u32) -> TypeId {
1347 self.interner.recursive(depth)
1348 }
1349
1350 fn type_param(&self, info: TypeParamInfo) -> TypeId {
1351 self.interner.type_param(info)
1352 }
1353
1354 fn type_query(&self, symbol: SymbolRef) -> TypeId {
1355 self.interner.type_query(symbol)
1356 }
1357
1358 fn enum_type(&self, def_id: DefId, structural_type: TypeId) -> TypeId {
1359 self.interner.enum_type(def_id, structural_type)
1360 }
1361
1362 fn application(&self, base: TypeId, args: Vec<TypeId>) -> TypeId {
1363 self.interner.application(base, args)
1364 }
1365
1366 fn literal_string_atom(&self, atom: Atom) -> TypeId {
1367 self.interner.literal_string_atom(atom)
1368 }
1369
1370 fn union_preserve_members(&self, members: Vec<TypeId>) -> TypeId {
1371 self.interner.union_preserve_members(members)
1372 }
1373
1374 fn readonly_type(&self, inner: TypeId) -> TypeId {
1375 self.interner.readonly_type(inner)
1376 }
1377
1378 fn keyof(&self, inner: TypeId) -> TypeId {
1379 self.interner.keyof(inner)
1380 }
1381
1382 fn index_access(&self, object_type: TypeId, index_type: TypeId) -> TypeId {
1383 self.interner.index_access(object_type, index_type)
1384 }
1385
1386 fn this_type(&self) -> TypeId {
1387 self.interner.this_type()
1388 }
1389
1390 fn no_infer(&self, inner: TypeId) -> TypeId {
1391 self.interner.no_infer(inner)
1392 }
1393
1394 fn unique_symbol(&self, symbol: SymbolRef) -> TypeId {
1395 self.interner.unique_symbol(symbol)
1396 }
1397
1398 fn infer(&self, info: TypeParamInfo) -> TypeId {
1399 self.interner.infer(info)
1400 }
1401
1402 fn string_intrinsic(&self, kind: StringIntrinsicKind, type_arg: TypeId) -> TypeId {
1403 self.interner.string_intrinsic(kind, type_arg)
1404 }
1405
1406 fn get_class_base_type(&self, symbol_id: SymbolId) -> Option<TypeId> {
1407 self.interner.get_class_base_type(symbol_id)
1409 }
1410
1411 fn is_unit_type(&self, type_id: TypeId) -> bool {
1412 self.interner.is_unit_type(type_id)
1413 }
1414}
1415
1416impl TypeResolver for QueryCache<'_> {
1422 fn resolve_ref(&self, _symbol: SymbolRef, _interner: &dyn TypeDatabase) -> Option<TypeId> {
1423 None
1424 }
1425
1426 fn resolve_lazy(&self, _def_id: DefId, _interner: &dyn TypeDatabase) -> Option<TypeId> {
1427 None
1428 }
1429
1430 fn get_type_params(&self, _symbol: SymbolRef) -> Option<Vec<TypeParamInfo>> {
1431 None
1432 }
1433
1434 fn get_lazy_type_params(&self, _def_id: DefId) -> Option<Vec<TypeParamInfo>> {
1435 None
1436 }
1437
1438 fn def_to_symbol_id(&self, _def_id: DefId) -> Option<SymbolId> {
1439 None
1440 }
1441
1442 fn symbol_to_def_id(&self, _symbol: SymbolRef) -> Option<DefId> {
1443 None
1444 }
1445
1446 fn get_boxed_type(&self, kind: IntrinsicKind) -> Option<TypeId> {
1447 self.interner.get_boxed_type(kind)
1448 }
1449
1450 fn get_array_base_type(&self) -> Option<TypeId> {
1451 self.interner.get_array_base_type()
1452 }
1453
1454 fn get_array_base_type_params(&self) -> &[TypeParamInfo] {
1455 self.interner.get_array_base_type_params()
1456 }
1457}
1458
1459impl QueryDatabase for QueryCache<'_> {
1460 fn as_type_database(&self) -> &dyn TypeDatabase {
1461 self
1462 }
1463
1464 fn register_array_base_type(&self, type_id: TypeId, type_params: Vec<TypeParamInfo>) {
1465 self.interner.set_array_base_type(type_id, type_params);
1466 }
1467
1468 fn register_boxed_type(&self, kind: IntrinsicKind, type_id: TypeId) {
1469 self.interner.set_boxed_type(kind, type_id);
1470 }
1471
1472 fn evaluate_type(&self, type_id: TypeId) -> TypeId {
1473 self.evaluate_type_with_options(type_id, self.no_unchecked_indexed_access())
1474 }
1475
1476 fn evaluate_type_with_options(
1477 &self,
1478 type_id: TypeId,
1479 no_unchecked_indexed_access: bool,
1480 ) -> TypeId {
1481 let trace_enabled = crate::query_trace::enabled();
1482 let trace_query_id = trace_enabled.then(|| {
1483 let query_id = crate::query_trace::next_query_id();
1484 crate::query_trace::unary_start(
1485 query_id,
1486 "evaluate_type_with_options",
1487 type_id,
1488 no_unchecked_indexed_access,
1489 );
1490 query_id
1491 });
1492 let key = (type_id, no_unchecked_indexed_access);
1493 let cached = match self.eval_cache.read() {
1495 Ok(cache) => cache.get(&key).copied(),
1496 Err(e) => e.into_inner().get(&key).copied(),
1497 };
1498
1499 if let Some(result) = cached {
1500 if let Some(query_id) = trace_query_id {
1501 crate::query_trace::unary_end(query_id, "evaluate_type_with_options", result, true);
1502 }
1503 return result;
1504 }
1505
1506 let mut evaluator = crate::evaluate::TypeEvaluator::new(self.as_type_database());
1507 evaluator.set_no_unchecked_indexed_access(no_unchecked_indexed_access);
1508 evaluator = evaluator.with_query_db(self);
1509 let result = evaluator.evaluate(type_id);
1510 match self.eval_cache.write() {
1511 Ok(mut cache) => {
1512 cache.insert(key, result);
1513 }
1514 Err(e) => {
1515 e.into_inner().insert(key, result);
1516 }
1517 }
1518 if let Some(query_id) = trace_query_id {
1519 crate::query_trace::unary_end(query_id, "evaluate_type_with_options", result, false);
1520 }
1521 result
1522 }
1523
1524 fn lookup_application_eval_cache(
1525 &self,
1526 def_id: DefId,
1527 args: &[TypeId],
1528 no_unchecked_indexed_access: bool,
1529 ) -> Option<TypeId> {
1530 self.check_application_eval_cache((def_id, args.to_vec(), no_unchecked_indexed_access))
1531 }
1532
1533 fn insert_application_eval_cache(
1534 &self,
1535 def_id: DefId,
1536 args: &[TypeId],
1537 no_unchecked_indexed_access: bool,
1538 result: TypeId,
1539 ) {
1540 self.insert_application_eval_cache(
1541 (def_id, args.to_vec(), no_unchecked_indexed_access),
1542 result,
1543 );
1544 }
1545
1546 fn is_subtype_of_with_flags(&self, source: TypeId, target: TypeId, flags: u16) -> bool {
1547 let trace_enabled = crate::query_trace::enabled();
1548 let trace_query_id = trace_enabled.then(|| {
1549 let query_id = crate::query_trace::next_query_id();
1550 crate::query_trace::relation_start(
1551 query_id,
1552 "is_subtype_of_with_flags",
1553 source,
1554 target,
1555 flags,
1556 );
1557 query_id
1558 });
1559 let key = RelationCacheKey::subtype(source, target, flags, 0);
1560 let cached = match self.subtype_cache.read() {
1562 Ok(cache) => cache.get(&key).copied(),
1563 Err(e) => e.into_inner().get(&key).copied(),
1564 };
1565
1566 if let Some(result) = cached {
1567 if let Some(query_id) = trace_query_id {
1568 crate::query_trace::relation_end(
1569 query_id,
1570 "is_subtype_of_with_flags",
1571 result,
1572 true,
1573 );
1574 }
1575 return result;
1576 }
1577
1578 let result = crate::subtype::is_subtype_of_with_flags(
1579 self.as_type_database(),
1580 source,
1581 target,
1582 flags,
1583 );
1584 match self.subtype_cache.write() {
1585 Ok(mut cache) => {
1586 cache.insert(key, result);
1587 }
1588 Err(e) => {
1589 e.into_inner().insert(key, result);
1590 }
1591 }
1592 if let Some(query_id) = trace_query_id {
1593 crate::query_trace::relation_end(query_id, "is_subtype_of_with_flags", result, false);
1594 }
1595 result
1596 }
1597
1598 fn is_assignable_to_with_flags(&self, source: TypeId, target: TypeId, flags: u16) -> bool {
1599 let trace_enabled = crate::query_trace::enabled();
1600 let trace_query_id = trace_enabled.then(|| {
1601 let query_id = crate::query_trace::next_query_id();
1602 crate::query_trace::relation_start(
1603 query_id,
1604 "is_assignable_to_with_flags",
1605 source,
1606 target,
1607 flags,
1608 );
1609 query_id
1610 });
1611 let key = RelationCacheKey::assignability(source, target, flags, 0);
1613
1614 if let Some(result) = self.check_cache(&self.assignability_cache, key) {
1615 if let Some(query_id) = trace_query_id {
1616 crate::query_trace::relation_end(
1617 query_id,
1618 "is_assignable_to_with_flags",
1619 result,
1620 true,
1621 );
1622 }
1623 return result;
1624 }
1625
1626 use crate::compat::CompatChecker;
1628 let mut checker = CompatChecker::new(self.as_type_database());
1629
1630 checker.apply_flags(flags);
1634
1635 let result = checker.is_assignable(source, target);
1636
1637 self.insert_cache(&self.assignability_cache, key, result);
1638 if let Some(query_id) = trace_query_id {
1639 crate::query_trace::relation_end(
1640 query_id,
1641 "is_assignable_to_with_flags",
1642 result,
1643 false,
1644 );
1645 }
1646 result
1647 }
1648
1649 fn is_subtype_of(&self, source: TypeId, target: TypeId) -> bool {
1651 self.is_subtype_of_with_flags(source, target, 0) }
1653
1654 fn is_assignable_to(&self, source: TypeId, target: TypeId) -> bool {
1656 self.is_assignable_to_with_flags(source, target, 0) }
1658
1659 fn lookup_subtype_cache(&self, key: RelationCacheKey) -> Option<bool> {
1660 let result = match self.subtype_cache.read() {
1661 Ok(cache) => cache.get(&key).copied(),
1662 Err(e) => e.into_inner().get(&key).copied(),
1663 };
1664 if result.is_some() {
1665 self.subtype_cache_hits.fetch_add(1, Ordering::Relaxed);
1666 } else {
1667 self.subtype_cache_misses.fetch_add(1, Ordering::Relaxed);
1668 }
1669 result
1670 }
1671
1672 fn insert_subtype_cache(&self, key: RelationCacheKey, result: bool) {
1673 match self.subtype_cache.write() {
1674 Ok(mut cache) => {
1675 cache.insert(key, result);
1676 }
1677 Err(e) => {
1678 e.into_inner().insert(key, result);
1679 }
1680 }
1681 }
1682
1683 fn lookup_assignability_cache(&self, key: RelationCacheKey) -> Option<bool> {
1684 let result = match self.assignability_cache.read() {
1685 Ok(cache) => cache.get(&key).copied(),
1686 Err(e) => e.into_inner().get(&key).copied(),
1687 };
1688 if result.is_some() {
1689 self.assignability_cache_hits
1690 .fetch_add(1, Ordering::Relaxed);
1691 } else {
1692 self.assignability_cache_misses
1693 .fetch_add(1, Ordering::Relaxed);
1694 }
1695 result
1696 }
1697
1698 fn insert_assignability_cache(&self, key: RelationCacheKey, result: bool) {
1699 match self.assignability_cache.write() {
1700 Ok(mut cache) => {
1701 cache.insert(key, result);
1702 }
1703 Err(e) => {
1704 e.into_inner().insert(key, result);
1705 }
1706 }
1707 }
1708
1709 fn get_index_signatures(&self, type_id: TypeId) -> IndexInfo {
1710 self.interner.get_index_signatures(type_id)
1712 }
1713
1714 fn is_nullish_type(&self, type_id: TypeId) -> bool {
1715 self.interner.is_nullish_type(type_id)
1717 }
1718
1719 fn remove_nullish(&self, type_id: TypeId) -> TypeId {
1720 self.interner.remove_nullish(type_id)
1722 }
1723
1724 fn resolve_property_access(
1725 &self,
1726 object_type: TypeId,
1727 prop_name: &str,
1728 ) -> crate::operations_property::PropertyAccessResult {
1729 self.resolve_property_access_with_options(
1730 object_type,
1731 prop_name,
1732 self.no_unchecked_indexed_access(),
1733 )
1734 }
1735
1736 fn resolve_property_access_with_options(
1737 &self,
1738 object_type: TypeId,
1739 prop_name: &str,
1740 no_unchecked_indexed_access: bool,
1741 ) -> crate::operations_property::PropertyAccessResult {
1742 let prop_atom = self.interner.intern_string(prop_name);
1745 let key = (object_type, prop_atom, no_unchecked_indexed_access);
1746 if let Some(result) = self.check_property_cache(key) {
1747 return result;
1748 }
1749
1750 let mut evaluator = crate::operations_property::PropertyAccessEvaluator::new(self);
1751 evaluator.set_no_unchecked_indexed_access(no_unchecked_indexed_access);
1752 let result = evaluator.resolve_property_access(object_type, prop_name);
1753 self.insert_property_cache(key, result.clone());
1754 result
1755 }
1756
1757 fn resolve_element_access_type(
1758 &self,
1759 object_type: TypeId,
1760 index_type: TypeId,
1761 literal_index: Option<usize>,
1762 ) -> TypeId {
1763 let key = (
1764 object_type,
1765 index_type,
1766 literal_index.map(|idx| idx as u32),
1767 self.no_unchecked_indexed_access(),
1768 );
1769 if let Some(result) = self.check_element_access_cache(key) {
1770 return result;
1771 }
1772
1773 let result = match self.resolve_element_access(object_type, index_type, literal_index) {
1774 crate::element_access::ElementAccessResult::Success(type_id) => type_id,
1775 _ => TypeId::ERROR,
1776 };
1777
1778 self.insert_element_access_cache(key, result);
1779 result
1780 }
1781
1782 fn collect_object_spread_properties(&self, spread_type: TypeId) -> Vec<PropertyInfo> {
1783 if let Some(cached) = self.check_object_spread_properties_cache(spread_type) {
1784 return cached;
1785 }
1786
1787 let mut visited: FxHashSet<TypeId> = FxHashSet::default();
1788 let result = self.collect_object_spread_properties_inner(spread_type, &mut visited);
1789 self.insert_object_spread_properties_cache(spread_type, result.clone());
1790 result
1791 }
1792
1793 fn no_unchecked_indexed_access(&self) -> bool {
1794 self.no_unchecked_indexed_access.load(Ordering::Relaxed)
1795 }
1796
1797 fn set_no_unchecked_indexed_access(&self, enabled: bool) {
1798 self.no_unchecked_indexed_access
1799 .store(enabled, Ordering::Relaxed);
1800 }
1801
1802 fn get_type_param_variance(&self, def_id: DefId) -> Option<Arc<[Variance]>> {
1803 if let Ok(cache) = self.variance_cache.read()
1805 && let Some(cached) = cache.get(&def_id)
1806 {
1807 return Some(Arc::clone(cached));
1808 }
1809
1810 let params = self.get_lazy_type_params(def_id)?;
1813 if params.is_empty() {
1814 return None;
1815 }
1816
1817 let body = self.resolve_lazy(def_id, self.as_type_database())?;
1818
1819 let mut variances = Vec::with_capacity(params.len());
1820 for param in ¶ms {
1821 let v = crate::variance::compute_variance(self, body, param.name);
1823 variances.push(v);
1824 }
1825 let result = Arc::from(variances);
1826
1827 match self.variance_cache.write() {
1829 Ok(mut cache) => {
1830 cache.insert(def_id, Arc::clone(&result));
1831 }
1832 Err(e) => {
1833 e.into_inner().insert(def_id, Arc::clone(&result));
1834 }
1835 }
1836
1837 Some(result)
1838 }
1839
1840 fn canonical_id(&self, type_id: TypeId) -> TypeId {
1841 let cached = match self.canonical_cache.read() {
1843 Ok(cache) => cache.get(&type_id).copied(),
1844 Err(e) => e.into_inner().get(&type_id).copied(),
1845 };
1846
1847 if let Some(canonical) = cached {
1848 return canonical;
1849 }
1850
1851 use crate::canonicalize::Canonicalizer;
1855 let mut canon = Canonicalizer::new(self.as_type_database(), self);
1856 let canonical = canon.canonicalize(type_id);
1857
1858 match self.canonical_cache.write() {
1860 Ok(mut cache) => {
1861 cache.insert(type_id, canonical);
1862 }
1863 Err(e) => {
1864 e.into_inner().insert(type_id, canonical);
1865 }
1866 }
1867
1868 canonical
1869 }
1870}
1871
1872#[cfg(test)]
1873#[path = "../tests/db_tests.rs"]
1874mod tests;