| Index: runtime/vm/flow_graph_builder.cc
|
| diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
|
| index 38068a349f056738ca6a08d23d9dc666b3c1b787..53ae53b110010e69e75205afc4e2370c6aff297b 100644
|
| --- a/runtime/vm/flow_graph_builder.cc
|
| +++ b/runtime/vm/flow_graph_builder.cc
|
| @@ -1233,7 +1233,7 @@ void ValueGraphVisitor::VisitTypeNode(TypeNode* node) {
|
| instantiator_type_arguments = BuildInstantiatorTypeArguments(token_pos);
|
| }
|
| Value* function_type_arguments = NULL;
|
| - if (type.IsInstantiated(kCurrentFunction)) {
|
| + if (type.IsInstantiated(kFunctions)) {
|
| function_type_arguments = BuildNullValue(token_pos);
|
| } else {
|
| function_type_arguments = BuildFunctionTypeArguments(token_pos);
|
| @@ -1433,7 +1433,7 @@ PushArgumentInstr* EffectGraphVisitor::PushInstantiatorTypeArguments(
|
| PushArgumentInstr* EffectGraphVisitor::PushFunctionTypeArguments(
|
| const AbstractType& type,
|
| TokenPosition token_pos) {
|
| - if (type.IsInstantiated(kCurrentFunction)) {
|
| + if (type.IsInstantiated(kFunctions)) {
|
| return PushArgument(BuildNullValue(token_pos));
|
| } else {
|
| Value* function_type_args = BuildFunctionTypeArguments(token_pos);
|
| @@ -1448,6 +1448,13 @@ Value* EffectGraphVisitor::BuildNullValue(TokenPosition token_pos) {
|
| }
|
|
|
|
|
| +Value* EffectGraphVisitor::BuildEmptyTypeArguments(TokenPosition token_pos) {
|
| + return Bind(new (Z) ConstantInstr(
|
| + TypeArguments::ZoneHandle(Z, Object::empty_type_arguments().raw()),
|
| + token_pos));
|
| +}
|
| +
|
| +
|
| // Used for testing incoming arguments.
|
| AssertAssignableInstr* EffectGraphVisitor::BuildAssertAssignable(
|
| TokenPosition token_pos,
|
| @@ -1462,7 +1469,7 @@ AssertAssignableInstr* EffectGraphVisitor::BuildAssertAssignable(
|
| } else {
|
| instantiator_type_arguments = BuildInstantiatorTypeArguments(token_pos);
|
| }
|
| - if (dst_type.IsInstantiated(kCurrentFunction)) {
|
| + if (dst_type.IsInstantiated(kFunctions)) {
|
| function_type_arguments = BuildNullValue(token_pos);
|
| } else {
|
| function_type_arguments = BuildFunctionTypeArguments(token_pos);
|
| @@ -2344,14 +2351,24 @@ void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) {
|
| Value* closure_val = Bind(alloc);
|
| {
|
| LocalVariable* closure_tmp_var = EnterTempLocalScope(closure_val);
|
| - // Store instantiator type arguments if signature is uninstantiated.
|
| + // Store instantiator type arguments if signature is class-uninstantiated.
|
| if (!function.HasInstantiatedSignature(kCurrentClass)) {
|
| Value* closure_tmp_val =
|
| Bind(new (Z) LoadLocalInstr(*closure_tmp_var, node->token_pos()));
|
| Value* type_arguments = BuildInstantiatorTypeArguments(node->token_pos());
|
| - Do(new (Z) StoreInstanceFieldInstr(Closure::instantiator_offset(),
|
| - closure_tmp_val, type_arguments,
|
| - kEmitStoreBarrier, node->token_pos()));
|
| + Do(new (Z) StoreInstanceFieldInstr(
|
| + Closure::instantiator_type_arguments_offset(), closure_tmp_val,
|
| + type_arguments, kEmitStoreBarrier, node->token_pos()));
|
| + }
|
| +
|
| + // Store function type arguments if signature is function-uninstantiated.
|
| + if (!function.HasInstantiatedSignature(kFunctions)) {
|
| + Value* closure_tmp_val =
|
| + Bind(new (Z) LoadLocalInstr(*closure_tmp_var, node->token_pos()));
|
| + Value* type_arguments = BuildFunctionTypeArguments(node->token_pos());
|
| + Do(new (Z) StoreInstanceFieldInstr(
|
| + Closure::function_type_arguments_offset(), closure_tmp_val,
|
| + type_arguments, kEmitStoreBarrier, node->token_pos()));
|
| }
|
|
|
| // Store function.
|
| @@ -2715,8 +2732,28 @@ Value* EffectGraphVisitor::BuildInstantiatorTypeArguments(
|
|
|
|
|
| Value* EffectGraphVisitor::BuildFunctionTypeArguments(TokenPosition token_pos) {
|
| - UNIMPLEMENTED();
|
| - return NULL;
|
| + LocalVariable* function_type_arguments_var =
|
| + owner()->parsed_function().function_type_arguments();
|
| + if (function_type_arguments_var == NULL) {
|
| + // We encountered an uninstantiated type referring to type parameters of a
|
| + // signature that is local to the function being compiled. The type remains
|
| + // uninstantiated. Example: Foo(f<T>(T t)) => null;
|
| + // Foo is non-generic, but takes a generic function f as argument.
|
| + // The uninstantiated function type of f cannot be instantiated from within
|
| + // Foo and should not be instantiated. It is used in uninstantiated form to
|
| + // check incoming closures for assignability. We pass an empty function
|
| + // type argument vector.
|
| + return BuildEmptyTypeArguments(token_pos);
|
| +
|
| + // Note that the function type could also get partially instantiated:
|
| + // Bar<B>(B g<T>(T t)) => null;
|
| + // In this case, function_type_arguments_var will not be null, since Bar
|
| + // is generic, and will be used to partially instantiate the type of g, more
|
| + // specifically the result type of g. Note that the instantiator vector will
|
| + // have length 1, and type parameters with indices above 0, e.g. T, must
|
| + // remain uninstantiated.
|
| + }
|
| + return Bind(BuildLoadLocal(*function_type_arguments_var, token_pos));
|
| }
|
|
|
|
|
| @@ -2729,15 +2766,20 @@ Value* EffectGraphVisitor::BuildInstantiatedTypeArguments(
|
| // The type arguments are uninstantiated.
|
| const Class& instantiator_class =
|
| Class::ZoneHandle(Z, owner()->function().Owner());
|
| - Value* instantiator_type_args = BuildInstantiatorTypeArguments(token_pos);
|
| - const bool use_instantiator_type_args =
|
| - type_arguments.IsUninstantiatedIdentity() ||
|
| - type_arguments.CanShareInstantiatorTypeArguments(instantiator_class);
|
| - if (use_instantiator_type_args) {
|
| - return instantiator_type_args;
|
| + Value* instantiator_type_args = NULL;
|
| + if (type_arguments.IsInstantiated(kCurrentClass)) {
|
| + instantiator_type_args = BuildNullValue(token_pos);
|
| + } else {
|
| + instantiator_type_args = BuildInstantiatorTypeArguments(token_pos);
|
| + const bool use_instantiator_type_args =
|
| + type_arguments.IsUninstantiatedIdentity() ||
|
| + type_arguments.CanShareInstantiatorTypeArguments(instantiator_class);
|
| + if (use_instantiator_type_args) {
|
| + return instantiator_type_args;
|
| + }
|
| }
|
| Value* function_type_args = NULL;
|
| - if (type_arguments.IsInstantiated(kCurrentFunction)) {
|
| + if (type_arguments.IsInstantiated(kFunctions)) {
|
| function_type_args = BuildNullValue(token_pos);
|
| } else {
|
| function_type_args = BuildFunctionTypeArguments(token_pos);
|
|
|