OLD | NEW |
---|---|
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE.md file. | 3 // BSD-style license that can be found in the LICENSE.md file. |
4 | 4 |
5 import 'package:front_end/src/base/instrumentation.dart'; | 5 import 'package:front_end/src/base/instrumentation.dart'; |
6 import 'package:front_end/src/fasta/errors.dart' show internalError; | 6 import 'package:front_end/src/fasta/errors.dart' show internalError; |
7 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart'; | 7 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart'; |
8 import 'package:front_end/src/fasta/names.dart' show callName; | 8 import 'package:front_end/src/fasta/names.dart' show callName; |
9 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart'; | 9 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart'; |
10 import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart' ; | 10 import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart' ; |
11 import 'package:front_end/src/fasta/type_inference/type_promotion.dart'; | 11 import 'package:front_end/src/fasta/type_inference/type_promotion.dart'; |
12 import 'package:front_end/src/fasta/type_inference/type_schema.dart'; | 12 import 'package:front_end/src/fasta/type_inference/type_schema.dart'; |
13 import 'package:front_end/src/fasta/type_inference/type_schema_elimination.dart' ; | 13 import 'package:front_end/src/fasta/type_inference/type_schema_elimination.dart' ; |
14 import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart' ; | 14 import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart' ; |
15 import 'package:kernel/ast.dart' | 15 import 'package:kernel/ast.dart' |
16 show | 16 show |
17 Arguments, | 17 Arguments, |
18 AsyncMarker, | 18 AsyncMarker, |
19 BottomType, | 19 BottomType, |
20 Class, | 20 Class, |
21 DartType, | 21 DartType, |
22 DynamicType, | 22 DynamicType, |
23 Expression, | 23 Expression, |
24 Field, | 24 Field, |
25 FunctionNode, | |
25 FunctionType, | 26 FunctionType, |
26 Initializer, | 27 Initializer, |
27 InterfaceType, | 28 InterfaceType, |
28 InvocationExpression, | 29 InvocationExpression, |
29 Member, | 30 Member, |
30 MethodInvocation, | 31 MethodInvocation, |
31 Name, | 32 Name, |
32 Procedure, | 33 Procedure, |
33 ProcedureKind, | 34 ProcedureKind, |
34 PropertyGet, | 35 PropertyGet, |
35 PropertySet, | 36 PropertySet, |
37 ReturnStatement, | |
36 Statement, | 38 Statement, |
37 SuperMethodInvocation, | 39 SuperMethodInvocation, |
38 SuperPropertyGet, | 40 SuperPropertyGet, |
39 SuperPropertySet, | 41 SuperPropertySet, |
42 TypeParameter, | |
40 TypeParameterType, | 43 TypeParameterType, |
41 VariableDeclaration, | 44 VariableDeclaration, |
42 VoidType; | 45 VoidType; |
43 import 'package:kernel/class_hierarchy.dart'; | 46 import 'package:kernel/class_hierarchy.dart'; |
44 import 'package:kernel/core_types.dart'; | 47 import 'package:kernel/core_types.dart'; |
45 import 'package:kernel/type_algebra.dart'; | 48 import 'package:kernel/type_algebra.dart'; |
46 | 49 |
47 bool isOverloadableArithmeticOperator(String name) { | 50 bool isOverloadableArithmeticOperator(String name) { |
48 return identical(name, '+') || | 51 return identical(name, '+') || |
49 identical(name, '-') || | 52 identical(name, '-') || |
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
630 } | 633 } |
631 DartType inferredType; | 634 DartType inferredType; |
632 if (typeNeeded) { | 635 if (typeNeeded) { |
633 inferredType = substitution == null | 636 inferredType = substitution == null |
634 ? returnType | 637 ? returnType |
635 : substitution.substituteType(returnType); | 638 : substitution.substituteType(returnType); |
636 } | 639 } |
637 return inferredType; | 640 return inferredType; |
638 } | 641 } |
639 | 642 |
643 DartType inferLocalFunction(FunctionNode function, DartType typeContext, | |
Siggi Cherem (dart-lang)
2017/06/21 22:34:27
I assume this just moved, but otherwise is the sam
Paul Berry
2017/06/22 17:44:20
There are two small changes. See comments below.
| |
644 bool typeNeeded, int fileOffset, DartType returnContext, bool isNamed) { | |
Paul Berry
2017/06/22 17:44:20
Previously, returnContext was always initially `nu
| |
645 bool hasImplicitReturnType = returnContext == null; | |
646 if (!isTopLevel) { | |
647 for (var parameter in function.positionalParameters) { | |
648 if (parameter.initializer != null) { | |
649 inferExpression(parameter.initializer, parameter.type, false); | |
650 } | |
651 } | |
652 for (var parameter in function.namedParameters) { | |
653 if (parameter.initializer != null) { | |
654 inferExpression(parameter.initializer, parameter.type, false); | |
655 } | |
656 } | |
657 } | |
658 | |
659 // Let `<T0, ..., Tn>` be the set of type parameters of the closure (with | |
660 // `n`=0 if there are no type parameters). | |
661 List<TypeParameter> typeParameters = function.typeParameters; | |
662 | |
663 // Let `(P0 x0, ..., Pm xm)` be the set of formal parameters of the closure | |
664 // (including required, positional optional, and named optional parameters). | |
665 // If any type `Pi` is missing, denote it as `_`. | |
666 List<VariableDeclaration> formals = function.positionalParameters.toList() | |
667 ..addAll(function.namedParameters); | |
668 | |
669 // Let `B` denote the closure body. If `B` is an expression function body | |
670 // (`=> e`), treat it as equivalent to a block function body containing a | |
671 // single `return` statement (`{ return e; }`). | |
672 | |
673 // Attempt to match `K` as a function type compatible with the closure (that | |
674 // is, one having n type parameters and a compatible set of formal | |
675 // parameters). If there is a successful match, let `<S0, ..., Sn>` be the | |
676 // set of matched type parameters and `(Q0, ..., Qm)` be the set of matched | |
677 // formal parameter types, and let `N` be the return type. | |
678 Substitution substitution; | |
679 List<DartType> formalTypesFromContext = | |
680 new List<DartType>.filled(formals.length, null); | |
681 if (strongMode && typeContext is FunctionType) { | |
682 for (int i = 0; i < formals.length; i++) { | |
683 if (i < function.positionalParameters.length) { | |
684 formalTypesFromContext[i] = | |
685 getPositionalParameterType(typeContext, i); | |
686 } else { | |
687 formalTypesFromContext[i] = | |
688 getNamedParameterType(typeContext, formals[i].name); | |
689 } | |
690 } | |
691 returnContext = typeContext.returnType; | |
692 | |
693 // Let `[T/S]` denote the type substitution where each `Si` is replaced wi th | |
Siggi Cherem (dart-lang)
2017/06/21 22:34:27
nit: wrap
Paul Berry
2017/06/22 17:44:20
Done.
| |
694 // the corresponding `Ti`. | |
695 var substitutionMap = <TypeParameter, DartType>{}; | |
696 for (int i = 0; i < typeContext.typeParameters.length; i++) { | |
697 substitutionMap[typeContext.typeParameters[i]] = | |
698 i < typeParameters.length | |
699 ? new TypeParameterType(typeParameters[i]) | |
700 : const DynamicType(); | |
701 } | |
702 substitution = Substitution.fromMap(substitutionMap); | |
703 } else { | |
704 // If the match is not successful because `K` is `_`, let all `Si`, all | |
705 // `Qi`, and `N` all be `_`. | |
706 | |
707 // If the match is not successful for any other reason, this will result i n | |
708 // a type error, so the implementation is free to choose the best error | |
709 // recovery path. | |
710 substitution = Substitution.empty; | |
711 } | |
712 | |
713 // Define `Ri` as follows: if `Pi` is not `_`, let `Ri` be `Pi`. | |
714 // Otherwise, if `Qi` is not `_`, let `Ri` be the greatest closure of | |
715 // `Qi[T/S]` with respect to `?`. Otherwise, let `Ri` be `dynamic`. | |
716 for (int i = 0; i < formals.length; i++) { | |
717 KernelVariableDeclaration formal = formals[i]; | |
718 if (KernelVariableDeclaration.isImplicitlyTyped(formal)) { | |
719 DartType inferredType; | |
720 if (formalTypesFromContext[i] != null) { | |
721 inferredType = greatestClosure(coreTypes, | |
722 substitution.substituteType(formalTypesFromContext[i])); | |
723 } else { | |
724 inferredType = const DynamicType(); | |
725 } | |
726 instrumentation?.record(Uri.parse(uri), formal.fileOffset, 'type', | |
727 new InstrumentationValueForType(inferredType)); | |
728 formal.type = inferredType; | |
729 } | |
730 } | |
731 | |
732 // Let `N'` be `N[T/S]`. The [ClosureContext] constructor will adjust | |
733 // accordingly if the closure is declared with `async`, `async*`, or | |
734 // `sync*`. | |
735 if (returnContext != null) { | |
736 returnContext = substitution.substituteType(returnContext); | |
737 } | |
738 | |
739 // Apply type inference to `B` in return context `N’`, with any references | |
740 // to `xi` in `B` having type `Pi`. This produces `B’`. | |
741 bool isExpressionFunction = function.body is ReturnStatement; | |
742 bool needToSetReturnType = hasImplicitReturnType && | |
Paul Berry
2017/06/22 17:44:20
Previously this was:
bool needToSetReturnType = i
| |
743 ((isExpressionFunction && !isNamed) || strongMode); | |
744 ClosureContext oldClosureContext = this.closureContext; | |
745 ClosureContext closureContext = | |
746 new ClosureContext(this, function.asyncMarker, returnContext); | |
747 this.closureContext = closureContext; | |
748 inferStatement(function.body); | |
749 | |
750 // If the closure is declared with `async*` or `sync*`, let `M` be the least | |
751 // upper bound of the types of the `yield` expressions in `B’`, or `void` if | |
752 // `B’` contains no `yield` expressions. Otherwise, let `M` be the least | |
753 // upper bound of the types of the `return` expressions in `B’`, or `void` | |
754 // if `B’` contains no `return` expressions. | |
755 DartType inferredReturnType; | |
756 if (needToSetReturnType || typeNeeded) { | |
757 inferredReturnType = | |
758 closureContext.inferReturnType(this, isExpressionFunction); | |
759 } | |
760 | |
761 // Then the result of inference is `<T0, ..., Tn>(R0 x0, ..., Rn xn) B` with | |
762 // type `<T0, ..., Tn>(R0, ..., Rn) -> M’` (with some of the `Ri` and `xi` | |
763 // denoted as optional or named parameters, if appropriate). | |
764 if (needToSetReturnType) { | |
765 instrumentation?.record(Uri.parse(uri), fileOffset, 'returnType', | |
766 new InstrumentationValueForType(inferredReturnType)); | |
767 function.returnType = inferredReturnType; | |
768 } | |
769 this.closureContext = oldClosureContext; | |
770 return typeNeeded ? function.functionType : null; | |
771 } | |
772 | |
640 /// Performs the core type inference algorithm for method invocations (this | 773 /// Performs the core type inference algorithm for method invocations (this |
641 /// handles both null-aware and non-null-aware method invocations). | 774 /// handles both null-aware and non-null-aware method invocations). |
642 DartType inferMethodInvocation( | 775 DartType inferMethodInvocation( |
643 Expression expression, | 776 Expression expression, |
644 Expression receiver, | 777 Expression receiver, |
645 int fileOffset, | 778 int fileOffset, |
646 MethodInvocation desugaredInvocation, | 779 MethodInvocation desugaredInvocation, |
647 bool isImplicitCall, | 780 bool isImplicitCall, |
648 DartType typeContext, | 781 DartType typeContext, |
649 bool typeNeeded, | 782 bool typeNeeded, |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
812 void _forEachArgument( | 945 void _forEachArgument( |
813 Arguments arguments, void callback(String name, Expression expression)) { | 946 Arguments arguments, void callback(String name, Expression expression)) { |
814 for (var expression in arguments.positional) { | 947 for (var expression in arguments.positional) { |
815 callback(null, expression); | 948 callback(null, expression); |
816 } | 949 } |
817 for (var namedExpression in arguments.named) { | 950 for (var namedExpression in arguments.named) { |
818 callback(namedExpression.name, namedExpression.value); | 951 callback(namedExpression.name, namedExpression.value); |
819 } | 952 } |
820 } | 953 } |
821 } | 954 } |
OLD | NEW |