]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile/internal/types2: port of https://golang.org/cl/270957
authorRobert Griesemer <gri@golang.org>
Wed, 18 Nov 2020 00:12:29 +0000 (16:12 -0800)
committerRobert Griesemer <gri@golang.org>
Wed, 18 Nov 2020 04:13:19 +0000 (04:13 +0000)
This ports the latest updates to the dev.go2go version of types2
to the dev.typeparams version.

Change-Id: Ic1b09a8aaeefc701a5c194a587be26e0878e64da
Reviewed-on: https://go-review.googlesource.com/c/go/+/270958
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/expr.go
src/cmd/compile/internal/types2/testdata/expr3.src
src/cmd/compile/internal/types2/testdata/typeparams.go2

index f83aa86f6e367acc7dd70cce9228db6f58e23860..7c07950b01f13891d6863fdf3c3b7a708c02e9ff 100644 (file)
@@ -1467,18 +1467,18 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
                        var key operand
                        check.expr(&key, e.Index)
                        check.assignment(&key, typ.key, "map index")
-                       if x.mode == invalid {
-                               goto Error
-                       }
+                       // ok to continue even if indexing failed - map element type is known
                        x.mode = mapindex
                        x.typ = typ.elem
                        x.expr = e
                        return expression
 
                case *Sum:
-                       // A sum type can be indexed if all the sum's types
-                       // support indexing and have the same element type.
-                       var elem Type
+                       // A sum type can be indexed if all of the sum's types
+                       // support indexing and have the same index and element
+                       // type. Special rules apply for maps in the sum type.
+                       var tkey, telem Type // key is for map types only
+                       nmaps := 0           // number of map types in sum type
                        if typ.is(func(t Type) bool {
                                var e Type
                                switch t := t.Under().(type) {
@@ -1495,21 +1495,58 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
                                case *Slice:
                                        e = t.elem
                                case *Map:
+                                       // If there are multiple maps in the sum type,
+                                       // they must have identical key types.
+                                       // TODO(gri) We may be able to relax this rule
+                                       // but it becomes complicated very quickly.
+                                       if tkey != nil && !Identical(t.key, tkey) {
+                                               return false
+                                       }
+                                       tkey = t.key
                                        e = t.elem
+                                       nmaps++
                                case *TypeParam:
                                        check.errorf(x, "type of %s contains a type parameter - cannot index (implementation restriction)", x)
                                case *instance:
-                                       unimplemented()
+                                       panic("unimplemented")
                                }
-                               if e != nil && (e == elem || elem == nil) {
-                                       elem = e
-                                       return true
+                               if e == nil || telem != nil && !Identical(e, telem) {
+                                       return false
                                }
-                               return false
+                               telem = e
+                               return true
                        }) {
-                               valid = true
-                               x.mode = variable
-                               x.typ = elem
+                               // If there are maps, the index expression must be assignable
+                               // to the map key type (as for simple map index expressions).
+                               if nmaps > 0 {
+                                       var key operand
+                                       check.expr(&key, e.Index)
+                                       check.assignment(&key, tkey, "map index")
+                                       // ok to continue even if indexing failed - map element type is known
+
+                                       // If there are only maps, we are done.
+                                       if nmaps == len(typ.types) {
+                                               x.mode = mapindex
+                                               x.typ = telem
+                                               x.expr = e
+                                               return expression
+                                       }
+
+                                       // Otherwise we have mix of maps and other types. For
+                                       // now we require that the map key be an integer type.
+                                       // TODO(gri) This is probably not good enough.
+                                       valid = isInteger(tkey)
+                                       // avoid 2nd indexing error if indexing failed above
+                                       if !valid && key.mode == invalid {
+                                               goto Error
+                                       }
+                                       x.mode = value // map index expressions are not addressable
+                               } else {
+                                       // no maps
+                                       valid = true
+                                       x.mode = variable
+                               }
+                               x.typ = telem
                        }
                }
 
index 3c6e36f148240c2069bdebebfc683bd188ff7562..071c9bb367babc06ba1009a84e6581f9237eb040 100644 (file)
@@ -103,6 +103,7 @@ func indexes() {
        var ok mybool
        _, ok = m["bar"]
        _ = ok
+       _ = m[0 /* ERROR "cannot convert 0" */ ] + "foo" // ERROR "cannot convert"
 
        var t string
        _ = t[- /* ERROR "negative" */ 1]
index 54cb34ec3baca8df4eb798e7432f0d29d74d006c..04f563029fc0c22e11163a76262ec04dad0205e6 100644 (file)
@@ -94,11 +94,19 @@ func _[T any] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
 func _[T interface{ type int }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
 func _[T interface{ type string }] (x T, i int) { _ = x[i] }
 func _[T interface{ type []int }] (x T, i int) { _ = x[i] }
-func _[T interface{ type [10]int, *[20]int, map[string]int }] (x T, i int) { _ = x[i] }
+func _[T interface{ type [10]int, *[20]int, map[int]int }] (x T, i int) { _ = x[i] }
 func _[T interface{ type string, []byte }] (x T, i int) { _ = x[i] }
 func _[T interface{ type []int, [1]rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
 func _[T interface{ type string, []rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] }
 
+// indexing with various combinations of map types in type lists (see issue #42616)
+func _[T interface{ type []E, map[int]E }, E any](x T, i int) { _ = x[i] }
+func _[T interface{ type []E }, E any](x T, i int) { _ = &x[i] }
+func _[T interface{ type map[int]E }, E any](x T, i int) { _, _ = x[i] } // comma-ok permitted
+func _[T interface{ type []E, map[int]E }, E any](x T, i int) { _ = &x /* ERROR cannot take address */ [i] }
+func _[T interface{ type []E, map[int]E, map[uint]E }, E any](x T, i int) { _ = x /* ERROR cannot index */ [i] } // different map element types
+func _[T interface{ type []E, map[string]E }, E any](x T, i int) { _ = x[i /* ERROR cannot use i */ ] }
+
 // slicing
 // TODO(gri) implement this