Skip to content

Commit be5cd63

Browse files
Jenny Messerlycommit-bot@chromium.org
Jenny Messerly
authored andcommitted
fix #34296, generic function instantiation should be checked eagerly
Change-Id: I8c6e0980c23d8ca2cb22db9411028b59be5eb8db Reviewed-on: https://dart-review.googlesource.com/72545 Reviewed-by: Vijay Menon <[email protected]> Commit-Queue: Jenny Messerly <[email protected]>
1 parent cd3dded commit be5cd63

File tree

3 files changed

+20
-11
lines changed

3 files changed

+20
-11
lines changed

pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart

+6-4
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,14 @@ bindCall(obj, name) {
8282
///
8383
/// We need to apply the type arguments both to the function, as well as its
8484
/// associated function type.
85-
gbind(f, @rest typeArgs) {
85+
gbind(f, @rest List typeArgs) {
86+
GenericFunctionType type = JS('!', '#[#]', f, _runtimeType);
87+
type.checkBounds(typeArgs);
88+
// Create a JS wrapper function that will also pass the type arguments, and
89+
// tag it with the instantiated function type.
8690
var result =
8791
JS('', '(...args) => #.apply(null, #.concat(args))', f, typeArgs);
88-
var sig = JS('', '#[#].instantiate(#)', f, _runtimeType, typeArgs);
89-
fn(result, sig);
90-
return result;
92+
return fn(result, type.instantiate(typeArgs));
9193
}
9294

9395
dloadRepl(obj, field) => dload(obj, replNameLookup(obj, field), false);

pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart

+14-6
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,13 @@ class GenericFunctionType extends AbstractFunctionType {
536536
return _typeFormals = _typeFormalsFromFunction(_instantiateTypeParts);
537537
}
538538

539-
checkBounds(List typeArgs) {
539+
/// Checks that [typeArgs] satisfies the upper bounds of the [typeFormals],
540+
/// and throws a [TypeError] if they do not.
541+
void checkBounds(List typeArgs) {
542+
// If we don't have explicit type parameter bounds, the bounds default to
543+
// a top type, so there's nothing to check here.
544+
if (_instantiateTypeBounds == null) return;
545+
540546
var bounds = instantiateTypeBounds(typeArgs);
541547
var typeFormals = this.typeFormals;
542548
for (var i = 0; i < typeArgs.length; i++) {
@@ -554,11 +560,12 @@ class GenericFunctionType extends AbstractFunctionType {
554560
var boundsFn = _instantiateTypeBounds;
555561
if (boundsFn == null) {
556562
// The Dart 1 spec says omitted type parameters have an upper bound of
557-
// Object. However strong mode assumes `dynamic` for all purposes
558-
// (such as instantiate to bounds) so we use that here.
563+
// Object. However Dart 2 uses `dynamic` for the purpose of instantiate to
564+
// bounds, so we use that here.
559565
return List.filled(formalCount, _dynamic);
560566
}
561-
// If bounds are recursive, we need to apply type formals and return them.
567+
// Bounds can be recursive or depend on other type parameters, so we need to
568+
// apply type arguments and return the resulting bounds.
562569
return JS('List', '#.apply(null, #)', boundsFn, typeArgs);
563570
}
564571

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

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

743-
throwTypeError('type `$type` does not extend `$bound`'
744-
' of `$name`.');
752+
throwTypeError('type `$type` does not extend `$bound` of `$name`.');
745753
}
746754

747755
String typeName(type) => JS('', '''(() => {

tests/language_2/language_2_dartdevc.status

-1
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,6 @@ number_identity2_test: RuntimeError # Issue 29920; Expect.isTrue(false) fails.
476476
number_identity_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
477477
numbers_test: RuntimeError # Issue 29920; Expect.equals(expected: <false>, actual: <true>) fails.
478478
parser_quirks_test: CompileTimeError
479-
partial_instantiation_eager_bounds_check_test: RuntimeError # Issue 34296
480479
regress_16640_test: RuntimeError # Issue 29920; Uncaught Error: type arguments should not be null: E => {
481480
regress_22443_test: RuntimeError # Uncaught Expect.isTrue(false) fails.
482481
stack_overflow_stacktrace_test: RuntimeError # Issue 29920; RangeError: Maximum call stack size exceeded

0 commit comments

Comments
 (0)