]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Infer type arguments when calling generic methods
authorJürg Billeter <j@bitron.ch>
Sat, 20 Mar 2010 18:12:37 +0000 (19:12 +0100)
committerJürg Billeter <j@bitron.ch>
Sat, 20 Mar 2010 18:12:37 +0000 (19:12 +0100)
Fixes bug 611235.

vala/valamethodcall.vala

index e519b779f57baa9d54bdc0b9cdf05b8e6be3d6c3..b9be421274de980cd81ee80815787e84961af5d8 100644 (file)
@@ -288,6 +288,21 @@ public class Vala.MethodCall : Expression {
                                        params = m.get_async_end_parameters ();
                                }
                        }
+
+                       if (m != null && m.get_type_parameters ().size > 0) {
+                               var ma = (MemberAccess) call;
+                               int n_type_params = m.get_type_parameters ().size;
+                               int n_type_args = ma.get_type_arguments ().size;
+                               if (n_type_args > 0 && n_type_args < n_type_params) {
+                                       error = true;
+                                       Report.error (ma.source_reference, "too few type arguments");
+                                       return false;
+                               } else if (n_type_args > 0 && n_type_args > n_type_params) {
+                                       error = true;
+                                       Report.error (ma.source_reference, "too many type arguments");
+                                       return false;
+                               }
+                       }
                }
 
                Expression last_arg = null;
@@ -535,6 +550,67 @@ public class Vala.MethodCall : Expression {
                                }
                                dynamic_sig.handler.target_type = new DelegateType (dynamic_sig.get_delegate (new ObjectType ((ObjectTypeSymbol) dynamic_sig.parent_symbol), this));
                        }
+
+                       if (m != null && m.get_type_parameters ().size > 0) {
+                               var ma = (MemberAccess) call;
+                               if (ma.get_type_arguments ().size == 0) {
+                                       // infer type arguments
+                                       foreach (var type_param in m.get_type_parameters ()) {
+                                               DataType type_arg = null;
+
+                                               // infer type arguments from arguments
+                                               arg_it = args.iterator ();
+                                               foreach (FormalParameter param in params) {
+                                                       if (param.ellipsis || param.params_array) {
+                                                               break;
+                                                       }
+
+                                                       if (arg_it.next ()) {
+                                                               Expression arg = arg_it.get ();
+
+                                                               var generic_type = param.parameter_type as GenericType;
+                                                               if (generic_type != null && generic_type.type_parameter == type_param) {
+                                                                       type_arg = arg.value_type;
+                                                                       break;
+                                                               }
+
+                                                               arg.target_type = arg.formal_target_type.get_actual_type (target_object_type, call as MemberAccess, this);
+                                                       }
+                                               }
+
+                                               // infer type arguments from expected return type
+                                               if (type_arg == null) {
+                                                       var generic_type = m.return_type as GenericType;
+                                                       if (generic_type != null && generic_type.type_parameter == type_param) {
+                                                               type_arg = target_type;
+                                                       }
+                                               }
+
+                                               if (type_arg == null) {
+                                                       Report.error (ma.source_reference, "cannot infer generic type argument for type parameter `%s'".printf (type_param.get_full_name ()));
+                                               }
+
+                                               ma.add_type_argument (type_arg);
+                                       }
+
+                                       // recalculate argument target types with new information
+                                       arg_it = args.iterator ();
+                                       foreach (FormalParameter param in params) {
+                                               if (param.ellipsis || param.params_array) {
+                                                       break;
+                                               }
+
+                                               if (arg_it.next ()) {
+                                                       Expression arg = arg_it.get ();
+
+                                                       arg.target_type = arg.formal_target_type.get_actual_type (target_object_type, call as MemberAccess, this);
+                                               }
+                                       }
+
+                                       // recalculate return value type with new information
+                                       value_type = formal_value_type.get_actual_type (target_object_type, call as MemberAccess, this);
+                               }
+                       }
                } else if (mtype is DelegateType) {
                        var d = ((DelegateType) mtype).delegate_symbol;
                        foreach (DataType error_type in d.get_error_types ()) {