From: Rico Tzschichholz Date: Sun, 6 Feb 2022 07:57:35 +0000 (+0100) Subject: parser: Allow usage of dynamic on VarType X-Git-Tag: 0.55.3~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7b3fc94ce5d057bd7d26ce0e2d891a58710f6903;p=thirdparty%2Fvala.git parser: Allow usage of dynamic on VarType dynamic var foo = bar.get_foo(); Fixes https://gitlab.gnome.org/GNOME/vala/issues/187 --- diff --git a/tests/Makefile.am b/tests/Makefile.am index a0ee32a6c..4190a0de1 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -982,6 +982,7 @@ TESTS = \ parser/using-ambiguous-reference.test \ parser/using-directive.vala \ parser/using-invalid-namespace.test \ + parser/var-type-dynamic.vala \ parser/var-type-nullable.vala \ parser/with-embedded.vala \ parser/with-empty.vala \ diff --git a/tests/parser/var-type-dynamic.c-expected b/tests/parser/var-type-dynamic.c-expected new file mode 100644 index 000000000..75eaaae57 --- /dev/null +++ b/tests/parser/var-type-dynamic.c-expected @@ -0,0 +1,523 @@ +/* parser_var_type_dynamic.c generated by valac, the Vala compiler + * generated from parser_var_type_dynamic.vala, do not modify */ + +#include +#include +#include +#include + +#if !defined(VALA_EXTERN) +#if defined(_MSC_VER) +#define VALA_EXTERN __declspec(dllexport) extern +#elif __GNUC__ >= 4 +#define VALA_EXTERN __attribute__((visibility("default"))) extern +#else +#define VALA_EXTERN extern +#endif +#endif + +#define TYPE_FOO (foo_get_type ()) +#define FOO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_FOO, Foo)) +#define FOO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_FOO, FooClass)) +#define IS_FOO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_FOO)) +#define IS_FOO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_FOO)) +#define FOO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_FOO, FooClass)) + +typedef struct _Foo Foo; +typedef struct _FooClass FooClass; +typedef struct _FooPrivate FooPrivate; +enum { + FOO_0_PROPERTY, + FOO_BAR_PROPERTY, + FOO_NUM_PROPERTIES +}; +static GParamSpec* foo_properties[FOO_NUM_PROPERTIES]; +#define _g_free0(var) (var = (g_free (var), NULL)) +#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_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); + +struct _Foo { + GObject parent_instance; + FooPrivate * priv; +}; + +struct _FooClass { + GObjectClass parent_class; +}; + +struct _FooPrivate { + gchar* _bar; +}; + +static gint Foo_private_offset; +static gpointer foo_parent_class = NULL; + +VALA_EXTERN GType foo_get_type (void) G_GNUC_CONST ; +G_DEFINE_AUTOPTR_CLEANUP_FUNC (Foo, g_object_unref) +VALA_EXTERN Foo* foo_new (void); +VALA_EXTERN Foo* foo_construct (GType object_type); +VALA_EXTERN gchar* foo_get_bar (Foo* self); +VALA_EXTERN void foo_set_bar (Foo* self, + const gchar* value); +static void foo_finalize (GObject * obj); +static GType foo_get_type_once (void); +static void _vala_foo_get_property (GObject * object, + guint property_id, + GValue * value, + GParamSpec * pspec); +static void _vala_foo_set_property (GObject * object, + guint property_id, + const GValue * value, + GParamSpec * pspec); +static void _vala_main (void); +static void _g_object_unref0_ (gpointer var); +static inline void _g_list_free__g_object_unref0_ (GList* self); + +static inline gpointer +foo_get_instance_private (Foo* self) +{ + return G_STRUCT_MEMBER_P (self, Foo_private_offset); +} + +Foo* +foo_construct (GType object_type) +{ + Foo * self = NULL; + self = (Foo*) g_object_new (object_type, NULL); + return self; +} + +Foo* +foo_new (void) +{ + return foo_construct (TYPE_FOO); +} + +gchar* +foo_get_bar (Foo* self) +{ + gchar* result; + const gchar* _tmp0_; + gchar* _tmp1_; + g_return_val_if_fail (IS_FOO (self), NULL); + _tmp0_ = self->priv->_bar; + _tmp1_ = g_strdup (_tmp0_); + result = _tmp1_; + return result; +} + +void +foo_set_bar (Foo* self, + const gchar* value) +{ + gchar* old_value; + g_return_if_fail (IS_FOO (self)); + old_value = foo_get_bar (self); + if (g_strcmp0 (value, old_value) != 0) { + gchar* _tmp0_; + _tmp0_ = g_strdup (value); + _g_free0 (self->priv->_bar); + self->priv->_bar = _tmp0_; + g_object_notify_by_pspec ((GObject *) self, foo_properties[FOO_BAR_PROPERTY]); + } + _g_free0 (old_value); +} + +static void +foo_class_init (FooClass * klass, + gpointer klass_data) +{ + foo_parent_class = g_type_class_peek_parent (klass); + g_type_class_adjust_private_offset (klass, &Foo_private_offset); + G_OBJECT_CLASS (klass)->get_property = _vala_foo_get_property; + G_OBJECT_CLASS (klass)->set_property = _vala_foo_set_property; + G_OBJECT_CLASS (klass)->finalize = foo_finalize; + g_object_class_install_property (G_OBJECT_CLASS (klass), FOO_BAR_PROPERTY, foo_properties[FOO_BAR_PROPERTY] = g_param_spec_string ("manam", "bar", "bar", NULL, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE)); +} + +static void +foo_instance_init (Foo * self, + gpointer klass) +{ + gchar* _tmp0_; + self->priv = foo_get_instance_private (self); + _tmp0_ = g_strdup ("foo"); + self->priv->_bar = _tmp0_; +} + +static void +foo_finalize (GObject * obj) +{ + Foo * self; + self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_FOO, Foo); + _g_free0 (self->priv->_bar); + G_OBJECT_CLASS (foo_parent_class)->finalize (obj); +} + +static GType +foo_get_type_once (void) +{ + static const GTypeInfo g_define_type_info = { sizeof (FooClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) foo_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Foo), 0, (GInstanceInitFunc) foo_instance_init, NULL }; + GType foo_type_id; + foo_type_id = g_type_register_static (G_TYPE_OBJECT, "Foo", &g_define_type_info, 0); + Foo_private_offset = g_type_add_instance_private (foo_type_id, sizeof (FooPrivate)); + return foo_type_id; +} + +GType +foo_get_type (void) +{ + static volatile gsize foo_type_id__once = 0; + if (g_once_init_enter (&foo_type_id__once)) { + GType foo_type_id; + foo_type_id = foo_get_type_once (); + g_once_init_leave (&foo_type_id__once, foo_type_id); + } + return foo_type_id__once; +} + +static void +_vala_foo_get_property (GObject * object, + guint property_id, + GValue * value, + GParamSpec * pspec) +{ + Foo * self; + self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_FOO, Foo); + switch (property_id) { + case FOO_BAR_PROPERTY: + g_value_take_string (value, foo_get_bar (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +_vala_foo_set_property (GObject * object, + guint property_id, + const GValue * value, + GParamSpec * pspec) +{ + Foo * self; + self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_FOO, Foo); + switch (property_id) { + case FOO_BAR_PROPERTY: + foo_set_bar (self, g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static gpointer +_g_object_ref0 (gpointer self) +{ + return self ? g_object_ref (self) : NULL; +} + +static void +_g_object_unref0_ (gpointer var) +{ + (var == NULL) ? NULL : (var = (g_object_unref (var), NULL)); +} + +static inline void +_g_list_free__g_object_unref0_ (GList* self) +{ + g_list_free_full (self, (GDestroyNotify) _g_object_unref0_); +} + +static void +_vala_main (void) +{ + Foo* foo = NULL; + Foo* _tmp0_; + GList* foo_list = NULL; + Foo* _tmp1_; + Foo* _tmp2_; + _tmp0_ = foo_new (); + foo = _tmp0_; + foo_list = NULL; + _tmp1_ = foo; + _tmp2_ = _g_object_ref0 (_tmp1_); + foo_list = g_list_prepend (foo_list, _tmp2_); + { + Foo* bar = NULL; + Foo* _tmp3_; + Foo* _tmp4_; + gchar* s = NULL; + Foo* _tmp5_; + gchar* _tmp6_; + gchar* _tmp7_; + const gchar* _tmp8_; + _tmp3_ = foo; + _tmp4_ = _g_object_ref0 (_tmp3_); + bar = _tmp4_; + _tmp5_ = bar; + g_object_get (_tmp5_, "manam", &_tmp6_, NULL); + _tmp7_ = _tmp6_; + s = _tmp7_; + _tmp8_ = s; + _vala_assert (g_strcmp0 (_tmp8_, "foo") == 0, "s == \"foo\""); + _g_free0 (s); + _g_object_unref0 (bar); + } + { + Foo* bar = NULL; + Foo* _tmp9_; + gchar* s = NULL; + Foo* _tmp10_; + gchar* _tmp11_; + gchar* _tmp12_; + const gchar* _tmp13_; + _tmp9_ = foo; + bar = _tmp9_; + _tmp10_ = bar; + g_object_get (_tmp10_, "manam", &_tmp11_, NULL); + _tmp12_ = _tmp11_; + s = _tmp12_; + _tmp13_ = s; + _vala_assert (g_strcmp0 (_tmp13_, "foo") == 0, "s == \"foo\""); + _g_free0 (s); + } + { + Foo* bar = NULL; + Foo* _tmp14_; + Foo* _tmp15_; + gchar* s = NULL; + Foo* _tmp16_; + gchar* _tmp17_; + gchar* _tmp18_; + const gchar* _tmp19_; + _tmp14_ = foo; + _tmp15_ = _g_object_ref0 (_tmp14_); + bar = _tmp15_; + _tmp16_ = bar; + g_object_get (_tmp16_, "manam", &_tmp17_, NULL); + _tmp18_ = _tmp17_; + s = _tmp18_; + _tmp19_ = s; + _vala_assert (g_strcmp0 (_tmp19_, "foo") == 0, "s == \"foo\""); + _g_free0 (s); + _g_object_unref0 (bar); + } + { + Foo* bar = NULL; + Foo* _tmp20_; + gchar* s = NULL; + Foo* _tmp21_; + gchar* _tmp22_; + gchar* _tmp23_; + const gchar* _tmp24_; + _tmp20_ = foo; + bar = _tmp20_; + _tmp21_ = bar; + g_object_get (_tmp21_, "manam", &_tmp22_, NULL); + _tmp23_ = _tmp22_; + s = _tmp23_; + _tmp24_ = s; + _vala_assert (g_strcmp0 (_tmp24_, "foo") == 0, "s == \"foo\""); + _g_free0 (s); + } + { + GList* _tmp25_; + _tmp25_ = foo_list; + { + GList* bar_collection = NULL; + GList* bar_it = NULL; + bar_collection = _tmp25_; + for (bar_it = bar_collection; bar_it != NULL; bar_it = bar_it->next) { + Foo* _tmp26_; + Foo* bar = NULL; + _tmp26_ = _g_object_ref0 ((Foo*) bar_it->data); + bar = _tmp26_; + { + gchar* s = NULL; + Foo* _tmp27_; + gchar* _tmp28_; + gchar* _tmp29_; + const gchar* _tmp30_; + _tmp27_ = bar; + g_object_get (_tmp27_, "manam", &_tmp28_, NULL); + _tmp29_ = _tmp28_; + s = _tmp29_; + _tmp30_ = s; + _vala_assert (g_strcmp0 (_tmp30_, "foo") == 0, "s == \"foo\""); + _g_free0 (s); + _g_object_unref0 (bar); + } + } + } + } + { + GList* _tmp31_; + _tmp31_ = foo_list; + { + GList* bar_collection = NULL; + GList* bar_it = NULL; + bar_collection = _tmp31_; + for (bar_it = bar_collection; bar_it != NULL; bar_it = bar_it->next) { + Foo* bar = NULL; + bar = (Foo*) bar_it->data; + { + gchar* s = NULL; + Foo* _tmp32_; + gchar* _tmp33_; + gchar* _tmp34_; + const gchar* _tmp35_; + _tmp32_ = bar; + g_object_get (_tmp32_, "manam", &_tmp33_, NULL); + _tmp34_ = _tmp33_; + s = _tmp34_; + _tmp35_ = s; + _vala_assert (g_strcmp0 (_tmp35_, "foo") == 0, "s == \"foo\""); + _g_free0 (s); + } + } + } + } + { + GList* _tmp36_; + _tmp36_ = foo_list; + { + GList* bar_collection = NULL; + GList* bar_it = NULL; + bar_collection = _tmp36_; + for (bar_it = bar_collection; bar_it != NULL; bar_it = bar_it->next) { + Foo* _tmp37_; + Foo* bar = NULL; + _tmp37_ = _g_object_ref0 ((Foo*) bar_it->data); + bar = _tmp37_; + { + gchar* s = NULL; + Foo* _tmp38_; + gchar* _tmp39_; + gchar* _tmp40_; + const gchar* _tmp41_; + _tmp38_ = bar; + g_object_get (_tmp38_, "manam", &_tmp39_, NULL); + _tmp40_ = _tmp39_; + s = _tmp40_; + _tmp41_ = s; + _vala_assert (g_strcmp0 (_tmp41_, "foo") == 0, "s == \"foo\""); + _g_free0 (s); + _g_object_unref0 (bar); + } + } + } + } + { + GList* _tmp42_; + _tmp42_ = foo_list; + { + GList* bar_collection = NULL; + GList* bar_it = NULL; + bar_collection = _tmp42_; + for (bar_it = bar_collection; bar_it != NULL; bar_it = bar_it->next) { + Foo* bar = NULL; + bar = (Foo*) bar_it->data; + { + gchar* s = NULL; + Foo* _tmp43_; + gchar* _tmp44_; + gchar* _tmp45_; + const gchar* _tmp46_; + _tmp43_ = bar; + g_object_get (_tmp43_, "manam", &_tmp44_, NULL); + _tmp45_ = _tmp44_; + s = _tmp45_; + _tmp46_ = s; + _vala_assert (g_strcmp0 (_tmp46_, "foo") == 0, "s == \"foo\""); + _g_free0 (s); + } + } + } + } + { + { + Foo* bar = NULL; + Foo* _tmp47_; + Foo* _tmp48_; + gchar* s = NULL; + gchar* _tmp49_; + gchar* _tmp50_; + _tmp47_ = foo; + _tmp48_ = _g_object_ref0 (_tmp47_); + bar = _tmp48_; + g_object_get (bar, "manam", &_tmp49_, NULL); + _tmp50_ = _tmp49_; + s = _tmp50_; + _vala_assert (g_strcmp0 (s, "foo") == 0, "s == \"foo\""); + _g_free0 (s); + _g_object_unref0 (bar); + } + } + { + { + Foo* bar = NULL; + Foo* _tmp51_; + gchar* s = NULL; + gchar* _tmp52_; + gchar* _tmp53_; + _tmp51_ = foo; + bar = _tmp51_; + g_object_get (bar, "manam", &_tmp52_, NULL); + _tmp53_ = _tmp52_; + s = _tmp53_; + _vala_assert (g_strcmp0 (s, "foo") == 0, "s == \"foo\""); + _g_free0 (s); + } + } + { + { + Foo* bar = NULL; + Foo* _tmp54_; + Foo* _tmp55_; + gchar* s = NULL; + gchar* _tmp56_; + gchar* _tmp57_; + _tmp54_ = foo; + _tmp55_ = _g_object_ref0 (_tmp54_); + bar = _tmp55_; + g_object_get (bar, "manam", &_tmp56_, NULL); + _tmp57_ = _tmp56_; + s = _tmp57_; + _vala_assert (g_strcmp0 (s, "foo") == 0, "s == \"foo\""); + _g_free0 (s); + _g_object_unref0 (bar); + } + } + { + { + Foo* bar = NULL; + Foo* _tmp58_; + gchar* s = NULL; + gchar* _tmp59_; + gchar* _tmp60_; + _tmp58_ = foo; + bar = _tmp58_; + g_object_get (bar, "manam", &_tmp59_, NULL); + _tmp60_ = _tmp59_; + s = _tmp60_; + _vala_assert (g_strcmp0 (s, "foo") == 0, "s == \"foo\""); + _g_free0 (s); + } + } + (foo_list == NULL) ? NULL : (foo_list = (_g_list_free__g_object_unref0_ (foo_list), NULL)); + _g_object_unref0 (foo); +} + +int +main (int argc, + char ** argv) +{ + _vala_main (); + return 0; +} + diff --git a/tests/parser/var-type-dynamic.vala b/tests/parser/var-type-dynamic.vala new file mode 100644 index 000000000..3fd513efa --- /dev/null +++ b/tests/parser/var-type-dynamic.vala @@ -0,0 +1,79 @@ +class Foo : Object { + [CCode (cname = "manam")] + public string bar { owned get; set; default = "foo"; } +} + +void main () { + var foo = new Foo (); + var foo_list = new List (); + foo_list.prepend (foo); + + { + dynamic var bar = foo; + string s = bar.manam; + assert (s == "foo"); + } + { + dynamic unowned var bar = foo; + string s = bar.manam; + assert (s == "foo"); + } + { + dynamic var? bar = foo; + string s = bar.manam; + assert (s == "foo"); + } + { + dynamic unowned var? bar = foo; + string s = bar.manam; + assert (s == "foo"); + } + { + foreach (dynamic var bar in foo_list) { + string s = bar.manam; + assert (s == "foo"); + } + } + { + foreach (dynamic unowned var bar in foo_list) { + string s = bar.manam; + assert (s == "foo"); + } + } + { + foreach (dynamic var? bar in foo_list) { + string s = bar.manam; + assert (s == "foo"); + } + } + { + foreach (dynamic unowned var? bar in foo_list) { + string s = bar.manam; + assert (s == "foo"); + } + } + { + with (dynamic var bar = foo) { + string s = bar.manam; + assert (s == "foo"); + } + } + { + with (dynamic unowned var bar = foo) { + string s = bar.manam; + assert (s == "foo"); + } + } + { + with (dynamic var? bar = foo) { + string s = bar.manam; + assert (s == "foo"); + } + } + { + with (dynamic unowned var? bar = foo) { + string s = bar.manam; + assert (s == "foo"); + } + } +} diff --git a/vala/valaforeachstatement.vala b/vala/valaforeachstatement.vala index f491c037f..84370e5b0 100644 --- a/vala/valaforeachstatement.vala +++ b/vala/valaforeachstatement.vala @@ -342,6 +342,7 @@ public class Vala.ForeachStatement : Block { // var type bool nullable = type_reference.nullable; bool value_owned = type_reference.value_owned; + bool is_dynamic = type_reference.is_dynamic; type_reference = element_type.copy (); // FIXME Only follows "unowned var" otherwise inherit ownership of element-type if (!value_owned) { @@ -350,6 +351,9 @@ public class Vala.ForeachStatement : Block { if (nullable) { type_reference.nullable = true; } + if (is_dynamic) { + type_reference.is_dynamic = 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 ()); @@ -369,6 +373,7 @@ public class Vala.ForeachStatement : Block { // var type bool nullable = type_reference.nullable; bool value_owned = type_reference.value_owned; + bool is_dynamic = type_reference.is_dynamic; type_reference = element_type.copy (); // FIXME Only follows "unowned var" otherwise inherit ownership of element-type if (!value_owned) { @@ -377,6 +382,9 @@ public class Vala.ForeachStatement : Block { if (nullable) { type_reference.nullable = true; } + if (is_dynamic) { + type_reference.is_dynamic = 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 ()); diff --git a/vala/valalocalvariable.vala b/vala/valalocalvariable.vala index e2a5c92c2..7fbde469f 100644 --- a/vala/valalocalvariable.vala +++ b/vala/valalocalvariable.vala @@ -156,12 +156,16 @@ public class Vala.LocalVariable : Variable { bool nullable = variable_type.nullable; bool value_owned = variable_type.value_owned; + bool is_dynamic = variable_type.is_dynamic; variable_type = initializer.value_type.copy (); variable_type.value_owned = value_owned; variable_type.floating_reference = false; if (nullable) { variable_type.nullable = true; } + if (is_dynamic) { + variable_type.is_dynamic = true; + } initializer.target_type = variable_type; variable_type.check (context); diff --git a/vala/valaparser.vala b/vala/valaparser.vala index 1e84c8bfa..a8f083a82 100644 --- a/vala/valaparser.vala +++ b/vala/valaparser.vala @@ -2063,15 +2063,20 @@ public class Vala.Parser : CodeVisitor { void parse_local_variable_declarations (Block block) throws ParseError { var begin = get_location (); DataType variable_type; + bool is_dynamic = accept (TokenType.DYNAMIC); if (accept (TokenType.UNOWNED) && accept (TokenType.VAR)) { variable_type = new VarType (false); variable_type.nullable = accept (TokenType.INTERR); + variable_type.is_dynamic = is_dynamic; } else { rollback (begin); + is_dynamic = accept (TokenType.DYNAMIC); if (accept (TokenType.VAR)) { variable_type = new VarType (); variable_type.nullable = accept (TokenType.INTERR); + variable_type.is_dynamic = is_dynamic; } else { + rollback (begin); variable_type = parse_type (true, true); } } @@ -2375,15 +2380,20 @@ public class Vala.Parser : CodeVisitor { expect (TokenType.OPEN_PARENS); var var_or_type = get_location (); DataType type; + bool is_dynamic = accept (TokenType.DYNAMIC); if (accept (TokenType.UNOWNED) && accept (TokenType.VAR)) { type = new VarType (false); type.nullable = accept (TokenType.INTERR); + type.is_dynamic = is_dynamic; } else { rollback (var_or_type); + is_dynamic = accept (TokenType.DYNAMIC); if (accept (TokenType.VAR)) { type = new VarType (); type.nullable = accept (TokenType.INTERR); + type.is_dynamic = is_dynamic; } else { + rollback (var_or_type); type = parse_type (true, true); if (accept (TokenType.IN)) { Report.error (type.source_reference, "syntax error, expected `unowned var', `var' or type"); @@ -2551,14 +2561,18 @@ public class Vala.Parser : CodeVisitor { // Try "with (var identifier = expr)" rollback (expr_or_decl); DataType variable_type; + bool is_dynamic = accept (TokenType.DYNAMIC); if (accept (TokenType.UNOWNED) && accept (TokenType.VAR)) { variable_type = new VarType (false); variable_type.nullable = accept (TokenType.INTERR); + variable_type.is_dynamic = is_dynamic; } else { rollback (expr_or_decl); + is_dynamic = accept (TokenType.DYNAMIC); if (accept (TokenType.VAR)) { variable_type = new VarType (); variable_type.nullable = accept (TokenType.INTERR); + variable_type.is_dynamic = is_dynamic; } else { variable_type = parse_type (true, true); } diff --git a/vala/valavartype.vala b/vala/valavartype.vala index be97e1752..b31af255f 100644 --- a/vala/valavartype.vala +++ b/vala/valavartype.vala @@ -35,6 +35,7 @@ public class Vala.VarType : DataType { public override DataType copy () { var result = new VarType (value_owned); result.nullable = nullable; + result.is_dynamic = is_dynamic; return result; } }