From: Juerg Billeter Date: Mon, 14 Apr 2008 15:54:19 +0000 (+0000) Subject: move experimental null reference checking to separate visitor X-Git-Tag: VALA_0_3_1~81 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6bab2a017d8946b707c30f3be8d4255a8b3544ad;p=platform%2Fupstream%2Fvala.git move experimental null reference checking to separate visitor 2008-04-14 Juerg Billeter * vala/Makefile.am, vala/valaarraytype.vala, vala/valaclasstype.vala, vala/valacodenode.vala, vala/valadatatype.vala, vala/valaerrortype.vala, vala/valaintegertype.vala, vala/valainterfacetype.vala, vala/valamethodtype.vala, vala/valanullchecker.vala, vala/valanulltype.vala, vala/valaparser.vala, vala/valapointertype.vala, vala/valasemanticanalyzer.vala, vala/valasymbolresolver.vala, vala/valatypeparametertype.vala, vala/valaunresolvedtype.vala, vala/valavaluetype.vala, gobject/valaccodegenerator.vala, compiler/valacompiler.vala, vapigen/valagidlparser.vala: move experimental null reference checking to separate visitor svn path=/trunk/; revision=1221 --- diff --git a/ChangeLog b/ChangeLog index 6a77175..7b6a8a4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2008-04-14 Jürg Billeter + + * vala/Makefile.am, vala/valaarraytype.vala, + vala/valaclasstype.vala, vala/valacodenode.vala, + vala/valadatatype.vala, vala/valaerrortype.vala, + vala/valaintegertype.vala, vala/valainterfacetype.vala, + vala/valamethodtype.vala, vala/valanullchecker.vala, + vala/valanulltype.vala, vala/valaparser.vala, + vala/valapointertype.vala, vala/valasemanticanalyzer.vala, + vala/valasymbolresolver.vala, vala/valatypeparametertype.vala, + vala/valaunresolvedtype.vala, vala/valavaluetype.vala, + gobject/valaccodegenerator.vala, compiler/valacompiler.vala, + vapigen/valagidlparser.vala: move experimental null reference + checking to separate visitor + 2008-04-14 Marc-Andre Lureau * vapi/glib-2.0.vapi (Value): renamed register_transform to diff --git a/compiler/valacompiler.vala b/compiler/valacompiler.vala index 48a7f7e..4f79567 100644 --- a/compiler/valacompiler.vala +++ b/compiler/valacompiler.vala @@ -252,6 +252,15 @@ class Vala.Compiler : Object { return quit (); } + if (context.non_null_experimental) { + var null_checker = new NullChecker (); + null_checker.check (context); + + if (Report.get_errors () > 0) { + return quit (); + } + } + var memory_manager = new MemoryManager (); memory_manager.analyze (context); diff --git a/gobject/valaccodegenerator.vala b/gobject/valaccodegenerator.vala index 081eafe..84c2227 100644 --- a/gobject/valaccodegenerator.vala +++ b/gobject/valaccodegenerator.vala @@ -1331,7 +1331,7 @@ public class Vala.CCodeGenerator : CodeGenerator { // g_free (NULL) is allowed bool uses_gfree = (type.data_type != null && !type.data_type.is_reference_counting () && type.data_type.get_free_function () == "g_free"); uses_gfree = uses_gfree || type is ArrayType; - if ((context.non_null_experimental && !type.requires_null_check) || uses_gfree) { + if (uses_gfree) { return new CCodeParenthesizedExpression (cassign); } @@ -2700,7 +2700,7 @@ public class Vala.CCodeGenerator : CodeGenerator { var ccall = new CCodeFunctionCall (dupexpr); - if (((context.non_null_experimental && !expr.static_type.requires_null_check) && expr.static_type.type_parameter == null) || expr is StringLiteral) { + if (expr is StringLiteral) { // expression is non-null ccall.add_argument ((CCodeExpression) expr.ccodenode); diff --git a/vala/Makefile.am b/vala/Makefile.am index 7b6f0ef..e4c23de 100644 --- a/vala/Makefile.am +++ b/vala/Makefile.am @@ -90,6 +90,7 @@ libvalacore_la_VALASOURCES = \ valanamedargument.vala \ valanamespace.vala \ valanamespacereference.vala \ + valanullchecker.vala \ valanullliteral.vala \ valanulltype.vala \ valaobjectcreationexpression.vala \ diff --git a/vala/valaarraytype.vala b/vala/valaarraytype.vala index b8e745f..12ba61b 100644 --- a/vala/valaarraytype.vala +++ b/vala/valaarraytype.vala @@ -121,7 +121,6 @@ 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; @@ -144,7 +143,7 @@ public class Vala.ArrayType : ReferenceType { return element_type.to_string () + "[]"; } - public override bool compatible (DataType target_type, bool enable_non_null) { + public override bool compatible (DataType target_type) { if (target_type is PointerType || (target_type.data_type != null && target_type.data_type.get_attribute ("PointerType") != null)) { /* any array type can be cast to a generic pointer */ return true; @@ -162,10 +161,6 @@ public class Vala.ArrayType : ReferenceType { if (element_type.compatible (target_array_type.element_type) && target_array_type.element_type.compatible (element_type)) { - if (requires_null_check && !target_type.nullable) { - // incompatibility between null and non-null types - return !enable_non_null; - } return true; } diff --git a/vala/valaclasstype.vala b/vala/valaclasstype.vala index 94ef2f9..c20ee70 100644 --- a/vala/valaclasstype.vala +++ b/vala/valaclasstype.vala @@ -43,7 +43,6 @@ public class Vala.ClassType : 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; diff --git a/vala/valacodenode.vala b/vala/valacodenode.vala index 4d65e1f..05ffa70 100644 --- a/vala/valacodenode.vala +++ b/vala/valacodenode.vala @@ -32,13 +32,13 @@ public abstract class Vala.CodeNode : Object { /** * Parent of this code node. */ - public weak CodeNode parent_node { get; set; } + public weak CodeNode? parent_node { get; set; } /** * References the location in the source file where this code node has * been written. */ - public SourceReference source_reference { get; set; } + public SourceReference? source_reference { get; set; } /** * Contains all attributes that have been specified for this code node. @@ -48,7 +48,7 @@ public abstract class Vala.CodeNode : Object { /** * Generated CCodeNode that corresponds to this code node. */ - public CCodeNode ccodenode { + public CCodeNode? ccodenode { get { return _ccodenode; } @@ -66,7 +66,7 @@ public abstract class Vala.CodeNode : Object { /** * Binding to the generated code. */ - public CodeBinding code_binding { get; set; } + public CodeBinding? code_binding { get; set; } /** * Specifies whether a fatal error has been detected in this code node. @@ -117,7 +117,7 @@ public abstract class Vala.CodeNode : Object { return null; } - private CCodeNode _ccodenode; + private CCodeNode? _ccodenode; /** * Returns a string that represents this code node. diff --git a/vala/valadatatype.vala b/vala/valadatatype.vala index 4b4ddec..f760adf 100644 --- a/vala/valadatatype.vala +++ b/vala/valadatatype.vala @@ -51,12 +51,6 @@ public abstract class Vala.DataType : CodeNode { public bool nullable { get; set; } /** - * Specifies that the expression may not be dereferenced without - * prior null check. - */ - public bool requires_null_check { get; set; } - - /** * The referred data type. */ public weak Typesymbol data_type { get; set; } @@ -324,7 +318,7 @@ public abstract class Vala.DataType : CodeNode { } } - public virtual bool compatible (DataType target_type, bool enable_non_null = true) { + public virtual bool compatible (DataType target_type) { if (target_type is DelegateType && this is DelegateType) { return ((DelegateType) target_type).delegate_symbol == ((DelegateType) this).delegate_symbol; } @@ -361,10 +355,6 @@ public abstract 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; } @@ -386,10 +376,6 @@ public abstract class Vala.DataType : CodeNode { } 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; } diff --git a/vala/valaerrortype.vala b/vala/valaerrortype.vala index 29651d7..1414152 100644 --- a/vala/valaerrortype.vala +++ b/vala/valaerrortype.vala @@ -38,7 +38,7 @@ public class Vala.ErrorType : ReferenceType { this.source_reference = source_reference; } - public override bool compatible (DataType target_type, bool enable_non_null = true) { + public override bool compatible (DataType target_type) { /* temporarily ignore type parameters */ if (target_type.type_parameter != null) { return true; diff --git a/vala/valaintegertype.vala b/vala/valaintegertype.vala index 04d51ac..b2bee55 100644 --- a/vala/valaintegertype.vala +++ b/vala/valaintegertype.vala @@ -39,7 +39,7 @@ public class Vala.IntegerType : ValueType { return type; } - public override bool compatible (DataType target_type, bool enable_non_null = true) { + public override bool compatible (DataType target_type) { 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 @@ -59,6 +59,6 @@ public class Vala.IntegerType : ValueType { } } - return base.compatible (target_type, enable_non_null); + return base.compatible (target_type); } } diff --git a/vala/valainterfacetype.vala b/vala/valainterfacetype.vala index d728872..c154c57 100644 --- a/vala/valainterfacetype.vala +++ b/vala/valainterfacetype.vala @@ -43,7 +43,6 @@ public class Vala.InterfaceType : 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; diff --git a/vala/valamethodtype.vala b/vala/valamethodtype.vala index 95c39c2..62fedf9 100644 --- a/vala/valamethodtype.vala +++ b/vala/valamethodtype.vala @@ -49,7 +49,7 @@ public class Vala.MethodType : DataType { return new MethodType (method_symbol); } - public override bool compatible (DataType target_type, bool enable_non_null = true) { + public override bool compatible (DataType target_type) { var dt = target_type as DelegateType; if (dt == null) { // method types incompatible to anything but delegates diff --git a/vala/valanullchecker.vala b/vala/valanullchecker.vala new file mode 100644 index 0000000..e38a324 --- /dev/null +++ b/vala/valanullchecker.vala @@ -0,0 +1,241 @@ +/* valanullchecker.vala + * + * Copyright (C) 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 + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Jürg Billeter + */ + +using GLib; + +/** + * Code visitor checking null references. + */ +public class Vala.NullChecker : CodeVisitor { + private CodeContext context; + + DataType current_return_type; + + public NullChecker () { + } + + public void check (CodeContext context) { + this.context = context; + + context.accept (this); + } + + void check_compatible (Expression expr, DataType target_type) { + if (!target_type.nullable) { + if (expr.static_type is NullType) { + Report.error (expr.source_reference, "`null' incompatible with `%s'".printf (target_type.to_string ())); + } else if (expr.static_type.nullable) { + Report.warning (expr.source_reference, "`%s' incompatible with `%s'".printf (expr.static_type.to_string (), target_type.to_string ())); + } + } + } + + void check_non_null (Expression expr) { + if (expr.static_type is NullType) { + Report.error (expr.source_reference, "null dereference"); + } else if (expr.static_type.nullable) { + Report.warning (expr.source_reference, "possible null dereference"); + } + } + + public override void visit_source_file (SourceFile file) { + file.accept_children (this); + } + + public override void visit_class (Class cl) { + cl.accept_children (this); + } + + public override void visit_struct (Struct st) { + st.accept_children (this); + } + + public override void visit_interface (Interface iface) { + iface.accept_children (this); + } + + public override void visit_enum (Enum en) { + en.accept_children (this); + } + + public override void visit_field (Field f) { + f.accept_children (this); + } + + public override void visit_method (Method m) { + var old_return_type = current_return_type; + current_return_type = m.return_type; + + m.accept_children (this); + + current_return_type = old_return_type; + } + + public override void visit_creation_method (CreationMethod m) { + m.accept_children (this); + } + + public override void visit_formal_parameter (FormalParameter p) { + p.accept_children (this); + + if (p.default_expression != null) { + check_compatible (p.default_expression, p.type_reference); + } + } + + public override void visit_property (Property prop) { + prop.accept_children (this); + } + + public override void visit_property_accessor (PropertyAccessor acc) { + acc.accept_children (this); + } + + public override void visit_constructor (Constructor c) { + c.accept_children (this); + } + + public override void visit_destructor (Destructor d) { + d.accept_children (this); + } + + public override void visit_block (Block b) { + b.accept_children (this); + } + + public override void visit_variable_declarator (VariableDeclarator decl) { + decl.accept_children (this); + + if (decl.initializer != null) { + check_compatible (decl.initializer, decl.type_reference); + } + } + + public override void visit_if_statement (IfStatement stmt) { + stmt.accept_children (this); + + check_non_null (stmt.condition); + } + + public override void visit_switch_section (SwitchSection section) { + section.accept_children (this); + } + + public override void visit_while_statement (WhileStatement stmt) { + stmt.accept_children (this); + + check_non_null (stmt.condition); + } + + public override void visit_do_statement (DoStatement stmt) { + stmt.accept_children (this); + + check_non_null (stmt.condition); + } + + public override void visit_for_statement (ForStatement stmt) { + stmt.accept_children (this); + + check_non_null (stmt.condition); + } + + public override void visit_foreach_statement (ForeachStatement stmt) { + stmt.accept_children (this); + + check_non_null (stmt.collection); + } + + public override void visit_return_statement (ReturnStatement stmt) { + stmt.accept_children (this); + + if (stmt.return_expression != null) { + check_compatible (stmt.return_expression, current_return_type); + } + } + + public override void visit_throw_statement (ThrowStatement stmt) { + stmt.accept_children (this); + + check_non_null (stmt.error_expression); + } + + public override void visit_try_statement (TryStatement stmt) { + stmt.accept_children (this); + } + + public override void visit_catch_clause (CatchClause clause) { + clause.accept_children (this); + } + + public override void visit_delete_statement (DeleteStatement stmt) { + stmt.accept_children (this); + } + + public override void visit_invocation_expression (InvocationExpression expr) { + expr.accept_children (this); + + var mtype = expr.call.static_type as MethodType; + var ma = expr.call as MemberAccess; + if (mtype != null && mtype.method_symbol.instance && ma != null) { + if (ma.inner == null) { + // implicit this call, always non-null + } else { + check_non_null (ma.inner); + } + } + } + + public override void visit_element_access (ElementAccess expr) { + check_non_null (expr.container); + } + + public override void visit_postfix_expression (PostfixExpression expr) { + check_non_null (expr.inner); + } + + public override void visit_unary_expression (UnaryExpression expr) { + switch (expr.operator) { + case UnaryOperator.PLUS: + case UnaryOperator.MINUS: + case UnaryOperator.LOGICAL_NEGATION: + case UnaryOperator.BITWISE_COMPLEMENT: + case UnaryOperator.INCREMENT: + case UnaryOperator.DECREMENT: + check_non_null (expr.inner); + break; + } + } + + public override void visit_conditional_expression (ConditionalExpression expr) { + check_non_null (expr.condition); + } + + public override void visit_lambda_expression (LambdaExpression l) { + l.accept_children (this); + } + + public override void visit_assignment (Assignment a) { + a.accept_children (this); + + check_compatible (a.right, a.left.static_type); + } +} diff --git a/vala/valanulltype.vala b/vala/valanulltype.vala index 47655aa..8c7a157 100644 --- a/vala/valanulltype.vala +++ b/vala/valanulltype.vala @@ -30,7 +30,7 @@ public class Vala.NullType : ReferenceType { this.source_reference = source_reference; } - public override bool compatible (DataType target_type, bool enable_non_null = true) { + public override bool compatible (DataType target_type) { if (!(target_type is PointerType) && (target_type is NullType || (target_type.data_type == null && target_type.type_parameter == null))) { return true; } @@ -47,8 +47,7 @@ public class Vala.NullType : ReferenceType { if (target_type.data_type.is_reference_type () || target_type is ArrayType || target_type is DelegateType) { - // incompatibility between null and non-null types - return !enable_non_null; + return true; } /* null is not compatible with any other type (i.e. value types) */ diff --git a/vala/valaparser.vala b/vala/valaparser.vala index 503d61e..42880a8 100644 --- a/vala/valaparser.vala +++ b/vala/valaparser.vala @@ -390,7 +390,6 @@ public class Vala.Parser : CodeVisitor { type.pointer_level = stars; type.array_rank = array_rank; type.nullable = nullable; - type.requires_null_check = nullable; type.transfers_ownership = transfers_ownership; return type; } @@ -1263,8 +1262,6 @@ public class Vala.Parser : CodeVisitor { if (!((UnresolvedType) type).is_weak) { type.takes_ownership = true; } - type.requires_null_check = false; - type.nullable = true; decl = context.create_local_variable_declaration (type, get_src (begin)); foreach (VariableDeclarator var_decl in declarators) { var_decl.type_reference = type.copy (); diff --git a/vala/valapointertype.vala b/vala/valapointertype.vala index 6571142..1c35c7e 100644 --- a/vala/valapointertype.vala +++ b/vala/valapointertype.vala @@ -52,7 +52,7 @@ public class Vala.PointerType : DataType { return new PointerType (base_type); } - public override bool compatible (DataType target_type, bool enable_non_null = true) { + public override bool compatible (DataType target_type) { if (target_type is PointerType || (target_type.data_type != null && target_type.data_type.get_attribute ("PointerType") != null)) { return true; } @@ -64,7 +64,7 @@ public class Vala.PointerType : DataType { if (base_type.is_reference_type_or_type_parameter ()) { // Object* is compatible with Object if Object is a reference type - return base_type.compatible (target_type, enable_non_null); + return base_type.compatible (target_type); } return false; diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala index 3172ff0..b48a827 100644 --- a/vala/valasemanticanalyzer.vala +++ b/vala/valasemanticanalyzer.vala @@ -904,13 +904,9 @@ public class Vala.SemanticAnalyzer : CodeVisitor { if (unary != null && (unary.operator == UnaryOperator.REF || unary.operator == UnaryOperator.OUT)) { // TODO check type for ref and out expressions } else if (!e.static_type.compatible (e.expected_type)) { - if (!e.static_type.compatible (e.expected_type, false)) { - error = true; - e.error = true; - Report.error (e.source_reference, "Expected initializer of type `%s' but got `%s'".printf (e.expected_type.to_string (), e.static_type.to_string ())); - } else if (context.non_null_experimental) { - Report.warning (e.source_reference, "Expected initializer of type `%s' but got `%s'".printf (e.expected_type.to_string (), e.static_type.to_string ())); - } + error = true; + e.error = true; + Report.error (e.source_reference, "Expected initializer of type `%s' but got `%s'".printf (e.expected_type.to_string (), e.static_type.to_string ())); } } @@ -1061,12 +1057,12 @@ public class Vala.SemanticAnalyzer : CodeVisitor { var array_type = (ArrayType) collection_type; element_data_type = array_type.element_type; need_type_check = true; - } else if (collection_type.compatible (glist_type, false) || collection_type.compatible (gslist_type, false)) { + } else if (collection_type.compatible (glist_type) || collection_type.compatible (gslist_type)) { if (collection_type.get_type_arguments ().size > 0) { element_data_type = (DataType) collection_type.get_type_arguments ().get (0); need_type_check = true; } - } else if (iterable_type != null && collection_type.compatible (iterable_type, false)) { + } else if (iterable_type != null && collection_type.compatible (iterable_type)) { stmt.iterator_variable_declarator = new VariableDeclarator ("%s_it".printf (stmt.variable_name)); stmt.iterator_variable_declarator.type_reference = new InterfaceType (iterator_type); stmt.iterator_variable_declarator.type_reference.takes_ownership = true; @@ -1131,12 +1127,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor { if (stmt.return_expression != null && !stmt.return_expression.static_type.compatible (current_return_type)) { - 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.non_null_experimental) { - Report.warning (stmt.source_reference, "Return value may not be null"); - } + 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 != null && @@ -1815,13 +1807,9 @@ public class Vala.SemanticAnalyzer : CodeVisitor { return false; } } else if (!arg.static_type.compatible (param.type_reference)) { - 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.non_null_experimental) { - Report.warning (expr.source_reference, "Argument %d: Argument may not be null".printf (i + 1)); - } + 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 { // 0 => null, 1 => in, 2 => ref, 3 => out int arg_type = 1; @@ -2681,15 +2669,9 @@ public class Vala.SemanticAnalyzer : CodeVisitor { if (!expr.right.static_type.compatible (expr.left.static_type) && !expr.left.static_type.compatible (expr.right.static_type)) { - 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.non_null_experimental) { - // 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 ())); - } + 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; } if (expr.left.static_type.compatible (string_type) @@ -3010,14 +2992,9 @@ public class Vala.SemanticAnalyzer : CodeVisitor { * i.e. a.{left|right}.static_type == null, skip type check */ if (!a.right.static_type.compatible (a.left.static_type)) { - 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.non_null_experimental) { - // 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 ())); - } + 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.transfers_ownership) { @@ -3038,14 +3015,9 @@ public class Vala.SemanticAnalyzer : CodeVisitor { var ea = (ElementAccess) a.left; if (!a.right.static_type.compatible (a.left.static_type)) { - 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.non_null_experimental) { - // 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 ())); - } + 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.transfers_ownership) { diff --git a/vala/valasymbolresolver.vala b/vala/valasymbolresolver.vala index b71afd9..082d89d 100644 --- a/vala/valasymbolresolver.vala +++ b/vala/valasymbolresolver.vala @@ -270,7 +270,6 @@ 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); } @@ -292,11 +291,6 @@ 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; - } } /* check for array */ @@ -306,7 +300,6 @@ public class Vala.SymbolResolver : CodeVisitor { element_type.is_ref = false; element_type.is_out = false; element_type.nullable = false; - element_type.requires_null_check = false; type = new ArrayType (element_type, unresolved_type.array_rank, unresolved_type.source_reference); type.add_type_argument (element_type); @@ -316,7 +309,6 @@ 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; } return type; @@ -334,6 +326,9 @@ public class Vala.SymbolResolver : CodeVisitor { public override void visit_variable_declarator (VariableDeclarator decl) { decl.accept_children (this); + if (decl.type_reference is ReferenceType) { + decl.type_reference.nullable = true; + } } public override void visit_initializer_list (InitializerList list) { diff --git a/vala/valatypeparametertype.vala b/vala/valatypeparametertype.vala index eee2b73..0cb12aa 100644 --- a/vala/valatypeparametertype.vala +++ b/vala/valatypeparametertype.vala @@ -37,7 +37,6 @@ public class Vala.TypeParameterType : DataType { 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; diff --git a/vala/valaunresolvedtype.vala b/vala/valaunresolvedtype.vala index 97de2ea..10f06b3 100644 --- a/vala/valaunresolvedtype.vala +++ b/vala/valaunresolvedtype.vala @@ -109,7 +109,6 @@ 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.unresolved_symbol = unresolved_symbol.copy (); result.array_rank = array_rank; result.pointer_level = pointer_level; diff --git a/vala/valavaluetype.vala b/vala/valavaluetype.vala index 43b07c9..29f582f 100644 --- a/vala/valavaluetype.vala +++ b/vala/valavaluetype.vala @@ -43,7 +43,6 @@ public class Vala.ValueType : DataType { 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; diff --git a/vapigen/valagidlparser.vala b/vapigen/valagidlparser.vala index 8d2c565..e21f6bd 100644 --- a/vapigen/valagidlparser.vala +++ b/vapigen/valagidlparser.vala @@ -1336,7 +1336,6 @@ public class Vala.GIdlParser : CodeVisitor { } else if (nv[0] == "nullable") { if (eval (nv[1]) == "1") { param_type.nullable = true; - param_type.requires_null_check = true; } } else if (nv[0] == "transfer_ownership") { if (eval (nv[1]) == "1") { @@ -1683,7 +1682,6 @@ public class Vala.GIdlParser : CodeVisitor { } else if (nv[0] == "nullable") { if (eval (nv[1]) == "1") { param_type.nullable = true; - param_type.requires_null_check = true; } } else if (nv[0] == "type_name") { param_type.unresolved_symbol = new UnresolvedSymbol (null, eval (nv[1]));