|
1 From 095710b39ec15e4df62eab0781a9d685dbe575a5 Mon Sep 17 00:00:00 2001 |
|
2 From: Keith Randall <[email protected]> |
|
3 Date: Tue, 8 Sep 2015 13:41:51 -0700 |
|
4 Subject: [PATCH 32/63] [release-branch.go1.5] cmd/compile/internal/gc: handle |
|
5 weird map literals in key dedup |
|
6 |
|
7 We compute whether two keys k1 and k2 in a map literal are duplicates by |
|
8 constructing the expression OEQ(k1, k2) and calling the constant |
|
9 expression evaluator on that expression, then extracting the boolean |
|
10 result. |
|
11 |
|
12 Unfortunately, the constant expression evaluator can fail for various |
|
13 reasons. I'm not really sure why it is dying in the case of 12536, but |
|
14 to be safe we should use the result only if we get a constant back (if |
|
15 we get a constant back, it must be boolean). This probably isn't a |
|
16 permanent fix, but it should be good enough for 1.5.2. |
|
17 |
|
18 A permanent fix would be to ensure that the constant expression |
|
19 evaluator can always work for map literal keys, and if not the compiler |
|
20 should generate an error saying that the key isn't a constant (or isn't |
|
21 comparable to some specific other key). |
|
22 |
|
23 This patch has the effect of allowing the map literal to compile when |
|
24 constant eval of the OEQ fails. If the keys are really equal (which the |
|
25 map impl will notice at runtime), one will overwrite the other in the |
|
26 resulting map. Not great, but better than a compiler crash. |
|
27 |
|
28 Fixes #12536 |
|
29 |
|
30 Change-Id: Ic151a5e3f131c2e8efa0c25c9218b431c55c1b30 |
|
31 Reviewed-on: https://go-review.googlesource.com/14400 |
|
32 Reviewed-by: Ian Lance Taylor <[email protected]> |
|
33 Reviewed-on: https://go-review.googlesource.com/16965 |
|
34 Run-TryBot: Austin Clements <[email protected]> |
|
35 Reviewed-by: Russ Cox <[email protected]> |
|
36 --- |
|
37 src/cmd/compile/internal/gc/typecheck.go | 9 +++++++-- |
|
38 1 file changed, 7 insertions(+), 2 deletions(-) |
|
39 |
|
40 diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go |
|
41 index befe3b2..e5ae967 100644 |
|
42 --- a/src/cmd/compile/internal/gc/typecheck.go |
|
43 +++ b/src/cmd/compile/internal/gc/typecheck.go |
|
44 @@ -2874,12 +2874,17 @@ func keydup(n *Node, hash map[uint32][]*Node) { |
|
45 if Eqtype(a.Left.Type, n.Type) { |
|
46 cmp.Right = a.Left |
|
47 evconst(&cmp) |
|
48 - b = uint32(obj.Bool2int(cmp.Val().U.(bool))) |
|
49 + if cmp.Op == OLITERAL { |
|
50 + // Sometimes evconst fails. See issue 12536. |
|
51 + b = uint32(obj.Bool2int(cmp.Val().U.(bool))) |
|
52 + } |
|
53 } |
|
54 } else if Eqtype(a.Type, n.Type) { |
|
55 cmp.Right = a |
|
56 evconst(&cmp) |
|
57 - b = uint32(obj.Bool2int(cmp.Val().U.(bool))) |
|
58 + if cmp.Op == OLITERAL { |
|
59 + b = uint32(obj.Bool2int(cmp.Val().U.(bool))) |
|
60 + } |
|
61 } |
|
62 |
|
63 if b != 0 { |
|
64 -- |
|
65 2.6.1 |
|
66 |