[vala] Recursively infer generic type arguments
- From: Luca Bruno <lucabru src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala] Recursively infer generic type arguments
- Date: Sun, 16 Nov 2014 23:47:23 +0000 (UTC)
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]