Chromium Code Reviews| 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 |