1use crate::TypeDatabase;
13#[cfg(test)]
14use crate::types::*;
15use crate::types::{
16 CallSignature, CallableShape, ConditionalType, FunctionShape, IndexSignature, IntrinsicKind,
17 LiteralValue, MappedType, ObjectShape, ParamInfo, PropertyInfo, TemplateSpan, TupleElement,
18 TypeData, TypeId, TypeParamInfo, TypePredicate,
19};
20use rustc_hash::FxHashMap;
21use tsz_common::interner::Atom;
22
23pub const MAX_INSTANTIATION_DEPTH: u32 = 50;
25
26#[derive(Clone, Debug, Default)]
28pub struct TypeSubstitution {
29 map: FxHashMap<Atom, TypeId>,
31}
32
33impl TypeSubstitution {
34 pub fn new() -> Self {
36 Self {
37 map: FxHashMap::default(),
38 }
39 }
40
41 pub fn from_args(
52 interner: &dyn TypeDatabase,
53 type_params: &[TypeParamInfo],
54 type_args: &[TypeId],
55 ) -> Self {
56 let mut map = FxHashMap::default();
57 for (i, param) in type_params.iter().enumerate() {
58 let type_id = if i < type_args.len() {
59 type_args[i]
60 } else {
61 match param.default {
63 Some(default) => {
64 if i > 0 && !map.is_empty() {
66 let subst = Self { map: map.clone() };
67 instantiate_type(interner, default, &subst)
68 } else {
69 default
70 }
71 }
72 None => {
73 continue;
76 }
77 }
78 };
79 map.insert(param.name, type_id);
80 }
81 Self { map }
82 }
83
84 pub fn insert(&mut self, name: Atom, type_id: TypeId) {
86 self.map.insert(name, type_id);
87 }
88
89 pub fn get(&self, name: Atom) -> Option<TypeId> {
91 self.map.get(&name).copied()
92 }
93
94 pub fn is_empty(&self) -> bool {
96 self.map.is_empty()
97 }
98
99 pub fn len(&self) -> usize {
101 self.map.len()
102 }
103
104 pub const fn map(&self) -> &FxHashMap<Atom, TypeId> {
108 &self.map
109 }
110}
111
112pub struct TypeInstantiator<'a> {
114 interner: &'a dyn TypeDatabase,
115 substitution: &'a TypeSubstitution,
116 visiting: FxHashMap<TypeId, TypeId>,
118 shadowed: Vec<Atom>,
120 substitute_infer: bool,
121 pub this_type: Option<TypeId>,
123 depth: u32,
124 max_depth: u32,
125 depth_exceeded: bool,
126}
127
128impl<'a> TypeInstantiator<'a> {
129 pub fn new(interner: &'a dyn TypeDatabase, substitution: &'a TypeSubstitution) -> Self {
131 TypeInstantiator {
132 interner,
133 substitution,
134 visiting: FxHashMap::default(),
135 shadowed: Vec::new(),
136 substitute_infer: false,
137 this_type: None,
138 depth: 0,
139 max_depth: MAX_INSTANTIATION_DEPTH,
140 depth_exceeded: false,
141 }
142 }
143
144 fn is_shadowed(&self, name: Atom) -> bool {
145 self.shadowed.contains(&name)
146 }
147
148 pub fn instantiate(&mut self, type_id: TypeId) -> TypeId {
150 if type_id.is_intrinsic() {
152 return type_id;
153 }
154
155 if self.depth_exceeded {
156 return TypeId::ERROR;
157 }
158
159 if self.depth >= self.max_depth {
160 self.depth_exceeded = true;
161 return TypeId::ERROR;
162 }
163
164 self.depth += 1;
165 let result = self.instantiate_inner(type_id);
166 self.depth -= 1;
167 result
168 }
169
170 fn instantiate_inner(&mut self, type_id: TypeId) -> TypeId {
171 if let Some(&cached) = self.visiting.get(&type_id) {
173 return cached;
174 }
175
176 let key = match self.interner.lookup(type_id) {
178 Some(k) => k,
179 None => return type_id,
180 };
181
182 self.visiting.insert(type_id, type_id);
184
185 let result = self.instantiate_key(&key);
186
187 self.visiting.insert(type_id, result);
189
190 result
191 }
192
193 fn instantiate_call_signature(&mut self, sig: &CallSignature) -> CallSignature {
195 let shadowed_len = self.shadowed.len();
196
197 let saved_visiting = (!sig.type_params.is_empty()).then(|| {
205 let saved = self.visiting.clone();
206 for tp in &sig.type_params {
210 let tp_id = self.interner.type_param(tp.clone());
211 self.visiting.remove(&tp_id);
212 }
213 saved
214 });
215
216 self.shadowed
217 .extend(sig.type_params.iter().map(|tp| tp.name));
218
219 let type_predicate = sig
220 .type_predicate
221 .as_ref()
222 .map(|predicate| self.instantiate_type_predicate(predicate));
223 let this_type = sig.this_type.map(|type_id| self.instantiate(type_id));
224 let type_params: Vec<TypeParamInfo> = sig
225 .type_params
226 .iter()
227 .map(|tp| TypeParamInfo {
228 is_const: false,
229 name: tp.name,
230 constraint: tp.constraint.map(|c| self.instantiate(c)),
231 default: tp.default.map(|d| self.instantiate(d)),
232 })
233 .collect();
234 let params: Vec<ParamInfo> = sig
235 .params
236 .iter()
237 .map(|p| ParamInfo {
238 name: p.name,
239 type_id: self.instantiate(p.type_id),
240 optional: p.optional,
241 rest: p.rest,
242 })
243 .collect();
244 let return_type = self.instantiate(sig.return_type);
245
246 self.shadowed.truncate(shadowed_len);
247
248 if let Some(saved) = saved_visiting {
251 self.visiting = saved;
252 }
253
254 CallSignature {
255 type_params,
256 params,
257 this_type,
258 return_type,
259 type_predicate,
260 is_method: sig.is_method,
261 }
262 }
263
264 fn instantiate_type_predicate(&mut self, predicate: &TypePredicate) -> TypePredicate {
265 TypePredicate {
266 asserts: predicate.asserts,
267 target: predicate.target.clone(),
268 type_id: predicate.type_id.map(|type_id| self.instantiate(type_id)),
269 parameter_index: predicate.parameter_index,
270 }
271 }
272
273 fn instantiate_key(&mut self, key: &TypeData) -> TypeId {
275 match key {
276 TypeData::TypeParameter(info) => {
278 if self.is_shadowed(info.name) {
279 return self.interner.intern(key.clone());
280 }
281 if let Some(substituted) = self.substitution.get(info.name) {
282 substituted
283 } else {
284 if let Some(constraint) = info.constraint {
289 let instantiated_constraint = self.instantiate(constraint);
290 if instantiated_constraint != constraint {
292 return instantiated_constraint;
293 }
294 }
295 self.interner.intern(key.clone())
297 }
298 }
299
300 TypeData::Intrinsic(_) | TypeData::Literal(_) | TypeData::Error => {
302 self.interner.intern(key.clone())
303 }
304
305 TypeData::Lazy(_)
307 | TypeData::Recursive(_)
308 | TypeData::BoundParameter(_)
309 | TypeData::TypeQuery(_)
310 | TypeData::UniqueSymbol(_)
311 | TypeData::ModuleNamespace(_) => self.interner.intern(key.clone()),
312
313 TypeData::Enum(def_id, member_type) => {
316 let instantiated_member = self.instantiate(*member_type);
317 self.interner.enum_type(*def_id, instantiated_member)
318 }
319
320 TypeData::Application(app_id) => {
322 let app = self.interner.type_application(*app_id);
323 let base = self.instantiate(app.base);
324 let args: Vec<TypeId> = app.args.iter().map(|&arg| self.instantiate(arg)).collect();
325 self.interner.application(base, args)
326 }
327
328 TypeData::ThisType => {
330 if let Some(this_type) = self.this_type {
331 this_type
332 } else {
333 self.interner.intern(key.clone())
334 }
335 }
336
337 TypeData::Union(members) => {
339 let members = self.interner.type_list(*members);
340 let instantiated: Vec<TypeId> =
341 members.iter().map(|&m| self.instantiate(m)).collect();
342 self.interner.union(instantiated)
343 }
344
345 TypeData::Intersection(members) => {
347 let members = self.interner.type_list(*members);
348 let instantiated: Vec<TypeId> =
349 members.iter().map(|&m| self.instantiate(m)).collect();
350 self.interner.intersection(instantiated)
351 }
352
353 TypeData::Array(elem) => {
355 let instantiated_elem = self.instantiate(*elem);
356 self.interner.array(instantiated_elem)
357 }
358
359 TypeData::Tuple(elements) => {
361 let elements = self.interner.tuple_list(*elements);
362 let instantiated: Vec<TupleElement> = elements
363 .iter()
364 .map(|e| TupleElement {
365 type_id: self.instantiate(e.type_id),
366 name: e.name,
367 optional: e.optional,
368 rest: e.rest,
369 })
370 .collect();
371 self.interner.tuple(instantiated)
372 }
373
374 TypeData::Object(shape_id) => {
376 let shape = self.interner.object_shape(*shape_id);
377 let instantiated: Vec<PropertyInfo> = shape
378 .properties
379 .iter()
380 .map(|p| PropertyInfo {
381 name: p.name,
382 type_id: self.instantiate(p.type_id),
383 write_type: self.instantiate(p.write_type),
384 optional: p.optional,
385 readonly: p.readonly,
386 is_method: p.is_method,
387 visibility: p.visibility,
388 parent_id: p.parent_id,
389 })
390 .collect();
391 self.interner
392 .object_with_flags_and_symbol(instantiated, shape.flags, shape.symbol)
393 }
394
395 TypeData::ObjectWithIndex(shape_id) => {
397 let shape = self.interner.object_shape(*shape_id);
398 let instantiated_props: Vec<PropertyInfo> = shape
399 .properties
400 .iter()
401 .map(|p| PropertyInfo {
402 name: p.name,
403 type_id: self.instantiate(p.type_id),
404 write_type: self.instantiate(p.write_type),
405 optional: p.optional,
406 readonly: p.readonly,
407 is_method: p.is_method,
408 visibility: p.visibility,
409 parent_id: p.parent_id,
410 })
411 .collect();
412 let instantiated_string_idx =
413 shape.string_index.as_ref().map(|idx| IndexSignature {
414 key_type: self.instantiate(idx.key_type),
415 value_type: self.instantiate(idx.value_type),
416 readonly: idx.readonly,
417 });
418 let instantiated_number_idx =
419 shape.number_index.as_ref().map(|idx| IndexSignature {
420 key_type: self.instantiate(idx.key_type),
421 value_type: self.instantiate(idx.value_type),
422 readonly: idx.readonly,
423 });
424 self.interner.object_with_index(ObjectShape {
425 flags: shape.flags,
426 properties: instantiated_props,
427 string_index: instantiated_string_idx,
428 number_index: instantiated_number_idx,
429 symbol: shape.symbol,
430 })
431 }
432
433 TypeData::Function(shape_id) => {
436 let shape = self.interner.function_shape(*shape_id);
437 let shadowed_len = self.shadowed.len();
438 let saved_visiting = (!shape.type_params.is_empty()).then(|| {
439 let saved = self.visiting.clone();
440 for tp in &shape.type_params {
446 let tp_id = self.interner.type_param(tp.clone());
447 self.visiting.remove(&tp_id);
448 }
449 saved
450 });
451 self.shadowed
452 .extend(shape.type_params.iter().map(|tp| tp.name));
453
454 let type_predicate = shape
455 .type_predicate
456 .as_ref()
457 .map(|predicate| self.instantiate_type_predicate(predicate));
458 let this_type = shape.this_type.map(|type_id| self.instantiate(type_id));
459 let instantiated_type_params: Vec<TypeParamInfo> = shape
460 .type_params
461 .iter()
462 .map(|tp| TypeParamInfo {
463 is_const: false,
464 name: tp.name,
465 constraint: tp.constraint.map(|c| self.instantiate(c)),
466 default: tp.default.map(|d| self.instantiate(d)),
467 })
468 .collect();
469 let instantiated_params: Vec<ParamInfo> = shape
470 .params
471 .iter()
472 .map(|p| ParamInfo {
473 name: p.name,
474 type_id: self.instantiate(p.type_id),
475 optional: p.optional,
476 rest: p.rest,
477 })
478 .collect();
479 let instantiated_return = self.instantiate(shape.return_type);
480
481 self.shadowed.truncate(shadowed_len);
482 if let Some(saved) = saved_visiting {
483 self.visiting = saved;
484 }
485
486 self.interner.function(FunctionShape {
487 type_params: instantiated_type_params,
488 params: instantiated_params,
489 this_type,
490 return_type: instantiated_return,
491 type_predicate,
492 is_constructor: shape.is_constructor,
493 is_method: shape.is_method,
494 })
495 }
496
497 TypeData::Callable(shape_id) => {
499 let shape = self.interner.callable_shape(*shape_id);
500 let instantiated_call: Vec<CallSignature> = shape
501 .call_signatures
502 .iter()
503 .map(|sig| self.instantiate_call_signature(sig))
504 .collect();
505 let instantiated_construct: Vec<CallSignature> = shape
506 .construct_signatures
507 .iter()
508 .map(|sig| self.instantiate_call_signature(sig))
509 .collect();
510 let instantiated_props = shape
511 .properties
512 .iter()
513 .map(|p| PropertyInfo {
514 name: p.name,
515 type_id: self.instantiate(p.type_id),
516 write_type: self.instantiate(p.write_type),
517 optional: p.optional,
518 readonly: p.readonly,
519 is_method: p.is_method,
520 visibility: p.visibility,
521 parent_id: p.parent_id,
522 })
523 .collect();
524
525 self.interner.callable(CallableShape {
526 call_signatures: instantiated_call,
527 construct_signatures: instantiated_construct,
528 properties: instantiated_props,
529 string_index: shape.string_index.clone(),
530 number_index: shape.number_index.clone(),
531 symbol: shape.symbol,
532 })
533 }
534
535 TypeData::Conditional(cond_id) => {
537 let cond = self.interner.conditional_type(*cond_id);
538 if cond.is_distributive
539 && let Some(TypeData::TypeParameter(info)) =
540 self.interner.lookup(cond.check_type)
541 && !self.is_shadowed(info.name)
542 && let Some(substituted) = self.substitution.get(info.name)
543 {
544 if substituted == crate::types::TypeId::NEVER {
546 return substituted;
547 }
548 if substituted == TypeId::BOOLEAN {
552 let cond_type = self.interner.conditional(cond.as_ref().clone());
553 let mut results = Vec::with_capacity(2);
554 for &member in &[TypeId::BOOLEAN_TRUE, TypeId::BOOLEAN_FALSE] {
555 if self.depth_exceeded {
556 return TypeId::ERROR;
557 }
558 let mut member_subst = self.substitution.clone();
559 member_subst.insert(info.name, member);
560 let instantiated =
561 instantiate_type(self.interner, cond_type, &member_subst);
562 if instantiated == TypeId::ERROR {
563 self.depth_exceeded = true;
564 return TypeId::ERROR;
565 }
566 let evaluated =
567 crate::evaluate::evaluate_type(self.interner, instantiated);
568 if evaluated == TypeId::ERROR {
569 self.depth_exceeded = true;
570 return TypeId::ERROR;
571 }
572 results.push(evaluated);
573 }
574 return self.interner.union(results);
575 }
576 if let Some(TypeData::Union(members)) = self.interner.lookup(substituted) {
577 let members = self.interner.type_list(members);
578 const MAX_DISTRIBUTION_SIZE: usize = 100;
581 if members.len() > MAX_DISTRIBUTION_SIZE {
582 self.depth_exceeded = true;
583 return TypeId::ERROR;
584 }
585 let cond_type = self.interner.conditional(cond.as_ref().clone());
586 let mut results = Vec::with_capacity(members.len());
587 for &member in members.iter() {
588 if self.depth_exceeded {
590 return TypeId::ERROR;
591 }
592 let mut member_subst = self.substitution.clone();
593 member_subst.insert(info.name, member);
594 let instantiated =
595 instantiate_type(self.interner, cond_type, &member_subst);
596 if instantiated == TypeId::ERROR {
598 self.depth_exceeded = true;
599 return TypeId::ERROR;
600 }
601 let evaluated =
602 crate::evaluate::evaluate_type(self.interner, instantiated);
603 if evaluated == TypeId::ERROR {
605 self.depth_exceeded = true;
606 return TypeId::ERROR;
607 }
608 results.push(evaluated);
609 }
610 return self.interner.union(results);
611 }
612 }
613 let instantiated = ConditionalType {
614 check_type: self.instantiate(cond.check_type),
615 extends_type: self.instantiate(cond.extends_type),
616 true_type: self.instantiate(cond.true_type),
617 false_type: self.instantiate(cond.false_type),
618 is_distributive: cond.is_distributive,
619 };
620 self.interner.conditional(instantiated)
621 }
622
623 TypeData::Mapped(mapped_id) => {
625 let mapped = self.interner.mapped_type(*mapped_id);
626 let shadowed_len = self.shadowed.len();
627 let saved = self.visiting.clone();
628 let tp_id = self.interner.type_param(mapped.type_param.clone());
629 self.visiting.remove(&tp_id);
630 let saved_visiting = Some(saved);
631 self.shadowed.push(mapped.type_param.name);
632
633 let new_constraint = self.instantiate(mapped.constraint);
634 let new_template = self.instantiate(mapped.template);
635 let new_name_type = mapped.name_type.map(|t| self.instantiate(t));
636 let new_param_constraint =
637 mapped.type_param.constraint.map(|c| self.instantiate(c));
638 let new_param_default = mapped.type_param.default.map(|d| self.instantiate(d));
639
640 self.shadowed.truncate(shadowed_len);
641 if let Some(saved) = saved_visiting {
642 self.visiting = saved;
643 }
644
645 let unchanged = new_constraint == mapped.constraint
649 && new_template == mapped.template
650 && new_name_type == mapped.name_type
651 && new_param_constraint == mapped.type_param.constraint
652 && new_param_default == mapped.type_param.default;
653
654 if unchanged {
655 return self.interner.mapped((*mapped).clone());
656 }
657
658 let instantiated = MappedType {
659 type_param: TypeParamInfo {
660 is_const: false,
661 name: mapped.type_param.name,
662 constraint: new_param_constraint,
663 default: new_param_default,
664 },
665 constraint: new_constraint,
666 name_type: new_name_type,
667 template: new_template,
668 readonly_modifier: mapped.readonly_modifier,
669 optional_modifier: mapped.optional_modifier,
670 };
671
672 let mapped_type = self.interner.mapped(instantiated);
677 crate::evaluate::evaluate_type(self.interner, mapped_type)
678 }
679
680 TypeData::IndexAccess(obj, idx) => {
683 let inst_obj = self.instantiate(*obj);
684 let inst_idx = self.instantiate(*idx);
685 if crate::visitor::contains_type_parameters(self.interner, inst_obj)
690 || crate::visitor::contains_type_parameters(self.interner, inst_idx)
691 {
692 return self.interner.index_access(inst_obj, inst_idx);
693 }
694 crate::evaluate::evaluate_index_access(self.interner, inst_obj, inst_idx)
696 }
697
698 TypeData::KeyOf(operand) => {
701 let inst_operand = self.instantiate(*operand);
702 if crate::visitor::contains_type_parameters(self.interner, inst_operand) {
709 return self.interner.keyof(inst_operand);
710 }
711 crate::evaluate::evaluate_keyof(self.interner, inst_operand)
713 }
714
715 TypeData::ReadonlyType(operand) => {
717 let inst_operand = self.instantiate(*operand);
718 self.interner.readonly_type(inst_operand)
719 }
720
721 TypeData::NoInfer(inner) => {
723 let inst_inner = self.instantiate(*inner);
724 self.interner.no_infer(inst_inner)
725 }
726
727 TypeData::TemplateLiteral(spans) => {
731 let spans = self.interner.template_list(*spans);
732 let mut instantiated: Vec<TemplateSpan> = Vec::with_capacity(spans.len());
733 let mut needs_evaluation = false;
734
735 for span in spans.iter() {
736 match span {
737 TemplateSpan::Text(t) => instantiated.push(TemplateSpan::Text(*t)),
738 TemplateSpan::Type(t) => {
739 let inst_type = self.instantiate(*t);
740 if let Some(
745 TypeData::Union(_)
746 | TypeData::Literal(
747 LiteralValue::String(_)
748 | LiteralValue::Number(_)
749 | LiteralValue::Boolean(_),
750 )
751 | TypeData::Intrinsic(
752 IntrinsicKind::String
753 | IntrinsicKind::Number
754 | IntrinsicKind::Boolean,
755 ),
756 ) = self.interner.lookup(inst_type)
757 {
758 needs_evaluation = true;
759 }
760 instantiated.push(TemplateSpan::Type(inst_type));
761 }
762 }
763 }
764
765 let template_type = self.interner.template_literal(instantiated);
766
767 if needs_evaluation {
770 crate::evaluate::evaluate_type(self.interner, template_type)
771 } else {
772 template_type
773 }
774 }
775
776 TypeData::StringIntrinsic { kind, type_arg } => {
780 let inst_arg = self.instantiate(*type_arg);
781 let string_intrinsic = self.interner.string_intrinsic(*kind, inst_arg);
782
783 if let Some(key) = self.interner.lookup(inst_arg) {
785 match key {
786 TypeData::Union(_)
787 | TypeData::Literal(LiteralValue::String(_))
788 | TypeData::TemplateLiteral(_)
789 | TypeData::Intrinsic(IntrinsicKind::String) => {
790 crate::evaluate::evaluate_type(self.interner, string_intrinsic)
791 }
792 _ => string_intrinsic,
793 }
794 } else {
795 string_intrinsic
796 }
797 }
798
799 TypeData::Infer(info) => {
801 if self.substitute_infer
802 && !self.is_shadowed(info.name)
803 && let Some(substituted) = self.substitution.get(info.name)
804 {
805 return substituted;
806 }
807 self.interner.infer(info.clone())
808 }
809 }
810 }
811}
812
813pub fn instantiate_type(
815 interner: &dyn TypeDatabase,
816 type_id: TypeId,
817 substitution: &TypeSubstitution,
818) -> TypeId {
819 if substitution.is_empty() {
820 return type_id;
821 }
822 let mut instantiator = TypeInstantiator::new(interner, substitution);
823 let result = instantiator.instantiate(type_id);
824 if instantiator.depth_exceeded {
825 TypeId::ERROR
826 } else {
827 result
828 }
829}
830
831pub fn instantiate_type_with_infer(
833 interner: &dyn TypeDatabase,
834 type_id: TypeId,
835 substitution: &TypeSubstitution,
836) -> TypeId {
837 if substitution.is_empty() {
838 return type_id;
839 }
840 let mut instantiator = TypeInstantiator::new(interner, substitution);
841 instantiator.substitute_infer = true;
842 let result = instantiator.instantiate(type_id);
843 if instantiator.depth_exceeded {
844 TypeId::ERROR
845 } else {
846 result
847 }
848}
849
850pub fn instantiate_generic(
852 interner: &dyn TypeDatabase,
853 type_id: TypeId,
854 type_params: &[TypeParamInfo],
855 type_args: &[TypeId],
856) -> TypeId {
857 if type_params.is_empty() || type_args.is_empty() {
858 return type_id;
859 }
860 let substitution = TypeSubstitution::from_args(interner, type_params, type_args);
861 instantiate_type(interner, type_id, &substitution)
862}
863
864pub fn substitute_this_type(
873 interner: &dyn TypeDatabase,
874 type_id: TypeId,
875 this_type: TypeId,
876) -> TypeId {
877 if type_id.is_intrinsic() {
879 return type_id;
880 }
881 let empty_subst = TypeSubstitution::new();
882 let mut instantiator = TypeInstantiator::new(interner, &empty_subst);
883 instantiator.this_type = Some(this_type);
884 let result = instantiator.instantiate(type_id);
885 if instantiator.depth_exceeded {
886 TypeId::ERROR
887 } else {
888 result
889 }
890}
891
892#[cfg(test)]
893#[path = "../tests/instantiate_tests.rs"]
894mod tests;