This allows to improve type safety for handle types.
TESTS = \
basic-types/gassert.vala \
basic-types/integer-literals.vala \
+ basic-types/integer-negative-rank-incompatible.test \
+ basic-types/integer-negative-rank-incompatible2.test \
+ basic-types/integer-negative-rank-incompatible3.test \
basic-types/integer-signed-binary-erange.test \
basic-types/integer-signed-erange.test \
basic-types/integer-signed-erange2.test \
basic-types/integers-binary.vala \
basic-types/integers.vala \
basic-types/integers-boxed-cast.vala \
+ basic-types/integers-negative-rank.vala \
basic-types/integers-octal-invalid.test \
basic-types/integers-octal.vala \
basic-types/escape-chars.vala \
--- /dev/null
+Invalid Code
+
+[CCode (cname = "gint", cheader_filename = "glib.h", default_value = "0", has_type_id = false)]
+[IntegerType (rank = -1)]
+struct FooHandle {
+}
+
+[CCode (cname = "gint", cheader_filename = "glib.h", default_value = "0", has_type_id = false)]
+[IntegerType (rank = -1)]
+struct BarHandle {
+}
+
+void main () {
+ FooHandle foo = 42;
+ BarHandle bar = foo;
+}
--- /dev/null
+Invalid Code
+
+[CCode (cname = "gint", cheader_filename = "glib.h", default_value = "0", has_type_id = false)]
+[IntegerType (rank = -1)]
+struct FooHandle {
+}
+
+void main () {
+ FooHandle foo = 42;
+ int bar = foo;
+}
--- /dev/null
+Invalid Code
+
+[CCode (cname = "gint", cheader_filename = "glib.h", default_value = "0", has_type_id = false)]
+[IntegerType (rank = -1)]
+struct BarHandle {
+}
+
+void main () {
+ int foo = 42;
+ BarHandle bar = foo;
+}
--- /dev/null
+/* basic_types_integers_negative_rank.c generated by valac, the Vala compiler
+ * generated from basic_types_integers_negative_rank.vala, do not modify */
+
+#include <stdint.h>
+#include <glib.h>
+
+typedef int32_t gint;
+typedef gint BarHandle;
+#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
+_vala_main (void)
+{
+ {
+ gint foo = 0;
+ foo = 0;
+ _vala_assert (foo == 0, "foo == 0");
+ }
+ {
+ gint foo = 0;
+ foo = -1;
+ _vala_assert (foo == -1, "foo == -1");
+ }
+ {
+ gint foo = 0;
+ foo = 42;
+ _vala_assert (foo == 42, "foo == 42");
+ foo = 64;
+ _vala_assert (foo == 64, "foo == 64");
+ }
+ {
+ gint foo = 0;
+ BarHandle bar = 0;
+ foo = 36;
+ bar = (BarHandle) 64;
+ foo = (gint) bar;
+ _vala_assert (foo == 64, "foo == 64");
+ foo = 88;
+ bar = (BarHandle) foo;
+ _vala_assert (((gint) bar) == 88, "bar == 88");
+ }
+ {
+ gint foo = 0;
+ BarHandle bar = 0;
+ guint baz = 0U;
+ foo = 99;
+ bar = (BarHandle) foo;
+ _vala_assert (((gint) bar) == 99, "bar == 99");
+ baz = (guint) bar;
+ _vala_assert (baz == ((guint) 99), "baz == 99");
+ }
+ {
+ gint foo = 0;
+ gint baz = 0;
+ foo = 28;
+ baz = (gint) foo;
+ _vala_assert (baz == 28, "baz == 28");
+ }
+}
+
+int
+main (int argc,
+ char ** argv)
+{
+ _vala_main ();
+ return 0;
+}
+
--- /dev/null
+[CCode (cname = "gint", cheader_filename = "glib.h", default_value = "0", has_type_id = false)]
+[IntegerType (rank = -1)]
+struct FooHandle {
+}
+
+struct BarHandle : FooHandle {
+}
+
+[IntegerType (rank = -2)]
+[CCode (cname = "gint", cheader_filename = "glib.h", default_value = "0", has_type_id = false)]
+struct BazHandle {
+}
+
+void main () {
+ {
+ FooHandle foo = 0;
+ assert (foo == 0);
+ }
+ {
+ FooHandle foo = -1;
+ assert (foo == -1);
+ }
+ {
+ FooHandle foo = 42;
+ assert (foo == 42);
+ foo = 64;
+ assert (foo == 64);
+ }
+ {
+ FooHandle foo = 36;
+ BarHandle bar = 64;
+ foo = bar;
+ assert (foo == 64);
+ foo = 88;
+ bar = foo;
+ assert (bar == 88);
+ }
+ {
+ int foo = 99;
+ BarHandle bar = (BarHandle) foo;
+ assert (bar == 99);
+ uint baz = (uint) bar;
+ assert (baz == 99);
+ }
+ {
+ FooHandle foo = 28;
+ BazHandle baz = (BazHandle) foo;
+ assert (baz == 28);
+ }
+}
if (type_symbol is Struct && target_type.type_symbol is Struct) {
unowned Struct expr_struct = (Struct) type_symbol;
- unowned Struct expect_struct = (Struct) target_type.type_symbol;
+ unowned Struct target_struct = (Struct) target_type.type_symbol;
- /* integer types may be implicitly cast to floating point types */
- if (expr_struct.is_integer_type () && expect_struct.is_floating_type ()) {
+ // Allow compatibility of struct subtypes in both ways
+ if (target_struct.is_subtype_of (expr_struct)) {
return true;
}
- if ((expr_struct.is_integer_type () && expect_struct.is_integer_type ()) ||
- (expr_struct.is_floating_type () && expect_struct.is_floating_type ())) {
- if (expr_struct.rank <= expect_struct.rank) {
- return true;
- }
+ // Negative ranks are used for handle types that are not implicitly convertible
+ if ((expr_struct.is_integer_type () || expr_struct.is_floating_type ()) && expr_struct.rank < 0) {
+ return false;
+ } else if ((target_struct.is_integer_type () || target_struct.is_floating_type ()) && target_struct.rank < 0) {
+ return false;
}
- if (expr_struct.is_boolean_type () && expect_struct.is_boolean_type ()) {
+ /* integer types may be implicitly cast to floating point types */
+ if (expr_struct.is_integer_type () && target_struct.is_floating_type ()) {
return true;
}
- // Allow compatibility of struct subtypes in both ways
- if (expect_struct.is_subtype_of (expr_struct)) {
+ if ((expr_struct.is_integer_type () && target_struct.is_integer_type ()) ||
+ (expr_struct.is_floating_type () && target_struct.is_floating_type ())) {
+ if (expr_struct.rank <= target_struct.rank) {
+ return true;
+ }
+ }
+
+ if (expr_struct.is_boolean_type () && target_struct.is_boolean_type ()) {
return true;
}
}