]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
vala: Handle non-null in coalescing expression
authorMarvin W <git@larma.de>
Tue, 11 Apr 2017 15:19:58 +0000 (17:19 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Mon, 17 Apr 2017 08:58:45 +0000 (10:58 +0200)
https://bugzilla.gnome.org/show_bug.cgi?id=611223

tests/Makefile.am
tests/nullability/bug611223.vala [new file with mode: 0644]
vala/valabinaryexpression.vala

index e368b6b950d550cd4b028a3909ca2a4f0a7909f4..2a2f4d43c5d9f91b0cf123136c01b39b04eaea08 100644 (file)
@@ -286,11 +286,17 @@ TESTS = \
        annotations/description.vala \
        $(NULL)
 
-check-TESTS: $(TESTS)
+NON_NULL_TESTS = \
+       nullability/bug611223.vala \
+       $(NULL)
+
+check-TESTS: $(TESTS) $(NON_NULL_TESTS)
        @EXEEXT=$(EXEEXT) EXEEXT=$(EXEEXT) CFLAGS='$(CFLAGS)' CPPFLAGS='$(CPPFLAGS)' LDFLAGS='$(LDFLAGS)' $(srcdir)/testrunner.sh $(TESTS)
+       @EXEEXT=$(EXEEXT) EXEEXT=$(EXEEXT) CFLAGS='$(CFLAGS)' CPPFLAGS='$(CPPFLAGS)' LDFLAGS='$(LDFLAGS)' VALAFLAGS="--enable-experimental-non-null" $(srcdir)/testrunner.sh $(NON_NULL_TESTS)
 
 EXTRA_DIST = \
        testrunner.sh \
        $(TESTS) \
+       $(NON_NULL_TESTS) \
        $(NULL)
 
diff --git a/tests/nullability/bug611223.vala b/tests/nullability/bug611223.vala
new file mode 100644 (file)
index 0000000..9fbf30c
--- /dev/null
@@ -0,0 +1,7 @@
+void main() {
+       string? nullable = null;
+       string non_null = nullable ?? "";
+       string? some_null = nullable ?? null;
+       string also_non_null = null ?? non_null;
+       string really_non_null = non_null ?? nullable;
+}
index 82e605398d8fd6333f6dbaf205dd72afdc015a67..19287da85cfdebe8878cb69a7ca14b465be715f8 100644 (file)
@@ -210,12 +210,31 @@ public class Vala.BinaryExpression : Expression {
                        }
 
                        DataType local_type = null;
-                       if (left.value_type != null) {
+                       bool cast_non_null = false;
+                       if (left.value_type is NullType && right.value_type != null) {
+                               Report.warning (left.source_reference, "left operand is always null");
+                               local_type = right.value_type.copy ();
+                               local_type.nullable = true;
+                               if (!right.value_type.nullable) {
+                                       cast_non_null = true;
+                               }
+                       } else if (left.value_type != null) {
                                local_type = left.value_type.copy ();
                                if (right.value_type != null && right.value_type.value_owned) {
                                        // value owned if either left or right is owned
                                        local_type.value_owned = true;
                                }
+                               if (context.experimental_non_null) {
+                                       if (!local_type.nullable) {
+                                               Report.warning (left.source_reference, "left operand is never null");
+                                               if (right.value_type != null && right.value_type.nullable) {
+                                                       local_type.nullable = true;
+                                                       cast_non_null = true;
+                                               }
+                                       } else if (right.value_type != null && !right.value_type.nullable) {
+                                               cast_non_null = true;
+                                       }
+                               }
                        } else if (right.value_type != null) {
                                local_type = right.value_type.copy ();
                        }
@@ -246,10 +265,16 @@ public class Vala.BinaryExpression : Expression {
                                return false;
                        }
 
-                       var temp_access = SemanticAnalyzer.create_temp_access (local, target_type);
-                       temp_access.check (context);
+                       var replace_expr = SemanticAnalyzer.create_temp_access (local, target_type);
+                       if (cast_non_null && replace_expr.target_type != null) {
+                               var cast = new CastExpression.non_null (replace_expr, source_reference);
+                               cast.target_type = replace_expr.target_type.copy ();
+                               cast.target_type.nullable = false;
+                               replace_expr = cast;
+                       }
+                       replace_expr.check (context);
 
-                       parent_node.replace_expression (this, temp_access);
+                       parent_node.replace_expression (this, replace_expr);
 
                        return true;
                }