1
0
mirror of https://github.com/golang/go synced 2024-09-24 03:10:16 -06:00

[dev.typeparams] cmd/compile/internal/types2: port of https://golang.org/cl/270957

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>
This commit is contained in:
Robert Griesemer 2020-11-17 16:12:29 -08:00
parent 6877ee1e07
commit 2140049172
3 changed files with 61 additions and 15 deletions

View 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
}
}

View 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]

View 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