Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(301)

Side by Side Diff: pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart

Issue 2950213002: Infer the return types of local functions where appropriate. (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart ('k') | pkg/front_end/test/fasta/kompile.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698