Commit 97a9f3bc authored by Jürg Billeter's avatar Jürg Billeter Committed by Jürg Billeter

add more non-null warnings

2008-02-01  Juerg Billeter  <j@bitron.ch>

	* vala/parser.y, vala/valaarraytype.vala, vala/valadatatype.vala,
	  vala/valaintegertype.vala, vala/valanulltype.vala,
	  vala/valapointertype.vala, vala/valasemanticanalyzer.vala,
	  vala/valasymbolresolver.vala, vala/valaunresolvedtype.vala,
	  ccode/valaccodeassignment.vala, ccode/valaccodebinaryexpression.vala,
	  gobject/valaccodegenerator.vala: add more non-null warnings

svn path=/trunk/; revision=940
parent c878f08e
2008-02-01 Jürg Billeter <j@bitron.ch>
* vala/parser.y, vala/valaarraytype.vala, vala/valadatatype.vala,
vala/valaintegertype.vala, vala/valanulltype.vala,
vala/valapointertype.vala, vala/valasemanticanalyzer.vala,
vala/valasymbolresolver.vala, vala/valaunresolvedtype.vala,
ccode/valaccodeassignment.vala, ccode/valaccodebinaryexpression.vala,
gobject/valaccodegenerator.vala: add more non-null warnings
2008-01-31 Jürg Billeter <j@bitron.ch>
* vapi/atk.vapi, vapi/gdk-pixbuf-2.0.vapi, vapi/gstreamer-0.10.vapi,
......
/* valaccodeassignment.vala
*
* Copyright (C) 2006 Jürg Billeter
* Copyright (C) 2006-2008 Jürg Billeter
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -48,9 +48,8 @@ public class Vala.CCodeAssignment : CCodeExpression {
}
public override void write (CCodeWriter! writer) {
if (left != null) {
left.write (writer);
}
left.write (writer);
writer.write_string (" ");
if (operator == CCodeAssignmentOperator.BITWISE_OR) {
......@@ -76,9 +75,8 @@ public class Vala.CCodeAssignment : CCodeExpression {
}
writer.write_string ("= ");
if (right != null) {
right.write (writer);
}
right.write (writer);
}
}
......
/* valaccodebinaryexpression.vala
*
* Copyright (C) 2006 Jürg Billeter
* Copyright (C) 2006-2008 Jürg Billeter
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -48,9 +48,8 @@ public class Vala.CCodeBinaryExpression : CCodeExpression {
}
public override void write (CCodeWriter! writer) {
if (left != null) {
left.write (writer);
}
left.write (writer);
writer.write_string (" ");
if (operator == CCodeBinaryOperator.PLUS) {
writer.write_string ("+");
......@@ -89,10 +88,10 @@ public class Vala.CCodeBinaryExpression : CCodeExpression {
} else if (operator == CCodeBinaryOperator.OR) {
writer.write_string ("||");
}
writer.write_string (" ");
if (right != null) {
right.write (writer);
}
right.write (writer);
}
}
......
......@@ -1057,10 +1057,6 @@ public class Vala.CCodeGenerator : CodeGenerator {
* if foo is of static type non-null
*/
if (type.is_null) {
return new CCodeConstant ("NULL");
}
var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cvar, new CCodeConstant ("NULL"));
if (type.data_type == null) {
if (!(current_type_symbol is Class) || !current_class.is_subtype_of (gobject_type)) {
......@@ -1131,7 +1127,7 @@ public class Vala.CCodeGenerator : CodeGenerator {
var cassign = new CCodeAssignment (cvar, ccomma);
// g_free (NULL) is allowed
if ((context.non_null && !type.nullable) || (type.data_type != null && !type.data_type.is_reference_counting () && type.data_type.get_free_function () == "g_free")) {
if ((context.non_null && !type.requires_null_check) || (type.data_type != null && !type.data_type.is_reference_counting () && type.data_type.get_free_function () == "g_free")) {
return new CCodeParenthesizedExpression (cassign);
}
......@@ -2415,7 +2411,8 @@ public class Vala.CCodeGenerator : CodeGenerator {
var ccall = new CCodeFunctionCall (dupexpr);
if (((context.non_null && !expr.static_type.nullable) && expr.static_type.type_parameter == null) || expr is LiteralExpression) {
if (((context.non_null && !expr.static_type.requires_null_check) && expr.static_type.type_parameter == null) || expr is LiteralExpression) {
// expression is non-null
ccall.add_argument ((CCodeExpression) expr.ccodenode);
return ccall;
......
......@@ -526,7 +526,8 @@ type
$$ = $1;
vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $2);
if ($4) {
vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_data_type_set_nullable ($$, TRUE);
vala_data_type_set_requires_null_check ($$, TRUE);
}
}
| WEAK type_name opt_rank_specifier opt_op_neg opt_any_interr
......@@ -535,44 +536,49 @@ type
vala_unresolved_type_set_is_weak (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $3);
if ($5) {
vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_data_type_set_nullable ($$, TRUE);
vala_data_type_set_requires_null_check ($$, TRUE);
}
}
| type_name opt_rank_specifier opt_op_neg opt_any_interr HASH
{
$$ = $1;
vala_unresolved_type_set_transfers_ownership (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_data_type_set_transfers_ownership ($$, TRUE);
vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $2);
if ($4) {
vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_data_type_set_nullable ($$, TRUE);
vala_data_type_set_requires_null_check ($$, TRUE);
}
}
| REF type_name opt_rank_specifier opt_op_neg opt_any_interr
{
$$ = $2;
vala_unresolved_type_set_is_ref (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_data_type_set_is_ref ($$, TRUE);
vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $3);
if ($5) {
vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_data_type_set_nullable ($$, TRUE);
vala_data_type_set_requires_null_check ($$, TRUE);
}
}
| OUT type_name opt_rank_specifier opt_op_neg opt_any_interr
{
$$ = $2;
vala_unresolved_type_set_is_out (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_data_type_set_is_out ($$, TRUE);
vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $3);
if ($5) {
vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_data_type_set_nullable ($$, TRUE);
vala_data_type_set_requires_null_check ($$, TRUE);
}
}
| OUT WEAK type_name opt_rank_specifier opt_op_neg opt_any_interr
{
$$ = $3;
vala_unresolved_type_set_is_weak (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_unresolved_type_set_is_out (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_data_type_set_is_out ($$, TRUE);
vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $4);
if ($6) {
vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_data_type_set_nullable ($$, TRUE);
vala_data_type_set_requires_null_check ($$, TRUE);
}
}
| type_name stars opt_rank_specifier
......@@ -1901,11 +1907,9 @@ local_variable_type
$$ = VALA_DATA_TYPE (vala_unresolved_type_new_from_expression ($1));
g_object_unref ($1);
g_object_unref (src);
vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_data_type_set_takes_ownership ($$, TRUE);
vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $2);
if ($4) {
vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE);
}
vala_data_type_set_nullable ($$, TRUE);
}
| primary_expression stars
{
......@@ -1922,9 +1926,7 @@ local_variable_type
g_object_unref ($2);
g_object_unref (src);
vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $3);
if ($5) {
vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE);
}
vala_data_type_set_nullable ($$, TRUE);
}
| VOID
{
......@@ -2275,7 +2277,7 @@ foreach_statement
{
ValaSourceReference *src = src(@3);
if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($3))) {
vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($3), TRUE);
vala_data_type_set_takes_ownership ($3, TRUE);
}
$$ = VALA_STATEMENT (vala_code_context_create_foreach_statement (context, $3, $4, $6, $8, src));
g_object_unref ($3);
......@@ -2896,11 +2898,11 @@ field_declaration
src = src_com(@5, $1);
if (VALA_IS_UNRESOLVED_TYPE ($5)) {
if (vala_unresolved_type_get_is_ref (VALA_UNRESOLVED_TYPE ($5)) || vala_unresolved_type_get_is_out (VALA_UNRESOLVED_TYPE ($5))) {
if (vala_data_type_get_is_ref ($5) || vala_data_type_get_is_out ($5)) {
vala_report_error (src, "`ref' and `out' may only be used for parameters.");
}
if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($5))) {
vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($5), TRUE);
vala_data_type_set_takes_ownership ($5, TRUE);
}
}
......@@ -3048,11 +3050,11 @@ method_header
src = src_com(@6, $1);
if (VALA_IS_UNRESOLVED_TYPE ($5)) {
if (vala_unresolved_type_get_is_ref (VALA_UNRESOLVED_TYPE ($5)) || vala_unresolved_type_get_is_out (VALA_UNRESOLVED_TYPE ($5))) {
if (vala_data_type_get_is_ref ($5) || vala_data_type_get_is_out ($5)) {
vala_report_error (src, "`ref' and `out' may only be used for parameters.");
}
if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($5))) {
vala_unresolved_type_set_transfers_ownership (VALA_UNRESOLVED_TYPE ($5), TRUE);
vala_data_type_set_transfers_ownership ($5, TRUE);
}
}
......@@ -3216,15 +3218,14 @@ fixed_parameter
src = src(@3);
if (VALA_IS_UNRESOLVED_TYPE ($3)) {
if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($3))) {
vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($3), TRUE);
vala_data_type_set_takes_ownership ($3, TRUE);
}
if (!vala_unresolved_type_get_is_ref (VALA_UNRESOLVED_TYPE ($3))
&& !vala_unresolved_type_get_is_out (VALA_UNRESOLVED_TYPE ($3))
&& !vala_unresolved_type_get_transfers_ownership (VALA_UNRESOLVED_TYPE ($3))) {
/* FIXME take_ownership for in parameters that don't transfer ownership is not supported yet
* this may require an additional local variable per parameter */
vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($3), FALSE);
if (!vala_data_type_get_is_ref ($3)
&& !vala_data_type_get_is_out ($3)
&& !vala_data_type_get_transfers_ownership ($3)) {
/* take_ownership for in parameters that don't transfer ownership is not supported */
vala_data_type_set_takes_ownership ($3, FALSE);
}
}
......@@ -3241,15 +3242,14 @@ fixed_parameter
src = src(@3);
if (VALA_IS_UNRESOLVED_TYPE ($3)) {
if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($3))) {
vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($3), TRUE);
vala_data_type_set_takes_ownership ($3, TRUE);
}
if (!vala_unresolved_type_get_is_ref (VALA_UNRESOLVED_TYPE ($3))
&& !vala_unresolved_type_get_is_out (VALA_UNRESOLVED_TYPE ($3))
&& !vala_unresolved_type_get_transfers_ownership (VALA_UNRESOLVED_TYPE ($3))) {
/* FIXME take_ownership for in parameters that don't transfer ownership is not supported yet
* this may require an additional local variable per parameter */
vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($3), FALSE);
if (!vala_data_type_get_is_ref ($3)
&& !vala_data_type_get_is_out ($3)
&& !vala_data_type_get_transfers_ownership ($3)) {
/* take_ownership for in parameters that don't transfer ownership is not supported */
vala_data_type_set_takes_ownership ($3, FALSE);
}
}
......@@ -3336,7 +3336,7 @@ property_declaration
ValaSourceReference *src;
if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($5))) {
vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($5), TRUE);
vala_data_type_set_takes_ownership ($5, TRUE);
}
src = src_com(@5, $1);
......@@ -3369,7 +3369,7 @@ property_declaration
ValaSourceReference *src;
if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($5))) {
vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($5), TRUE);
vala_data_type_set_takes_ownership ($5, TRUE);
}
src = src_com(@5, $1);
......@@ -4119,7 +4119,7 @@ type_argument
$$ = $1;
if (VALA_IS_UNRESOLVED_TYPE ($$)) {
if (!vala_unresolved_type_get_is_weak (VALA_UNRESOLVED_TYPE ($$))) {
vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_data_type_set_takes_ownership ($$, TRUE);
}
}
}
......
......@@ -54,6 +54,7 @@ public class Vala.ArrayType : ReferenceType {
result.takes_ownership = takes_ownership;
result.is_out = is_out;
result.nullable = nullable;
result.requires_null_check = requires_null_check;
result.floating_reference = floating_reference;
result.is_ref = is_ref;
......
......@@ -51,10 +51,11 @@ public class Vala.DataType : CodeNode {
public bool nullable { get; set; }
/**
* Specifies that the expression is known to be null.
* Specifies that the expression may not be dereferenced without
* prior null check.
*/
public bool is_null { get; set; }
public bool requires_null_check { get; set; }
/**
* The referred data type.
*/
......@@ -228,6 +229,7 @@ public class Vala.DataType : CodeNode {
result.takes_ownership = takes_ownership;
result.is_out = is_out;
result.nullable = nullable;
result.requires_null_check = requires_null_check;
result.data_type = data_type;
result.type_parameter = type_parameter;
result.floating_reference = floating_reference;
......@@ -331,7 +333,7 @@ public class Vala.DataType : CodeNode {
}
}
public virtual bool compatible (DataType! target_type) {
public virtual bool compatible (DataType! target_type, bool enable_non_null = true) {
if (target_type is DelegateType && this is DelegateType) {
return ((DelegateType) target_type).delegate_symbol == ((DelegateType) this).delegate_symbol;
}
......@@ -369,6 +371,10 @@ public class Vala.DataType : CodeNode {
}
if (data_type == target_type.data_type) {
if (requires_null_check && !target_type.nullable && data_type != null && data_type.is_reference_type ()) {
// incompatibility between null and non-null types
return !enable_non_null;
}
return true;
}
......@@ -389,7 +395,15 @@ public class Vala.DataType : CodeNode {
}
}
return (data_type != null && target_type.data_type != null && data_type.is_subtype_of (target_type.data_type));
if (data_type != null && target_type.data_type != null && data_type.is_subtype_of (target_type.data_type)) {
if (requires_null_check && !target_type.nullable && data_type.is_reference_type ()) {
// incompatibility between null and non-null types
return !enable_non_null;
}
return true;
}
return false;
}
/**
......
......@@ -38,7 +38,7 @@ public class Vala.IntegerType : ValueType {
return type;
}
public override bool compatible (DataType! target_type) {
public override bool compatible (DataType! target_type, bool enable_non_null = true) {
if (target_type.data_type is Struct && literal.get_type_name () == "int") {
// int literals are implicitly convertible to integer types
// of a lower rank if the value of the literal is within
......@@ -53,6 +53,6 @@ public class Vala.IntegerType : ValueType {
}
}
return base.compatible (target_type);
return base.compatible (target_type, enable_non_null);
}
}
......@@ -26,10 +26,11 @@ using GLib;
* The type of the null literal.
*/
public class Vala.NullType : ReferenceType {
public NullType () {
public NullType (SourceReference source_reference) {
this.source_reference = source_reference;
}
public override bool compatible (DataType! target_type) {
public override bool compatible (DataType! target_type, bool enable_non_null = true) {
if (!(target_type is PointerType) && (target_type is NullType || (target_type.data_type == null && target_type.type_parameter == null))) {
return true;
}
......@@ -46,7 +47,8 @@ public class Vala.NullType : ReferenceType {
if (target_type.data_type.is_reference_type () ||
target_type is ArrayType ||
target_type.data_type is Delegate) {
return !(CodeContext.is_non_null_enabled ());
// incompatibility between null and non-null types
return !enable_non_null;
}
/* null is not compatible with any other type (i.e. value types) */
......@@ -54,6 +56,6 @@ public class Vala.NullType : ReferenceType {
}
public override DataType! copy () {
return new NullType ();
return new NullType (source_reference);
}
}
......@@ -50,7 +50,7 @@ public class Vala.PointerType : DataType {
return new PointerType (base_type);
}
public override bool compatible (DataType! target_type) {
public override bool compatible (DataType! target_type, bool enable_non_null = true) {
if (target_type is PointerType || (target_type.data_type != null && target_type.data_type.get_attribute ("PointerType") != null)) {
return true;
}
......
......@@ -812,9 +812,13 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
continue;
}
if (!e.static_type.compatible (array_type.element_type)) {
error = true;
e.error = true;
Report.error (e.source_reference, "Expected initializer of type `%s' but got `%s'".printf (array_type.element_type.data_type.name, e.static_type.data_type.name));
if (!e.static_type.compatible (array_type.element_type, false)) {
error = true;
e.error = true;
Report.error (e.source_reference, "Expected initializer of type `%s' but got `%s'".printf (array_type.element_type.data_type.name, e.static_type.to_string ()));
} else if (context.is_non_null_enabled ()) {
Report.warning (e.source_reference, "Expected initializer of type `%s' but got `%s'".printf (array_type.element_type.data_type.name, e.static_type.to_string ()));
}
}
}
......@@ -1032,8 +1036,12 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
if (stmt.return_expression != null &&
!stmt.return_expression.static_type.compatible (current_return_type)) {
Report.error (stmt.source_reference, "Return: Cannot convert from `%s' to `%s'".printf (stmt.return_expression.static_type.to_string (), current_return_type.to_string ()));
return;
if (!stmt.return_expression.static_type.compatible (current_return_type, false)) {
Report.error (stmt.source_reference, "Return: Cannot convert from `%s' to `%s'".printf (stmt.return_expression.static_type.to_string (), current_return_type.to_string ()));
return;
} else if (context.is_non_null_enabled ()) {
Report.warning (stmt.source_reference, "Return value may not be null");
}
}
if (stmt.return_expression != null &&
......@@ -1232,7 +1240,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
}
public override void visit_null_literal (NullLiteral! expr) {
expr.static_type = new NullType ();
expr.static_type = new NullType (expr.source_reference);
}
public override void visit_literal_expression (LiteralExpression! expr) {
......@@ -1630,9 +1638,13 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
return false;
}
} else if (!arg.static_type.compatible (param.type_reference)) {
expr.error = true;
Report.error (expr.source_reference, "Argument %d: Cannot convert from `%s' to `%s'".printf (i + 1, arg.static_type.to_string (), param.type_reference.to_string ()));
return false;
if (!arg.static_type.compatible (param.type_reference, false)) {
expr.error = true;
Report.error (expr.source_reference, "Argument %d: Cannot convert from `%s' to `%s'".printf (i + 1, arg.static_type.to_string (), param.type_reference.to_string ()));
return false;
} else if (context.is_non_null_enabled ()) {
Report.warning (expr.source_reference, "Argument %d: Argument may not be null".printf (i + 1, arg.static_type.to_string (), param.type_reference.to_string ()));
}
} else {
// 0 => null, 1 => in, 2 => ref, 3 => out
int arg_type = 1;
......@@ -2426,9 +2438,15 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
if (!expr.right.static_type.compatible (expr.left.static_type)
&& !expr.left.static_type.compatible (expr.right.static_type)) {
Report.error (expr.source_reference, "Equality operation: `%s' and `%s' are incompatible, comparison would always evaluate to false".printf (expr.right.static_type.to_string (), expr.left.static_type.to_string ()));
expr.error = true;
return;
if (!expr.right.static_type.compatible (expr.left.static_type, false)
&& !expr.left.static_type.compatible (expr.right.static_type, false)) {
Report.error (expr.source_reference, "Equality operation: `%s' and `%s' are incompatible".printf (expr.right.static_type.to_string (), expr.left.static_type.to_string ()));
expr.error = true;
return;
} else if (context.is_non_null_enabled ()) {
// warn about incompatibility between null and non-null types
Report.warning (expr.source_reference, "Equality operation: `%s' and `%s' are incompatible".printf (expr.right.static_type.to_string (), expr.left.static_type.to_string ()));
}
}
if (expr.left.static_type.compatible (string_type)
......@@ -2761,12 +2779,18 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
return;
}
} else if (a.left.static_type != null && a.right.static_type != null) {
/* if there was an error on either side,
* i.e. a.{left|right}.static_type == null, skip type check */
if (!a.right.static_type.compatible (a.left.static_type)) {
/* if there was an error on either side,
* i.e. a.{left|right}.static_type == null, skip type check */
a.error = true;
Report.error (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.static_type.to_string (), a.left.static_type.to_string ()));
return;
if (!a.right.static_type.compatible (a.left.static_type, false)) {
a.error = true;
Report.error (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.static_type.to_string (), a.left.static_type.to_string ()));
return;
} else if (context.is_non_null_enabled ()) {
// warn about incompatibility between null and non-null types
Report.warning (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.static_type.to_string (), a.left.static_type.to_string ()));
}
}
if (a.right.static_type.transfers_ownership) {
......@@ -2787,11 +2811,14 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
var ea = (ElementAccess) a.left;
if (!a.right.static_type.compatible (a.left.static_type)) {
/* if there was an error on either side,
* i.e. a.{left|right}.static_type == null, skip type check */
a.error = true;
Report.error (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.static_type.to_string (), a.left.static_type.to_string ()));
return;
if (!a.right.static_type.compatible (a.left.static_type, false)) {
a.error = true;
Report.error (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.static_type.to_string (), a.left.static_type.to_string ()));
return;
} else if (context.is_non_null_enabled ()) {
// warn about incompatibility between null and non-null types
Report.warning (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.static_type.to_string (), a.left.static_type.to_string ()));
}
}
if (a.right.static_type.transfers_ownership) {
......
......@@ -188,6 +188,7 @@ public class Vala.SymbolResolver : CodeVisitor {
type.is_ref = unresolved_type.is_ref;
type.is_out = unresolved_type.is_out;
type.nullable = unresolved_type.nullable;
type.requires_null_check = unresolved_type.requires_null_check;
foreach (DataType type_arg in unresolved_type.get_type_arguments ()) {
type.add_type_argument (type_arg);
}
......@@ -295,6 +296,7 @@ public class Vala.SymbolResolver : CodeVisitor {
type.is_ref = unresolved_type.is_ref;
type.is_out = unresolved_type.is_out;
type.nullable = unresolved_type.nullable;
type.requires_null_check = unresolved_type.nullable;
}
if (type.data_type != null && !type.data_type.is_reference_type ()) {
......@@ -304,6 +306,11 @@ public class Vala.SymbolResolver : CodeVisitor {
*/
type.takes_ownership = false;
type.transfers_ownership = false;
/* reset nullable of value-types for local variables */
if (type.nullable && !type.requires_null_check) {
type.nullable = false;
}
}
return type;
......
......@@ -49,38 +49,12 @@ public class Vala.UnresolvedType : DataType {
* indicates no pointer-type.
*/
public int pointer_level { get; set; }
/**
* Specifies that the expression transfers ownership of its value.
*/
public bool transfers_ownership { get; set; }
/**
* Specifies that the expression assumes ownership if used as an lvalue
* in an assignment.
*/
public bool takes_ownership { get; set; }
/**
* The weak modifier has been specified.
*/
public bool is_weak { get; set; }
/**
* Specifies that the expression is a reference used in ref parameters.
*/
public bool is_ref { get; set; }
/**
* Specifies that the expression is a reference used in out parameters.
*/
public bool is_out { get; set; }
/**
* Specifies that the expression may be null.
*/
public bool nullable { get; set; }
public UnresolvedType () {
}
......@@ -142,6 +116,7 @@ public class Vala.UnresolvedType : DataType {
result.takes_ownership = takes_ownership;
result.is_out = is_out;
result.nullable = nullable;
result.requires_null_check = requires_null_check;
result.namespace_name = namespace_name;
result.type_name = type_name;
result.array_rank = array_rank;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment