diff options
author | Simon Werbeck <simon.werbeck@gmail.com> | 2014-08-14 23:46:17 +0200 |
---|---|---|
committer | Luca Bruno <lucabru@src.gnome.org> | 2014-11-17 00:47:13 +0100 |
commit | 11e6d28ab4dcbf93278c9f77489a05bf5cb8fce1 (patch) | |
tree | a3f3b05947f5fefabc939cdc13880a0e33d48c38 | |
parent | 9644dd2a97fcc3e9a55cf90f322cdb1a901150cf (diff) | |
download | vala-11e6d28ab4dcbf93278c9f77489a05bf5cb8fce1.tar.gz |
Recursively infer generic type arguments
Slightly changed by Luca Bruno.
Fixes bug 626783
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rw-r--r-- | tests/methods/bug626783.vala | 22 | ||||
-rw-r--r-- | vala/valaarraytype.vala | 9 | ||||
-rw-r--r-- | vala/valadatatype.vala | 18 | ||||
-rw-r--r-- | vala/valagenerictype.vala | 10 | ||||
-rw-r--r-- | vala/valamethodcall.vala | 12 | ||||
-rw-r--r-- | vala/valapointertype.vala | 9 |
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; |