summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRico Tzschichholz <ricotz@ubuntu.com>2023-04-13 20:36:08 +0200
committerRico Tzschichholz <ricotz@ubuntu.com>2023-04-14 09:14:11 +0200
commitb42c4b54a3589cffcab9dcce603c82728bcd82d0 (patch)
treedbd833d214300b7306a57340a180b8c6e2b7d94e
parentcff2e6e470efae1f4e178ab13cb2b3d5dde502c3 (diff)
downloadvala-b42c4b54a3589cffcab9dcce603c82728bcd82d0.tar.gz
vala: Don't make GenericType nullable by default
Allow equality between nullable and non-nullable generic-types for now Fixes https://gitlab.gnome.org/GNOME/vala/issues/1191
-rw-r--r--tests/Makefile.am3
-rw-r--r--tests/generics/foreach-iterator-nullable.c-expected98
-rw-r--r--tests/generics/foreach-iterator-nullable.vala7
-rw-r--r--tests/girwriter/GirTest-1.0.gir-expected2
-rw-r--r--tests/girwriter/girtest.vala4
-rw-r--r--tests/girwriter/girtest.vapi-expected4
-rw-r--r--tests/nullability/generics-invalid.test16
-rw-r--r--tests/nullability/generics.c-expected58
-rw-r--r--tests/nullability/generics.vala8
-rw-r--r--vala/valadatatype.vala6
-rw-r--r--vala/valagenerictype.vala7
-rw-r--r--vala/valamemberaccess.vala1
-rw-r--r--vala/valasymbolresolver.vala9
13 files changed, 206 insertions, 17 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 99cee6206..daf2a8cf9 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -801,6 +801,7 @@ TESTS = \
generics/constructor-chain-up.vala \
generics/delegate-return-type-missing.test \
generics/floating-type-cast.vala \
+ generics/foreach-iterator-nullable.vala \
generics/gvariant-serialization.test \
generics/inference-argument-may-fail.vala \
generics/inference-static-function.vala \
@@ -1361,6 +1362,8 @@ TESTS = \
nullability/array-element-class.vala \
nullability/array-element-string.vala \
nullability/bug611223.vala \
+ nullability/generics-invalid.test \
+ nullability/generics.vala \
nullability/local-variable-invalid-convert.test \
nullability/member-access-narrowed-instance.vala \
nullability/member-access-nullable-instance.test \
diff --git a/tests/generics/foreach-iterator-nullable.c-expected b/tests/generics/foreach-iterator-nullable.c-expected
new file mode 100644
index 000000000..ba88ee255
--- /dev/null
+++ b/tests/generics/foreach-iterator-nullable.c-expected
@@ -0,0 +1,98 @@
+/* generics_foreach_iterator_nullable.c generated by valac, the Vala compiler
+ * generated from generics_foreach_iterator_nullable.vala, do not modify */
+
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define _g_hash_table_unref0(var) ((var == NULL) ? NULL : (var = (g_hash_table_unref (var), NULL)))
+#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
+#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
+#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+
+static void _vala_main (void);
+static void _g_free0_ (gpointer var);
+
+static void
+_g_free0_ (gpointer var)
+{
+ var = (g_free (var), NULL);
+}
+
+static gconstpointer
+_vala_hash_set_next_value (GHashTableIter *self)
+{
+ void* vi = NULL;
+ GHashTableIter* htp = NULL;
+ void* _tmp0_;
+ gconstpointer value = NULL;
+ gconstpointer _tmp1_ = NULL;
+ gconstpointer _tmp2_ = NULL;
+ gboolean _tmp3_;
+ gconstpointer result;
+ vi = &(*self);
+ _tmp0_ = vi;
+ htp = _tmp0_;
+ _tmp3_ = g_hash_table_iter_next (htp, (gpointer*) (&_tmp2_), (gpointer*) NULL);
+ value = _tmp2_;
+ if (_tmp3_) {
+ gconstpointer _tmp4_;
+ _tmp4_ = value;
+ _tmp1_ = _tmp4_;
+ } else {
+ _tmp1_ = NULL;
+ }
+ result = _tmp1_;
+ return result;
+}
+
+static void
+_vala_main (void)
+{
+ GHashTable* gs = NULL;
+ GHashFunc _tmp0_;
+ GEqualFunc _tmp1_;
+ GHashTable* _tmp2_;
+ GHashTable* _tmp3_;
+ gchar* _tmp4_;
+ _tmp0_ = g_str_hash;
+ _tmp1_ = g_str_equal;
+ _tmp2_ = g_hash_table_new_full (_tmp0_, _tmp1_, NULL, _g_free0_);
+ gs = _tmp2_;
+ _tmp3_ = gs;
+ _tmp4_ = g_strdup ("foo");
+ g_hash_table_add (_tmp3_, _tmp4_);
+ {
+ GHashTableIter _s_it = {0};
+ GHashTable* _tmp5_;
+ GHashTableIter _tmp6_ = {0};
+ const gchar* s = NULL;
+ _tmp5_ = gs;
+ g_hash_table_iter_init (&_tmp6_, _tmp5_);
+ _s_it = _tmp6_;
+ while (TRUE) {
+ gconstpointer _tmp7_;
+ const gchar* _tmp8_;
+ const gchar* _tmp9_;
+ _tmp7_ = _vala_hash_set_next_value (&_s_it);
+ s = (const gchar*) _tmp7_;
+ _tmp8_ = s;
+ if (!(_tmp8_ != NULL)) {
+ break;
+ }
+ _tmp9_ = s;
+ _vala_assert (g_strcmp0 (_tmp9_, "foo") == 0, "s == \"foo\"");
+ }
+ }
+ _g_hash_table_unref0 (gs);
+}
+
+int
+main (int argc,
+ char ** argv)
+{
+ _vala_main ();
+ return 0;
+}
+
diff --git a/tests/generics/foreach-iterator-nullable.vala b/tests/generics/foreach-iterator-nullable.vala
new file mode 100644
index 000000000..3c23d3df6
--- /dev/null
+++ b/tests/generics/foreach-iterator-nullable.vala
@@ -0,0 +1,7 @@
+void main () {
+ var gs = new GenericSet<string> (GLib.str_hash, GLib.str_equal);
+ gs.add ("foo");
+ foreach (var s in gs) {
+ assert (s == "foo");
+ }
+}
diff --git a/tests/girwriter/GirTest-1.0.gir-expected b/tests/girwriter/GirTest-1.0.gir-expected
index c308e62a1..5aafe5126 100644
--- a/tests/girwriter/GirTest-1.0.gir-expected
+++ b/tests/girwriter/GirTest-1.0.gir-expected
@@ -2935,7 +2935,7 @@
<parameter name="t_destroy_func" transfer-ownership="none">
<type name="GLib.DestroyNotify" c:type="GDestroyNotify"/>
</parameter>
- <parameter name="g" transfer-ownership="none" nullable="1">
+ <parameter name="g" transfer-ownership="none">
<type name="gpointer" c:type="gpointer"/>
</parameter>
<parameter name="t" transfer-ownership="none" nullable="1">
diff --git a/tests/girwriter/girtest.vala b/tests/girwriter/girtest.vala
index b2b107385..1125bfa1c 100644
--- a/tests/girwriter/girtest.vala
+++ b/tests/girwriter/girtest.vala
@@ -163,7 +163,7 @@ namespace GirTest {
public delegate bool DelegateErrorTest () throws ErrorTest;
- public delegate bool DelegateGenericsTest<G,T> (G g, T t);
+ public delegate bool DelegateGenericsTest<G,T> (G g, T? t);
[GIR (visible = false)]
public delegate void SkippedDelegate ();
@@ -436,7 +436,7 @@ namespace GirTest {
public GenericsTest.typed (owned DelegateGenericsTest<G,T> cb) {
}
- public void method (T param) {
+ public void method (T? param) {
}
}
diff --git a/tests/girwriter/girtest.vapi-expected b/tests/girwriter/girtest.vapi-expected
index 578d588dc..b63aad4aa 100644
--- a/tests/girwriter/girtest.vapi-expected
+++ b/tests/girwriter/girtest.vapi-expected
@@ -40,7 +40,7 @@ namespace GirTest {
[CCode (cheader_filename = "girtest.h")]
public class GenericsTest<G,T> {
public GenericsTest (owned GirTest.DelegateTest cb);
- public void method (T param);
+ public void method (T? param);
public GenericsTest.typed (owned GirTest.DelegateGenericsTest<G,T> cb);
}
[CCode (cheader_filename = "girtest.h")]
@@ -258,7 +258,7 @@ namespace GirTest {
[CCode (cheader_filename = "girtest.h")]
public delegate bool DelegateErrorTest () throws GirTest.ErrorTest;
[CCode (cheader_filename = "girtest.h")]
- public delegate bool DelegateGenericsTest<G,T> (G g, T t);
+ public delegate bool DelegateGenericsTest<G,T> (G g, T? t);
[CCode (cheader_filename = "girtest.h")]
public delegate bool DelegateTest (void* a, void* b);
[CCode (cheader_filename = "girtest.h")]
diff --git a/tests/nullability/generics-invalid.test b/tests/nullability/generics-invalid.test
new file mode 100644
index 000000000..e82fd74d5
--- /dev/null
+++ b/tests/nullability/generics-invalid.test
@@ -0,0 +1,16 @@
+Invalid Code
+
+G? foo<G> () {
+ return null;
+}
+
+void manam<K> (K k) {
+}
+
+void bar<T> () {
+ T t = foo<T> ();
+ manam (t);
+}
+
+void main () {
+}
diff --git a/tests/nullability/generics.c-expected b/tests/nullability/generics.c-expected
new file mode 100644
index 000000000..ca4783adb
--- /dev/null
+++ b/tests/nullability/generics.c-expected
@@ -0,0 +1,58 @@
+/* nullability_generics.c generated by valac, the Vala compiler
+ * generated from nullability_generics.vala, do not modify */
+
+#include <glib-object.h>
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if !defined(VALA_EXTERN)
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define VALA_EXTERN __declspec(dllexport) extern
+#elif __GNUC__ >= 4
+#define VALA_EXTERN __attribute__((visibility("default"))) extern
+#else
+#define VALA_EXTERN extern
+#endif
+#endif
+
+#define _g_free0(var) (var = (g_free (var), NULL))
+#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
+#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
+#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+
+VALA_EXTERN gpointer foo (GType g_type,
+ GBoxedCopyFunc g_dup_func,
+ GDestroyNotify g_destroy_func);
+static void _vala_main (void);
+
+gpointer
+foo (GType g_type,
+ GBoxedCopyFunc g_dup_func,
+ GDestroyNotify g_destroy_func)
+{
+ gpointer result;
+ result = NULL;
+ return result;
+}
+
+static void
+_vala_main (void)
+{
+ gchar* s = NULL;
+ gpointer _tmp0_;
+ _tmp0_ = foo (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, (GDestroyNotify) g_free);
+ s = (gchar*) _tmp0_;
+ _vala_assert (s == NULL, "s == null");
+ _g_free0 (s);
+}
+
+int
+main (int argc,
+ char ** argv)
+{
+ _vala_main ();
+ return 0;
+}
+
diff --git a/tests/nullability/generics.vala b/tests/nullability/generics.vala
new file mode 100644
index 000000000..8568f8baa
--- /dev/null
+++ b/tests/nullability/generics.vala
@@ -0,0 +1,8 @@
+G? foo<G> () {
+ return null;
+}
+
+void main () {
+ var s = foo<string> ();
+ assert (s == null);
+}
diff --git a/vala/valadatatype.vala b/vala/valadatatype.vala
index fec7e9010..897eaf72c 100644
--- a/vala/valadatatype.vala
+++ b/vala/valadatatype.vala
@@ -204,7 +204,11 @@ public abstract class Vala.DataType : CodeNode {
return false;
}
if (type2.nullable != nullable) {
- return false;
+ //TODO Allow equality between nullable and non-nullable generic-types
+ // This mitigation allows fixing affected source code without breaking it.
+ // It has to be removed at some point
+ var context = CodeContext.get ();
+ return !context.experimental_non_null && this is GenericType == type2 is GenericType;
}
if (type2.type_symbol != type_symbol) {
return false;
diff --git a/vala/valagenerictype.vala b/vala/valagenerictype.vala
index 32b32ba0e..50c713bce 100644
--- a/vala/valagenerictype.vala
+++ b/vala/valagenerictype.vala
@@ -40,8 +40,6 @@ public class Vala.GenericType : DataType {
public GenericType (TypeParameter type_parameter, SourceReference? source_reference = null) {
base.with_symbol (type_parameter, source_reference);
- // type parameters are always considered nullable
- this.nullable = true;
}
public override DataType copy () {
@@ -62,6 +60,9 @@ public class Vala.GenericType : DataType {
}
result = SemanticAnalyzer.get_actual_type (derived_instance_type, method_type_arguments, (GenericType) result, node_reference);
+ if (!result.is_non_null_simple_type ()) {
+ result.nullable = result.nullable || nullable;
+ }
return result;
}
@@ -77,7 +78,7 @@ public class Vala.GenericType : DataType {
}
public override string to_qualified_string (Scope? scope = null) {
- return type_parameter.name;
+ return "%s%s".printf (type_parameter.name, nullable ? "?" : "");
}
public override Symbol? get_member (string member_name) {
diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala
index 2b75adcc5..23078f25b 100644
--- a/vala/valamemberaccess.vala
+++ b/vala/valamemberaccess.vala
@@ -620,6 +620,7 @@ public class Vala.MemberAccess : Expression {
} else if (symbol_reference.error) {
//ignore previous error
error = true;
+ value_type = new InvalidType ();
return false;
}
diff --git a/vala/valasymbolresolver.vala b/vala/valasymbolresolver.vala
index 87352bd00..d029aa9a7 100644
--- a/vala/valasymbolresolver.vala
+++ b/vala/valasymbolresolver.vala
@@ -473,16 +473,9 @@ public class Vala.SymbolResolver : CodeVisitor {
type.source_reference = unresolved_type.source_reference;
type.value_owned = unresolved_type.value_owned;
+ type.nullable = unresolved_type.nullable;
sym.used = true;
- if (type is GenericType) {
- // type parameters are always considered nullable
- // actual type argument may or may not be nullable
- type.nullable = true;
- } else {
- type.nullable = unresolved_type.nullable;
- }
-
type.is_dynamic = unresolved_type.is_dynamic;
foreach (DataType type_arg in unresolved_type.get_type_arguments ()) {
type.add_type_argument (type_arg);