Skip to content

Commit

Permalink
[VM generic functions] Disallow generic function types as type argume…
Browse files Browse the repository at this point in the history
…nts or bounds.

Adjust existing test and status file.

R=asiva@google.com

Review-Url: https://codereview.chromium.org/2989513002 .
  • Loading branch information
crelier committed Jul 21, 2017
1 parent 44e8da3 commit cc81f38
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 8 deletions.
37 changes: 37 additions & 0 deletions runtime/vm/class_finalizer.cc
Expand Up @@ -796,6 +796,19 @@ intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
if (type_arg.IsMalformed()) {
// Malformed type arguments are mapped to dynamic.
type_arg = Type::DynamicType();
} else if (type_arg.IsFunctionType()) {
const Function& signature_function =
Function::Handle(zone, Type::Cast(type_arg).signature());
if (signature_function.IsGeneric()) {
const String& type_arg_name =
String::Handle(zone, type_arg.UserVisibleName());
const String& type_name =
String::Handle(zone, type.UserVisibleName());
ReportError(cls, type_arg.token_pos(),
"generic function type '%s' not allowed as type "
"argument of type '%s'",
type_arg_name.ToCString(), type_name.ToCString());
}
}
full_arguments.SetTypeAt(offset + i, type_arg);
}
Expand Down Expand Up @@ -1341,6 +1354,18 @@ void ClassFinalizer::ResolveSignature(const Class& cls,
type_param ^= type_params.TypeAt(i);
type = type_param.bound();
ResolveType(cls, type);
if (type.IsFunctionType()) {
const Function& signature_function =
Function::Handle(Type::Cast(type).signature());
if (signature_function.IsGeneric()) {
const String& type_name = String::Handle(type.UserVisibleName());
const String& type_param_name = String::Handle(type_param.name());
ReportError(cls, type.token_pos(),
"generic function type '%s' not allowed as bound of "
"function type parameter '%s'",
type_name.ToCString(), type_param_name.ToCString());
}
}
}
}
// Resolve result type.
Expand Down Expand Up @@ -1459,6 +1484,18 @@ void ClassFinalizer::ResolveUpperBounds(const Class& cls) {
type_param ^= type_params.TypeAt(i);
bound = type_param.bound();
ResolveType(cls, bound);
if (bound.IsFunctionType()) {
const Function& signature_function =
Function::Handle(Type::Cast(bound).signature());
if (signature_function.IsGeneric()) {
const String& bound_name = String::Handle(bound.UserVisibleName());
const String& type_param_name = String::Handle(type_param.name());
ReportError(cls, bound.token_pos(),
"generic function type '%s' not allowed as bound of "
"class type parameter '%s'",
bound_name.ToCString(), type_param_name.ToCString());
}
}
}
}

Expand Down
18 changes: 12 additions & 6 deletions tests/language_2/generic_methods_generic_function_result_test.dart
Expand Up @@ -4,19 +4,25 @@
//
// VMOptions=--generic-method-syntax,--error-on-bad-type

// Verify that function type parameter S can be resolved in bar.
// Verify that function type parameter S can be resolved in bar's result type.
// Verify that generic function types are not allowed as type arguments.

import "package:expect/expect.dart";

T foo<T extends num>(int i, T t) => i + t;
int foo
<T> //# 01: continued
(int i, int j) => i + j;

List<T Function<T extends num>(S, T)> bar<S extends int>() {
return <T Function<T extends num>(S, T)>[foo, foo];
List<int Function
<T> //# 01: compile-time error
(S, int)> bar<S extends int>() {
return <int Function
<T> //# 01: continued
(S, int)>[foo, foo];
}

void main() {
var list = bar<int>();
print(list[0]
.runtimeType); // "<T extends num>(int, T) => T" when reifying generic functions.
print(list[0].runtimeType);
Expect.equals(123, list[1]<int>(100, 23));
}
7 changes: 5 additions & 2 deletions tests/language_2/language_2.status
Expand Up @@ -37,8 +37,11 @@ accessor_conflict_import_prefixed2_test: StaticWarning # Issue 25626
accessor_conflict_import_prefixed_test: StaticWarning # Issue 25626
accessor_conflict_import_test: StaticWarning # Issue 25626

[ $compiler == dart2analyzer && ! $strong ]
generic_methods_generic_function_result_test/01: MissingCompileTimeError # Issue #30207

[ $compiler == dart2analyzer && $strong ]
generic_methods_generic_function_result_test: CompileTimeError # Issue #30207
generic_methods_generic_function_result_test/none: CompileTimeError # Issue #30207

[ $compiler == dart2js || $compiler == dartk || $compiler == dartdevc ]
generic_methods_generic_function_result_test: CompileTimeError # Issue #30208
generic_methods_generic_function_result_test/none: CompileTimeError # Issue #30208

0 comments on commit cc81f38

Please sign in to comment.