Index: pkg/compiler/lib/src/ssa/builder.dart |
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart |
index 13350ca4400098b06c50736383263ede3859390c..c67afb43fafc5ca3fafa673473625c65c1d21280 100644 |
--- a/pkg/compiler/lib/src/ssa/builder.dart |
+++ b/pkg/compiler/lib/src/ssa/builder.dart |
@@ -1058,6 +1058,13 @@ class SsaBuilder extends ResolvedVisitor { |
// We build the Ssa graph by simulating a stack machine. |
List<HInstruction> stack = <HInstruction>[]; |
+ /// Returns `true` if the current element is an `async` function. |
+ bool get isBuildingAsyncFunction { |
+ Element element = sourceElement; |
+ return (element is FunctionElement && |
+ element.asyncMarker == AsyncMarker.ASYNC); |
+ } |
+ |
SsaBuilder(JavaScriptBackend backend, |
CodegenWorkItem work, |
this.nativeEmitter, |
@@ -5179,6 +5186,28 @@ class SsaBuilder extends ResolvedVisitor { |
emitReturn(value, node); |
} |
+ /// Returns true if the [type] is a valid return type for an asynchronous |
+ /// function. |
+ /// |
+ /// Asynchronous functions return a `Future`, and a valid return is thus |
+ /// either dynamic, Object, or Future. |
+ /// |
+ /// We do not accept the internal Future implementation class. |
+ bool isValidAsyncReturnType(DartType type) { |
+ assert (isBuildingAsyncFunction); |
+ // TODO(sigurdm): In an internal library a function could be declared: |
+ // |
+ // _FutureImpl foo async => 1; |
+ // |
+ // This should be valid (because the actual value returned from an async |
+ // function is a `_FutureImpl`), but currently false is returned in this |
+ // case. |
+ return type.isDynamic || |
+ type.isObject || |
+ (type is InterfaceType && |
+ type.element == compiler.futureClass); |
+ } |
+ |
visitReturn(ast.Return node) { |
if (identical(node.beginToken.stringValue, 'native')) { |
native.handleSsaNative(this, node.expression); |
@@ -5190,7 +5219,19 @@ class SsaBuilder extends ResolvedVisitor { |
} else { |
visit(node.expression); |
value = pop(); |
- value = potentiallyCheckOrTrustType(value, returnType); |
+ if (isBuildingAsyncFunction) { |
+ if (compiler.enableTypeAssertions && |
+ !isValidAsyncReturnType(returnType)) { |
+ String message = |
+ "Async function returned a Future, " |
+ "was declared to return a $returnType."; |
+ generateTypeError(node, message); |
+ pop(); |
+ return; |
+ } |
+ } else { |
+ value = potentiallyCheckOrTrustType(value, returnType); |
+ } |
} |
handleInTryStatement(); |