]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Support explicit nullable var-type declarations
authorRico Tzschichholz <ricotz@ubuntu.com>
Thu, 15 Apr 2021 14:49:14 +0000 (16:49 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Thu, 15 Apr 2021 14:49:14 +0000 (16:49 +0200)
    var? foo = "foo";
    unowned var? bar = "bar";

Fixes https://gitlab.gnome.org/GNOME/vala/issues/1146

tests/Makefile.am
tests/nullability/var-type.vala [new file with mode: 0644]
tests/parser/var-type-nullable.vala [new file with mode: 0644]
vala/valaforeachstatement.vala
vala/valalocalvariable.vala
vala/valaparser.vala
vala/valavartype.vala

index 1b3d4783139e605cf6608f8b3f7c7ddc6d3ef159..5b2610dd6c1ff4ab9ca13bde158717936dab8c92 100644 (file)
@@ -879,6 +879,7 @@ TESTS = \
        parser/using-ambiguous-reference.test \
        parser/using-directive.vala \
        parser/using-invalid-namespace.test \
+       parser/var-type-nullable.vala \
        parser/with-embedded.vala \
        parser/with-empty.vala \
        parser/with-invalid-declaration.test \
@@ -1151,6 +1152,7 @@ TESTS = \
        nullability/method-return-invalid-convert.test \
        nullability/string-concat.test \
        nullability/with-non-null.test \
+       nullability/var-type.vala \
        version/since-constant.test \
        version/since-field.test \
        version/since-local-variable.test \
diff --git a/tests/nullability/var-type.vala b/tests/nullability/var-type.vala
new file mode 100644 (file)
index 0000000..3497d86
--- /dev/null
@@ -0,0 +1,11 @@
+void main () {
+       {
+               unowned var? foo = "foo";
+               assert (foo != null);
+       }
+       {
+               foreach (unowned var? foo in new string[] { "foo", "bar" }) {
+                       assert (foo != null);
+               }
+       }
+}
diff --git a/tests/parser/var-type-nullable.vala b/tests/parser/var-type-nullable.vala
new file mode 100644 (file)
index 0000000..fb32569
--- /dev/null
@@ -0,0 +1,16 @@
+void main () {
+       {
+               var? foo = "foo";
+       }
+       {
+               unowned var? foo = "foo";
+       }
+       {
+               foreach (var? foo in new string[] { "foo", "bar" }) {
+               }
+       }
+       {
+               foreach (unowned var? foo in new string[] { "foo", "bar" }) {
+               }
+       }
+}
index bea6c4e9360cd67167bbaeb927cb60eb2c123c03..0af0b52bad90c5dbe2af1d626da376f81b47a156 100644 (file)
@@ -336,12 +336,16 @@ public class Vala.ForeachStatement : Block {
                // analyze element type
                if (type_reference is VarType) {
                        // var type
+                       bool nullable = type_reference.nullable;
                        bool value_owned = type_reference.value_owned;
                        type_reference = element_type.copy ();
                        // FIXME Only follows "unowned var" otherwise inherit ownership of element-type
                        if (!value_owned) {
                                type_reference.value_owned = false;
                        }
+                       if (nullable) {
+                               type_reference.nullable = true;
+                       }
                } else if (!element_type.compatible (type_reference)) {
                        error = true;
                        Report.error (source_reference, "Foreach: Cannot convert from `%s' to `%s'", element_type.to_string (), type_reference.to_string ());
@@ -359,12 +363,16 @@ public class Vala.ForeachStatement : Block {
                // analyze element type
                if (type_reference is VarType) {
                        // var type
+                       bool nullable = type_reference.nullable;
                        bool value_owned = type_reference.value_owned;
                        type_reference = element_type.copy ();
                        // FIXME Only follows "unowned var" otherwise inherit ownership of element-type
                        if (!value_owned) {
                                type_reference.value_owned = false;
                        }
+                       if (nullable) {
+                               type_reference.nullable = true;
+                       }
                } else if (!element_type.compatible (type_reference)) {
                        error = true;
                        Report.error (source_reference, "Foreach: Cannot convert from `%s' to `%s'", element_type.to_string (), type_reference.to_string ());
index eeb8e912b43a733bf1b951fd6e5126240b12bbc6..e6d15cf19811b94dc368d0278d9a3c2d84fe5c68 100644 (file)
@@ -154,10 +154,14 @@ public class Vala.LocalVariable : Variable {
                                return false;
                        }
 
+                       bool nullable = variable_type.nullable;
                        bool value_owned = variable_type.value_owned;
                        variable_type = initializer.value_type.copy ();
                        variable_type.value_owned = value_owned;
                        variable_type.floating_reference = false;
+                       if (nullable) {
+                               variable_type.nullable = true;
+                       }
 
                        initializer.target_type = variable_type;
                        variable_type.check (context);
index 49336c94ced05520f47361ff95da055cf9e7635d..9ecc96e9b123b218c74220828f2747915dd9a76e 100644 (file)
@@ -1944,10 +1944,12 @@ public class Vala.Parser : CodeVisitor {
                DataType variable_type;
                if (accept (TokenType.UNOWNED) && accept (TokenType.VAR)) {
                        variable_type = new VarType (false);
+                       variable_type.nullable = accept (TokenType.INTERR);
                } else {
                        rollback (begin);
                        if (accept (TokenType.VAR)) {
                                variable_type = new VarType ();
+                               variable_type.nullable = accept (TokenType.INTERR);
                        } else {
                                variable_type = parse_type (true, true);
                        }
@@ -2211,10 +2213,12 @@ public class Vala.Parser : CodeVisitor {
                DataType type;
                if (accept (TokenType.UNOWNED) && accept (TokenType.VAR)) {
                        type = new VarType (false);
+                       type.nullable = accept (TokenType.INTERR);
                } else {
                        rollback (var_or_type);
                        if (accept (TokenType.VAR)) {
                                type = new VarType ();
+                               type.nullable = accept (TokenType.INTERR);
                        } else {
                                type = parse_type (true, true);
                                if (accept (TokenType.IN)) {
@@ -2380,10 +2384,12 @@ public class Vala.Parser : CodeVisitor {
                        DataType variable_type;
                        if (accept (TokenType.UNOWNED) && accept (TokenType.VAR)) {
                                variable_type = new VarType (false);
+                               variable_type.nullable = accept (TokenType.INTERR);
                        } else {
                                rollback (expr_or_decl);
                                if (accept (TokenType.VAR)) {
                                        variable_type = new VarType ();
+                                       variable_type.nullable = accept (TokenType.INTERR);
                                } else {
                                        variable_type = parse_type (true, true);
                                }
index dada3ca327b41028163e4372841691de26a6f027..be97e175230bacafed230945fa6eda77715f0ca2 100644 (file)
@@ -33,6 +33,8 @@ public class Vala.VarType : DataType {
        }
 
        public override DataType copy () {
-               return new VarType (value_owned);
+               var result = new VarType (value_owned);
+               result.nullable = nullable;
+               return result;
        }
 }