Do assignability checks on return/yield using the greatest closure of the context.

Without this fix, there is a risk that the unknown type ("?") will
leak into kernel code via the "as" expression inserted for an implicit
downcast.

Change-Id: Iea7276c8489eff80fe32f33e53efd42571c94a89
Reviewed-on: https://dart-review.googlesource.com/26861
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This commit is contained in:
Paul Berry 2017-12-06 22:41:50 +00:00 committed by commit-bot@chromium.org
parent b81d8a1c33
commit 5710de9c78
6 changed files with 51 additions and 1 deletions

View file

@ -213,7 +213,13 @@ class ClosureContext {
var expectedType = isYieldStar
? _wrapAsyncOrGenerator(inferrer, returnContext)
: returnContext;
inferrer.checkAssignability(expectedType, type, expression, fileOffset);
if (expectedType != null) {
inferrer.checkAssignability(
greatestClosure(inferrer.coreTypes, expectedType),
type,
expression,
fileOffset);
}
}
}
@ -393,6 +399,7 @@ abstract class TypeInferrerImpl extends TypeInferrer {
/// an implicit downcast if appropriate.
Expression checkAssignability(DartType expectedType, DartType actualType,
Expression expression, int fileOffset) {
assert(expectedType == null || isKnown(expectedType));
// We don't need to insert assignability checks when doing top level type
// inference since top level type inference only cares about the type that
// is inferred (the kernel code is discarded).

View file

@ -0,0 +1,14 @@
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
bool f(List x) {
return x.expand((y) {
// Since y has type dynamic, y.split(',') has type dynamic, so an implicit
// downcast is needed. The return context is Iterable<?>. We should
// generate an implicit downcast to Iterable<dynamic>.
return y.split(',');
}).any((y) => y == 'z');
}
main() {}

View file

@ -0,0 +1,10 @@
library;
import self as self;
import "dart:core" as core;
static method f(core::List<dynamic> x) → core::bool {
return x.expand((dynamic y) → dynamic {
return y.split(",");
}).any((dynamic y) → dynamic => y.==("z"));
}
static method main() → dynamic {}

View file

@ -0,0 +1,8 @@
library;
import self as self;
import "dart:core" as core;
static method f(core::List<dynamic> x) → core::bool
;
static method main() → dynamic
;

View file

@ -0,0 +1,10 @@
library;
import self as self;
import "dart:core" as core;
static method f(core::List<dynamic> x) → core::bool {
return x.{core::Iterable::expand}<dynamic>((dynamic y) → core::Iterable<dynamic> {
return y.split(",") as{TypeError} core::Iterable<dynamic>;
}).{core::Iterable::any}((dynamic y) → core::bool => y.{core::Object::==}("z"));
}
static method main() → dynamic {}

View file

@ -1244,6 +1244,7 @@ async_star_test/03: CompileTimeError # Issue 31402 (Invocation arguments)
async_star_test/04: CompileTimeError # Issue 31402 (Invocation arguments)
async_star_test/05: CompileTimeError # Issue 31402 (Invocation arguments)
async_star_test/none: CompileTimeError # Issue 31402 (Invocation arguments)
await_test: CompileTimeError # Issue 31541
bad_named_parameters2_test/01: MissingCompileTimeError
bad_named_parameters_test/01: MissingCompileTimeError
bad_named_parameters_test/02: MissingCompileTimeError