From 11e6d28ab4dcbf93278c9f77489a05bf5cb8fce1 Mon Sep 17 00:00:00 2001 From: Simon Werbeck Date: Thu, 14 Aug 2014 23:46:17 +0200 Subject: [PATCH] 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(-) create mode 100644 tests/methods/bug626783.vala 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 { +} + +public void foo (Test t) { +} + +public void bar (Test,int> t) { +} + +public T* baz () { + return null; +} + +void main () { + var f = new Test (); + foo (f); + + var g = new Test,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; -- 2.47.2