[vala] Infer type arguments when calling generic methods
- From: Jürg Billeter <juergbi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala] Infer type arguments when calling generic methods
- Date: Sat, 20 Mar 2010 18:16:13 +0000 (UTC)
commit 45d2fd2172efaf7d4f2521a3e9963b6b24c72e5b
Author: Jürg Billeter <j bitron ch>
Date: Sat Mar 20 19:12:37 2010 +0100
Infer type arguments when calling generic methods
Fixes bug 611235.
vala/valamethodcall.vala | 76 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 76 insertions(+), 0 deletions(-)
---
diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala
index e519b77..b9be421 100644
--- a/vala/valamethodcall.vala
+++ b/vala/valamethodcall.vala
@@ -288,6 +288,21 @@ public class Vala.MethodCall : Expression {
params = m.get_async_end_parameters ();
}
}
+
+ if (m != null && m.get_type_parameters ().size > 0) {
+ var ma = (MemberAccess) call;
+ int n_type_params = m.get_type_parameters ().size;
+ int n_type_args = ma.get_type_arguments ().size;
+ if (n_type_args > 0 && n_type_args < n_type_params) {
+ error = true;
+ Report.error (ma.source_reference, "too few type arguments");
+ return false;
+ } else if (n_type_args > 0 && n_type_args > n_type_params) {
+ error = true;
+ Report.error (ma.source_reference, "too many type arguments");
+ return false;
+ }
+ }
}
Expression last_arg = null;
@@ -535,6 +550,67 @@ public class Vala.MethodCall : Expression {
}
dynamic_sig.handler.target_type = new DelegateType (dynamic_sig.get_delegate (new ObjectType ((ObjectTypeSymbol) dynamic_sig.parent_symbol), this));
}
+
+ if (m != null && m.get_type_parameters ().size > 0) {
+ var ma = (MemberAccess) call;
+ if (ma.get_type_arguments ().size == 0) {
+ // infer type arguments
+ foreach (var type_param in m.get_type_parameters ()) {
+ DataType type_arg = null;
+
+ // infer type arguments from arguments
+ arg_it = args.iterator ();
+ foreach (FormalParameter param in params) {
+ if (param.ellipsis || param.params_array) {
+ break;
+ }
+
+ if (arg_it.next ()) {
+ Expression arg = arg_it.get ();
+
+ var generic_type = param.parameter_type as GenericType;
+ if (generic_type != null && generic_type.type_parameter == type_param) {
+ type_arg = arg.value_type;
+ break;
+ }
+
+ arg.target_type = arg.formal_target_type.get_actual_type (target_object_type, call as MemberAccess, this);
+ }
+ }
+
+ // infer type arguments from expected return type
+ if (type_arg == null) {
+ var generic_type = m.return_type as GenericType;
+ if (generic_type != null && generic_type.type_parameter == type_param) {
+ type_arg = target_type;
+ }
+ }
+
+ if (type_arg == null) {
+ Report.error (ma.source_reference, "cannot infer generic type argument for type parameter `%s'".printf (type_param.get_full_name ()));
+ }
+
+ ma.add_type_argument (type_arg);
+ }
+
+ // recalculate argument target types with new information
+ arg_it = args.iterator ();
+ foreach (FormalParameter param in params) {
+ if (param.ellipsis || param.params_array) {
+ break;
+ }
+
+ if (arg_it.next ()) {
+ Expression arg = arg_it.get ();
+
+ arg.target_type = arg.formal_target_type.get_actual_type (target_object_type, call as MemberAccess, this);
+ }
+ }
+
+ // recalculate return value type with new information
+ value_type = formal_value_type.get_actual_type (target_object_type, call as MemberAccess, this);
+ }
+ }
} else if (mtype is DelegateType) {
var d = ((DelegateType) mtype).delegate_symbol;
foreach (DataType error_type in d.get_error_types ()) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]