interfaceType
typeParamType
instType
+ unionType
)
const io_SeekCurrent = 1 // io.SeekCurrent (not defined in Go 1.4)
// we must always use the methods of the base (orig) type.
t := types2.Instantiate(pos, baseType, targs)
return t
+
+ case unionType:
+ if r.p.exportVersion < iexportVersionGenerics {
+ errorf("unexpected instantiation type")
+ }
+ nt := int(r.uint64())
+ terms := make([]types2.Type, nt)
+ tildes := make([]bool, nt)
+ for i := range terms {
+ terms[i] = r.typ()
+ tildes[i] = r.bool()
+ }
+ return types2.NewUnion(terms, tildes)
}
}
for i := range embeddeds {
// TODO(mdempsky): Get embedding position.
e := typ.EmbeddedType(i)
+
+ // With Go 1.18, an embedded element can be any type, not
+ // just an interface.
if t := types2.AsInterface(e); t != nil {
if t.IsComparable() {
// Ignore predefined type 'comparable', since it
// relevant methods.
continue
}
- embeddeds[j] = types.NewField(src.NoXPos, nil, g.typ1(e))
- j++
}
- // Ignore embedded non-interface types - they correspond
- // to type lists which we currently don't handle here.
+ embeddeds[j] = types.NewField(src.NoXPos, nil, g.typ1(e))
+ j++
}
embeddeds = embeddeds[:j]
tp.SetBound(bound)
return tp
+ case *types2.Union:
+ nt := typ.NumTerms()
+ tlist := make([]*types.Type, nt)
+ tildes := make([]bool, nt)
+ for i := range tlist {
+ term, _ := typ.Term(i)
+ tlist[i] = g.typ1(term)
+ }
+ return types.NewUnion(tlist, tildes)
+
case *types2.Tuple:
// Tuples are used for the type of a function call (i.e. the
// return value of the function).
interfaceType
typeParamType
instType
+ unionType
)
const (
w.signature(f.Type)
}
+ case types.TUNION:
+ // TODO(danscales): possibly put out the tilde bools in more
+ // compact form.
+ w.startType(unionType)
+ nt := t.NumTerms()
+ w.uint64(uint64(nt))
+ for i := 0; i < nt; i++ {
+ t, b := t.Term(i)
+ w.typ(t)
+ w.bool(b)
+ }
+
default:
base.Fatalf("unexpected type: %v", t)
}
baseType := r.typ()
t := Instantiate(pos, baseType, targs)
return t
+
+ case unionType:
+ if r.p.exportVersion < iexportVersionGenerics {
+ base.Fatalf("unexpected instantiation type")
+ }
+ nt := int(r.uint64())
+ terms := make([]*types.Type, nt)
+ tildes := make([]bool, nt)
+ for i := range terms {
+ terms[i] = r.typ()
+ tildes[i] = r.bool()
+ }
+ return types.NewUnion(terms, tildes)
}
}
_ = x[TSTRING-27]
_ = x[TUNSAFEPTR-28]
_ = x[TTYPEPARAM-29]
- _ = x[TIDEAL-30]
- _ = x[TNIL-31]
- _ = x[TBLANK-32]
- _ = x[TFUNCARGS-33]
- _ = x[TCHANARGS-34]
- _ = x[TSSA-35]
- _ = x[TTUPLE-36]
- _ = x[TRESULTS-37]
- _ = x[NTYPE-38]
+ _ = x[TUNION-30]
+ _ = x[TIDEAL-31]
+ _ = x[TNIL-32]
+ _ = x[TBLANK-33]
+ _ = x[TFUNCARGS-34]
+ _ = x[TCHANARGS-35]
+ _ = x[TSSA-36]
+ _ = x[TTUPLE-37]
+ _ = x[TRESULTS-38]
+ _ = x[NTYPE-39]
}
-const _Kind_name = "xxxINT8UINT8INT16UINT16INT32UINT32INT64UINT64INTUINTUINTPTRCOMPLEX64COMPLEX128FLOAT32FLOAT64BOOLPTRFUNCSLICEARRAYSTRUCTCHANMAPINTERFORWANYSTRINGUNSAFEPTRTYPEPARAMIDEALNILBLANKFUNCARGSCHANARGSSSATUPLERESULTSNTYPE"
+const _Kind_name = "xxxINT8UINT8INT16UINT16INT32UINT32INT64UINT64INTUINTUINTPTRCOMPLEX64COMPLEX128FLOAT32FLOAT64BOOLPTRFUNCSLICEARRAYSTRUCTCHANMAPINTERFORWANYSTRINGUNSAFEPTRTYPEPARAMUNIONIDEALNILBLANKFUNCARGSCHANARGSSSATUPLERESULTSNTYPE"
-var _Kind_index = [...]uint8{0, 3, 7, 12, 17, 23, 28, 34, 39, 45, 48, 52, 59, 68, 78, 85, 92, 96, 99, 103, 108, 113, 119, 123, 126, 131, 135, 138, 144, 153, 162, 167, 170, 175, 183, 191, 194, 199, 206, 211}
+var _Kind_index = [...]uint8{0, 3, 7, 12, 17, 23, 28, 34, 39, 45, 48, 52, 59, 68, 78, 85, 92, 96, 99, 103, 108, 113, 119, 123, 126, 131, 135, 138, 144, 153, 162, 167, 172, 175, 180, 188, 196, 199, 204, 211, 216}
func (i Kind) String() string {
if i >= Kind(len(_Kind_index)-1) {
continue
}
+ if m.Type.IsUnion() {
+ continue
+ }
+
+ // Once we go to 1.18, then embedded types can be anything, but
+ // for now, just interfaces and unions.
if !m.Type.IsInterface() {
- base.ErrorfAt(m.Pos, "interface contains embedded non-interface %v", m.Type)
+ base.ErrorfAt(m.Pos, "interface contains embedded non-interface, non-union %v", m.Type)
m.SetBroke(true)
t.SetBroke(true)
// Add to fields so that error messages
t.Align = uint8(PtrSize)
expandiface(t)
+ case TUNION:
+ // Always part of an interface for now, so size/align don't matter.
+ // Pretend a union is represented like an interface.
+ w = 2 * int64(PtrSize)
+ t.Align = uint8(PtrSize)
+
case TCHAN: // implemented as pointer
w = int64(PtrSize)
TSTRING
TUNSAFEPTR
TTYPEPARAM
+ TUNION
// pseudo-types for literals
TIDEAL // untyped numeric constants
bound *Type
}
+// Union contains Type fields specific to union types.
+type Union struct {
+ terms []*Type
+ tildes []bool // whether terms[i] is of form ~T
+}
+
// Ptr contains Type fields specific to pointer types.
type Ptr struct {
Elem *Type // element type
t.Extra = new(Results)
case TTYPEPARAM:
t.Extra = new(Typeparam)
+ case TUNION:
+ t.Extra = new(Union)
}
return t
}
return t.kind == TINTER
}
+func (t *Type) IsUnion() bool {
+ return t.kind == TUNION
+}
+
// IsEmptyInterface reports whether t is an empty interface type.
func (t *Type) IsEmptyInterface() bool {
return t.IsInterface() && t.AllMethods().Len() == 0
return t.Extra.(*Typeparam).bound
}
+// NewUnion returns a new union with the specified set of terms (types). If
+// tildes[i] is true, then terms[i] represents ~T, rather than just T.
+func NewUnion(terms []*Type, tildes []bool) *Type {
+ t := New(TUNION)
+ if len(terms) != len(tildes) {
+ base.Fatalf("Mismatched terms and tildes for NewUnion")
+ }
+ t.Extra.(*Union).terms = terms
+ t.Extra.(*Union).tildes = tildes
+ return t
+}
+
+// NumTerms returns the number of terms in a union type.
+func (t *Type) NumTerms() int {
+ t.wantEtype(TUNION)
+ return len(t.Extra.(*Union).terms)
+}
+
+// Term returns ith term of a union type as (term, tilde). If tilde is true, term
+// represents ~T, rather than just T.
+func (t *Type) Term(i int) (*Type, bool) {
+ t.wantEtype(TUNION)
+ u := t.Extra.(*Union)
+ return u.terms[i], u.tildes[i]
+}
+
const BOGUS_FUNARG_OFFSET = -1000000000
func unzeroFieldOffsets(f []*Field) {
}
// NewInterfaceType returns a new (incomplete) interface for the given methods and embedded types.
-// Each embedded type must have an underlying type of interface type (this property is not
-// verified for defined types, which may be in the process of being set up and which don't
-// have a valid underlying type yet).
// NewInterfaceType takes ownership of the provided methods and may modify their types by setting
// missing receivers. To compute the method set of the interface, Complete must be called.
func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface {
}
}
- // All embedded types should be interfaces; however, defined types
- // may not yet be fully resolved. Only verify that non-defined types
- // are interfaces. This matches the behavior of the code before the
- // fix for #25301 (issue #25596).
- for _, t := range embeddeds {
- if _, ok := t.(*Named); !ok && !IsInterface(t) {
- panic("embedded type is not an interface")
- }
- }
-
// sort for API stability
sortMethods(methods)
sortTypes(embeddeds)
-// errorcheck
+// errorcheck -lang=go1.17
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
-// errorcheck
+// errorcheck -lang=go1.17
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
--- /dev/null
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type Ordered interface {
+ type int, int64, float64
+}
+
+func Min[T Ordered](x, y T) T {
+ if x < y {
+ return x
+ }
+ return y
+}
--- /dev/null
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "a"
+ "fmt"
+)
+
+func main() {
+ const want = 2
+ if got := a.Min[int](2, 3); got != want {
+ panic(fmt.Sprintf("got %d, want %d", got, want))
+ }
+
+ if got := a.Min(2, 3); got != want {
+ panic(fmt.Sprintf("want %d, got %d", want, got))
+ }
+
+ if got := a.Min[float64](3.5, 2.0); got != want {
+ panic(fmt.Sprintf("got %d, want %d", got, want))
+ }
+
+ if got := a.Min(3.5, 2.0); got != want {
+ panic(fmt.Sprintf("got %d, want %d", got, want))
+ }
+
+ const want2 = "ay"
+ if got := a.Min[string]("bb", "ay"); got != want2 { // ERROR "string does not satisfy interface{int|int64|float64}"
+ panic(fmt.Sprintf("got %d, want %d", got, want2))
+ }
+
+ if got := a.Min("bb", "ay"); got != want2 { // ERROR "string does not satisfy interface{int|int64|float64}"
+ panic(fmt.Sprintf("got %d, want %d", got, want2))
+ }
+}
--- /dev/null
+// errorcheckdir -G=3
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored