Skip to content

Commit

Permalink
fix #34296, generic function instantiation should be checked eagerly
Browse files Browse the repository at this point in the history
Change-Id: I8c6e0980c23d8ca2cb22db9411028b59be5eb8db
Reviewed-on: https://dart-review.googlesource.com/72545
Reviewed-by: Vijay Menon <[email protected]>
Commit-Queue: Jenny Messerly <[email protected]>
  • Loading branch information
Jenny Messerly authored and [email protected] committed Sep 7, 2018
1 parent cd3dded commit be5cd63
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,14 @@ bindCall(obj, name) {
///
/// We need to apply the type arguments both to the function, as well as its
/// associated function type.
gbind(f, @rest typeArgs) {
gbind(f, @rest List typeArgs) {
GenericFunctionType type = JS('!', '#[#]', f, _runtimeType);
type.checkBounds(typeArgs);
// Create a JS wrapper function that will also pass the type arguments, and
// tag it with the instantiated function type.
var result =
JS('', '(...args) => #.apply(null, #.concat(args))', f, typeArgs);
var sig = JS('', '#[#].instantiate(#)', f, _runtimeType, typeArgs);
fn(result, sig);
return result;
return fn(result, type.instantiate(typeArgs));
}

dloadRepl(obj, field) => dload(obj, replNameLookup(obj, field), false);
Expand Down
20 changes: 14 additions & 6 deletions pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,13 @@ class GenericFunctionType extends AbstractFunctionType {
return _typeFormals = _typeFormalsFromFunction(_instantiateTypeParts);
}

checkBounds(List typeArgs) {
/// Checks that [typeArgs] satisfies the upper bounds of the [typeFormals],
/// and throws a [TypeError] if they do not.
void checkBounds(List typeArgs) {
// If we don't have explicit type parameter bounds, the bounds default to
// a top type, so there's nothing to check here.
if (_instantiateTypeBounds == null) return;

var bounds = instantiateTypeBounds(typeArgs);
var typeFormals = this.typeFormals;
for (var i = 0; i < typeArgs.length; i++) {
Expand All @@ -554,11 +560,12 @@ class GenericFunctionType extends AbstractFunctionType {
var boundsFn = _instantiateTypeBounds;
if (boundsFn == null) {
// The Dart 1 spec says omitted type parameters have an upper bound of
// Object. However strong mode assumes `dynamic` for all purposes
// (such as instantiate to bounds) so we use that here.
// Object. However Dart 2 uses `dynamic` for the purpose of instantiate to
// bounds, so we use that here.
return List.filled(formalCount, _dynamic);
}
// If bounds are recursive, we need to apply type formals and return them.
// Bounds can be recursive or depend on other type parameters, so we need to
// apply type arguments and return the resulting bounds.
return JS('List', '#.apply(null, #)', boundsFn, typeArgs);
}

Expand Down Expand Up @@ -738,10 +745,11 @@ getFunctionTypeMirror(AbstractFunctionType type) {
bool isType(obj) => JS('', '#[#] === #', obj, _runtimeType, Type);

void checkTypeBound(type, bound, name) {
// TODO(jmesserly): we've optimized `is`/`as`/implicit type checks, it would
// be nice to have similar optimizations for the subtype relation.
if (JS('!', '#', isSubtype(type, bound))) return;

throwTypeError('type `$type` does not extend `$bound`'
' of `$name`.');
throwTypeError('type `$type` does not extend `$bound` of `$name`.');
}

String typeName(type) => JS('', '''(() => {
Expand Down
1 change: 0 additions & 1 deletion tests/language_2/language_2_dartdevc.status
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,6 @@ number_identity2_test: RuntimeError # Issue 29920; Expect.isTrue(false) fails.
number_identity_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
numbers_test: RuntimeError # Issue 29920; Expect.equals(expected: <false>, actual: <true>) fails.
parser_quirks_test: CompileTimeError
partial_instantiation_eager_bounds_check_test: RuntimeError # Issue 34296
regress_16640_test: RuntimeError # Issue 29920; Uncaught Error: type arguments should not be null: E => {
regress_22443_test: RuntimeError # Uncaught Expect.isTrue(false) fails.
stack_overflow_stacktrace_test: RuntimeError # Issue 29920; RangeError: Maximum call stack size exceeded
Expand Down

0 comments on commit be5cd63

Please sign in to comment.