1use std::{borrow::Cow, collections::hash_map::Entry};
2
3use source_map::{Nullable, SourceId, SpanWithSource};
4
5use crate::{
6 context::{
7 environment::{ContextLocation, ExpectedReturnType, FunctionScope},
8 get_on_ctx,
9 information::{merge_info, LocalInformation},
10 ContextType, Syntax,
11 },
12 diagnostics::{TypeCheckError, TypeStringRepresentation},
13 events::RootReference,
14 features::{create_closed_over_references, objects::ObjectBuilder},
15 subtyping::{type_is_subtype_object, SubTypeResult},
16 types::{
17 self,
18 calling::Callable,
19 classes::ClassValue,
20 functions::{FunctionBehavior, SynthesisedParameters},
21 generics::GenericTypeParameters,
22 logical::{Logical, LogicalOrValid},
23 printing::print_type,
24 properties::{get_property_unbound, PropertyKey, PropertyValue, Publicity},
25 substitute, Constructor, FunctionEffect, FunctionType, InternalFunctionEffect,
26 PartiallyAppliedGenerics, PolyNature, SubstitutionArguments, SynthesisedParameter,
27 SynthesisedRestParameter, TypeStore,
28 },
29 ASTImplementation, CheckingData, Constant, Environment, FunctionId, GeneralContext, Map,
30 ReadFromFS, Scope, Type, TypeId, VariableId,
31};
32
33#[derive(Debug, Clone, Copy)]
34pub enum GetterSetter {
35 Getter,
36 Setter,
37}
38
39pub fn register_arrow_function<T: crate::ReadFromFS, A: crate::ASTImplementation>(
40 expecting: TypeId,
41 is_async: bool,
42 function: &impl SynthesisableFunction<A>,
43 environment: &mut Environment,
44 checking_data: &mut CheckingData<T, A>,
45) -> TypeId {
46 let function_type = synthesise_function(
47 function,
48 FunctionRegisterBehavior::ArrowFunction { expecting, is_async },
49 environment,
50 checking_data,
51 );
52 checking_data.types.new_function_type(function_type)
53}
54
55#[allow(clippy::too_many_arguments)]
56pub fn register_expression_function<T: crate::ReadFromFS, A: crate::ASTImplementation>(
57 expected: TypeId,
58 is_async: bool,
59 is_generator: bool,
60 location: ContextLocation,
61 name: Option<String>,
62 function: &impl SynthesisableFunction<A>,
63 environment: &mut Environment,
64 checking_data: &mut CheckingData<T, A>,
65) -> TypeId {
66 let name = if let Some(name) = name {
67 checking_data.types.new_constant_type(Constant::String(name))
68 } else {
69 extract_name(expected, &checking_data.types, environment)
70 };
71 let function_type = synthesise_function(
72 function,
73 FunctionRegisterBehavior::ExpressionFunction {
74 expecting: expected,
75 is_async,
76 is_generator,
77 location,
78 name,
79 },
80 environment,
81 checking_data,
82 );
83 checking_data.types.new_function_type(function_type)
84}
85
86#[allow(clippy::too_many_arguments)]
87pub fn synthesise_hoisted_statement_function<T: crate::ReadFromFS, A: crate::ASTImplementation>(
88 variable_id: crate::VariableId,
89 overloaded: bool,
90 is_async: bool,
91 is_generator: bool,
92 location: ContextLocation,
93 name: String,
94 function: &impl SynthesisableFunction<A>,
95 environment: &mut Environment,
96 checking_data: &mut CheckingData<T, A>,
97) -> TypeId {
98 let name = checking_data.types.new_constant_type(Constant::String(name));
99 let behavior = FunctionRegisterBehavior::StatementFunction {
100 variable_id,
101 is_async,
102 is_generator,
103 location,
104 internal_marker: None,
105 name,
106 };
107
108 let function = synthesise_function(function, behavior, environment, checking_data);
109
110 if overloaded {
111 let _last_type = checking_data
112 .local_type_mappings
113 .variables_to_constraints
114 .0
115 .get(&variable_id)
116 .expect("variable constraint not set when trying to unify overload");
117
118 crate::utilities::notify!("TODO check that the result is the same");
119 }
120
121 let v = checking_data.types.new_function_type(function);
124 environment.info.variable_current_value.insert(variable_id, v);
125 v
126}
127
128#[allow(clippy::too_many_arguments)]
129pub fn synthesise_declare_statement_function<T: crate::ReadFromFS, A: crate::ASTImplementation>(
130 variable_id: crate::VariableId,
131 _overloaded: bool,
132 is_async: bool,
133 is_generator: bool,
134 location: ContextLocation,
135 name: String,
136 internal_marker: Option<InternalFunctionEffect>,
137 function: &impl SynthesisableFunction<A>,
138 environment: &mut Environment,
139 checking_data: &mut CheckingData<T, A>,
140) -> TypeId {
141 let name = checking_data.types.new_constant_type(Constant::String(name));
142 let behavior = FunctionRegisterBehavior::StatementFunction {
143 variable_id,
144 is_async,
145 is_generator,
146 location,
147 internal_marker,
148 name,
149 };
150
151 let function = synthesise_function(function, behavior, environment, checking_data);
152 let ty = checking_data.types.new_function_type(function);
153 environment.info.variable_current_value.insert(variable_id, ty);
154 ty
155}
156
157pub fn function_to_property(
158 getter_setter: Option<GetterSetter>,
159 function: FunctionType,
160 types: &mut TypeStore,
161 is_declare: bool,
162) -> PropertyValue {
163 match getter_setter {
164 Some(GetterSetter::Getter) => {
165 PropertyValue::Getter(Callable::new_from_function(function, types))
166 }
167 Some(GetterSetter::Setter) => {
168 PropertyValue::Setter(Callable::new_from_function(function, types))
169 }
170 None => PropertyValue::Value(
171 if is_declare && matches!(function.effect, FunctionEffect::Unknown) {
172 types.new_hoisted_function_type(function)
173 } else {
174 types.new_function_type(function)
175 },
176 ),
177 }
178}
179
180pub fn synthesise_function_default_value<'a, T: crate::ReadFromFS, A: ASTImplementation>(
181 parameter_ty: TypeId,
182 parameter_constraint: TypeId,
183 environment: &mut Environment,
184 checking_data: &mut CheckingData<T, A>,
185 expression: &'a A::Expression<'a>,
186) -> TypeId {
187 let (value, out, ..) = environment.new_lexical_environment_fold_into_parent(
188 Scope::DefaultFunctionParameter {},
189 checking_data,
190 |environment, checking_data| {
191 A::synthesise_expression(expression, parameter_constraint, environment, checking_data)
192 },
193 );
194
195 let at = A::expression_position(expression).with_source(environment.get_source());
196
197 {
198 let result = type_is_subtype_object(
199 parameter_constraint,
200 value,
201 environment,
202 &mut checking_data.types,
203 );
204
205 if let SubTypeResult::IsNotSubType(_) = result {
206 let expected = TypeStringRepresentation::from_type_id(
207 parameter_ty,
208 environment,
209 &checking_data.types,
210 false,
211 );
212
213 let found = TypeStringRepresentation::from_type_id(
214 value,
215 environment,
216 &checking_data.types,
217 false,
218 );
219
220 checking_data
221 .diagnostics_container
222 .add_error(TypeCheckError::InvalidDefaultParameter { at, expected, found });
223 }
224 }
225
226 let is_undefined_condition =
228 checking_data.types.register_type(Type::Constructor(Constructor::TypeExtends(
229 types::TypeExtends { item: parameter_ty, extends: TypeId::UNDEFINED_TYPE },
230 )));
231
232 let result =
236 checking_data.types.register_type(Type::Constructor(Constructor::ConditionalResult {
237 condition: is_undefined_condition,
238 truthy_result: value,
239 otherwise_result: parameter_ty,
240 result_union: parameter_constraint,
241 }));
242
243 let Some(GeneralContext::Syntax(parent)) = environment.context_type.get_parent() else {
245 unreachable!()
246 };
247 merge_info(
248 *parent,
249 &mut environment.info,
250 is_undefined_condition,
251 out.unwrap().0,
252 None,
253 &mut checking_data.types,
254 at,
255 );
256
257 result
258}
259
260#[derive(Clone, Copy)]
261pub struct ReturnType(pub TypeId, pub SpanWithSource);
262
263pub struct PartialFunction(
264 pub Option<GenericTypeParameters>,
265 pub SynthesisedParameters,
266 pub Option<ReturnType>,
267);
268
269pub trait SynthesisableFunction<A: crate::ASTImplementation> {
271 fn id(&self, source_id: SourceId) -> FunctionId {
272 FunctionId(source_id, self.get_position().start)
273 }
274
275 fn get_name(&self) -> Option<&str>;
277
278 fn get_position(&self) -> source_map::Span;
280
281 fn has_body(&self) -> bool;
283
284 fn type_parameters<T: ReadFromFS>(
289 &self,
290 environment: &mut Environment,
291 checking_data: &mut CheckingData<T, A>,
292 ) -> Option<GenericTypeParameters>;
293
294 fn this_constraint<T: ReadFromFS>(
295 &self,
296 environment: &mut Environment,
297 checking_data: &mut CheckingData<T, A>,
298 ) -> Option<TypeId>;
299
300 fn super_constraint<T: ReadFromFS>(
302 &self,
303 environment: &mut Environment,
304 checking_data: &mut CheckingData<T, A>,
305 ) -> Option<TypeId>;
306
307 fn parameters<T: ReadFromFS>(
309 &self,
310 environment: &mut Environment,
311 checking_data: &mut CheckingData<T, A>,
312 expected_parameters: Option<&SynthesisedParameters>,
313 ) -> SynthesisedParameters;
314
315 fn return_type_annotation<T: ReadFromFS>(
316 &self,
317 environment: &mut Environment,
318 checking_data: &mut CheckingData<T, A>,
319 ) -> Option<ReturnType>;
320
321 fn body<T: ReadFromFS>(
323 &self,
324 environment: &mut Environment,
325 checking_data: &mut CheckingData<T, A>,
326 );
327}
328
329pub enum FunctionRegisterBehavior<'a, A: crate::ASTImplementation> {
331 ArrowFunction {
332 expecting: TypeId,
333 is_async: bool,
334 },
335 ExpressionFunction {
336 expecting: TypeId,
337 is_async: bool,
338 is_generator: bool,
339 location: ContextLocation,
340 name: TypeId,
341 },
342 StatementFunction {
343 variable_id: VariableId,
345 is_async: bool,
346 is_generator: bool,
347 location: ContextLocation,
348 internal_marker: Option<InternalFunctionEffect>,
349 name: TypeId,
350 },
351 ObjectMethod {
352 expecting: TypeId,
354 is_async: bool,
355 is_generator: bool,
356 name: TypeId, },
358 ClassMethod {
359 expecting: TypeId,
361 is_async: bool,
362 is_generator: bool,
363 super_type: Option<TypeId>,
364 internal_marker: Option<InternalFunctionEffect>,
365 this_shape: TypeId,
367 name: TypeId,
368 },
369 Constructor {
370 prototype: TypeId,
371 super_type: Option<TypeId>,
373 properties: ClassPropertiesToRegister<'a, A>,
374 internal_marker: Option<InternalFunctionEffect>,
375 name: TypeId,
377 },
378}
379
380pub struct ClassPropertiesToRegister<'a, A: crate::ASTImplementation> {
381 pub properties: Vec<ClassValue<'a, A>>,
382}
383
384impl<'a, A: crate::ASTImplementation> FunctionRegisterBehavior<'a, A> {
385 #[must_use]
386 pub fn is_async(&self) -> bool {
387 match self {
388 FunctionRegisterBehavior::ArrowFunction { is_async, .. }
389 | FunctionRegisterBehavior::ExpressionFunction { is_async, .. }
390 | FunctionRegisterBehavior::StatementFunction { is_async, .. }
391 | FunctionRegisterBehavior::ObjectMethod { is_async, .. }
392 | FunctionRegisterBehavior::ClassMethod { is_async, .. } => *is_async,
393 FunctionRegisterBehavior::Constructor { .. } => false,
394 }
395 }
396
397 #[must_use]
398 pub fn is_generator(&self) -> bool {
399 match self {
400 FunctionRegisterBehavior::ExpressionFunction { is_generator, .. }
401 | FunctionRegisterBehavior::StatementFunction { is_generator, .. }
402 | FunctionRegisterBehavior::ObjectMethod { is_generator, .. }
403 | FunctionRegisterBehavior::ClassMethod { is_generator, .. } => *is_generator,
404 FunctionRegisterBehavior::ArrowFunction { .. }
405 | FunctionRegisterBehavior::Constructor { .. } => false,
406 }
407 }
408}
409
410#[derive(Clone, Debug, Default, binary_serialize_derive::BinarySerializable)]
411pub struct ClosedOverVariables(pub(crate) Map<VariableId, TypeId>);
412
413#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, binary_serialize_derive::BinarySerializable)]
414pub struct ClosureId(pub(crate) u32);
415
416pub trait ClosureChain {
417 fn get_fact_from_closure<T, R>(&self, fact: &LocalInformation, cb: T) -> Option<R>
418 where
419 T: Fn(ClosureId) -> Option<R>;
420}
421
422pub(crate) fn synthesise_function<T, A, F>(
423 function: &F,
424 behavior: FunctionRegisterBehavior<A>,
425 base_environment: &mut Environment,
426 checking_data: &mut CheckingData<T, A>,
427) -> FunctionType
428where
429 T: crate::ReadFromFS,
430 A: crate::ASTImplementation,
431 F: SynthesisableFunction<A>,
432{
433 struct FunctionKind<'a, A: crate::ASTImplementation> {
434 pub(super) behavior: FunctionBehavior,
435 pub(super) scope: FunctionScope,
436 pub(super) internal: Option<InternalFunctionEffect>,
437 pub(super) constructor: Option<(TypeId, ClassPropertiesToRegister<'a, A>)>,
439 pub(super) expected_parameters: Option<SynthesisedParameters>,
440 pub(super) this_shape: Option<TypeId>,
441 }
442
443 let _is_async = behavior.is_async();
444 let _is_generator = behavior.is_generator();
445
446 let kind: FunctionKind<A> = match behavior {
448 FunctionRegisterBehavior::Constructor {
449 super_type,
450 prototype,
451 properties,
452 internal_marker,
453 name,
454 } => {
455 FunctionKind {
456 behavior: FunctionBehavior::Constructor {
457 prototype,
458 this_object_type: TypeId::IS_ASSIGNED_VALUE_LATER,
459 name,
460 },
461 scope: FunctionScope::Constructor {
462 extends: super_type.is_some(),
463 type_of_super: super_type,
464 this_object_type: TypeId::IS_ASSIGNED_VALUE_LATER,
465 },
466 internal: internal_marker,
467 constructor: Some((prototype, properties)),
468 expected_parameters: None,
469 this_shape: None,
471 }
472 }
473 FunctionRegisterBehavior::ArrowFunction { expecting, is_async } => {
474 let (expected_parameters, expected_return) = get_expected_parameters_from_type(
475 expecting,
476 &mut checking_data.types,
477 base_environment,
478 );
479
480 if let Some((or, _)) =
481 expected_parameters.as_ref().and_then(|a| a.get_parameter_type_at_index(0))
482 {
483 crate::utilities::notify!(
484 "First expected parameter {:?}",
485 print_type(or, &checking_data.types, base_environment, true)
486 );
487 }
488
489 FunctionKind {
490 behavior: FunctionBehavior::ArrowFunction { is_async },
491 scope: FunctionScope::ArrowFunction {
492 free_this_type: TypeId::IS_ASSIGNED_VALUE_LATER,
493 is_async,
494 expected_return: expected_return.map(ExpectedReturnType::Inferred),
495 },
496 internal: None,
497 constructor: None,
498 expected_parameters,
499 this_shape: None,
500 }
501 }
502 FunctionRegisterBehavior::ExpressionFunction {
503 expecting,
504 is_async,
505 is_generator,
506 location,
507 name,
508 } => {
509 let (expected_parameters, expected_return) = get_expected_parameters_from_type(
510 expecting,
511 &mut checking_data.types,
512 base_environment,
513 );
514
515 let prototype = checking_data
516 .types
517 .register_type(Type::Object(crate::types::ObjectNature::RealDeal));
518
519 FunctionKind {
520 behavior: FunctionBehavior::Function {
521 is_async,
522 is_generator,
523 this_id: TypeId::IS_ASSIGNED_VALUE_LATER,
524 prototype,
525 name,
526 },
527 scope: FunctionScope::Function {
528 is_generator,
529 is_async,
530 this_type: TypeId::IS_ASSIGNED_VALUE_LATER,
532 type_of_super: TypeId::ANY_TYPE,
533 expected_return: expected_return.map(ExpectedReturnType::Inferred),
534 location,
535 },
536 internal: None,
537 constructor: None,
538 expected_parameters,
539 this_shape: None,
540 }
541 }
542 FunctionRegisterBehavior::StatementFunction {
543 variable_id: _variable_id,
544 is_async,
545 is_generator,
546 location,
547 internal_marker,
548 name,
549 } => {
550 let prototype = checking_data
551 .types
552 .register_type(Type::Object(crate::types::ObjectNature::RealDeal));
553
554 FunctionKind {
555 behavior: FunctionBehavior::Function {
556 is_async,
557 is_generator,
558 prototype,
559 this_id: TypeId::IS_ASSIGNED_VALUE_LATER,
560 name,
561 },
562 scope: FunctionScope::Function {
563 is_generator,
564 is_async,
565 this_type: TypeId::IS_ASSIGNED_VALUE_LATER,
566 type_of_super: TypeId::IS_ASSIGNED_VALUE_LATER,
567 expected_return: None,
568 location,
569 },
570 internal: internal_marker,
571 constructor: None,
572 expected_parameters: None,
573 this_shape: None,
574 }
575 }
576 FunctionRegisterBehavior::ClassMethod {
577 is_async,
578 is_generator,
579 super_type: _,
580 expecting,
581 internal_marker,
582 this_shape,
583 name,
584 } => {
585 let (expected_parameters, expected_return) = get_expected_parameters_from_type(
586 expecting,
587 &mut checking_data.types,
588 base_environment,
589 );
590
591 FunctionKind {
592 behavior: FunctionBehavior::Method {
593 is_async,
594 is_generator,
595 free_this_id: this_shape,
596 name,
597 },
598 scope: FunctionScope::MethodFunction {
599 free_this_type: this_shape,
600 is_async,
601 is_generator,
602 expected_return: expected_return.map(ExpectedReturnType::Inferred),
603 },
604 internal: internal_marker,
605 constructor: None,
606 expected_parameters,
607 this_shape: Some(this_shape),
608 }
609 }
610 FunctionRegisterBehavior::ObjectMethod { is_async, is_generator, expecting, name } => {
611 let (expected_parameters, expected_return) = get_expected_parameters_from_type(
612 expecting,
613 &mut checking_data.types,
614 base_environment,
615 );
616
617 FunctionKind {
618 behavior: FunctionBehavior::Method {
619 is_async,
620 is_generator,
621 free_this_id: TypeId::IS_ASSIGNED_VALUE_LATER,
622 name,
623 },
624 scope: FunctionScope::MethodFunction {
625 free_this_type: TypeId::IS_ASSIGNED_VALUE_LATER,
626 is_async,
627 is_generator,
628 expected_return: expected_return.map(ExpectedReturnType::Inferred),
629 },
630 internal: None,
631 constructor: None,
632 expected_parameters,
633 this_shape: None,
635 }
636 }
637 };
638
639 let id = function.id(base_environment.get_source());
640 let FunctionKind {
641 mut behavior,
642 scope,
643 internal,
644 constructor,
645 expected_parameters,
646 this_shape,
647 } = kind;
648
649 let mut function_environment = base_environment.new_lexical_environment(Scope::Function(scope));
650
651 if function.has_body() {
652 let type_parameters = if let Some((ref prototype, _)) = constructor {
653 class_generics_to_function_generics(*prototype, &checking_data.types)
655 } else {
656 function.type_parameters(&mut function_environment, checking_data)
657 };
658
659 let this_constraint =
661 function.this_constraint(&mut function_environment, checking_data).or(this_shape);
662
663 let position = function.get_position().with_source(base_environment.get_source());
664 if let Scope::Function(ref mut scope) = function_environment.context_type.scope {
666 match scope {
667 FunctionScope::ArrowFunction { ref mut free_this_type, .. }
668 | FunctionScope::MethodFunction { ref mut free_this_type, .. } => {
669 let type_id = if let Some(tc) = this_constraint {
670 checking_data.types.register_type(Type::RootPolyType(
671 PolyNature::FreeVariable {
672 reference: RootReference::This,
673 based_on: tc,
674 },
675 ))
676 } else {
677 TypeId::ANY_INFERRED_FREE_THIS
678 };
679
680 if let FunctionBehavior::Method { ref mut free_this_id, .. } = behavior {
681 *free_this_id = type_id;
682 }
683 *free_this_type = type_id;
684 }
685 FunctionScope::Function { ref mut this_type, .. } => {
686 let (this_free_variable, this_constructed_object) =
692 if let Some(this_constraint) = this_constraint {
693 let prototype = checking_data.types.register_type(Type::Constructor(
695 Constructor::Property {
696 on: TypeId::NEW_TARGET_ARG,
697 under: PropertyKey::String(Cow::Owned("value".to_owned())),
698 result: this_constraint,
699 mode: types::properties::AccessMode::Regular,
700 },
701 ));
702
703 let this_constructed_object = function_environment.info.new_object(
704 Some(prototype),
705 &mut checking_data.types,
706 position,
707 false,
708 );
709
710 let ty = Type::RootPolyType(PolyNature::FreeVariable {
711 reference: RootReference::This,
712 based_on: this_constraint,
713 });
714
715 let this_free_variable = checking_data.types.register_type(ty);
716
717 (this_free_variable, this_constructed_object)
718 } else {
719 let this_constructed_object = function_environment.info.new_object(
721 None,
722 &mut checking_data.types,
723 position,
724 false,
725 );
726 (TypeId::ANY_INFERRED_FREE_THIS, this_constructed_object)
727 };
728
729 let new_conditional_type = checking_data.types.new_conditional_type(
730 TypeId::NEW_TARGET_ARG,
731 this_constructed_object,
732 this_free_variable,
733 );
734
735 if let FunctionBehavior::Function { this_id: ref mut free_this_id, .. } =
737 behavior
738 {
739 *free_this_id = new_conditional_type;
740 }
741
742 *this_type = new_conditional_type;
746 }
747 FunctionScope::Constructor {
748 extends: _,
749 type_of_super: _,
750 ref mut this_object_type,
751 } => {
752 crate::utilities::notify!("Setting 'this' type here");
753 if let Some((prototype, properties)) = constructor {
754 let this_constructed_object = function_environment.info.new_object(
755 Some(prototype),
756 &mut checking_data.types,
757 position,
759 false,
760 );
761
762 *this_object_type = this_constructed_object;
763
764 types::classes::register_properties_into_environment(
766 &mut function_environment,
767 this_constructed_object,
768 checking_data,
769 properties,
770 position,
771 );
772
773 if let FunctionBehavior::Constructor { ref mut this_object_type, .. } =
777 behavior
778 {
779 crate::utilities::notify!("Set this object type");
780 *this_object_type = this_constructed_object;
781 } else {
782 unreachable!()
783 }
784 } else {
785 unreachable!()
786 }
787 }
788 }
789 } else {
790 unreachable!()
791 }
792
793 let synthesised_parameters = function.parameters(
795 &mut function_environment,
796 checking_data,
797 expected_parameters.as_ref(),
798 );
799
800 let return_type_annotation =
801 function.return_type_annotation(&mut function_environment, checking_data);
802
803 {
804 if let Scope::Function(ref mut scope) = function_environment.context_type.scope {
806 if !matches!(scope, FunctionScope::Constructor { .. }) {
807 if let (expect @ None, Some(ReturnType(return_type_annotation, pos))) =
808 (scope.get_expected_return_type_mut(), return_type_annotation)
809 {
810 *expect = Some(ExpectedReturnType::FromReturnAnnotation(
811 return_type_annotation,
812 pos.without_source(),
814 ));
815 }
816 }
817 }
818 }
819
820 function.body(&mut function_environment, checking_data);
821
822 let closes_over = create_closed_over_references(
823 &function_environment.context_type.closed_over_references,
824 &function_environment,
825 &checking_data.types,
826 );
827
828 let Syntax {
829 free_variables,
830 closed_over_references: function_closes_over,
831 requests: _,
832 ..
833 } = function_environment.context_type;
834
835 let info = function_environment.info;
843 let variable_names = function_environment.variable_names;
844
845 let returned = if function.has_body() {
846 let returned = info.state.get_returned(&mut checking_data.types);
847
848 if let Some(ReturnType(expected, _)) = return_type_annotation {
850 if crate::types::type_is_assert_is_type(expected, &checking_data.types).is_ok() {
851 let mut state = crate::subtyping::State {
852 already_checked: Default::default(),
853 mode: Default::default(),
854 contributions: Default::default(),
855 others: crate::subtyping::SubTypingOptions::default(),
856 object_constraints: None,
858 };
859
860 let result = crate::subtyping::type_is_subtype(
861 expected,
862 returned,
863 &mut state,
864 base_environment,
865 &checking_data.types,
866 );
867
868 if let crate::subtyping::SubTypeResult::IsNotSubType(_) = result {
869 checking_data.diagnostics_container.add_error(
870 TypeCheckError::ReturnedTypeDoesNotMatch {
871 expected_return_type: TypeStringRepresentation::from_type_id(
872 expected,
873 base_environment,
874 &checking_data.types,
875 checking_data.options.debug_types,
876 ),
877 returned_type: TypeStringRepresentation::from_type_id(
878 returned,
879 base_environment,
880 &checking_data.types,
881 checking_data.options.debug_types,
882 ),
883 annotation_position: position,
884 returned_position: function
885 .get_position()
886 .with_source(base_environment.get_source()),
887 },
888 );
889 }
890 }
891 }
892
893 returned
894 } else if let Some(ReturnType(ty, _)) = return_type_annotation {
895 ty
896 } else {
897 TypeId::UNDEFINED_TYPE
898 };
899
900 {
901 }
917
918 {
920 for (k, v) in &info.prototypes {
921 base_environment.info.prototypes.insert(*k, *v);
922 }
923
924 for (on, properties) in info.current_properties {
925 match base_environment.info.current_properties.entry(on) {
926 Entry::Occupied(_occupied) => {}
927 Entry::Vacant(vacant) => {
928 vacant.insert(properties);
929 }
930 }
931 }
932
933 for (on, properties) in info.closure_current_values {
935 match base_environment.info.closure_current_values.entry(on) {
936 Entry::Occupied(_occupied) => {}
937 Entry::Vacant(vacant) => {
938 vacant.insert(properties);
939 }
940 }
941 }
942 }
943
944 let continues_to_close_over = function_closes_over
946 .into_iter()
947 .filter(|r| match r {
948 RootReference::Variable(id) => {
949 let contains = base_environment
951 .parents_iter()
952 .any(|c| get_on_ctx!(&c.variable_names).contains_key(id));
953
954 crate::utilities::notify!("v-id {:?} con {:?}", id, contains);
955 contains
956 }
957 RootReference::This => !behavior.can_be_bound(),
958 })
959 .collect::<Vec<_>>();
960
961 if let Some(closed_over_variables) =
962 base_environment.context_type.get_closed_over_references_mut()
963 {
964 closed_over_variables.extend(free_variables.iter().cloned());
965 closed_over_variables.extend(continues_to_close_over);
966 }
967
968 let free_variables = free_variables
972 .into_iter()
973 .map(|reference| {
974 (reference, TypeId::ANY_TYPE)
976 })
977 .collect();
978
979 base_environment.variable_names.extend(variable_names);
981
982 let return_type = return_type_annotation.map_or(returned, |ReturnType(ty, _)| ty);
984
985 let effect = FunctionEffect::SideEffects {
986 events: info.events,
987 free_variables,
988 closed_over_variables: closes_over,
989 };
990
991 FunctionType {
992 id,
993 behavior,
994 type_parameters,
995 parameters: synthesised_parameters,
996 return_type,
997 effect,
998 }
999 } else {
1000 let type_parameters = function.type_parameters(&mut function_environment, checking_data);
1002
1003 let parameters = function.parameters(
1005 &mut function_environment,
1006 checking_data,
1007 expected_parameters.as_ref(),
1008 );
1009
1010 let return_type = function
1011 .return_type_annotation(&mut function_environment, checking_data)
1012 .map_or(TypeId::ANY_TYPE, |ReturnType(ty, _)| ty);
1013
1014 for (on, properties) in function_environment.info.current_properties {
1015 match base_environment.info.current_properties.entry(on) {
1016 Entry::Occupied(_occupied) => {}
1017 Entry::Vacant(vacant) => {
1018 vacant.insert(properties);
1019 }
1020 }
1021 }
1022
1023 let effect = internal.map_or(FunctionEffect::Unknown, Into::into);
1024
1025 FunctionType { id, type_parameters, parameters, return_type, behavior, effect }
1026 }
1027}
1028
1029fn get_expected_parameters_from_type(
1030 expecting: TypeId,
1031 types: &mut TypeStore,
1032 environment: &mut Environment,
1033) -> (Option<SynthesisedParameters>, Option<TypeId>) {
1034 let ty = types.get_type_by_id(expecting);
1035 if let Type::FunctionReference(func_id) = ty {
1036 let f = types.get_function_from_id(*func_id);
1037 (Some(f.parameters.clone()), Some(f.return_type))
1038 } else if let Type::PartiallyAppliedGenerics(PartiallyAppliedGenerics { arguments, on }) = ty {
1039 let structure_generic_arguments = arguments.clone();
1040
1041 let type_arguments = match structure_generic_arguments {
1043 types::generics::generic_type_arguments::GenericArguments::ExplicitRestrictions(
1044 explicit_restrictions,
1045 ) => SubstitutionArguments {
1046 parent: None,
1047 arguments: explicit_restrictions.into_iter().map(|(l, (r, _))| (l, r)).collect(),
1048 closures: Default::default(),
1049 },
1050 types::generics::generic_type_arguments::GenericArguments::Closure(_) => todo!(),
1051 types::generics::generic_type_arguments::GenericArguments::LookUp { .. } => todo!(),
1052 };
1053
1054 let (expected_parameters, expected_return_type) =
1055 get_expected_parameters_from_type(*on, types, environment);
1056
1057 (
1058 expected_parameters.map(|e| {
1059 let parameters = e
1060 .parameters
1061 .into_iter()
1062 .map(|p| SynthesisedParameter {
1063 ty: substitute(
1064 if let Type::RootPolyType(PolyNature::Parameter { fixed_to }) =
1065 types.get_type_by_id(p.ty)
1066 {
1067 *fixed_to
1068 } else {
1069 p.ty
1070 },
1071 &type_arguments,
1072 environment,
1073 types,
1074 ),
1075 ..p
1076 })
1077 .collect();
1078
1079 let rest_parameter = e.rest_parameter.map(|rp| SynthesisedRestParameter {
1080 item_type: substitute(rp.item_type, &type_arguments, environment, types),
1081 ..rp
1082 });
1083
1084 SynthesisedParameters { parameters, rest_parameter }
1085 }),
1086 expected_return_type.map(|rt| substitute(rt, &type_arguments, environment, types)),
1087 )
1088 } else {
1089 crate::utilities::notify!("(un)Expected = {:?}", ty);
1090 (None, None)
1091 }
1092}
1093
1094pub fn new_name_expected_object(
1100 name: TypeId,
1101 expected: TypeId,
1102 types: &mut TypeStore,
1103 environment: &mut Environment,
1104) -> TypeId {
1105 let mut name_object =
1106 ObjectBuilder::new(None, types, SpanWithSource::NULL, &mut environment.info);
1107
1108 name_object.append(
1109 types::properties::Publicity::Public,
1110 PropertyKey::String(Cow::Borrowed("name")),
1111 PropertyValue::Value(name),
1112 SpanWithSource::NULL,
1113 &mut environment.info,
1114 );
1115
1116 types.new_and_type(expected, name_object.build_object()) }
1118
1119#[must_use]
1121pub fn extract_name(expecting: TypeId, types: &TypeStore, environment: &Environment) -> TypeId {
1122 if let Type::And(_, rhs) = types.get_type_by_id(expecting) {
1123 if let Ok(LogicalOrValid::Logical(Logical::Pure(PropertyValue::Value(ty)))) =
1124 get_property_unbound(
1125 (*rhs, None),
1126 (Publicity::Public, &PropertyKey::String(Cow::Borrowed("name")), None),
1127 false,
1128 environment,
1129 types,
1130 ) {
1131 ty
1132 } else {
1133 crate::utilities::notify!("Here");
1134 TypeId::EMPTY_STRING
1135 }
1136 } else {
1137 TypeId::EMPTY_STRING
1138 }
1139}
1140
1141#[must_use]
1142pub fn class_generics_to_function_generics(
1143 prototype: TypeId,
1144 types: &TypeStore,
1145) -> Option<GenericTypeParameters> {
1146 types.get_type_by_id(prototype).get_parameters().map(|parameters| {
1147 parameters
1148 .into_iter()
1149 .map(|ty| {
1150 let Type::RootPolyType(PolyNature::StructureGeneric { name, .. }) =
1151 types.get_type_by_id(ty)
1152 else {
1153 unreachable!()
1154 };
1155 crate::types::generics::GenericTypeParameter {
1156 name: name.clone(),
1157 type_id: ty,
1159 default: None,
1160 }
1161 })
1162 .collect()
1163 })
1164}