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 fn instantiate_properties(&mut self, properties: &[PropertyInfo]) -> Vec<PropertyInfo> {
150 properties
151 .iter()
152 .map(|p| PropertyInfo {
153 name: p.name,
154 type_id: self.instantiate(p.type_id),
155 write_type: self.instantiate(p.write_type),
156 optional: p.optional,
157 readonly: p.readonly,
158 is_method: p.is_method,
159 visibility: p.visibility,
160 parent_id: p.parent_id,
161 })
162 .collect()
163 }
164
165 fn instantiate_index_signature(
167 &mut self,
168 idx: Option<&IndexSignature>,
169 ) -> Option<IndexSignature> {
170 idx.map(|idx| IndexSignature {
171 key_type: self.instantiate(idx.key_type),
172 value_type: self.instantiate(idx.value_type),
173 readonly: idx.readonly,
174 })
175 }
176
177 fn instantiate_type_params(&mut self, type_params: &[TypeParamInfo]) -> Vec<TypeParamInfo> {
179 type_params
180 .iter()
181 .map(|tp| TypeParamInfo {
182 is_const: false,
183 name: tp.name,
184 constraint: tp.constraint.map(|c| self.instantiate(c)),
185 default: tp.default.map(|d| self.instantiate(d)),
186 })
187 .collect()
188 }
189
190 fn instantiate_params(&mut self, params: &[ParamInfo]) -> Vec<ParamInfo> {
192 params
193 .iter()
194 .map(|p| ParamInfo {
195 name: p.name,
196 type_id: self.instantiate(p.type_id),
197 optional: p.optional,
198 rest: p.rest,
199 })
200 .collect()
201 }
202
203 fn enter_shadowing_scope(
208 &mut self,
209 type_params: &[TypeParamInfo],
210 ) -> (usize, Option<FxHashMap<TypeId, TypeId>>) {
211 let shadowed_len = self.shadowed.len();
212 let saved_visiting = (!type_params.is_empty()).then(|| {
213 let saved = self.visiting.clone();
214 for tp in type_params {
215 let tp_id = self.interner.type_param(tp.clone());
216 self.visiting.remove(&tp_id);
217 }
218 saved
219 });
220 self.shadowed.extend(type_params.iter().map(|tp| tp.name));
221 (shadowed_len, saved_visiting)
222 }
223
224 fn exit_shadowing_scope(
226 &mut self,
227 shadowed_len: usize,
228 saved_visiting: Option<FxHashMap<TypeId, TypeId>>,
229 ) {
230 self.shadowed.truncate(shadowed_len);
231 if let Some(saved) = saved_visiting {
232 self.visiting = saved;
233 }
234 }
235
236 pub fn instantiate(&mut self, type_id: TypeId) -> TypeId {
238 if type_id.is_intrinsic() {
240 return type_id;
241 }
242
243 if self.depth_exceeded {
244 return TypeId::ERROR;
245 }
246
247 if self.depth >= self.max_depth {
248 self.depth_exceeded = true;
249 return TypeId::ERROR;
250 }
251
252 self.depth += 1;
253 let result = self.instantiate_inner(type_id);
254 self.depth -= 1;
255 result
256 }
257
258 fn instantiate_inner(&mut self, type_id: TypeId) -> TypeId {
259 if let Some(&cached) = self.visiting.get(&type_id) {
261 return cached;
262 }
263
264 let key = match self.interner.lookup(type_id) {
266 Some(k) => k,
267 None => return type_id,
268 };
269
270 self.visiting.insert(type_id, type_id);
272
273 let result = self.instantiate_key(&key);
274
275 self.visiting.insert(type_id, result);
277
278 result
279 }
280
281 fn instantiate_call_signature(&mut self, sig: &CallSignature) -> CallSignature {
283 let (shadowed_len, saved_visiting) = self.enter_shadowing_scope(&sig.type_params);
284
285 let type_predicate = sig
286 .type_predicate
287 .as_ref()
288 .map(|predicate| self.instantiate_type_predicate(predicate));
289 let this_type = sig.this_type.map(|type_id| self.instantiate(type_id));
290 let type_params = self.instantiate_type_params(&sig.type_params);
291 let params = self.instantiate_params(&sig.params);
292 let return_type = self.instantiate(sig.return_type);
293
294 self.exit_shadowing_scope(shadowed_len, saved_visiting);
295
296 CallSignature {
297 type_params,
298 params,
299 this_type,
300 return_type,
301 type_predicate,
302 is_method: sig.is_method,
303 }
304 }
305
306 fn instantiate_type_predicate(&mut self, predicate: &TypePredicate) -> TypePredicate {
307 TypePredicate {
308 asserts: predicate.asserts,
309 target: predicate.target.clone(),
310 type_id: predicate.type_id.map(|type_id| self.instantiate(type_id)),
311 parameter_index: predicate.parameter_index,
312 }
313 }
314
315 fn instantiate_key(&mut self, key: &TypeData) -> TypeId {
317 match key {
318 TypeData::TypeParameter(info) => {
320 if self.is_shadowed(info.name) {
321 return self.interner.intern(key.clone());
322 }
323 if let Some(substituted) = self.substitution.get(info.name) {
324 substituted
325 } else {
326 if let Some(constraint) = info.constraint {
331 let instantiated_constraint = self.instantiate(constraint);
332 if instantiated_constraint != constraint {
334 return instantiated_constraint;
335 }
336 }
337 self.interner.intern(key.clone())
339 }
340 }
341
342 TypeData::Intrinsic(_) | TypeData::Literal(_) | TypeData::Error => {
344 self.interner.intern(key.clone())
345 }
346
347 TypeData::Lazy(_)
349 | TypeData::Recursive(_)
350 | TypeData::BoundParameter(_)
351 | TypeData::TypeQuery(_)
352 | TypeData::UniqueSymbol(_)
353 | TypeData::ModuleNamespace(_) => self.interner.intern(key.clone()),
354
355 TypeData::Enum(def_id, member_type) => {
358 let instantiated_member = self.instantiate(*member_type);
359 self.interner.enum_type(*def_id, instantiated_member)
360 }
361
362 TypeData::Application(app_id) => {
364 let app = self.interner.type_application(*app_id);
365 let base = self.instantiate(app.base);
366 let args: Vec<TypeId> = app.args.iter().map(|&arg| self.instantiate(arg)).collect();
367 self.interner.application(base, args)
368 }
369
370 TypeData::ThisType => {
372 if let Some(this_type) = self.this_type {
373 this_type
374 } else {
375 self.interner.intern(key.clone())
376 }
377 }
378
379 TypeData::Union(members) => {
381 let members = self.interner.type_list(*members);
382 let instantiated: Vec<TypeId> =
383 members.iter().map(|&m| self.instantiate(m)).collect();
384 self.interner.union(instantiated)
385 }
386
387 TypeData::Intersection(members) => {
389 let members = self.interner.type_list(*members);
390 let instantiated: Vec<TypeId> =
391 members.iter().map(|&m| self.instantiate(m)).collect();
392 self.interner.intersection(instantiated)
393 }
394
395 TypeData::Array(elem) => {
397 let instantiated_elem = self.instantiate(*elem);
398 self.interner.array(instantiated_elem)
399 }
400
401 TypeData::Tuple(elements) => {
403 let elements = self.interner.tuple_list(*elements);
404 let instantiated: Vec<TupleElement> = elements
405 .iter()
406 .map(|e| TupleElement {
407 type_id: self.instantiate(e.type_id),
408 name: e.name,
409 optional: e.optional,
410 rest: e.rest,
411 })
412 .collect();
413 self.interner.tuple(instantiated)
414 }
415
416 TypeData::Object(shape_id) => {
418 let shape = self.interner.object_shape(*shape_id);
419 let instantiated = self.instantiate_properties(&shape.properties);
420 self.interner
421 .object_with_flags_and_symbol(instantiated, shape.flags, shape.symbol)
422 }
423
424 TypeData::ObjectWithIndex(shape_id) => {
426 let shape = self.interner.object_shape(*shape_id);
427 let instantiated_props = self.instantiate_properties(&shape.properties);
428 let instantiated_string_idx =
429 self.instantiate_index_signature(shape.string_index.as_ref());
430 let instantiated_number_idx =
431 self.instantiate_index_signature(shape.number_index.as_ref());
432 self.interner.object_with_index(ObjectShape {
433 flags: shape.flags,
434 properties: instantiated_props,
435 string_index: instantiated_string_idx,
436 number_index: instantiated_number_idx,
437 symbol: shape.symbol,
438 })
439 }
440
441 TypeData::Function(shape_id) => {
444 let shape = self.interner.function_shape(*shape_id);
445 let (shadowed_len, saved_visiting) = self.enter_shadowing_scope(&shape.type_params);
446
447 let type_predicate = shape
448 .type_predicate
449 .as_ref()
450 .map(|predicate| self.instantiate_type_predicate(predicate));
451 let this_type = shape.this_type.map(|type_id| self.instantiate(type_id));
452 let instantiated_type_params = self.instantiate_type_params(&shape.type_params);
453 let instantiated_params = self.instantiate_params(&shape.params);
454 let instantiated_return = self.instantiate(shape.return_type);
455
456 self.exit_shadowing_scope(shadowed_len, saved_visiting);
457
458 self.interner.function(FunctionShape {
459 type_params: instantiated_type_params,
460 params: instantiated_params,
461 this_type,
462 return_type: instantiated_return,
463 type_predicate,
464 is_constructor: shape.is_constructor,
465 is_method: shape.is_method,
466 })
467 }
468
469 TypeData::Callable(shape_id) => {
471 let shape = self.interner.callable_shape(*shape_id);
472 let instantiated_call: Vec<CallSignature> = shape
473 .call_signatures
474 .iter()
475 .map(|sig| self.instantiate_call_signature(sig))
476 .collect();
477 let instantiated_construct: Vec<CallSignature> = shape
478 .construct_signatures
479 .iter()
480 .map(|sig| self.instantiate_call_signature(sig))
481 .collect();
482 let instantiated_props = self.instantiate_properties(&shape.properties);
483
484 self.interner.callable(CallableShape {
485 call_signatures: instantiated_call,
486 construct_signatures: instantiated_construct,
487 properties: instantiated_props,
488 string_index: shape.string_index.clone(),
489 number_index: shape.number_index.clone(),
490 symbol: shape.symbol,
491 })
492 }
493
494 TypeData::Conditional(cond_id) => {
496 let cond = self.interner.conditional_type(*cond_id);
497 if cond.is_distributive
498 && let Some(TypeData::TypeParameter(info)) =
499 self.interner.lookup(cond.check_type)
500 && !self.is_shadowed(info.name)
501 && let Some(substituted) = self.substitution.get(info.name)
502 {
503 if substituted == crate::types::TypeId::NEVER {
505 return substituted;
506 }
507 if substituted == TypeId::BOOLEAN {
511 let cond_type = self.interner.conditional(cond.as_ref().clone());
512 let mut results = Vec::with_capacity(2);
513 for &member in &[TypeId::BOOLEAN_TRUE, TypeId::BOOLEAN_FALSE] {
514 if self.depth_exceeded {
515 return TypeId::ERROR;
516 }
517 let mut member_subst = self.substitution.clone();
518 member_subst.insert(info.name, member);
519 let instantiated =
520 instantiate_type(self.interner, cond_type, &member_subst);
521 if instantiated == TypeId::ERROR {
522 self.depth_exceeded = true;
523 return TypeId::ERROR;
524 }
525 let evaluated = crate::evaluation::evaluate::evaluate_type(
526 self.interner,
527 instantiated,
528 );
529 if evaluated == TypeId::ERROR {
530 self.depth_exceeded = true;
531 return TypeId::ERROR;
532 }
533 results.push(evaluated);
534 }
535 return self.interner.union(results);
536 }
537 if let Some(TypeData::Union(members)) = self.interner.lookup(substituted) {
538 let members = self.interner.type_list(members);
539 const MAX_DISTRIBUTION_SIZE: usize = 100;
542 if members.len() > MAX_DISTRIBUTION_SIZE {
543 self.depth_exceeded = true;
544 return TypeId::ERROR;
545 }
546 let cond_type = self.interner.conditional(cond.as_ref().clone());
547 let mut results = Vec::with_capacity(members.len());
548 for &member in members.iter() {
549 if self.depth_exceeded {
551 return TypeId::ERROR;
552 }
553 let mut member_subst = self.substitution.clone();
554 member_subst.insert(info.name, member);
555 let instantiated =
556 instantiate_type(self.interner, cond_type, &member_subst);
557 if instantiated == TypeId::ERROR {
559 self.depth_exceeded = true;
560 return TypeId::ERROR;
561 }
562 let evaluated = crate::evaluation::evaluate::evaluate_type(
563 self.interner,
564 instantiated,
565 );
566 if evaluated == TypeId::ERROR {
568 self.depth_exceeded = true;
569 return TypeId::ERROR;
570 }
571 results.push(evaluated);
572 }
573 return self.interner.union(results);
574 }
575 }
576 let instantiated = ConditionalType {
577 check_type: self.instantiate(cond.check_type),
578 extends_type: self.instantiate(cond.extends_type),
579 true_type: self.instantiate(cond.true_type),
580 false_type: self.instantiate(cond.false_type),
581 is_distributive: cond.is_distributive,
582 };
583 self.interner.conditional(instantiated)
584 }
585
586 TypeData::Mapped(mapped_id) => {
588 let mapped = self.interner.mapped_type(*mapped_id);
589 let tp_slice = std::slice::from_ref(&mapped.type_param);
590 let (shadowed_len, saved_visiting) = self.enter_shadowing_scope(tp_slice);
591
592 let new_constraint = self.instantiate(mapped.constraint);
593 let new_template = self.instantiate(mapped.template);
594 let new_name_type = mapped.name_type.map(|t| self.instantiate(t));
595 let new_param_constraint =
596 mapped.type_param.constraint.map(|c| self.instantiate(c));
597 let new_param_default = mapped.type_param.default.map(|d| self.instantiate(d));
598
599 self.exit_shadowing_scope(shadowed_len, saved_visiting);
600
601 let unchanged = new_constraint == mapped.constraint
605 && new_template == mapped.template
606 && new_name_type == mapped.name_type
607 && new_param_constraint == mapped.type_param.constraint
608 && new_param_default == mapped.type_param.default;
609
610 if unchanged {
611 return self.interner.mapped((*mapped).clone());
612 }
613
614 let instantiated = MappedType {
615 type_param: TypeParamInfo {
616 is_const: false,
617 name: mapped.type_param.name,
618 constraint: new_param_constraint,
619 default: new_param_default,
620 },
621 constraint: new_constraint,
622 name_type: new_name_type,
623 template: new_template,
624 readonly_modifier: mapped.readonly_modifier,
625 optional_modifier: mapped.optional_modifier,
626 };
627
628 let mapped_type = self.interner.mapped(instantiated);
633 crate::evaluation::evaluate::evaluate_type(self.interner, mapped_type)
634 }
635
636 TypeData::IndexAccess(obj, idx) => {
639 let inst_obj = self.instantiate(*obj);
640 let inst_idx = self.instantiate(*idx);
641 if crate::visitor::contains_type_parameters(self.interner, inst_obj)
646 || crate::visitor::contains_type_parameters(self.interner, inst_idx)
647 {
648 return self.interner.index_access(inst_obj, inst_idx);
649 }
650 crate::evaluation::evaluate::evaluate_index_access(
652 self.interner,
653 inst_obj,
654 inst_idx,
655 )
656 }
657
658 TypeData::KeyOf(operand) => {
661 let inst_operand = self.instantiate(*operand);
662 if crate::visitor::contains_type_parameters(self.interner, inst_operand) {
669 return self.interner.keyof(inst_operand);
670 }
671 crate::evaluation::evaluate::evaluate_keyof(self.interner, inst_operand)
673 }
674
675 TypeData::ReadonlyType(operand) => {
677 let inst_operand = self.instantiate(*operand);
678 self.interner.readonly_type(inst_operand)
679 }
680
681 TypeData::NoInfer(inner) => {
683 let inst_inner = self.instantiate(*inner);
684 self.interner.no_infer(inst_inner)
685 }
686
687 TypeData::TemplateLiteral(spans) => {
691 let spans = self.interner.template_list(*spans);
692 let mut instantiated: Vec<TemplateSpan> = Vec::with_capacity(spans.len());
693 let mut needs_evaluation = false;
694
695 for span in spans.iter() {
696 match span {
697 TemplateSpan::Text(t) => instantiated.push(TemplateSpan::Text(*t)),
698 TemplateSpan::Type(t) => {
699 let inst_type = self.instantiate(*t);
700 if let Some(
705 TypeData::Union(_)
706 | TypeData::Literal(
707 LiteralValue::String(_)
708 | LiteralValue::Number(_)
709 | LiteralValue::Boolean(_),
710 )
711 | TypeData::Intrinsic(
712 IntrinsicKind::String
713 | IntrinsicKind::Number
714 | IntrinsicKind::Boolean,
715 ),
716 ) = self.interner.lookup(inst_type)
717 {
718 needs_evaluation = true;
719 }
720 instantiated.push(TemplateSpan::Type(inst_type));
721 }
722 }
723 }
724
725 let template_type = self.interner.template_literal(instantiated);
726
727 if needs_evaluation {
730 crate::evaluation::evaluate::evaluate_type(self.interner, template_type)
731 } else {
732 template_type
733 }
734 }
735
736 TypeData::StringIntrinsic { kind, type_arg } => {
740 let inst_arg = self.instantiate(*type_arg);
741 let string_intrinsic = self.interner.string_intrinsic(*kind, inst_arg);
742
743 if let Some(key) = self.interner.lookup(inst_arg) {
745 match key {
746 TypeData::Union(_)
747 | TypeData::Literal(LiteralValue::String(_))
748 | TypeData::TemplateLiteral(_)
749 | TypeData::Intrinsic(IntrinsicKind::String) => {
750 crate::evaluation::evaluate::evaluate_type(
751 self.interner,
752 string_intrinsic,
753 )
754 }
755 _ => string_intrinsic,
756 }
757 } else {
758 string_intrinsic
759 }
760 }
761
762 TypeData::Infer(info) => {
764 if self.substitute_infer
765 && !self.is_shadowed(info.name)
766 && let Some(substituted) = self.substitution.get(info.name)
767 {
768 return substituted;
769 }
770 self.interner.infer(info.clone())
771 }
772 }
773 }
774}
775
776pub fn instantiate_type(
778 interner: &dyn TypeDatabase,
779 type_id: TypeId,
780 substitution: &TypeSubstitution,
781) -> TypeId {
782 if substitution.is_empty() {
783 return type_id;
784 }
785 let mut instantiator = TypeInstantiator::new(interner, substitution);
786 let result = instantiator.instantiate(type_id);
787 if instantiator.depth_exceeded {
788 TypeId::ERROR
789 } else {
790 result
791 }
792}
793
794pub fn instantiate_type_with_infer(
796 interner: &dyn TypeDatabase,
797 type_id: TypeId,
798 substitution: &TypeSubstitution,
799) -> TypeId {
800 if substitution.is_empty() {
801 return type_id;
802 }
803 let mut instantiator = TypeInstantiator::new(interner, substitution);
804 instantiator.substitute_infer = true;
805 let result = instantiator.instantiate(type_id);
806 if instantiator.depth_exceeded {
807 TypeId::ERROR
808 } else {
809 result
810 }
811}
812
813pub fn instantiate_generic(
815 interner: &dyn TypeDatabase,
816 type_id: TypeId,
817 type_params: &[TypeParamInfo],
818 type_args: &[TypeId],
819) -> TypeId {
820 if type_params.is_empty() || type_args.is_empty() {
821 return type_id;
822 }
823 let substitution = TypeSubstitution::from_args(interner, type_params, type_args);
824 instantiate_type(interner, type_id, &substitution)
825}
826
827pub fn substitute_this_type(
836 interner: &dyn TypeDatabase,
837 type_id: TypeId,
838 this_type: TypeId,
839) -> TypeId {
840 if type_id.is_intrinsic() {
842 return type_id;
843 }
844 let empty_subst = TypeSubstitution::new();
845 let mut instantiator = TypeInstantiator::new(interner, &empty_subst);
846 instantiator.this_type = Some(this_type);
847 let result = instantiator.instantiate(type_id);
848 if instantiator.depth_exceeded {
849 TypeId::ERROR
850 } else {
851 result
852 }
853}
854
855#[cfg(test)]
856#[path = "../../tests/instantiate_tests.rs"]
857mod tests;