[VM/runtime] Fix generic signature instantiation and type parameter canonicalization check.

This fixes 2 issues:
1) The index of type parameters in an instantiated generic signature may require to be adjusted according to the number of parent type parameters.
2) The heap may contain canonical type parameters that are still unfinalized.

Closes https://github.com/dart-lang/sdk/issues/43537
Partially fixes https://github.com/dart-lang/sdk/issues/44141 (language and language_2 tests, but not vm/cc tests)

TEST=see above.

Change-Id: I17a87d0ffd4be302f25e3b269b94286a5b817400
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/171807
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: RĂ©gis Crelier <regis@google.com>
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 556b548..e6ff59a 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -303,8 +303,11 @@
     for (intptr_t i = 0; i < num_types; i++) {
       type_parameter ^= type_parameters.TypeAt(i);
       if (!type_parameter.IsFinalized()) {
-        type_parameter.set_index(type_parameter.index() + offset);
+        ASSERT(type_parameter.index() == i);
+        type_parameter.set_index(offset + i);
         type_parameter.SetIsFinalized();
+      } else {
+        ASSERT(type_parameter.index() == offset + i);
       }
       // The declaration of a type parameter is canonical.
       ASSERT(type_parameter.IsDeclaration());
@@ -821,8 +824,11 @@
     for (intptr_t i = 0; i < num_type_params; i++) {
       type_param ^= type_params.TypeAt(i);
       if (!type_param.IsFinalized()) {
+        ASSERT(type_param.index() == i);
         type_param.set_index(num_parent_type_params + i);
         type_param.SetIsFinalized();
+      } else {
+        ASSERT(type_param.index() == num_parent_type_params + i);
       }
       // The declaration of a type parameter is canonical.
       ASSERT(type_param.IsDeclaration());
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 82605a8..ea79c98 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -8326,6 +8326,7 @@
   // Note that parent pointers in newly instantiated signatures still points to
   // the original uninstantiated parent signatures. That is not a problem.
   const Function& parent = Function::Handle(zone, parent_function());
+  const intptr_t num_parent_type_params = NumParentTypeParameters();
 
   // See the comment on kCurrentAndEnclosingFree to understand why we don't
   // adjust 'num_free_fun_type_params' downward in this case.
@@ -8345,7 +8346,6 @@
     if (IsGeneric() || HasGenericParent()) {
       // We only consider the function type parameters declared by the parents
       // of this signature function as free.
-      const int num_parent_type_params = NumParentTypeParameters();
       if (num_parent_type_params < num_free_fun_type_params) {
         num_free_fun_type_params = num_parent_type_params;
       }
@@ -8354,6 +8354,8 @@
 
   Function& sig = Function::Handle(Function::NewSignatureFunction(
       owner, parent, TokenPosition::kNoSource, space));
+  const intptr_t offset =
+      sig.NumParentTypeParameters() - num_parent_type_params;
   AbstractType& type = AbstractType::Handle(zone);
 
   // Copy the type parameters and instantiate their bounds (if necessary).
@@ -8363,10 +8365,11 @@
     if (!type_params.IsNull()) {
       TypeArguments& instantiated_type_params = TypeArguments::Handle(zone);
       TypeParameter& type_param = TypeParameter::Handle(zone);
-      Class& cls = Class::Handle(zone);
+      const Class& null_class = 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);
+        ASSERT(type_param.index() == num_parent_type_params + i);
         type = type_param.bound();
         if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
           type = type.InstantiateFrom(instantiator_type_arguments,
@@ -8377,12 +8380,14 @@
           if (type.IsNull()) {
             return Function::null();
           }
-          cls = type_param.parameterized_class();
+        }
+        if (offset > 0 || type.raw() != type_param.bound()) {
           param_name = type_param.name();
+          ASSERT(type_param.IsFunctionTypeParameter());
           ASSERT(type_param.IsFinalized());
           ASSERT(type_param.IsCanonical());
           type_param = TypeParameter::New(
-              cls, sig, type_param.index(), param_name, type,
+              null_class, sig, type_param.index() + offset, param_name, type,
               type_param.IsGenericCovariantImpl(), type_param.nullability(),
               type_param.token_pos());
           type_param.SetIsFinalized();
@@ -8838,6 +8843,9 @@
 
   // Set closure function's type parameters.
   auto& type_args_handle = TypeArguments::Handle(zone, type_parameters());
+  // This function cannot be local, therefore it has no generic parent.
+  // Its implicit closure function therefore has no generic parent function
+  // either. That is why it is safe to simply copy the type parameters.
   closure_function.set_type_parameters(type_args_handle);
   closure_function.UpdateCachedDefaultTypeArguments(thread);
 
@@ -20757,6 +20765,7 @@
     }
     object_store->set_canonical_type_parameters(table.Release());
   }
+  ASSERT(!type_parameter.IsDeclaration());
   return type_parameter.raw();
 }
 
@@ -20771,8 +20780,10 @@
   const TypeArguments& type_params = TypeArguments::Handle(
       zone, cls.IsNull() ? function.type_parameters() : cls.type_parameters());
   const intptr_t offset =
-      cls.IsNull() ? function.NumParentTypeParameters()
-                   : (cls.NumTypeArguments() - cls.NumTypeParameters());
+      IsFinalized()
+          ? (cls.IsNull() ? function.NumParentTypeParameters()
+                          : (cls.NumTypeArguments() - cls.NumTypeParameters()))
+          : 0;
   TypeParameter& type_parameter = TypeParameter::Handle(zone);
   type_parameter ^= type_params.TypeAt(index() - offset);
   ASSERT(!type_parameter.IsNull());