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

Unified Diff: pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.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 side-by-side diff with in-line comments
Download patch
Index: pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
index 966d8217bfd48e40a2c8585aac93aca4ea0247ae..c7b4bce4de4bccf46e074ca3f043787a7e098aac 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
@@ -25,11 +25,9 @@ import 'package:front_end/src/fasta/type_inference/type_inferrer.dart';
import 'package:front_end/src/fasta/type_inference/type_promotion.dart';
import 'package:front_end/src/fasta/type_inference/type_schema.dart';
import 'package:front_end/src/fasta/type_inference/type_schema_elimination.dart';
-import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart';
import 'package:kernel/ast.dart'
hide InvalidExpression, InvalidInitializer, InvalidStatement;
import 'package:kernel/frontend/accessors.dart';
-import 'package:kernel/type_algebra.dart';
import 'package:kernel/type_environment.dart';
import '../errors.dart' show internalError;
@@ -715,31 +713,24 @@ class KernelForInStatement extends ForInStatement implements KernelStatement {
/// form.
class KernelFunctionDeclaration extends FunctionDeclaration
implements KernelStatement {
+ bool _hasImplicitReturnType = false;
+
KernelFunctionDeclaration(VariableDeclaration variable, FunctionNode function)
: super(variable, function);
@override
void _inferStatement(KernelTypeInferrer inferrer) {
inferrer.listener.functionDeclarationEnter(this);
- for (var parameter in function.positionalParameters) {
- if (parameter.initializer != null) {
- inferrer.inferExpression(parameter.initializer, parameter.type, false);
- }
- }
- for (var parameter in function.namedParameters) {
- if (parameter.initializer != null) {
- inferrer.inferExpression(parameter.initializer, parameter.type, false);
- }
- }
- if (!inferrer.isTopLevel) {
- var oldClosureContext = inferrer.closureContext;
- inferrer.closureContext = new ClosureContext(
- inferrer, function.asyncMarker, function.returnType);
- inferrer.inferStatement(function.body);
- inferrer.closureContext = oldClosureContext;
- }
+ inferrer.inferLocalFunction(function, null, false, fileOffset,
+ _hasImplicitReturnType ? null : function.returnType, true);
+ variable.type = function.functionType;
inferrer.listener.functionDeclarationExit(this);
}
+
+ static void setHasImplicitReturnType(
+ KernelFunctionDeclaration declaration, bool hasImplicitReturnType) {
+ declaration._hasImplicitReturnType = hasImplicitReturnType;
+ }
}
/// Concrete shadow object representing a function expression in kernel form.
@@ -774,137 +765,8 @@ class KernelFunctionExpression extends FunctionExpression
KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
typeNeeded = inferrer.listener.functionExpressionEnter(this, typeContext) ||
typeNeeded;
-
- if (!inferrer.isTopLevel) {
- for (var parameter in function.positionalParameters) {
- if (parameter.initializer != null) {
- inferrer.inferExpression(
- parameter.initializer, parameter.type, false);
- }
- }
- for (var parameter in function.namedParameters) {
- if (parameter.initializer != null) {
- inferrer.inferExpression(
- parameter.initializer, parameter.type, false);
- }
- }
- }
-
- // Let `<T0, ..., Tn>` be the set of type parameters of the closure (with
- // `n`=0 if there are no type parameters).
- List<TypeParameter> typeParameters = function.typeParameters;
-
- // Let `(P0 x0, ..., Pm xm)` be the set of formal parameters of the closure
- // (including required, positional optional, and named optional parameters).
- // If any type `Pi` is missing, denote it as `_`.
- List<VariableDeclaration> formals = function.positionalParameters.toList()
- ..addAll(function.namedParameters);
-
- // Let `B` denote the closure body. If `B` is an expression function body
- // (`=> e`), treat it as equivalent to a block function body containing a
- // single `return` statement (`{ return e; }`).
-
- // Attempt to match `K` as a function type compatible with the closure (that
- // is, one having n type parameters and a compatible set of formal
- // parameters). If there is a successful match, let `<S0, ..., Sn>` be the
- // set of matched type parameters and `(Q0, ..., Qm)` be the set of matched
- // formal parameter types, and let `N` be the return type.
- Substitution substitution;
- List<DartType> formalTypesFromContext =
- new List<DartType>.filled(formals.length, null);
- DartType returnContext;
- if (inferrer.strongMode && typeContext is FunctionType) {
- for (int i = 0; i < formals.length; i++) {
- if (i < function.positionalParameters.length) {
- formalTypesFromContext[i] =
- getPositionalParameterType(typeContext, i);
- } else {
- formalTypesFromContext[i] =
- getNamedParameterType(typeContext, formals[i].name);
- }
- }
- returnContext = typeContext.returnType;
-
- // Let `[T/S]` denote the type substitution where each `Si` is replaced with
- // the corresponding `Ti`.
- var substitutionMap = <TypeParameter, DartType>{};
- for (int i = 0; i < typeContext.typeParameters.length; i++) {
- substitutionMap[typeContext.typeParameters[i]] =
- i < typeParameters.length
- ? new TypeParameterType(typeParameters[i])
- : const DynamicType();
- }
- substitution = Substitution.fromMap(substitutionMap);
- } else {
- // If the match is not successful because `K` is `_`, let all `Si`, all
- // `Qi`, and `N` all be `_`.
-
- // If the match is not successful for any other reason, this will result in
- // a type error, so the implementation is free to choose the best error
- // recovery path.
- substitution = Substitution.empty;
- }
-
- // Define `Ri` as follows: if `Pi` is not `_`, let `Ri` be `Pi`.
- // Otherwise, if `Qi` is not `_`, let `Ri` be the greatest closure of
- // `Qi[T/S]` with respect to `?`. Otherwise, let `Ri` be `dynamic`.
- for (int i = 0; i < formals.length; i++) {
- KernelVariableDeclaration formal = formals[i];
- if (KernelVariableDeclaration.isImplicitlyTyped(formal)) {
- DartType inferredType;
- if (formalTypesFromContext[i] != null) {
- inferredType = greatestClosure(inferrer.coreTypes,
- substitution.substituteType(formalTypesFromContext[i]));
- } else {
- inferredType = const DynamicType();
- }
- inferrer.instrumentation?.record(
- Uri.parse(inferrer.uri),
- formal.fileOffset,
- 'type',
- new InstrumentationValueForType(inferredType));
- formal.type = inferredType;
- }
- }
-
- // Let `N'` be `N[T/S]`. The [ClosureContext] constructor will adjust
- // accordingly if the closure is declared with `async`, `async*`, or
- // `sync*`.
- if (returnContext != null) {
- returnContext = substitution.substituteType(returnContext);
- }
-
- // Apply type inference to `B` in return context `N’`, with any references
- // to `xi` in `B` having type `Pi`. This produces `B’`.
- bool isExpressionFunction = function.body is ReturnStatement;
- bool needToSetReturnType = isExpressionFunction || inferrer.strongMode;
- ClosureContext oldClosureContext = inferrer.closureContext;
- ClosureContext closureContext =
- new ClosureContext(inferrer, function.asyncMarker, returnContext);
- inferrer.closureContext = closureContext;
- inferrer.inferStatement(function.body);
-
- // If the closure is declared with `async*` or `sync*`, let `M` be the least
- // upper bound of the types of the `yield` expressions in `B’`, or `void` if
- // `B’` contains no `yield` expressions. Otherwise, let `M` be the least
- // upper bound of the types of the `return` expressions in `B’`, or `void`
- // if `B’` contains no `return` expressions.
- DartType inferredReturnType;
- if (needToSetReturnType || typeNeeded) {
- inferredReturnType =
- closureContext.inferReturnType(inferrer, isExpressionFunction);
- }
-
- // Then the result of inference is `<T0, ..., Tn>(R0 x0, ..., Rn xn) B` with
- // type `<T0, ..., Tn>(R0, ..., Rn) -> M’` (with some of the `Ri` and `xi`
- // denoted as optional or named parameters, if appropriate).
- if (needToSetReturnType) {
- inferrer.instrumentation?.record(Uri.parse(inferrer.uri), fileOffset,
- 'returnType', new InstrumentationValueForType(inferredReturnType));
- function.returnType = inferredReturnType;
- }
- inferrer.closureContext = oldClosureContext;
- var inferredType = typeNeeded ? function.functionType : null;
+ var inferredType = inferrer.inferLocalFunction(
+ function, typeContext, typeNeeded, fileOffset, null, false);
inferrer.listener.functionExpressionExit(this, inferredType);
return inferredType;
}

Powered by Google App Engine
This is Rietveld 408576698