[vala] Recursively infer generic type arguments



commit 11e6d28ab4dcbf93278c9f77489a05bf5cb8fce1
Author: Simon Werbeck <simon werbeck gmail com>
Date:   Thu Aug 14 23:46:17 2014 +0200

    Recursively infer generic type arguments
    
    Slightly changed by Luca Bruno.
    
    Fixes bug 626783

 tests/Makefile.am            |    1 +
 tests/methods/bug626783.vala |   22 ++++++++++++++++++++++
 vala/valaarraytype.vala      |    9 +++++++++
 vala/valadatatype.vala       |   18 ++++++++++++++++++
 vala/valagenerictype.vala    |   10 ++++++++++
 vala/valamethodcall.vala     |   12 +++---------
 vala/valapointertype.vala    |    9 +++++++++
 7 files changed, 72 insertions(+), 9 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 49357c5..0da5e3b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -50,6 +50,7 @@ TESTS = \
        methods/bug613483.vala \
        methods/bug620673.vala \
        methods/bug622570.vala \
+       methods/bug626783.vala \
        methods/bug639054.vala \
        methods/bug642885.vala \
        methods/bug642899.vala \
diff --git a/tests/methods/bug626783.vala b/tests/methods/bug626783.vala
new file mode 100644
index 0000000..d2b401b
--- /dev/null
+++ b/tests/methods/bug626783.vala
@@ -0,0 +1,22 @@
+public class Test<G,H> {
+}
+
+public void foo<T> (Test<T,int> t) {
+}
+
+public void bar<A,B> (Test<Test<A,B>,int> t) {
+}
+
+public T* baz<T> () {
+       return null;
+}
+
+void main () {
+       var f = new Test<int,int> ();
+       foo (f);
+
+       var g = new Test<Test<char,uint>,int> ();
+       bar (g);
+
+       int* i = baz ();
+}
diff --git a/vala/valaarraytype.vala b/vala/valaarraytype.vala
index 941485a..d993e3c 100644
--- a/vala/valaarraytype.vala
+++ b/vala/valaarraytype.vala
@@ -272,6 +272,15 @@ public class Vala.ArrayType : ReferenceType {
                return result;
        }
 
+       public override DataType? infer_type_argument (TypeParameter type_param, DataType value_type) {
+               var array_type = value_type as ArrayType;
+               if (array_type != null) {
+                       return element_type.infer_type_argument (type_param, array_type.element_type);
+               }
+
+               return null;
+       }
+
        public override bool is_disposable () {
                if (fixed_length) {
                        return element_type.is_disposable ();
diff --git a/vala/valadatatype.vala b/vala/valadatatype.vala
index 352885b..02b4cf1 100644
--- a/vala/valadatatype.vala
+++ b/vala/valadatatype.vala
@@ -462,6 +462,24 @@ public abstract class Vala.DataType : CodeNode {
                return result;
        }
 
+       /**
+        * Search for the type parameter in this formal type and match it in
+        * value_type.
+        */
+       public virtual DataType? infer_type_argument (TypeParameter type_param, DataType value_type) {
+               var value_type_arg_it = value_type.get_type_arguments ().iterator ();
+               foreach (var formal_type_arg in this.get_type_arguments ()) {
+                       if (value_type_arg_it.next ()) {
+                               var inferred_type = formal_type_arg.infer_type_argument (type_param, 
value_type_arg_it.get ());
+                               if (inferred_type != null) {
+                                       return inferred_type;
+                               }
+                       }
+               }
+
+               return null;
+       }
+
        public bool is_weak () {
                if (this.value_owned) {
                        return false;
diff --git a/vala/valagenerictype.vala b/vala/valagenerictype.vala
index 49a4c57..66415e6 100644
--- a/vala/valagenerictype.vala
+++ b/vala/valagenerictype.vala
@@ -42,6 +42,16 @@ public class Vala.GenericType : DataType {
                return result;
        }
 
+       public override DataType? infer_type_argument (TypeParameter type_param, DataType value_type) {
+               if (type_parameter == type_param) {
+                       var ret = value_type.copy ();
+                       ret.value_owned = true;
+                       return ret;
+               }
+
+               return null;
+       }
+
        public override string to_qualified_string (Scope? scope = null) {
                return type_parameter.name;
        }
diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala
index efce548..0229e40 100644
--- a/vala/valamethodcall.vala
+++ b/vala/valamethodcall.vala
@@ -536,10 +536,8 @@ public class Vala.MethodCall : Expression {
                                                        if (arg_it.next ()) {
                                                                Expression arg = arg_it.get ();
 
-                                                               var generic_type = param.variable_type as 
GenericType;
-                                                               if (generic_type != null && 
generic_type.type_parameter == type_param) {
-                                                                       type_arg = arg.value_type.copy ();
-                                                                       type_arg.value_owned = true;
+                                                               type_arg = 
param.variable_type.infer_type_argument (type_param, arg.value_type);
+                                                               if (type_arg != null) {
                                                                        break;
                                                                }
 
@@ -549,11 +547,7 @@ public class Vala.MethodCall : Expression {
 
                                                // infer type arguments from expected return type
                                                if (type_arg == null && target_type != null) {
-                                                       var generic_type = m.return_type as GenericType;
-                                                       if (generic_type != null && 
generic_type.type_parameter == type_param) {
-                                                               type_arg = target_type.copy ();
-                                                               type_arg.value_owned = true;
-                                                       }
+                                                       type_arg = m.return_type.infer_type_argument 
(type_param, target_type);
                                                }
 
                                                if (type_arg == null) {
diff --git a/vala/valapointertype.vala b/vala/valapointertype.vala
index 822123e..461983c 100644
--- a/vala/valapointertype.vala
+++ b/vala/valapointertype.vala
@@ -137,6 +137,15 @@ public class Vala.PointerType : DataType {
                return result;
        }
 
+       public override DataType? infer_type_argument (TypeParameter type_param, DataType value_type) {
+               var pointer_type = value_type as PointerType;
+               if (pointer_type != null) {
+                       return base_type.infer_type_argument (type_param, pointer_type.base_type);
+               }
+
+               return null;
+       }
+
        public override bool check (CodeContext context) {
                error = !base_type.check (context);
                return !error;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]