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 \
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 \
--- /dev/null
+void main () {
+ {
+ unowned var? foo = "foo";
+ assert (foo != null);
+ }
+ {
+ foreach (unowned var? foo in new string[] { "foo", "bar" }) {
+ assert (foo != null);
+ }
+ }
+}
--- /dev/null
+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" }) {
+ }
+ }
+}
// 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 ());
// 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 ());
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);
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);
}
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)) {
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);
}
}
public override DataType copy () {
- return new VarType (value_owned);
+ var result = new VarType (value_owned);
+ result.nullable = nullable;
+ return result;
}
}