[vm] Instantiate type parameter bounds on closures.
Fixes #34308.
Change-Id: I7d998daa752ada13368631fc327a5c3595ec406c
Reviewed-on: https://dart-review.googlesource.com/72160
Commit-Queue: Samir Jindel <sjindel@google.com>
Reviewed-by: RĂ©gis Crelier <regis@google.com>
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 9439ecc..593ea86 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -7131,11 +7131,50 @@
Function& sig = Function::Handle(Function::NewSignatureFunction(
owner, parent, TokenPosition::kNoSource, space));
+ AbstractType& type = AbstractType::Handle(zone);
+
+ // Copy the type parameters and instantiate their bounds (if necessary).
if (!delete_type_parameters) {
- sig.set_type_parameters(TypeArguments::Handle(zone, type_parameters()));
+ const TypeArguments& type_params =
+ TypeArguments::Handle(zone, type_parameters());
+ if (!type_params.IsNull()) {
+ TypeArguments& instantiated_type_params = TypeArguments::Handle(zone);
+ TypeParameter& type_param = TypeParameter::Handle(zone);
+ Class& cls = Class::Handle(zone);
+ String& param_name = String::Handle(zone);
+ for (intptr_t i = 0; i < type_params.Length(); ++i) {
+ type_param ^= type_params.TypeAt(i);
+ type = type_param.bound();
+ if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
+ type = type.InstantiateFrom(
+ instantiator_type_arguments, function_type_arguments,
+ num_free_fun_type_params, NULL, NULL, NULL, space);
+ cls = type_param.parameterized_class();
+ param_name = type_param.name();
+ ASSERT(type_param.IsFinalized());
+ type_param ^=
+ TypeParameter::New(cls, sig, type_param.index(), param_name, type,
+ type_param.token_pos());
+ type_param.SetIsFinalized();
+ if (instantiated_type_params.IsNull()) {
+ instantiated_type_params = TypeArguments::New(type_params.Length());
+ for (intptr_t j = 0; j < i; ++j) {
+ type = type_params.TypeAt(j);
+ instantiated_type_params.SetTypeAt(j, type);
+ }
+ }
+ instantiated_type_params.SetTypeAt(i, type_param);
+ } else if (!instantiated_type_params.IsNull()) {
+ instantiated_type_params.SetTypeAt(i, type_param);
+ }
+ }
+ sig.set_type_parameters(instantiated_type_params.IsNull()
+ ? type_params
+ : instantiated_type_params);
+ }
}
- AbstractType& type = AbstractType::Handle(zone, result_type());
+ type = result_type();
if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
type = type.InstantiateFrom(
instantiator_type_arguments, function_type_arguments,
@@ -7888,6 +7927,15 @@
return false;
}
}
+ TypeArguments& type_params = TypeArguments::Handle(type_parameters());
+ TypeParameter& type_param = TypeParameter::Handle();
+ for (intptr_t i = 0; i < type_params.Length(); ++i) {
+ type_param ^= type_params.TypeAt(i);
+ type = type_param.bound();
+ if (!type.IsInstantiated(genericity, num_free_fun_type_params, trail)) {
+ return false;
+ }
+ }
return true;
}
diff --git a/tests/language_2/tearoff_bounds_instantiation_test.dart b/tests/language_2/tearoff_bounds_instantiation_test.dart
new file mode 100644
index 0000000..b823c64
--- /dev/null
+++ b/tests/language_2/tearoff_bounds_instantiation_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2018, 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.
+//
+// This test checks that the type parameter bounds on tearoffs from generic
+// classes are properly instantiated in the signature of the tearoff.
+
+import "package:expect/expect.dart";
+
+class C<T> {
+ void foo<S extends T>(S x) {}
+}
+
+void foo<S extends int>(S x) {}
+
+void main() {
+ dynamic c = C<int>();
+ dynamic fn = c.foo;
+ Expect.equals("${fn.runtimeType}", "${foo.runtimeType}");
+}