From df778e6fd9a8ad4f50f734f08b8d07d4ce597c02 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 13:03:06 -0400 Subject: [PATCH] [dev.typeparams] go/types: replace optype() with under() in various cases (cleanup) This is a port of CL 332555 to go/types. Change-Id: I9b26bba8b605f5bbbd8f0f81fd6651a4a3ff4b57 Reviewed-on: https://go-review.googlesource.com/c/go/+/335111 Reviewed-by: Robert Griesemer Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot --- src/go/types/builtins.go | 8 +++++--- src/go/types/expr.go | 6 +++--- src/go/types/index.go | 6 +++--- src/go/types/predicates.go | 17 ++++++++--------- src/go/types/testdata/check/typeparams.go2 | 2 +- src/go/types/typeset.go | 1 + 6 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index e976e76cf1d..9b2a75458cb 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -337,13 +337,15 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b 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, _Todo, "copy on generic operands not yet implemented") } if dst == nil || src == nil { @@ -464,12 +466,12 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b 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 diff --git a/src/go/types/expr.go b/src/go/types/expr.go index edd7caf1c93..46f6e334631 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -622,7 +622,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const return x.typ, nil, 0 } - switch t := optype(target).(type) { + switch t := under(target).(type) { case *Basic: if x.mode == constant_ { v, code := check.representation(x, t) @@ -661,7 +661,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 @@ -1151,7 +1151,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { goto Error } - switch utyp := optype(base).(type) { + switch utyp := under(base).(type) { case *Struct: if len(e.Elts) == 0 { break diff --git a/src/go/types/index.go b/src/go/types/index.go index 036752c7340..b2a5a2e9488 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -199,7 +199,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.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.Slice3 { @@ -239,8 +239,8 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { valid = true // x.typ doesn't change - case *Union, *TypeParam: - check.errorf(x, 0, "generic slice expressions not yet implemented") + case *TypeParam: + check.errorf(x, _Todo, "generic slice expressions not yet implemented") x.mode = invalid return } diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index c3c168647da..c9be1218394 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -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(typ Type) bool { return is(typ, what) }) } return false @@ -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 diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index b832e6b760c..0e3795724b3 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -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 diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index 3fe48892fe9..d8fe42f7d08 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -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