From 59eb76c81d81f1c2886b4dcac2746b5b93364d92 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sun, 9 Jul 2023 09:41:24 -0300 Subject: [PATCH] v: allow `none` for not first values on map initialization (#18821) --- vlib/v/checker/containers.v | 8 +++++ vlib/v/checker/tests/map_with_none_err.out | 34 ++++++++++++++++++++++ vlib/v/checker/tests/map_with_none_err.vv | 15 ++++++++++ vlib/v/gen/c/cgen.v | 2 +- vlib/v/tests/option_map_none_test.v | 17 +++++++++++ 5 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 vlib/v/checker/tests/map_with_none_err.out create mode 100644 vlib/v/checker/tests/map_with_none_err.vv create mode 100644 vlib/v/tests/option_map_none_test.v diff --git a/vlib/v/checker/containers.v b/vlib/v/checker/containers.v index d8ca0f2242..b87913b7cd 100644 --- a/vlib/v/checker/containers.v +++ b/vlib/v/checker/containers.v @@ -409,6 +409,11 @@ fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type { expecting_interface_map := map_value_sym.kind == .interface_ // mut same_key_type := true + + if node.keys.len == 1 && val0_type == ast.none_type { + c.error('map value cannot be only `none`', node.vals[0].pos()) + } + for i, mut key in node.keys { if i == 0 && !use_expected_type { continue @@ -445,6 +450,9 @@ fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type { c.error('invalid map value: ${msg}', val.pos()) } } + if val_type == ast.none_type && val0_type.has_flag(.option) { + continue + } if !c.check_types(val_type, val0_type) || val0_type.has_flag(.option) != val_type.has_flag(.option) || (i == 0 && val_type.is_number() && val0_type.is_number() diff --git a/vlib/v/checker/tests/map_with_none_err.out b/vlib/v/checker/tests/map_with_none_err.out new file mode 100644 index 0000000000..6fc728e4b0 --- /dev/null +++ b/vlib/v/checker/tests/map_with_none_err.out @@ -0,0 +1,34 @@ +vlib/v/checker/tests/map_with_none_err.vv:2:6: warning: unused variable: `a` + 1 | fn main() { + 2 | mut a := { + | ^ + 3 | 'bar': none + 4 | } +vlib/v/checker/tests/map_with_none_err.vv:6:6: warning: unused variable: `b` + 4 | } + 5 | + 6 | mut b := { + | ^ + 7 | 'foo': 1, + 8 | 'bar': none +vlib/v/checker/tests/map_with_none_err.vv:11:6: warning: unused variable: `c` + 9 | } + 10 | + 11 | mut c := { + | ^ + 12 | 'foo': ?int(none), + 13 | 'bar': none +vlib/v/checker/tests/map_with_none_err.vv:3:10: error: map value cannot be only `none` + 1 | fn main() { + 2 | mut a := { + 3 | 'bar': none + | ~~~~ + 4 | } + 5 | +vlib/v/checker/tests/map_with_none_err.vv:8:10: error: invalid map value: expected `int`, not `none` + 6 | mut b := { + 7 | 'foo': 1, + 8 | 'bar': none + | ~~~~ + 9 | } + 10 | diff --git a/vlib/v/checker/tests/map_with_none_err.vv b/vlib/v/checker/tests/map_with_none_err.vv new file mode 100644 index 0000000000..bda994999b --- /dev/null +++ b/vlib/v/checker/tests/map_with_none_err.vv @@ -0,0 +1,15 @@ +fn main() { + mut a := { + 'bar': none + } + + mut b := { + 'foo': 1, + 'bar': none + } + + mut c := { + 'foo': ?int(none), + 'bar': none + } +} \ No newline at end of file diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index bca703a253..5a458227f5 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -4018,7 +4018,7 @@ fn (mut g Gen) map_init(node ast.MapInit) { } if value_sym.kind == .sum_type { g.expr_with_cast(expr, node.val_types[i], unwrap_val_typ) - } else if node.val_types[i].has_flag(.option) { + } else if node.val_types[i].has_flag(.option) || node.val_types[i] == ast.none_type { g.expr_with_opt(expr, node.val_types[i], unwrap_val_typ) } else { g.expr(expr) diff --git a/vlib/v/tests/option_map_none_test.v b/vlib/v/tests/option_map_none_test.v new file mode 100644 index 0000000000..722c809205 --- /dev/null +++ b/vlib/v/tests/option_map_none_test.v @@ -0,0 +1,17 @@ +fn test_main() { + mut a := { + 'foo': ?int(1) + 'bar': none + } + a['foo'] = 1 + assert dump(a) == a +} + +fn test_none() { + mut a := { + 'foo': ?int(1) + 'bar': none + } + a['foo'] = none + assert dump(a) == a +}