]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile/internal/types2: replace optype() with under() in variou...
authorRobert Griesemer <gri@golang.org>
Fri, 2 Jul 2021 23:54:14 +0000 (16:54 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 7 Jul 2021 23:42:19 +0000 (23:42 +0000)
This makes the behavior for type parameter operands explicit
in those cases.

Change-Id: I38438af67de4432f1a691dc4947e4576445f031b
Reviewed-on: https://go-review.googlesource.com/c/go/+/332555
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/builtins.go
src/cmd/compile/internal/types2/expr.go
src/cmd/compile/internal/types2/index.go
src/cmd/compile/internal/types2/predicates.go
src/cmd/compile/internal/types2/testdata/check/typeparams.go2
src/cmd/compile/internal/types2/typeset.go

index 7ba26509e8d782eedf793862a12550297a4b0cfc..83d1743ee2fca5718bc645639f84a884169298f8 100644 (file)
@@ -332,13 +332,15 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
                        return
                }
                var src Type
-               switch t := optype(y.typ).(type) {
+               switch t := under(y.typ).(type) {
                case *Basic:
                        if isString(y.typ) {
                                src = universeByte
                        }
                case *Slice:
                        src = t.elem
+               case *TypeParam:
+                       check.error(x, "copy on generic operands not yet implemented")
                }
 
                if dst == nil || src == nil {
@@ -455,12 +457,12 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
                var valid func(t Type) bool
                valid = func(t Type) bool {
                        var m int
-                       switch t := optype(t).(type) {
+                       switch t := under(t).(type) {
                        case *Slice:
                                m = 2
                        case *Map, *Chan:
                                m = 1
-                       case *Union:
+                       case *TypeParam:
                                return t.underIs(valid)
                        default:
                                return false
index 1cb0ad4752b05203af759209f833cb9135a1a2a1..bd35417c645a81edba944d5007e884743e344a18 100644 (file)
@@ -691,7 +691,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
                return nil, nil, _InvalidUntypedConversion
        }
 
-       switch t := optype(target).(type) {
+       switch t := under(target).(type) {
        case *Basic:
                if x.mode == constant_ {
                        v, code := check.representation(x, t)
@@ -723,7 +723,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
                default:
                        return nil, nil, _InvalidUntypedConversion
                }
-       case *Union:
+       case *TypeParam:
                ok := t.underIs(func(t Type) bool {
                        target, _, _ := check.implicitTypeAndValue(x, t)
                        return target != nil
@@ -1197,7 +1197,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
                        goto Error
                }
 
-               switch utyp := optype(base).(type) {
+               switch utyp := under(base).(type) {
                case *Struct:
                        if len(e.ElemList) == 0 {
                                break
index 5a4dcb47417028dfb78128cb4a1e436d3ff17f39..d3e0c71f05d56802f6a2f14d64fa9fe38820fdc6 100644 (file)
@@ -199,7 +199,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) {
 
        valid := false
        length := int64(-1) // valid if >= 0
-       switch typ := optype(x.typ).(type) {
+       switch typ := under(x.typ).(type) {
        case *Basic:
                if isString(typ) {
                        if e.Full {
@@ -239,7 +239,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) {
                valid = true
                // x.typ doesn't change
 
-       case *Union, *TypeParam:
+       case *TypeParam:
                check.error(x, "generic slice expressions not yet implemented")
                x.mode = invalid
                return
index 5ff7840d6f970eaefda85bb83d3cf69ef39bb11f..2f1089858576222c7b5a324bebfc6cb7599ab335 100644 (file)
@@ -25,10 +25,10 @@ func isGeneric(typ Type) bool {
 }
 
 func is(typ Type, what BasicInfo) bool {
-       switch t := optype(typ).(type) {
+       switch t := under(typ).(type) {
        case *Basic:
                return t.info&what != 0
-       case *Union:
+       case *TypeParam:
                return t.underIs(func(t Type) bool { return is(t, what) })
        }
        return false
@@ -56,7 +56,7 @@ func isNumericOrString(typ Type) bool { return is(typ, IsNumeric|IsString) }
 // are not fully set up.
 func isTyped(typ Type) bool {
        // isTyped is called with types that are not fully
-       // set up. Must not call Basic()!
+       // set up. Must not call asBasic()!
        // A *Named or *instance type is always typed, so
        // we only need to check if we have a true *Basic
        // type.
@@ -97,18 +97,19 @@ func comparable(T Type, seen map[Type]bool) bool {
        seen[T] = true
 
        // If T is a type parameter not constrained by any type
-       // list (i.e., it's operational type is the top type),
+       // (i.e., it's operational type is the top type),
        // T is comparable if it has the == method. Otherwise,
        // the operational type "wins". For instance
        //
        //     interface{ comparable; type []byte }
        //
        // is not comparable because []byte is not comparable.
+       // TODO(gri) this code is not 100% correct (see comment for TypeSet.IsComparable)
        if t := asTypeParam(T); t != nil && optype(t) == theTop {
                return t.Bound().IsComparable()
        }
 
-       switch t := optype(T).(type) {
+       switch t := under(T).(type) {
        case *Basic:
                // assume invalid types to be comparable
                // to avoid follow-up errors
@@ -124,24 +125,22 @@ func comparable(T Type, seen map[Type]bool) bool {
                return true
        case *Array:
                return comparable(t.elem, seen)
-       case *Union:
+       case *TypeParam:
                return t.underIs(func(t Type) bool {
                        return comparable(t, seen)
                })
-       case *TypeParam:
-               return t.Bound().IsComparable()
        }
        return false
 }
 
 // hasNil reports whether a type includes the nil value.
 func hasNil(typ Type) bool {
-       switch t := optype(typ).(type) {
+       switch t := under(typ).(type) {
        case *Basic:
                return t.kind == UnsafePointer
        case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan:
                return true
-       case *Union:
+       case *TypeParam:
                return t.underIs(hasNil)
        }
        return false
index 123567682a3aa3a9fc1a7ec6127937e44e68b9cb..8a7f6eb2c251aadf64ed95a4ce1982370c2b3e45 100644 (file)
@@ -119,7 +119,7 @@ func _[T interface{ [10]int | *[20]int | []int }](x T, i int) { _ = x[i]; _ = x[
 // slicing
 // TODO(gri) implement this
 
-func _[T interface{ ~string }] (x T, i, j, k int) { _ = x /* ERROR invalid operation */ [i:j:k] }
+func _[T interface{ ~string }] (x T, i, j, k int) { _ = x /* ERROR generic slice expressions not yet implemented */ [i:j:k] }
 
 // len/cap built-ins
 
index 6ff85639748b17724aa9ee2bc2c8c0f0736e9944..4aee8e409729e685234b40a8ae385c4879858d8b 100644 (file)
@@ -28,6 +28,7 @@ func (s *TypeSet) IsTop() bool { return len(s.methods) == 0 && s.types == nil }
 func (s *TypeSet) IsMethodSet() bool { return s.types == nil && !s.IsComparable() }
 
 // IsComparable reports whether each type in the set is comparable.
+// TODO(gri) this is not correct - there may be s.types values containing non-comparable types
 func (s *TypeSet) IsComparable() bool {
        _, m := s.LookupMethod(nil, "==")
        return m != nil