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; |
} |