+2008-11-28 Jürg Billeter <j@bitron.ch>
+
+ * 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 <j@bitron.ch>
* vala/valabinaryexpression.vala:
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);
+ }
+ }
}
}
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)) {
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 ();
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 ();
*/
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.
*/
}
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;
+ }
}
* 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.
*/
}
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) {
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) {
return false;
}
+ // type of target object
+ DataType target_object_type = null;
+
if (call is MemberAccess) {
var ma = (MemberAccess) call;
if (ma.prototype_access) {
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;
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;
}
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) {
}
}
- // 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<DataType> resolved_type_args = new ArrayList<DataType> ();
- 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;
}
}
- value_type = ret_type;
-
analyzer.check_arguments (this, mtype, params, get_argument_list ());
return !error;
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;
}
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 ());