1pub mod binary_ops;
39mod call_args;
40pub mod compound_assignment;
41mod constraints;
42mod constructors;
43pub mod expression_ops;
44mod generic_call;
45pub mod generics;
46pub mod iterators;
47pub mod property;
48mod property_readonly;
49mod property_visitor;
50pub mod widening;
51
52pub use binary_ops::{BinaryOpEvaluator, BinaryOpResult, PrimitiveClass};
54pub use compound_assignment::*;
55pub use expression_ops::*;
56pub use widening::*;
57
58use crate::diagnostics::PendingDiagnostic;
59use crate::instantiation::instantiate::{TypeSubstitution, instantiate_type};
60#[cfg(test)]
61use crate::types::*;
62use crate::types::{
63 CallSignature, CallableShape, CallableShapeId, FunctionShape, FunctionShapeId, IntrinsicKind,
64 LiteralValue, ParamInfo, TypeData, TypeId, TypeListId, TypePredicate,
65};
66use crate::visitor::TypeVisitor;
67use crate::{QueryDatabase, TypeDatabase};
68use rustc_hash::{FxHashMap, FxHashSet};
69use std::cell::RefCell;
70use tracing::debug;
71
72pub const MAX_CONSTRAINT_RECURSION_DEPTH: usize = 100;
74pub const MAX_CONSTRAINT_STEPS: usize = 20_000;
78
79pub trait AssignabilityChecker {
80 fn is_assignable_to(&mut self, source: TypeId, target: TypeId) -> bool;
81
82 fn is_assignable_to_strict(&mut self, source: TypeId, target: TypeId) -> bool {
83 self.is_assignable_to(source, target)
84 }
85
86 fn is_assignable_to_bivariant_callback(&mut self, source: TypeId, target: TypeId) -> bool {
91 self.is_assignable_to(source, target)
92 }
93
94 fn evaluate_type(&mut self, type_id: TypeId) -> TypeId {
99 type_id
100 }
101}
102
103#[derive(Clone, Debug)]
109pub enum CallResult {
110 Success(TypeId),
112
113 NotCallable { type_id: TypeId },
115
116 ThisTypeMismatch {
118 expected_this: TypeId,
119 actual_this: TypeId,
120 },
121
122 ArgumentCountMismatch {
124 expected_min: usize,
125 expected_max: Option<usize>,
126 actual: usize,
127 },
128
129 OverloadArgumentCountMismatch {
132 actual: usize,
133 expected_low: usize,
134 expected_high: usize,
135 },
136
137 ArgumentTypeMismatch {
139 index: usize,
140 expected: TypeId,
141 actual: TypeId,
142 },
143
144 NonVoidFunctionCalledWithNew,
146
147 TypeParameterConstraintViolation {
152 inferred_type: TypeId,
154 constraint_type: TypeId,
156 return_type: TypeId,
158 },
159
160 NoOverloadMatch {
162 func_type: TypeId,
163 arg_types: Vec<TypeId>,
164 failures: Vec<PendingDiagnostic>,
165 fallback_return: TypeId,
166 },
167}
168
169pub struct CallEvaluator<'a, C: AssignabilityChecker> {
171 pub(crate) interner: &'a dyn QueryDatabase,
172 pub(crate) checker: &'a mut C,
173 pub(crate) defaulted_placeholders: FxHashSet<TypeId>,
174 force_bivariant_callbacks: bool,
175 pub(crate) contextual_type: Option<TypeId>,
178 pub(crate) actual_this_type: Option<TypeId>,
180 pub(crate) constraint_recursion_depth: RefCell<usize>,
182 pub(crate) constraint_step_count: RefCell<usize>,
184 pub(crate) constraint_pairs: RefCell<FxHashSet<(TypeId, TypeId)>>,
186 pub(crate) constraint_fixed_union_members: RefCell<FxHashMap<TypeId, FxHashSet<TypeId>>>,
189 pub last_instantiated_predicate: Option<(TypePredicate, Vec<ParamInfo>)>,
192}
193
194impl<'a, C: AssignabilityChecker> CallEvaluator<'a, C> {
195 pub fn new(interner: &'a dyn QueryDatabase, checker: &'a mut C) -> Self {
196 CallEvaluator {
197 interner,
198 checker,
199 defaulted_placeholders: FxHashSet::default(),
200 force_bivariant_callbacks: false,
201 contextual_type: None,
202 actual_this_type: None,
203 constraint_recursion_depth: RefCell::new(0),
204 constraint_step_count: RefCell::new(0),
205 constraint_pairs: RefCell::new(FxHashSet::default()),
206 constraint_fixed_union_members: RefCell::new(FxHashMap::default()),
207 last_instantiated_predicate: None,
208 }
209 }
210
211 pub const fn set_actual_this_type(&mut self, type_id: Option<TypeId>) {
213 self.actual_this_type = type_id;
214 }
215
216 pub const fn set_contextual_type(&mut self, ctx_type: Option<TypeId>) {
221 self.contextual_type = ctx_type;
222 }
223
224 pub const fn set_force_bivariant_callbacks(&mut self, enabled: bool) {
225 self.force_bivariant_callbacks = enabled;
226 }
227
228 pub(crate) fn is_function_union_compat(
229 &mut self,
230 arg_type: TypeId,
231 mut target_type: TypeId,
232 ) -> bool {
233 if let Some(TypeData::Lazy(def_id)) = self.interner.lookup(target_type)
234 && let Some(resolved) = self.interner.resolve_lazy(def_id, self.interner)
235 {
236 target_type = resolved;
237 debug!(
238 target_type = target_type.0,
239 target_key = ?self.interner.lookup(target_type),
240 "is_function_union_compat: resolved lazy target"
241 );
242 }
243 if !matches!(self.interner.lookup(target_type), Some(TypeData::Union(_))) {
244 let evaluated = self.interner.evaluate_type(target_type);
245 if evaluated != target_type {
246 target_type = evaluated;
247 debug!(
248 target_type = target_type.0,
249 target_key = ?self.interner.lookup(target_type),
250 "is_function_union_compat: evaluated target"
251 );
252 }
253 if let Some(TypeData::Lazy(def_id)) = self.interner.lookup(target_type)
254 && let Some(resolved) = self.interner.resolve_lazy(def_id, self.interner)
255 {
256 target_type = resolved;
257 debug!(
258 target_type = target_type.0,
259 target_key = ?self.interner.lookup(target_type),
260 "is_function_union_compat: resolved lazy target after eval"
261 );
262 }
263 }
264 let Some(TypeData::Union(members_id)) = self.interner.lookup(target_type) else {
265 return false;
266 };
267 if !crate::type_queries::is_callable_type(self.interner, arg_type) {
268 return false;
269 }
270 let members = self.interner.type_list(members_id);
271 if members
272 .iter()
273 .any(|&member| self.checker.is_assignable_to(arg_type, member))
274 {
275 return true;
276 }
277 let synthetic_any_fn = self.interner.function(FunctionShape {
278 type_params: vec![],
279 params: vec![],
280 return_type: TypeId::ANY,
281 this_type: None,
282 type_predicate: None,
283 is_constructor: false,
284 is_method: false,
285 });
286 if members
287 .iter()
288 .any(|&member| self.checker.is_assignable_to(synthetic_any_fn, member))
289 {
290 return true;
291 }
292 members
293 .iter()
294 .any(|&member| self.is_function_like_union_member(member))
295 }
296
297 fn normalize_union_member(&self, mut member: TypeId) -> TypeId {
298 for _ in 0..8 {
299 let next = match self.interner.lookup(member) {
300 Some(TypeData::Lazy(def_id)) => self
301 .interner
302 .resolve_lazy(def_id, self.interner)
303 .unwrap_or(member),
304 Some(TypeData::Application(_) | TypeData::Mapped(_)) => {
305 self.interner.evaluate_type(member)
306 }
307 _ => member,
308 };
309 if next == member {
310 break;
311 }
312 member = next;
313 }
314 member
315 }
316
317 fn is_function_like_union_member(&self, member: TypeId) -> bool {
318 let member = self.normalize_union_member(member);
319 match self.interner.lookup(member) {
320 Some(TypeData::Intrinsic(IntrinsicKind::Function))
321 | Some(TypeData::Function(_) | TypeData::Callable(_)) => true,
322 Some(TypeData::Object(shape_id) | TypeData::ObjectWithIndex(shape_id)) => {
323 let shape = self.interner.object_shape(shape_id);
324 let apply = self.interner.intern_string("apply");
325 let call = self.interner.intern_string("call");
326 let has_apply = shape.properties.iter().any(|prop| prop.name == apply);
327 let has_call = shape.properties.iter().any(|prop| prop.name == call);
328 has_apply && has_call
329 }
330 Some(TypeData::Union(members_id)) => self
331 .interner
332 .type_list(members_id)
333 .iter()
334 .any(|&m| self.is_function_like_union_member(m)),
335 Some(TypeData::Intersection(members_id)) => self
336 .interner
337 .type_list(members_id)
338 .iter()
339 .any(|&m| self.is_function_like_union_member(m)),
340 _ => false,
341 }
342 }
343
344 pub fn infer_call_signature(&mut self, sig: &CallSignature, arg_types: &[TypeId]) -> TypeId {
345 let func = FunctionShape {
346 params: sig.params.clone(),
347 this_type: sig.this_type,
348 return_type: sig.return_type,
349 type_params: sig.type_params.clone(),
350 type_predicate: sig.type_predicate.clone(),
351 is_constructor: false,
352 is_method: sig.is_method,
353 };
354 match self.resolve_function_call(&func, arg_types) {
355 CallResult::Success(ret) => ret,
356 _ => TypeId::ERROR,
358 }
359 }
360
361 pub fn infer_generic_function(&mut self, func: &FunctionShape, arg_types: &[TypeId]) -> TypeId {
362 match self.resolve_function_call(func, arg_types) {
363 CallResult::Success(ret) => ret,
364 _ => TypeId::ERROR,
366 }
367 }
368
369 pub fn get_contextual_signature(
383 db: &dyn TypeDatabase,
384 type_id: TypeId,
385 ) -> Option<FunctionShape> {
386 Self::get_contextual_signature_for_arity(db, type_id, None)
387 }
388
389 pub fn get_contextual_signature_for_arity(
392 db: &dyn TypeDatabase,
393 type_id: TypeId,
394 arg_count: Option<usize>,
395 ) -> Option<FunctionShape> {
396 struct ContextualSignatureVisitor<'a> {
397 db: &'a dyn TypeDatabase,
398 arg_count: Option<usize>,
399 }
400
401 impl<'a> TypeVisitor for ContextualSignatureVisitor<'a> {
402 type Output = Option<FunctionShape>;
403
404 fn default_output() -> Self::Output {
405 None
406 }
407
408 fn visit_intrinsic(&mut self, _kind: IntrinsicKind) -> Self::Output {
409 None
410 }
411
412 fn visit_literal(&mut self, _value: &LiteralValue) -> Self::Output {
413 None
414 }
415
416 fn visit_ref(&mut self, ref_id: u32) -> Self::Output {
417 self.visit_type(self.db, TypeId(ref_id))
420 }
421
422 fn visit_function(&mut self, shape_id: u32) -> Self::Output {
423 let shape = self.db.function_shape(FunctionShapeId(shape_id));
425 Some(shape.as_ref().clone())
426 }
427
428 fn visit_callable(&mut self, shape_id: u32) -> Self::Output {
429 let shape = self.db.callable_shape(CallableShapeId(shape_id));
430
431 let signatures = if shape.call_signatures.is_empty() {
434 &shape.construct_signatures
435 } else {
436 &shape.call_signatures
437 };
438
439 let sig = if let Some(count) = self.arg_count {
441 signatures
442 .iter()
443 .find(|sig| {
444 let min_args =
445 sig.params.iter().filter(|p| !p.optional && !p.rest).count();
446 let has_rest = sig.params.iter().any(|p| p.rest);
447 count >= min_args && (has_rest || count <= sig.params.len())
448 })
449 .or_else(|| signatures.first())
450 } else {
451 signatures.first()
452 };
453
454 sig.map(|sig| FunctionShape {
455 type_params: sig.type_params.clone(),
456 params: sig.params.clone(),
457 this_type: sig.this_type,
458 return_type: sig.return_type,
459 type_predicate: sig.type_predicate.clone(),
460 is_constructor: false,
461 is_method: sig.is_method,
462 })
463 }
464
465 fn visit_application(&mut self, app_id: u32) -> Self::Output {
466 use crate::types::TypeApplicationId;
467
468 let app = self.db.type_application(TypeApplicationId(app_id));
470
471 let base_shape = self.visit_type(self.db, app.base)?;
474
475 let subst =
479 TypeSubstitution::from_args(self.db, &base_shape.type_params, &app.args);
480
481 if subst.is_empty() {
483 return Some(base_shape);
484 }
485
486 let instantiated_params: Vec<ParamInfo> = base_shape
488 .params
489 .iter()
490 .map(|p| ParamInfo {
491 name: p.name,
492 type_id: instantiate_type(self.db, p.type_id, &subst),
493 optional: p.optional,
494 rest: p.rest,
495 })
496 .collect();
497
498 let instantiated_return = instantiate_type(self.db, base_shape.return_type, &subst);
499
500 let instantiated_this = base_shape
501 .this_type
502 .map(|t| instantiate_type(self.db, t, &subst));
503
504 let instantiated_predicate =
506 base_shape
507 .type_predicate
508 .as_ref()
509 .map(|pred| TypePredicate {
510 asserts: pred.asserts,
511 target: pred.target.clone(),
512 type_id: pred.type_id.map(|t| instantiate_type(self.db, t, &subst)),
513 parameter_index: pred.parameter_index,
514 });
515
516 Some(FunctionShape {
518 type_params: Vec::new(),
521 params: instantiated_params,
522 this_type: instantiated_this,
523 return_type: instantiated_return,
524 type_predicate: instantiated_predicate,
525 is_constructor: base_shape.is_constructor,
526 is_method: base_shape.is_method,
527 })
528 }
529
530 fn visit_intersection(&mut self, list_id: u32) -> Self::Output {
531 let members = self.db.type_list(TypeListId(list_id));
532 for &member in members.iter() {
533 if let Some(shape) = self.visit_type(self.db, member) {
534 return Some(shape);
535 }
536 }
537 None
538 }
539
540 }
542
543 let mut visitor = ContextualSignatureVisitor { db, arg_count };
544 visitor.visit_type(db, type_id)
545 }
546
547 pub fn resolve_call(&mut self, func_type: TypeId, arg_types: &[TypeId]) -> CallResult {
551 self.last_instantiated_predicate = None;
552 let key = match self.interner.lookup(func_type) {
554 Some(k) => k,
555 None => return CallResult::NotCallable { type_id: func_type },
556 };
557
558 match key {
559 TypeData::Function(f_id) => {
560 let shape = self.interner.function_shape(f_id);
561 self.resolve_function_call(shape.as_ref(), arg_types)
562 }
563 TypeData::Callable(c_id) => {
564 let shape = self.interner.callable_shape(c_id);
565 self.resolve_callable_call(shape.as_ref(), arg_types)
566 }
567 TypeData::Union(list_id) => {
568 self.resolve_union_call(func_type, list_id, arg_types)
571 }
572 TypeData::Intersection(list_id) => {
573 self.resolve_intersection_call(func_type, list_id, arg_types)
576 }
577 TypeData::Application(_app_id) => {
578 let evaluated = self.checker.evaluate_type(func_type);
581 if evaluated != func_type {
582 self.resolve_call(evaluated, arg_types)
583 } else {
584 CallResult::NotCallable { type_id: func_type }
585 }
586 }
587 TypeData::TypeParameter(param_info) => {
588 if let Some(constraint) = param_info.constraint {
591 self.resolve_call(constraint, arg_types)
592 } else {
593 CallResult::NotCallable { type_id: func_type }
594 }
595 }
596 TypeData::Lazy(_)
597 | TypeData::Conditional(_)
598 | TypeData::IndexAccess(_, _)
599 | TypeData::Mapped(_)
600 | TypeData::TemplateLiteral(_) => {
601 let resolved = crate::evaluation::evaluate::evaluate_type(self.interner, func_type);
605 if resolved != func_type {
606 self.resolve_call(resolved, arg_types)
607 } else {
608 CallResult::NotCallable { type_id: func_type }
609 }
610 }
611 TypeData::Intrinsic(IntrinsicKind::Function | IntrinsicKind::Any) => {
614 CallResult::Success(TypeId::ANY)
615 }
616 TypeData::Error => CallResult::Success(TypeId::ERROR),
619 _ => CallResult::NotCallable { type_id: func_type },
620 }
621 }
622
623 fn resolve_union_call(
632 &mut self,
633 union_type: TypeId,
634 list_id: TypeListId,
635 arg_types: &[TypeId],
636 ) -> CallResult {
637 let members = self.interner.type_list(list_id);
638
639 let mut return_types = Vec::new();
641 let mut failures = Vec::new();
642
643 for &member in members.iter() {
644 let result = self.resolve_call(member, arg_types);
645 match result {
646 CallResult::Success(return_type) => {
647 return_types.push(return_type);
648 }
649 CallResult::NotCallable { .. } => {
650 return CallResult::NotCallable {
654 type_id: union_type,
655 };
656 }
657 other => {
658 failures.push(other);
660 }
661 }
662 }
663
664 if !return_types.is_empty() {
667 if return_types.len() == 1 {
668 return CallResult::Success(return_types[0]);
669 }
670 let union_result = self.interner.union(return_types);
672 CallResult::Success(union_result)
673 } else if !failures.is_empty() {
674 let all_arg_mismatches = failures
679 .iter()
680 .all(|f| matches!(f, CallResult::ArgumentTypeMismatch { .. }));
681
682 if all_arg_mismatches && !failures.is_empty() {
683 let mut param_types = Vec::new();
685 for failure in &failures {
686 if let CallResult::ArgumentTypeMismatch { expected, .. } = failure {
687 param_types.push(*expected);
688 }
689 }
690
691 let intersected_param = if param_types.len() == 1 {
694 param_types[0]
695 } else {
696 let mut result = param_types[0];
698 for ¶m_type in ¶m_types[1..] {
699 result = self.interner.intersection2(result, param_type);
700 }
701 result
702 };
703
704 let actual_arg_type =
707 if let Some(CallResult::ArgumentTypeMismatch { actual, .. }) = failures.first()
708 {
709 *actual
710 } else {
711 TypeId::ERROR
713 };
714
715 return CallResult::ArgumentTypeMismatch {
716 index: 0,
717 expected: intersected_param,
718 actual: actual_arg_type,
719 };
720 }
721
722 failures
724 .into_iter()
725 .next()
726 .unwrap_or(CallResult::NotCallable {
727 type_id: union_type,
728 })
729 } else {
730 CallResult::NotCallable {
732 type_id: union_type,
733 }
734 }
735 }
736
737 fn resolve_intersection_call(
746 &mut self,
747 intersection_type: TypeId,
748 list_id: TypeListId,
749 arg_types: &[TypeId],
750 ) -> CallResult {
751 let members = self.interner.type_list(list_id);
752
753 for &member in members.iter() {
757 let result = self.resolve_call(member, arg_types);
758 match result {
759 CallResult::Success(return_type) => {
760 return CallResult::Success(return_type);
762 }
763 CallResult::NotCallable { .. } => {
764 continue;
766 }
767 other => {
768 return other;
771 }
772 }
773 }
774
775 CallResult::NotCallable {
777 type_id: intersection_type,
778 }
779 }
780
781 pub(crate) fn resolve_function_call(
783 &mut self,
784 func: &FunctionShape,
785 arg_types: &[TypeId],
786 ) -> CallResult {
787 if !func.type_params.is_empty() {
789 return self.resolve_generic_call(func, arg_types);
790 }
791
792 if let Some(expected_this) = func.this_type {
794 if let Some(actual_this) = self.actual_this_type {
795 if !self.checker.is_assignable_to(actual_this, expected_this) {
796 return CallResult::ThisTypeMismatch {
797 expected_this,
798 actual_this,
799 };
800 }
801 }
802 else if !self.checker.is_assignable_to(TypeId::VOID, expected_this) {
805 return CallResult::ThisTypeMismatch {
806 expected_this,
807 actual_this: TypeId::VOID,
808 };
809 }
810 }
811
812 let (min_args, max_args) = self.arg_count_bounds(&func.params);
814
815 if arg_types.len() < min_args {
816 return CallResult::ArgumentCountMismatch {
817 expected_min: min_args,
818 expected_max: max_args,
819 actual: arg_types.len(),
820 };
821 }
822
823 if let Some(max) = max_args
824 && arg_types.len() > max
825 {
826 return CallResult::ArgumentCountMismatch {
827 expected_min: min_args,
828 expected_max: Some(max),
829 actual: arg_types.len(),
830 };
831 }
832
833 if let Some(result) = self.check_argument_types(&func.params, arg_types, func.is_method) {
836 return result;
837 }
838
839 CallResult::Success(func.return_type)
840 }
841
842 pub(crate) fn resolve_callable_call(
844 &mut self,
845 callable: &CallableShape,
846 arg_types: &[TypeId],
847 ) -> CallResult {
848 if callable.call_signatures.is_empty() {
851 return CallResult::NotCallable {
852 type_id: self.interner.callable(callable.clone()),
853 };
854 }
855
856 if callable.call_signatures.len() == 1 {
857 let sig = &callable.call_signatures[0];
858 let func = FunctionShape {
859 params: sig.params.clone(),
860 this_type: sig.this_type,
861 return_type: sig.return_type,
862 type_params: sig.type_params.clone(),
863 type_predicate: sig.type_predicate.clone(),
864 is_constructor: false,
865 is_method: sig.is_method,
866 };
867 return self.resolve_function_call(&func, arg_types);
868 }
869
870 let mut failures = Vec::new();
872 let mut all_arg_count_mismatches = true;
873 let mut min_expected = usize::MAX;
874 let mut max_expected = 0;
875 let mut any_has_rest = false;
876 let actual_count = arg_types.len();
877 let mut exact_expected_counts = FxHashSet::default();
878 let mut type_mismatch_count: usize = 0;
882 let mut first_type_mismatch: Option<(usize, TypeId, TypeId)> = None; let mut all_mismatches_identical = true;
884 let mut has_non_count_non_type_failure = false;
885
886 for sig in &callable.call_signatures {
887 let func = FunctionShape {
889 params: sig.params.clone(),
890 this_type: sig.this_type,
891 return_type: sig.return_type,
892 type_params: sig.type_params.clone(),
893 type_predicate: sig.type_predicate.clone(),
894 is_constructor: false,
895 is_method: sig.is_method,
896 };
897 tracing::debug!("resolve_callable_call: signature = {sig:?}");
898
899 match self.resolve_function_call(&func, arg_types) {
900 CallResult::Success(ret) => return CallResult::Success(ret),
901 CallResult::TypeParameterConstraintViolation { return_type, .. } => {
902 return CallResult::Success(return_type);
905 }
906 CallResult::ArgumentTypeMismatch {
907 index,
908 expected,
909 actual,
910 } => {
911 all_arg_count_mismatches = false;
912 type_mismatch_count += 1;
913 if type_mismatch_count == 1 {
914 first_type_mismatch = Some((index, expected, actual));
915 } else if first_type_mismatch != Some((index, expected, actual)) {
916 all_mismatches_identical = false;
917 }
918 failures.push(
919 crate::diagnostics::PendingDiagnosticBuilder::argument_not_assignable(
920 actual, expected,
921 ),
922 );
923 }
924 CallResult::ArgumentCountMismatch {
925 expected_min,
926 expected_max,
927 actual,
928 } => {
929 if expected_max.is_none() {
930 any_has_rest = true;
931 } else if expected_min == expected_max.unwrap_or(expected_min) {
932 exact_expected_counts.insert(expected_min);
933 }
934 let expected = expected_max.unwrap_or(expected_min);
935 min_expected = min_expected.min(expected_min);
936 max_expected = max_expected.max(expected);
937 failures.push(
938 crate::diagnostics::PendingDiagnosticBuilder::argument_count_mismatch(
939 expected, actual,
940 ),
941 );
942 }
943 _ => {
944 all_arg_count_mismatches = false;
945 has_non_count_non_type_failure = true;
946 }
947 }
948 }
949
950 if all_arg_count_mismatches && !failures.is_empty() {
952 if !any_has_rest
953 && !exact_expected_counts.is_empty()
954 && !exact_expected_counts.contains(&actual_count)
955 {
956 let mut lower = None;
957 let mut upper = None;
958 for &count in &exact_expected_counts {
959 if count < actual_count {
960 lower = Some(lower.map_or(count, |prev: usize| prev.max(count)));
961 } else if count > actual_count {
962 upper = Some(upper.map_or(count, |prev: usize| prev.min(count)));
963 }
964 }
965 if let (Some(expected_low), Some(expected_high)) = (lower, upper) {
966 return CallResult::OverloadArgumentCountMismatch {
967 actual: actual_count,
968 expected_low,
969 expected_high,
970 };
971 }
972 }
973 return CallResult::ArgumentCountMismatch {
974 expected_min: min_expected,
975 expected_max: if any_has_rest {
976 None
977 } else if max_expected > min_expected {
978 Some(max_expected)
979 } else {
980 Some(min_expected)
981 },
982 actual: actual_count,
983 };
984 }
985
986 if !has_non_count_non_type_failure
990 && type_mismatch_count > 0
991 && all_mismatches_identical
992 && let Some((index, expected, actual)) = first_type_mismatch
993 {
994 return CallResult::ArgumentTypeMismatch {
995 index,
996 expected,
997 actual,
998 };
999 }
1000
1001 CallResult::NoOverloadMatch {
1003 func_type: self.interner.callable(callable.clone()),
1004 arg_types: arg_types.to_vec(),
1005 failures,
1006 fallback_return: callable
1007 .call_signatures
1008 .first()
1009 .map(|s| s.return_type)
1010 .unwrap_or(TypeId::ANY),
1011 }
1012 }
1013}
1014
1015pub fn infer_call_signature<C: AssignabilityChecker>(
1016 interner: &dyn QueryDatabase,
1017 checker: &mut C,
1018 sig: &CallSignature,
1019 arg_types: &[TypeId],
1020) -> TypeId {
1021 let mut evaluator = CallEvaluator::new(interner, checker);
1022 evaluator.infer_call_signature(sig, arg_types)
1023}
1024
1025pub fn infer_generic_function<C: AssignabilityChecker>(
1026 interner: &dyn QueryDatabase,
1027 checker: &mut C,
1028 func: &FunctionShape,
1029 arg_types: &[TypeId],
1030) -> TypeId {
1031 let mut evaluator = CallEvaluator::new(interner, checker);
1032 evaluator.infer_generic_function(func, arg_types)
1033}
1034
1035pub fn resolve_call_with_checker<C: AssignabilityChecker>(
1036 interner: &dyn QueryDatabase,
1037 checker: &mut C,
1038 func_type: TypeId,
1039 arg_types: &[TypeId],
1040 force_bivariant_callbacks: bool,
1041 contextual_type: Option<TypeId>,
1042 actual_this_type: Option<TypeId>,
1043) -> (CallResult, Option<(TypePredicate, Vec<ParamInfo>)>) {
1044 let mut evaluator = CallEvaluator::new(interner, checker);
1045 evaluator.set_force_bivariant_callbacks(force_bivariant_callbacks);
1046 evaluator.set_contextual_type(contextual_type);
1047 evaluator.set_actual_this_type(actual_this_type);
1048 let result = evaluator.resolve_call(func_type, arg_types);
1049 let predicate = evaluator.last_instantiated_predicate.take();
1050 (result, predicate)
1051}
1052
1053pub fn resolve_new_with_checker<C: AssignabilityChecker>(
1054 interner: &dyn QueryDatabase,
1055 checker: &mut C,
1056 type_id: TypeId,
1057 arg_types: &[TypeId],
1058 force_bivariant_callbacks: bool,
1059) -> CallResult {
1060 let mut evaluator = CallEvaluator::new(interner, checker);
1061 evaluator.set_force_bivariant_callbacks(force_bivariant_callbacks);
1062 evaluator.resolve_new(type_id, arg_types)
1063}
1064
1065pub fn compute_contextual_types_with_compat_checker<'a, R, F>(
1066 interner: &'a dyn QueryDatabase,
1067 resolver: &'a R,
1068 shape: &FunctionShape,
1069 arg_types: &[TypeId],
1070 contextual_type: Option<TypeId>,
1071 configure_checker: F,
1072) -> TypeSubstitution
1073where
1074 R: crate::TypeResolver,
1075 F: FnOnce(&mut crate::CompatChecker<'a, R>),
1076{
1077 let mut checker = crate::CompatChecker::with_resolver(interner, resolver);
1078 configure_checker(&mut checker);
1079
1080 let mut evaluator = CallEvaluator::new(interner, &mut checker);
1081 evaluator.set_contextual_type(contextual_type);
1082 evaluator.compute_contextual_types(shape, arg_types)
1083}
1084
1085pub fn get_contextual_signature_with_compat_checker(
1086 db: &dyn TypeDatabase,
1087 type_id: TypeId,
1088) -> Option<FunctionShape> {
1089 CallEvaluator::<crate::CompatChecker>::get_contextual_signature(db, type_id)
1090}
1091
1092pub use generics::{GenericInstantiationResult, solve_generic_instantiation};
1094pub use iterators::{IteratorInfo, get_async_iterable_element_type, get_iterator_info};
1095
1096#[cfg(test)]
1097#[path = "../../tests/operations_tests.rs"]
1098mod tests;