Simplify ClosureContext
There are some invariants about this class and some improvements we
can make:
* needImplicitDowcasts is always true
* returnContext is never null so neither is declaredReturnType or
expectedType
* ensureAssignable calls greatestClosure on the expected type so we
don't have to
* we don't need to unwrap the type of the subexpression unless we
are inferring a return type based on it
Change-Id: I4eaf41f17dd9d5ad44143a04ef02fe11824b2aa7
Reviewed-on: https://dart-review.googlesource.com/71164
Reviewed-by: Daniel Hillerström <hillerstrom@google.com>
Commit-Queue: Kevin Millikin <kmillikin@google.com>
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index c53cd10..5d54fb7 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -191,8 +191,6 @@
final bool _needToInferReturnType;
- final bool _needImplicitDowncasts;
-
/// The type that actually appeared as the subexpression of `return` or
/// `yield` statements inside the function.
///
@@ -204,12 +202,9 @@
/// wrapping this type in `Stream` or `Iterator`, as appropriate.
DartType _inferredUnwrappedReturnOrYieldType;
- factory ClosureContext(
- TypeInferrerImpl inferrer,
- AsyncMarker asyncMarker,
- DartType returnContext,
- bool needToInferReturnType,
- bool needImplicitDowncasts) {
+ factory ClosureContext(TypeInferrerImpl inferrer, AsyncMarker asyncMarker,
+ DartType returnContext, bool needToInferReturnType) {
+ assert(returnContext != null);
DartType declaredReturnType = returnContext;
bool isAsync = asyncMarker == AsyncMarker.Async ||
asyncMarker == AsyncMarker.AsyncStar;
@@ -228,18 +223,11 @@
inferrer.typeSchemaEnvironment.unfutureType(returnContext));
}
return new ClosureContext._(isAsync, isGenerator, returnContext,
- declaredReturnType, needToInferReturnType, needImplicitDowncasts);
+ declaredReturnType, needToInferReturnType);
}
- ClosureContext._(
- this.isAsync,
- this.isGenerator,
- this.returnOrYieldContext,
- this.declaredReturnType,
- this._needToInferReturnType,
- this._needImplicitDowncasts) {
- assert(returnOrYieldContext != null);
- }
+ ClosureContext._(this.isAsync, this.isGenerator, this.returnOrYieldContext,
+ this.declaredReturnType, this._needToInferReturnType) {}
/// Updates the inferred return type based on the presence of a return
/// statement returning the given [type].
@@ -261,8 +249,7 @@
assert(_needToInferReturnType);
DartType inferredType =
inferrer.inferReturnType(_inferredUnwrappedReturnOrYieldType);
- if (returnOrYieldContext != null &&
- !_analyzerSubtypeOf(inferrer, inferredType, returnOrYieldContext)) {
+ if (!_analyzerSubtypeOf(inferrer, inferredType, returnOrYieldContext)) {
// If the inferred return type isn't a subtype of the context, we use the
// context.
inferredType = greatestClosure(inferrer.coreTypes, returnOrYieldContext);
@@ -279,35 +266,29 @@
bool isReturn,
bool isYieldStar,
bool isArrow) {
- if (_needImplicitDowncasts) {
- var expectedType = isYieldStar
- ? _wrapAsyncOrGenerator(inferrer, returnOrYieldContext)
- : returnOrYieldContext;
- if (expectedType != null) {
- expectedType = greatestClosure(inferrer.coreTypes, expectedType);
- if (inferrer.ensureAssignable(
- expectedType, type, expression, fileOffset,
- isReturnFromAsync: isAsync,
- isReturn: isReturn,
- declaredReturnType: declaredReturnType,
- isArrow: isArrow) !=
- null) {
- type = expectedType;
- }
- }
- }
- var unwrappedType = type;
- if (isAsync && isReturn) {
- unwrappedType = inferrer.typeSchemaEnvironment.unfutureType(type);
- } else if (isYieldStar) {
- unwrappedType = inferrer.getDerivedTypeArgumentOf(
- type,
- isAsync
- ? inferrer.coreTypes.streamClass
- : inferrer.coreTypes.iterableClass) ??
- type;
+ var expectedType = isYieldStar
+ ? _wrapAsyncOrGenerator(inferrer, returnOrYieldContext)
+ : returnOrYieldContext;
+ if (inferrer.ensureAssignable(expectedType, type, expression, fileOffset,
+ isReturnFromAsync: isAsync,
+ isReturn: isReturn,
+ declaredReturnType: declaredReturnType,
+ isArrow: isArrow) !=
+ null) {
+ type = greatestClosure(inferrer.coreTypes, expectedType);
}
if (_needToInferReturnType) {
+ var unwrappedType = type;
+ if (isAsync && isReturn) {
+ unwrappedType = inferrer.typeSchemaEnvironment.unfutureType(type);
+ } else if (isYieldStar) {
+ unwrappedType = inferrer.getDerivedTypeArgumentOf(
+ type,
+ isAsync
+ ? inferrer.coreTypes.streamClass
+ : inferrer.coreTypes.iterableClass) ??
+ type;
+ }
if (_inferredUnwrappedReturnOrYieldType == null) {
_inferredUnwrappedReturnOrYieldType = unwrappedType;
} else {
@@ -1255,8 +1236,7 @@
Statement body) {
assert(closureContext == null);
this.helper = helper;
- closureContext =
- new ClosureContext(this, asyncMarker, returnType, false, true);
+ closureContext = new ClosureContext(this, asyncMarker, returnType, false);
inferStatement(body);
closureContext = null;
this.helper = null;
@@ -1561,13 +1541,8 @@
// to `xi` in `B` having type `Pi`. This produces `B’`.
bool needToSetReturnType = hasImplicitReturnType && strongMode;
ClosureContext oldClosureContext = this.closureContext;
- bool needImplicitDowncasts = returnContext != null;
ClosureContext closureContext = new ClosureContext(
- this,
- function.asyncMarker,
- returnContext,
- needToSetReturnType,
- needImplicitDowncasts);
+ this, function.asyncMarker, returnContext, needToSetReturnType);
this.closureContext = closureContext;
inferStatement(function.body);