summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Werbeck <simon.werbeck@gmail.com>2014-08-14 23:46:17 +0200
committerLuca Bruno <lucabru@src.gnome.org>2014-11-17 00:47:13 +0100
commit11e6d28ab4dcbf93278c9f77489a05bf5cb8fce1 (patch)
treea3f3b05947f5fefabc939cdc13880a0e33d48c38
parent9644dd2a97fcc3e9a55cf90f322cdb1a901150cf (diff)
downloadvala-11e6d28ab4dcbf93278c9f77489a05bf5cb8fce1.tar.gz
Recursively infer generic type arguments
Slightly changed by Luca Bruno. Fixes bug 626783
-rw-r--r--tests/Makefile.am1
-rw-r--r--tests/methods/bug626783.vala22
-rw-r--r--vala/valaarraytype.vala9
-rw-r--r--vala/valadatatype.vala18
-rw-r--r--vala/valagenerictype.vala10
-rw-r--r--vala/valamethodcall.vala12
-rw-r--r--vala/valapointertype.vala9
7 files changed, 72 insertions, 9 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 49357c5ab..0da5e3bfb 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 000000000..d2b401b8c
--- /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 941485a1f..d993e3c93 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 352885bfd..02b4cf13f 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 49a4c5723..66415e6f9 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 efce5483a..0229e40b7 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 822123e91..461983c30 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;