From 77b3d40f462a2a1cadd5a35e35f33ee38c684b42 Mon Sep 17 00:00:00 2001 From: yuyi Date: Sat, 30 Jan 2021 18:55:10 +0800 Subject: [PATCH] checker: fix `map = {}` (#8435) --- vlib/builtin/map_test.v | 41 ++++++++++++++++++++++++++++++++-------- vlib/v/ast/ast.v | 2 +- vlib/v/checker/checker.v | 16 ++++++++++++++++ 3 files changed, 50 insertions(+), 9 deletions(-) diff --git a/vlib/builtin/map_test.v b/vlib/builtin/map_test.v index 8c0889cee9..d5ff22c4a8 100644 --- a/vlib/builtin/map_test.v +++ b/vlib/builtin/map_test.v @@ -243,7 +243,7 @@ fn test_delete_size() { for i in 0 .. 10 { m[arr[i]] = i } - assert (m.len == 10) + assert m.len == 10 println(m.len) for i in 0 .. 10 { m.delete(arr[i]) @@ -485,14 +485,18 @@ fn test_int_keys() { m[5] += 24 m[5]++ assert m[5] == 25 - m2 := {3:9 4:16 5:25} + m2 := { + 3: 9 + 4: 16 + 5: 25 + } assert m2.len == 3 // clone mc := m.clone() same := mc == m assert same assert mc.len == 3 - assert mc.keys() == [3,4,5] + assert mc.keys() == [3, 4, 5] mut all := []int{} for k, v in mc { assert m[k] == v @@ -513,14 +517,17 @@ fn test_voidptr_keys() { } fn test_rune_keys() { - mut m := {`!`:2 `%`:3} + mut m := { + `!`: 2 + `%`: 3 + } assert typeof(m).name == 'map[rune]int' assert m[`!`] == 2 m[`@`] = 7 assert m.len == 3 println(m) assert '$m' == '{`!`: 2, `%`: 3, `@`: 7}' - + mut a := []rune{} for k, v in m { a << k @@ -593,7 +600,25 @@ fn test_eq() { } fn test_non_string_key_map_str() { - assert {23: 4}.str() == '{23: 4}' - assert {`a`: 12, `b`: 13}.str() == '{`a`: 12, `b`: 13}' - assert {23: 'foo', 25: 'bar'}.str() == "{23: 'foo', 25: 'bar'}" + assert { + 23: 4 + }.str() == '{23: 4}' + assert { + `a`: 12 + `b`: 13 + }.str() == '{`a`: 12, `b`: 13}' + assert { + 23: 'foo' + 25: 'bar' + }.str() == "{23: 'foo', 25: 'bar'}" +} + +fn test_map_assign_empty_map_init() { + mut a := { + 'one': 1 + } + a = {} + println(a) + assert a == map[string]int{} + assert '$a' == '{}' } diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 8f6a82da08..06e02700d3 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -784,12 +784,12 @@ pub: // variable assign statement pub struct AssignStmt { pub: - right []Expr op token.Kind // include: =,:=,+=,-=,*=,/= and so on; for a list of all the assign operators, see vlib/token/token.v pos token.Position comments []Comment end_comments []Comment pub mut: + right []Expr left []Expr left_types []table.Type right_types []table.Type diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 7b53f47445..8fb6a16cbb 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2437,6 +2437,11 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) { } left_type = c.expr(left) c.expected_type = c.unwrap_generic(left_type) + // `map = {}` + sym := c.table.get_type_symbol(left_type) + if sym.kind == .map && assign_stmt.right[i] is ast.StructInit { + assign_stmt.right[i] = ast.MapInit{} + } } if assign_stmt.right_types.len < assign_stmt.left.len { // first type or multi return types added above right_type := c.expr(assign_stmt.right[i]) @@ -5065,6 +5070,17 @@ pub fn (mut c Checker) check_dup_keys(node &ast.MapInit, i int) { } pub fn (mut c Checker) map_init(mut node ast.MapInit) table.Type { + // `map = {}` + if node.keys.len == 0 && node.vals.len == 0 && node.typ == 0 { + sym := c.table.get_type_symbol(c.expected_type) + if sym.kind == .map { + info := sym.map_info() + node.typ = c.expected_type + node.key_type = info.key_type + node.value_type = info.value_type + return node.typ + } + } // `x := map[string]string` - set in parser if node.typ != 0 { info := c.table.get_type_symbol(node.typ).map_info()