From: Jürg Billeter Date: Fri, 28 Nov 2008 11:34:22 +0000 (+0000) Subject: Improve handling of generic values, fixes bug 562460 X-Git-Tag: VALA_0_5_2~44 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b3edafecb598c3018dcddee382fa4c5fe124d7aa;p=thirdparty%2Fvala.git Improve handling of generic values, fixes bug 562460 2008-11-28 Jürg Billeter * vala/valadatatype.vala: * vala/valaexpression.vala: * vala/valaintegertype.vala: * vala/valamemberaccess.vala: * vala/valamethodcall.vala: * vala/valasemanticanalyzer.vala: * vala/valavaluetype.vala: * gobject/valaccodebasemodule.vala: * gobject/valaccodecontrolflowmodule.vala: Improve handling of generic values, fixes bug 562460 svn path=/trunk/; revision=2067 --- diff --git a/ChangeLog b/ChangeLog index db6ca5801..6f2bff8cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2008-11-28 Jürg Billeter + + * vala/valadatatype.vala: + * vala/valaexpression.vala: + * vala/valaintegertype.vala: + * vala/valamemberaccess.vala: + * vala/valamethodcall.vala: + * vala/valasemanticanalyzer.vala: + * vala/valavaluetype.vala: + * gobject/valaccodebasemodule.vala: + * gobject/valaccodecontrolflowmodule.vala: + + Improve handling of generic values, fixes bug 562460 + 2008-11-28 Jürg Billeter * vala/valabinaryexpression.vala: diff --git a/gobject/valaccodebasemodule.vala b/gobject/valaccodebasemodule.vala index 039f369dd..99a868114 100644 --- a/gobject/valaccodebasemodule.vala +++ b/gobject/valaccodebasemodule.vala @@ -2092,8 +2092,22 @@ public class Vala.CCodeBaseModule : CCodeModule { public override void visit_expression (Expression expr) { if (expr.ccodenode != null && !expr.lvalue) { + if (expr.formal_value_type is GenericType && !(expr.value_type is GenericType)) { + if (expr.formal_value_type.type_parameter.parent_symbol != garray_type) { + // GArray doesn't use pointer-based generics + expr.ccodenode = convert_from_generic_pointer ((CCodeExpression) expr.ccodenode, expr.value_type); + } + } + // memory management, implicit casts, and boxing/unboxing expr.ccodenode = transform_expression ((CCodeExpression) expr.ccodenode, expr.value_type, expr.target_type, expr); + + if (expr.formal_target_type is GenericType && !(expr.target_type is GenericType)) { + if (expr.formal_target_type.type_parameter.parent_symbol != garray_type) { + // GArray doesn't use pointer-based generics + expr.ccodenode = convert_to_generic_pointer ((CCodeExpression) expr.ccodenode, expr.target_type); + } + } } } @@ -3005,12 +3019,6 @@ public class Vala.CCodeBaseModule : CCodeModule { cexpr = get_implicit_cast_expression (cexpr, expression_type, target_type, expr); } - if (expression_type.is_type_argument) { - cexpr = convert_from_generic_pointer (cexpr, target_type); - } else if (target_type.is_type_argument) { - cexpr = convert_to_generic_pointer (cexpr, expression_type); - } - if (target_type.value_owned && (!expression_type.value_owned || boxing || unboxing)) { // need to copy value if (requires_copy (target_type) && !(expression_type is NullType)) { diff --git a/gobject/valaccodecontrolflowmodule.vala b/gobject/valaccodecontrolflowmodule.vala index 340b2584e..309c508a5 100644 --- a/gobject/valaccodecontrolflowmodule.vala +++ b/gobject/valaccodecontrolflowmodule.vala @@ -429,7 +429,7 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule { var element_data_type = collection_type.get_type_arguments ().get (0).copy (); element_data_type.value_owned = false; - element_data_type.is_type_argument = true; + element_expr = convert_from_generic_pointer (element_expr, element_data_type); element_expr = transform_expression (element_expr, element_data_type, stmt.type_reference); var cfrag = new CCodeFragment (); @@ -472,6 +472,7 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule { var element_type = SemanticAnalyzer.get_actual_type (stmt.collection.value_type, (GenericType) get_method.return_type, stmt); + element_expr = convert_from_generic_pointer (element_expr, element_type); element_expr = transform_expression (element_expr, element_type, stmt.type_reference); var cfrag = new CCodeFragment (); diff --git a/vala/valadatatype.vala b/vala/valadatatype.vala index c0d187825..1b9b2efdb 100644 --- a/vala/valadatatype.vala +++ b/vala/valadatatype.vala @@ -39,11 +39,6 @@ public abstract class Vala.DataType : CodeNode { */ public bool nullable { get; set; } - /** - * Specifies that this type is a generic type argument. - */ - public bool is_type_argument { get; set; } - /** * The referred data type. */ @@ -481,4 +476,26 @@ public abstract class Vala.DataType : CodeNode { } return false; } + + public DataType get_actual_type (DataType? derived_instance_type, CodeNode node_reference) { + if (derived_instance_type == null) { + return this; + } + + DataType result = this; + + if (result is GenericType) { + result = SemanticAnalyzer.get_actual_type (derived_instance_type, (GenericType) result, node_reference); + } + + if (result.type_argument_list != null) { + // recursely get actual types for type arguments + result = result.copy (); + for (int i = 0; i < result.type_argument_list.size; i++) { + result.type_argument_list[i] = result.type_argument_list[i].get_actual_type (derived_instance_type, node_reference); + } + } + + return result; + } } diff --git a/vala/valaexpression.vala b/vala/valaexpression.vala index 95db85a5c..79ca8b13c 100644 --- a/vala/valaexpression.vala +++ b/vala/valaexpression.vala @@ -33,14 +33,18 @@ public abstract class Vala.Expression : CodeNode { * The semantic analyzer computes this value. */ public DataType value_type { get; set; } - + + public DataType? formal_value_type { get; set; } + /* * The static type this expression is expected to have. * * The semantic analyzer computes this value, lambda expressions use it. */ public DataType target_type { get; set; } - + + public DataType? formal_target_type { get; set; } + /** * The symbol this expression refers to. */ diff --git a/vala/valaintegertype.vala b/vala/valaintegertype.vala index ac8991327..88eee0390 100644 --- a/vala/valaintegertype.vala +++ b/vala/valaintegertype.vala @@ -37,9 +37,7 @@ public class Vala.IntegerType : ValueType { } public override DataType copy () { - var type = new IntegerType (type_symbol, literal_value, literal_type_name); - type.is_type_argument = is_type_argument; - return type; + return new IntegerType (type_symbol, literal_value, literal_type_name); } public override bool compatible (DataType target_type) { diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala index c5c9cce66..031d66f6f 100644 --- a/vala/valamemberaccess.vala +++ b/vala/valamemberaccess.vala @@ -487,16 +487,11 @@ public class Vala.MemberAccess : Expression { inner.symbol_reference = this_parameter; } - value_type = analyzer.get_value_type_for_symbol (symbol_reference, lvalue); - - // resolve generic return values - if (value_type is GenericType) { - if (inner != null) { - value_type = analyzer.get_actual_type (inner.value_type, (GenericType) value_type, this); - if (value_type == null) { - return false; - } - } + formal_value_type = analyzer.get_value_type_for_symbol (symbol_reference, lvalue); + if (inner != null && formal_value_type != null) { + value_type = formal_value_type.get_actual_type (inner.value_type, this); + } else { + value_type = formal_value_type; } if (symbol_reference is Method) { diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala index 4e2f92332..984318923 100644 --- a/vala/valamethodcall.vala +++ b/vala/valamethodcall.vala @@ -134,6 +134,9 @@ public class Vala.MethodCall : Expression { return false; } + // type of target object + DataType target_object_type = null; + if (call is MemberAccess) { var ma = (MemberAccess) call; if (ma.prototype_access) { @@ -141,6 +144,10 @@ public class Vala.MethodCall : Expression { Report.error (source_reference, "Access to instance member `%s' denied".printf (call.symbol_reference.get_full_name ())); return false; } + + if (ma.inner != null) { + target_object_type = ma.inner.value_type; + } } var mtype = call.value_type; @@ -220,16 +227,8 @@ public class Vala.MethodCall : Expression { Expression arg = arg_it.get (); /* store expected type for callback parameters */ - arg.target_type = param.parameter_type; - - // resolve generic type parameters - var ma = call as MemberAccess; - if (arg.target_type is GenericType) { - if (ma != null && ma.inner != null) { - arg.target_type = analyzer.get_actual_type (ma.inner.value_type, (GenericType) arg.target_type, arg); - assert (arg.target_type != null); - } - } + arg.formal_target_type = param.parameter_type; + arg.target_type = arg.formal_target_type.get_actual_type (target_object_type, this); last_arg = arg; } @@ -373,9 +372,7 @@ public class Vala.MethodCall : Expression { arg.check (analyzer); } - DataType ret_type; - - ret_type = mtype.get_return_type (); + DataType ret_type = mtype.get_return_type (); params = mtype.get_parameters (); if (ret_type is VoidType) { @@ -391,29 +388,8 @@ public class Vala.MethodCall : Expression { } } - // resolve generic return values - var ma = call as MemberAccess; - if (ret_type is GenericType) { - if (ma != null && ma.inner != null) { - ret_type = analyzer.get_actual_type (ma.inner.value_type, (GenericType) ret_type, this); - if (ret_type == null) { - return false; - } - } - } - Gee.List resolved_type_args = new ArrayList (); - foreach (DataType type_arg in ret_type.get_type_arguments ()) { - if (type_arg is GenericType && ma != null && ma.inner != null) { - resolved_type_args.add (analyzer.get_actual_type (ma.inner.value_type, (GenericType) type_arg, this)); - } else { - resolved_type_args.add (type_arg); - } - } - ret_type = ret_type.copy (); - ret_type.remove_all_type_arguments (); - foreach (DataType resolved_type_arg in resolved_type_args) { - ret_type.add_type_argument (resolved_type_arg); - } + formal_value_type = ret_type; + value_type = formal_value_type.get_actual_type (target_object_type, this); if (mtype is MethodType) { var m = ((MethodType) mtype).method_symbol; @@ -426,8 +402,6 @@ public class Vala.MethodCall : Expression { } } - value_type = ret_type; - analyzer.check_arguments (this, mtype, params, get_argument_list ()); return !error; diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala index f23448b45..4b6b7b8e9 100644 --- a/vala/valasemanticanalyzer.vala +++ b/vala/valasemanticanalyzer.vala @@ -569,10 +569,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor { return generic_type; } actual_type = actual_type.copy (); - if (!(derived_instance_type.data_type != null && derived_instance_type.data_type.get_full_name () == "GLib.Array")) { - // GArray doesn't use pointer-based generics - actual_type.is_type_argument = true; - } actual_type.value_owned = actual_type.value_owned && generic_type.value_owned; return actual_type; } diff --git a/vala/valavaluetype.vala b/vala/valavaluetype.vala index 08df08205..585337913 100644 --- a/vala/valavaluetype.vala +++ b/vala/valavaluetype.vala @@ -43,7 +43,6 @@ public class Vala.ValueType : DataType { result.nullable = nullable; result.is_dynamic = is_dynamic; result.floating_reference = floating_reference; - result.is_type_argument = is_type_argument; foreach (DataType arg in get_type_arguments ()) { result.add_type_argument (arg.copy ());