go/types, types2: rename structuralType/String to coreType/String

This is a pure rename of the respective Go functions/methods
with corresponding adjustments to error messages and tests.
A couple of comments were manually rephrased.

With this change, the implementation and error messages match
the latest spec.

No functionality change.

Change-Id: Iaa92a08b64756356fb2c5abdaca5c943c9105c96
Reviewed-on: https://go-review.googlesource.com/c/go/+/384618
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Robert Griesemer 2022-02-09 14:16:05 -08:00
parent ea3c546e9e
commit 2bf5ae0c28
39 changed files with 136 additions and 134 deletions

View File

@ -332,13 +332,13 @@ func (g *irgen) exprs(exprs []syntax.Expr) []ir.Node {
} }
func (g *irgen) compLit(typ types2.Type, lit *syntax.CompositeLit) ir.Node { func (g *irgen) compLit(typ types2.Type, lit *syntax.CompositeLit) ir.Node {
if ptr, ok := types2.StructuralType(typ).(*types2.Pointer); ok { if ptr, ok := types2.CoreType(typ).(*types2.Pointer); ok {
n := ir.NewAddrExpr(g.pos(lit), g.compLit(ptr.Elem(), lit)) n := ir.NewAddrExpr(g.pos(lit), g.compLit(ptr.Elem(), lit))
n.SetOp(ir.OPTRLIT) n.SetOp(ir.OPTRLIT)
return typed(g.typ(typ), n) return typed(g.typ(typ), n)
} }
_, isStruct := types2.StructuralType(typ).(*types2.Struct) _, isStruct := types2.CoreType(typ).(*types2.Struct)
exprs := make([]ir.Node, len(lit.ElemList)) exprs := make([]ir.Node, len(lit.ElemList))
for i, elem := range lit.ElemList { for i, elem := range lit.ElemList {

View File

@ -1338,10 +1338,10 @@ func (w *writer) compLit(lit *syntax.CompositeLit) {
w.typ(tv.Type) w.typ(tv.Type)
typ := tv.Type typ := tv.Type
if ptr, ok := types2.StructuralType(typ).(*types2.Pointer); ok { if ptr, ok := types2.CoreType(typ).(*types2.Pointer); ok {
typ = ptr.Elem() typ = ptr.Elem()
} }
str, isStruct := types2.StructuralType(typ).(*types2.Struct) str, isStruct := types2.CoreType(typ).(*types2.Struct)
w.len(len(lit.ElemList)) w.len(len(lit.ElemList))
for i, elem := range lit.ElemList { for i, elem := range lit.ElemList {

View File

@ -82,7 +82,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
// of S and the respective parameter passing rules apply." // of S and the respective parameter passing rules apply."
S := x.typ S := x.typ
var T Type var T Type
if s, _ := structuralType(S).(*Slice); s != nil { if s, _ := coreType(S).(*Slice); s != nil {
T = s.elem T = s.elem
} else { } else {
var cause string var cause string
@ -90,10 +90,10 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
case x.isNil(): case x.isNil():
cause = "have untyped nil" cause = "have untyped nil"
case isTypeParam(S): case isTypeParam(S):
if u := structuralType(S); u != nil { if u := coreType(S); u != nil {
cause = check.sprintf("%s has structural type %s", x, u) cause = check.sprintf("%s has core type %s", x, u)
} else { } else {
cause = check.sprintf("%s has no structural type", x) cause = check.sprintf("%s has no core type", x)
} }
default: default:
cause = check.sprintf("have %s", x) cause = check.sprintf("have %s", x)
@ -115,7 +115,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
if x.mode == invalid { if x.mode == invalid {
return return
} }
if t := structuralString(x.typ); t != nil && isString(t) { if t := coreString(x.typ); t != nil && isString(t) {
if check.Types != nil { if check.Types != nil {
sig := makeSig(S, S, x.typ) sig := makeSig(S, S, x.typ)
sig.variadic = true sig.variadic = true
@ -345,14 +345,14 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
case _Copy: case _Copy:
// copy(x, y []T) int // copy(x, y []T) int
dst, _ := structuralType(x.typ).(*Slice) dst, _ := coreType(x.typ).(*Slice)
var y operand var y operand
arg(&y, 1) arg(&y, 1)
if y.mode == invalid { if y.mode == invalid {
return return
} }
src0 := structuralString(y.typ) src0 := coreString(y.typ)
if src0 != nil && isString(src0) { if src0 != nil && isString(src0) {
src0 = NewSlice(universeByte) src0 = NewSlice(universeByte)
} }
@ -486,13 +486,13 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
} }
var min int // minimum number of arguments var min int // minimum number of arguments
switch structuralType(T).(type) { switch coreType(T).(type) {
case *Slice: case *Slice:
min = 2 min = 2
case *Map, *Chan: case *Map, *Chan:
min = 1 min = 1
case nil: case nil:
check.errorf(arg0, invalidArg+"cannot make %s: no structural type", arg0) check.errorf(arg0, invalidArg+"cannot make %s: no core type", arg0)
return return
default: default:
check.errorf(arg0, invalidArg+"cannot make %s; type must be slice, map, or channel", arg0) check.errorf(arg0, invalidArg+"cannot make %s; type must be slice, map, or channel", arg0)

View File

@ -168,7 +168,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind {
cgocall := x.mode == cgofunc cgocall := x.mode == cgofunc
// a type parameter may be "called" if all types have the same signature // a type parameter may be "called" if all types have the same signature
sig, _ := structuralType(x.typ).(*Signature) sig, _ := coreType(x.typ).(*Signature)
if sig == nil { if sig == nil {
check.errorf(x, invalidOp+"cannot call non-function %s", x) check.errorf(x, invalidOp+"cannot call non-function %s", x)
x.mode = invalid x.mode = invalid

View File

@ -19,12 +19,12 @@ func AsSignature(t Type) *Signature {
return u return u
} }
// If typ is a type parameter, structuralType returns the single underlying // If typ is a type parameter, CoreType returns the single underlying
// type of all types in the corresponding type constraint if it exists, or // type of all types in the corresponding type constraint if it exists, or
// nil otherwise. If the type set contains only unrestricted and restricted // nil otherwise. If the type set contains only unrestricted and restricted
// channel types (with identical element types), the single underlying type // channel types (with identical element types), the single underlying type
// is the restricted channel type if the restrictions are always the same. // is the restricted channel type if the restrictions are always the same.
// If typ is not a type parameter, structuralType returns the underlying type. // If typ is not a type parameter, CoreType returns the underlying type.
func StructuralType(t Type) Type { func CoreType(t Type) Type {
return structuralType(t) return coreType(t)
} }

View File

@ -182,9 +182,9 @@ func (check *Checker) unary(x *operand, e *syntax.Operation) {
return return
case syntax.Recv: case syntax.Recv:
u := structuralType(x.typ) u := coreType(x.typ)
if u == nil { if u == nil {
check.errorf(x, invalidOp+"cannot receive from %s: no structural type", x) check.errorf(x, invalidOp+"cannot receive from %s: no core type", x)
x.mode = invalid x.mode = invalid
return return
} }
@ -1359,7 +1359,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
case hint != nil: case hint != nil:
// no composite literal type present - use hint (element type of enclosing type) // no composite literal type present - use hint (element type of enclosing type)
typ = hint typ = hint
base, _ = deref(structuralType(typ)) // *T implies &T{} base, _ = deref(coreType(typ)) // *T implies &T{}
default: default:
// TODO(gri) provide better error messages depending on context // TODO(gri) provide better error messages depending on context
@ -1367,7 +1367,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
goto Error goto Error
} }
switch utyp := structuralType(base).(type) { switch utyp := coreType(base).(type) {
case *Struct: case *Struct:
// Prevent crash if the struct referred to is not yet set up. // Prevent crash if the struct referred to is not yet set up.
// See analogous comment for *Array. // See analogous comment for *Array.

View File

@ -213,9 +213,9 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) {
valid := false valid := false
length := int64(-1) // valid if >= 0 length := int64(-1) // valid if >= 0
switch u := structuralString(x.typ).(type) { switch u := coreString(x.typ).(type) {
case nil: case nil:
check.errorf(x, invalidOp+"cannot slice %s: %s has no structural type", x, x.typ) check.errorf(x, invalidOp+"cannot slice %s: %s has no core type", x, x.typ)
x.mode = invalid x.mode = invalid
return return

View File

@ -416,11 +416,11 @@ func (check *Checker) inferB(pos syntax.Pos, tparams []*TypeParam, targs []Type)
} }
} }
// If a constraint has a structural type, unify the corresponding type parameter with it. // If a constraint has a core type, unify the corresponding type parameter with it.
for _, tpar := range tparams { for _, tpar := range tparams {
sbound := structuralType(tpar) sbound := coreType(tpar)
if sbound != nil { if sbound != nil {
// If the structural type is the underlying type of a single // If the core type is the underlying type of a single
// defined type in the constraint, use that defined type instead. // defined type in the constraint, use that defined type instead.
if named, _ := tpar.singleType().(*Named); named != nil { if named, _ := tpar.singleType().(*Named); named != nil {
sbound = named sbound = named
@ -435,7 +435,7 @@ func (check *Checker) inferB(pos syntax.Pos, tparams []*TypeParam, targs []Type)
} }
// u.x.types() now contains the incoming type arguments plus any additional type // u.x.types() now contains the incoming type arguments plus any additional type
// arguments which were inferred from structural types. The newly inferred non- // arguments which were inferred from core types. The newly inferred non-
// nil entries may still contain references to other type parameters. // nil entries may still contain references to other type parameters.
// For instance, for [A any, B interface{ []C }, C interface{ *A }], if A == int // For instance, for [A any, B interface{ []C }, C interface{ *A }], if A == int
// was given, unification produced the type list [int, []C, *A]. We eliminate the // was given, unification produced the type list [int, []C, *A]. We eliminate the
@ -504,8 +504,8 @@ func (check *Checker) inferB(pos syntax.Pos, tparams []*TypeParam, targs []Type)
} }
// Once nothing changes anymore, we may still have type parameters left; // Once nothing changes anymore, we may still have type parameters left;
// e.g., a structural constraint *P may match a type parameter Q but we // e.g., a constraint with core type *P may match a type parameter Q but
// don't have any type arguments to fill in for *P or Q (issue #45548). // we don't have any type arguments to fill in for *P or Q (issue #45548).
// Don't let such inferences escape, instead nil them out. // Don't let such inferences escape, instead nil them out.
for i, typ := range types { for i, typ := range types {
if typ != nil && isParameterized(tparams, typ) { if typ != nil && isParameterized(tparams, typ) {

View File

@ -66,12 +66,12 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
obj, index, indirect = lookupFieldOrMethod(T, addressable, pkg, name, false) obj, index, indirect = lookupFieldOrMethod(T, addressable, pkg, name, false)
// If we didn't find anything and if we have a type parameter with a structural constraint, // If we didn't find anything and if we have a type parameter with a core type,
// see if there is a matching field (but not a method, those need to be declared explicitly // see if there is a matching field (but not a method, those need to be declared
// in the constraint). If the structural constraint is a named pointer type (see above), we // explicitly in the constraint). If the constraint is a named pointer type (see
// are ok here because only fields are accepted as results. // above), we are ok here because only fields are accepted as results.
if obj == nil && isTypeParam(T) { if obj == nil && isTypeParam(T) {
if t := structuralType(T); t != nil { if t := coreType(T); t != nil {
obj, index, indirect = lookupFieldOrMethod(t, addressable, pkg, name, false) obj, index, indirect = lookupFieldOrMethod(t, addressable, pkg, name, false)
if _, ok := obj.(*Var); !ok { if _, ok := obj.(*Var); !ok {
obj, index, indirect = nil, nil, false // accept fields (variables) only obj, index, indirect = nil, nil, false // accept fields (variables) only

View File

@ -31,7 +31,7 @@ func isBasic(t Type, info BasicInfo) bool {
// The allX predicates below report whether t is an X. // The allX predicates below report whether t is an X.
// If t is a type parameter the result is true if isX is true // If t is a type parameter the result is true if isX is true
// for all specified types of the type parameter's type set. // for all specified types of the type parameter's type set.
// allX is an optimized version of isX(structuralType(t)) (which // allX is an optimized version of isX(coreType(t)) (which
// is the same as underIs(t, isX)). // is the same as underIs(t, isX)).
func allBoolean(t Type) bool { return allBasic(t, IsBoolean) } func allBoolean(t Type) bool { return allBasic(t, IsBoolean) }
@ -45,7 +45,7 @@ func allNumericOrString(t Type) bool { return allBasic(t, IsNumeric|IsString) }
// allBasic reports whether under(t) is a basic type with the specified info. // allBasic reports whether under(t) is a basic type with the specified info.
// If t is a type parameter, the result is true if isBasic(t, info) is true // If t is a type parameter, the result is true if isBasic(t, info) is true
// for all specific types of the type parameter's type set. // for all specific types of the type parameter's type set.
// allBasic(t, info) is an optimized version of isBasic(structuralType(t), info). // allBasic(t, info) is an optimized version of isBasic(coreType(t), info).
func allBasic(t Type, info BasicInfo) bool { func allBasic(t Type, info BasicInfo) bool {
if tpar, _ := t.(*TypeParam); tpar != nil { if tpar, _ := t.(*TypeParam); tpar != nil {
return tpar.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) }) return tpar.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) })

View File

@ -409,9 +409,9 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
if ch.mode == invalid || val.mode == invalid { if ch.mode == invalid || val.mode == invalid {
return return
} }
u := structuralType(ch.typ) u := coreType(ch.typ)
if u == nil { if u == nil {
check.errorf(s, invalidOp+"cannot send to %s: no structural type", &ch) check.errorf(s, invalidOp+"cannot send to %s: no core type", &ch)
return return
} }
uch, _ := u.(*Chan) uch, _ := u.(*Chan)
@ -835,9 +835,9 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s
// determine key/value types // determine key/value types
var key, val Type var key, val Type
if x.mode != invalid { if x.mode != invalid {
// Ranging over a type parameter is permitted if it has a structural type. // Ranging over a type parameter is permitted if it has a core type.
var cause string var cause string
u := structuralType(x.typ) u := coreType(x.typ)
if t, _ := u.(*Chan); t != nil { if t, _ := u.(*Chan); t != nil {
if sValue != nil { if sValue != nil {
check.softErrorf(sValue, "range over %s permits only one iteration variable", &x) check.softErrorf(sValue, "range over %s permits only one iteration variable", &x)
@ -852,7 +852,7 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s
// ok to continue // ok to continue
} }
if u == nil { if u == nil {
cause = check.sprintf("%s has no structural type", x.typ) cause = check.sprintf("%s has no core type", x.typ)
} }
} }
key, val = rangeKeyVal(u) key, val = rangeKeyVal(u)

View File

@ -148,7 +148,7 @@ func _[
_ = make /* ERROR expects 2 or 3 arguments */ (S1) _ = make /* ERROR expects 2 or 3 arguments */ (S1)
_ = make(S1, 10, 20) _ = make(S1, 10, 20)
_ = make /* ERROR expects 2 or 3 arguments */ (S1, 10, 20, 30) _ = make /* ERROR expects 2 or 3 arguments */ (S1, 10, 20, 30)
_ = make(S2 /* ERROR cannot make S2: no structural type */ , 10) _ = make(S2 /* ERROR cannot make S2: no core type */ , 10)
type M0 map[string]int type M0 map[string]int
_ = make(map[string]int) _ = make(map[string]int)
@ -156,7 +156,7 @@ func _[
_ = make(M1) _ = make(M1)
_ = make(M1, 10) _ = make(M1, 10)
_ = make/* ERROR expects 1 or 2 arguments */(M1, 10, 20) _ = make/* ERROR expects 1 or 2 arguments */(M1, 10, 20)
_ = make(M2 /* ERROR cannot make M2: no structural type */ ) _ = make(M2 /* ERROR cannot make M2: no core type */ )
type C0 chan int type C0 chan int
_ = make(chan int) _ = make(chan int)
@ -164,7 +164,7 @@ func _[
_ = make(C1) _ = make(C1)
_ = make(C1, 10) _ = make(C1, 10)
_ = make/* ERROR expects 1 or 2 arguments */(C1, 10, 20) _ = make/* ERROR expects 1 or 2 arguments */(C1, 10, 20)
_ = make(C2 /* ERROR cannot make C2: no structural type */ ) _ = make(C2 /* ERROR cannot make C2: no core type */ )
_ = make(C3) _ = make(C3)
} }

View File

@ -134,11 +134,11 @@ func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x[i:j:k /* ERROR 3
type myByte1 []byte type myByte1 []byte
type myByte2 []byte type myByte2 []byte
func _[T interface{ []byte | myByte1 | myByte2 }] (x T, i, j, k int) { var _ T = x[i:j:k] } func _[T interface{ []byte | myByte1 | myByte2 }] (x T, i, j, k int) { var _ T = x[i:j:k] }
func _[T interface{ []byte | myByte1 | []int }] (x T, i, j, k int) { var _ T = x[ /* ERROR no structural type */ i:j:k] } func _[T interface{ []byte | myByte1 | []int }] (x T, i, j, k int) { var _ T = x[ /* ERROR no core type */ i:j:k] }
func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x[i:j] } func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x[i:j] }
func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x[i:j:k /* ERROR 3-index slice of string */ ] } func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x[i:j:k /* ERROR 3-index slice of string */ ] }
func _[T interface{ []byte | myByte1 | []int | string }] (x T, i, j, k int) { var _ T = x[ /* ERROR no structural type */ i:j] } func _[T interface{ []byte | myByte1 | []int | string }] (x T, i, j, k int) { var _ T = x[ /* ERROR no core type */ i:j] }
// len/cap built-ins // len/cap built-ins
@ -230,7 +230,7 @@ func _[
for _, _ = range s1 {} for _, _ = range s1 {}
var s2 S2 var s2 S2
for range s2 /* ERROR cannot range over s2.*no structural type */ {} for range s2 /* ERROR cannot range over s2.*no core type */ {}
var a0 []int var a0 []int
for range a0 {} for range a0 {}
@ -243,7 +243,7 @@ func _[
for _, _ = range a1 {} for _, _ = range a1 {}
var a2 A2 var a2 A2
for range a2 /* ERROR cannot range over a2.*no structural type */ {} for range a2 /* ERROR cannot range over a2.*no core type */ {}
var p0 *[10]int var p0 *[10]int
for range p0 {} for range p0 {}
@ -256,7 +256,7 @@ func _[
for _, _ = range p1 {} for _, _ = range p1 {}
var p2 P2 var p2 P2
for range p2 /* ERROR cannot range over p2.*no structural type */ {} for range p2 /* ERROR cannot range over p2.*no core type */ {}
var m0 map[string]int var m0 map[string]int
for range m0 {} for range m0 {}
@ -269,7 +269,7 @@ func _[
for _, _ = range m1 {} for _, _ = range m1 {}
var m2 M2 var m2 M2
for range m2 /* ERROR cannot range over m2.*no structural type */ {} for range m2 /* ERROR cannot range over m2.*no core type */ {}
} }
// type inference checks // type inference checks

View File

@ -113,7 +113,7 @@ func _() {
// from the first one through constraint type inference. // from the first one through constraint type inference.
related3[int]() related3[int]()
// The inferred type is the structural type of the Slice // The inferred type is the core type of the Slice
// type parameter. // type parameter.
var _ []int = related3[int]() var _ []int = related3[int]()

View File

@ -292,7 +292,7 @@ func _[T interface{~int|~float64}]() {
// It is possible to create composite literals of type parameter // It is possible to create composite literals of type parameter
// type as long as it's possible to create a composite literal // type as long as it's possible to create a composite literal
// of the structural type of the type parameter's constraint. // of the core type of the type parameter's constraint.
func _[P interface{ ~[]int }]() P { func _[P interface{ ~[]int }]() P {
return P{} return P{}
return P{1, 2, 3} return P{1, 2, 3}
@ -307,7 +307,7 @@ func _[P interface{ ~[]E }, E interface{ map[string]P } ]() P {
} }
// This is a degenerate case with a singleton type set, but we can create // This is a degenerate case with a singleton type set, but we can create
// composite literals even if the structural type is a defined type. // composite literals even if the core type is a defined type.
type MyInts []int type MyInts []int
func _[P MyInts]() P { func _[P MyInts]() P {

View File

@ -12,7 +12,7 @@ type C4 interface{ chan int | chan<- int }
type C5[T any] interface{ ~chan T | <-chan T } type C5[T any] interface{ ~chan T | <-chan T }
func _[T any](ch T) { func _[T any](ch T) {
<-ch // ERROR cannot receive from ch .* no structural type <-ch // ERROR cannot receive from ch .* no core type
} }
func _[T C0](ch T) { func _[T C0](ch T) {
@ -28,7 +28,7 @@ func _[T C2](ch T) {
} }
func _[T C3](ch T) { func _[T C3](ch T) {
<-ch // ERROR cannot receive from ch .* no structural type <-ch // ERROR cannot receive from ch .* no core type
} }
func _[T C4](ch T) { func _[T C4](ch T) {

View File

@ -12,7 +12,7 @@ type C4 interface{ chan int | chan<- int }
type C5[T any] interface{ ~chan T | chan<- T } type C5[T any] interface{ ~chan T | chan<- T }
func _[T any](ch T) { func _[T any](ch T) {
ch /* ERROR cannot send to ch .* no structural type */ <- 0 ch /* ERROR cannot send to ch .* no core type */ <- 0
} }
func _[T C0](ch T) { func _[T C0](ch T) {
@ -28,7 +28,7 @@ func _[T C2](ch T) {
} }
func _[T C3](ch T) { func _[T C3](ch T) {
ch /* ERROR cannot send to ch .* no structural type */ <- 0 ch /* ERROR cannot send to ch .* no core type */ <- 0
} }
func _[T C4](ch T) { func _[T C4](ch T) {

View File

@ -6,6 +6,6 @@ package p
func _[P1 any, P2 ~byte](s1 P1, s2 P2) { func _[P1 any, P2 ~byte](s1 P1, s2 P2) {
_ = append(nil /* ERROR first argument to append must be a slice; have untyped nil */ , 0) _ = append(nil /* ERROR first argument to append must be a slice; have untyped nil */ , 0)
_ = append(s1 /* ERROR s1 .* has no structural type */ , 0) _ = append(s1 /* ERROR s1 .* has no core type */ , 0)
_ = append(s2 /* ERROR s2 .* has structural type byte */ , 0) _ = append(s2 /* ERROR s2 .* has core type byte */ , 0)
} }

View File

@ -51,7 +51,7 @@ func f2[P interface{ Sfm; m() }](p P) {
var _ = f2[Sfm] var _ = f2[Sfm]
// special case: structural type is a named pointer type // special case: core type is a named pointer type
type PSfm *Sfm type PSfm *Sfm

View File

@ -27,13 +27,13 @@ func under(t Type) Type {
return t.Underlying() return t.Underlying()
} }
// If t is not a type parameter, structuralType returns the underlying type. // If t is not a type parameter, coreType returns the underlying type.
// If t is a type parameter, structuralType returns the single underlying // If t is a type parameter, coreType returns the single underlying
// type of all types in its type set if it exists, or nil otherwise. If the // type of all types in its type set if it exists, or nil otherwise. If the
// type set contains only unrestricted and restricted channel types (with // type set contains only unrestricted and restricted channel types (with
// identical element types), the single underlying type is the restricted // identical element types), the single underlying type is the restricted
// channel type if the restrictions are always the same, or nil otherwise. // channel type if the restrictions are always the same, or nil otherwise.
func structuralType(t Type) Type { func coreType(t Type) Type {
tpar, _ := t.(*TypeParam) tpar, _ := t.(*TypeParam)
if tpar == nil { if tpar == nil {
return under(t) return under(t)
@ -59,10 +59,10 @@ func structuralType(t Type) Type {
return nil return nil
} }
// structuralString is like structuralType but also considers []byte // coreString is like coreType but also considers []byte
// and strings as identical. In this case, if successful and we saw // and strings as identical. In this case, if successful and we saw
// a string, the result is of type (possibly untyped) string. // a string, the result is of type (possibly untyped) string.
func structuralString(t Type) Type { func coreString(t Type) Type {
tpar, _ := t.(*TypeParam) tpar, _ := t.(*TypeParam)
if tpar == nil { if tpar == nil {
return under(t) // string or untyped string return under(t) // string or untyped string

View File

@ -83,7 +83,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
// of S and the respective parameter passing rules apply." // of S and the respective parameter passing rules apply."
S := x.typ S := x.typ
var T Type var T Type
if s, _ := structuralType(S).(*Slice); s != nil { if s, _ := coreType(S).(*Slice); s != nil {
T = s.elem T = s.elem
} else { } else {
var cause string var cause string
@ -91,10 +91,10 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
case x.isNil(): case x.isNil():
cause = "have untyped nil" cause = "have untyped nil"
case isTypeParam(S): case isTypeParam(S):
if u := structuralType(S); u != nil { if u := coreType(S); u != nil {
cause = check.sprintf("%s has structural type %s", x, u) cause = check.sprintf("%s has core type %s", x, u)
} else { } else {
cause = check.sprintf("%s has no structural type", x) cause = check.sprintf("%s has no core type", x)
} }
default: default:
cause = check.sprintf("have %s", x) cause = check.sprintf("have %s", x)
@ -116,7 +116,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
if x.mode == invalid { if x.mode == invalid {
return return
} }
if t := structuralString(x.typ); t != nil && isString(t) { if t := coreString(x.typ); t != nil && isString(t) {
if check.Types != nil { if check.Types != nil {
sig := makeSig(S, S, x.typ) sig := makeSig(S, S, x.typ)
sig.variadic = true sig.variadic = true
@ -350,14 +350,14 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
case _Copy: case _Copy:
// copy(x, y []T) int // copy(x, y []T) int
dst, _ := structuralType(x.typ).(*Slice) dst, _ := coreType(x.typ).(*Slice)
var y operand var y operand
arg(&y, 1) arg(&y, 1)
if y.mode == invalid { if y.mode == invalid {
return return
} }
src0 := structuralString(y.typ) src0 := coreString(y.typ)
if src0 != nil && isString(src0) { if src0 != nil && isString(src0) {
src0 = NewSlice(universeByte) src0 = NewSlice(universeByte)
} }
@ -495,13 +495,13 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
} }
var min int // minimum number of arguments var min int // minimum number of arguments
switch structuralType(T).(type) { switch coreType(T).(type) {
case *Slice: case *Slice:
min = 2 min = 2
case *Map, *Chan: case *Map, *Chan:
min = 1 min = 1
case nil: case nil:
check.errorf(arg0, _InvalidMake, "cannot make %s: no structural type", arg0) check.errorf(arg0, _InvalidMake, "cannot make %s: no core type", arg0)
return return
default: default:
check.invalidArg(arg0, _InvalidMake, "cannot make %s; type must be slice, map, or channel", arg0) check.invalidArg(arg0, _InvalidMake, "cannot make %s; type must be slice, map, or channel", arg0)

View File

@ -171,7 +171,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind {
cgocall := x.mode == cgofunc cgocall := x.mode == cgofunc
// a type parameter may be "called" if all types have the same signature // a type parameter may be "called" if all types have the same signature
sig, _ := structuralType(x.typ).(*Signature) sig, _ := coreType(x.typ).(*Signature)
if sig == nil { if sig == nil {
check.invalidOp(x, _InvalidCall, "cannot call non-function %s", x) check.invalidOp(x, _InvalidCall, "cannot call non-function %s", x)
x.mode = invalid x.mode = invalid

View File

@ -173,9 +173,9 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr) {
return return
case token.ARROW: case token.ARROW:
u := structuralType(x.typ) u := coreType(x.typ)
if u == nil { if u == nil {
check.invalidOp(x, _InvalidReceive, "cannot receive from %s: no structural type", x) check.invalidOp(x, _InvalidReceive, "cannot receive from %s: no core type", x)
x.mode = invalid x.mode = invalid
return return
} }
@ -1338,7 +1338,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
case hint != nil: case hint != nil:
// no composite literal type present - use hint (element type of enclosing type) // no composite literal type present - use hint (element type of enclosing type)
typ = hint typ = hint
base, _ = deref(structuralType(typ)) // *T implies &T{} base, _ = deref(coreType(typ)) // *T implies &T{}
default: default:
// TODO(gri) provide better error messages depending on context // TODO(gri) provide better error messages depending on context
@ -1346,7 +1346,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
goto Error goto Error
} }
switch utyp := structuralType(base).(type) { switch utyp := coreType(base).(type) {
case *Struct: case *Struct:
// Prevent crash if the struct referred to is not yet set up. // Prevent crash if the struct referred to is not yet set up.
// See analogous comment for *Array. // See analogous comment for *Array.

View File

@ -214,9 +214,9 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) {
valid := false valid := false
length := int64(-1) // valid if >= 0 length := int64(-1) // valid if >= 0
switch u := structuralString(x.typ).(type) { switch u := coreString(x.typ).(type) {
case nil: case nil:
check.invalidOp(x, _NonSliceableOperand, "cannot slice %s: %s has no structural type", x, x.typ) check.invalidOp(x, _NonSliceableOperand, "cannot slice %s: %s has no core type", x, x.typ)
x.mode = invalid x.mode = invalid
return return

View File

@ -415,11 +415,11 @@ func (check *Checker) inferB(posn positioner, tparams []*TypeParam, targs []Type
} }
} }
// If a constraint has a structural type, unify the corresponding type parameter with it. // If a constraint has a core type, unify the corresponding type parameter with it.
for _, tpar := range tparams { for _, tpar := range tparams {
sbound := structuralType(tpar) sbound := coreType(tpar)
if sbound != nil { if sbound != nil {
// If the structural type is the underlying type of a single // If the core type is the underlying type of a single
// defined type in the constraint, use that defined type instead. // defined type in the constraint, use that defined type instead.
if named, _ := tpar.singleType().(*Named); named != nil { if named, _ := tpar.singleType().(*Named); named != nil {
sbound = named sbound = named
@ -434,7 +434,7 @@ func (check *Checker) inferB(posn positioner, tparams []*TypeParam, targs []Type
} }
// u.x.types() now contains the incoming type arguments plus any additional type // u.x.types() now contains the incoming type arguments plus any additional type
// arguments which were inferred from structural types. The newly inferred non- // arguments which were inferred from core types. The newly inferred non-
// nil entries may still contain references to other type parameters. // nil entries may still contain references to other type parameters.
// For instance, for [A any, B interface{ []C }, C interface{ *A }], if A == int // For instance, for [A any, B interface{ []C }, C interface{ *A }], if A == int
// was given, unification produced the type list [int, []C, *A]. We eliminate the // was given, unification produced the type list [int, []C, *A]. We eliminate the
@ -503,8 +503,8 @@ func (check *Checker) inferB(posn positioner, tparams []*TypeParam, targs []Type
} }
// Once nothing changes anymore, we may still have type parameters left; // Once nothing changes anymore, we may still have type parameters left;
// e.g., a structural constraint *P may match a type parameter Q but we // e.g., a constraint with core type *P may match a type parameter Q but
// don't have any type arguments to fill in for *P or Q (issue #45548). // we don't have any type arguments to fill in for *P or Q (issue #45548).
// Don't let such inferences escape, instead nil them out. // Don't let such inferences escape, instead nil them out.
for i, typ := range types { for i, typ := range types {
if typ != nil && isParameterized(tparams, typ) { if typ != nil && isParameterized(tparams, typ) {

View File

@ -66,12 +66,12 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
obj, index, indirect = lookupFieldOrMethod(T, addressable, pkg, name, false) obj, index, indirect = lookupFieldOrMethod(T, addressable, pkg, name, false)
// If we didn't find anything and if we have a type parameter with a structural constraint, // If we didn't find anything and if we have a type parameter with a core type,
// see if there is a matching field (but not a method, those need to be declared explicitly // see if there is a matching field (but not a method, those need to be declared
// in the constraint). If the structural constraint is a named pointer type (see above), we // explicitly in the constraint). If the constraint is a named pointer type (see
// are ok here because only fields are accepted as results. // above), we are ok here because only fields are accepted as results.
if obj == nil && isTypeParam(T) { if obj == nil && isTypeParam(T) {
if t := structuralType(T); t != nil { if t := coreType(T); t != nil {
obj, index, indirect = lookupFieldOrMethod(t, addressable, pkg, name, false) obj, index, indirect = lookupFieldOrMethod(t, addressable, pkg, name, false)
if _, ok := obj.(*Var); !ok { if _, ok := obj.(*Var); !ok {
obj, index, indirect = nil, nil, false // accept fields (variables) only obj, index, indirect = nil, nil, false // accept fields (variables) only

View File

@ -33,7 +33,7 @@ func isBasic(t Type, info BasicInfo) bool {
// The allX predicates below report whether t is an X. // The allX predicates below report whether t is an X.
// If t is a type parameter the result is true if isX is true // If t is a type parameter the result is true if isX is true
// for all specified types of the type parameter's type set. // for all specified types of the type parameter's type set.
// allX is an optimized version of isX(structuralType(t)) (which // allX is an optimized version of isX(coreType(t)) (which
// is the same as underIs(t, isX)). // is the same as underIs(t, isX)).
func allBoolean(typ Type) bool { return allBasic(typ, IsBoolean) } func allBoolean(typ Type) bool { return allBasic(typ, IsBoolean) }
@ -47,7 +47,7 @@ func allNumericOrString(typ Type) bool { return allBasic(typ, IsNumeric|IsString
// allBasic reports whether under(t) is a basic type with the specified info. // allBasic reports whether under(t) is a basic type with the specified info.
// If t is a type parameter, the result is true if isBasic(t, info) is true // If t is a type parameter, the result is true if isBasic(t, info) is true
// for all specific types of the type parameter's type set. // for all specific types of the type parameter's type set.
// allBasic(t, info) is an optimized version of isBasic(structuralType(t), info). // allBasic(t, info) is an optimized version of isBasic(coreType(t), info).
func allBasic(t Type, info BasicInfo) bool { func allBasic(t Type, info BasicInfo) bool {
if tpar, _ := t.(*TypeParam); tpar != nil { if tpar, _ := t.(*TypeParam); tpar != nil {
return tpar.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) }) return tpar.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) })

View File

@ -418,9 +418,9 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
if ch.mode == invalid || val.mode == invalid { if ch.mode == invalid || val.mode == invalid {
return return
} }
u := structuralType(ch.typ) u := coreType(ch.typ)
if u == nil { if u == nil {
check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to %s: no structural type", &ch) check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to %s: no core type", &ch)
return return
} }
uch, _ := u.(*Chan) uch, _ := u.(*Chan)
@ -831,12 +831,12 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
// determine key/value types // determine key/value types
var key, val Type var key, val Type
if x.mode != invalid { if x.mode != invalid {
// Ranging over a type parameter is permitted if it has a structural type. // Ranging over a type parameter is permitted if it has a core type.
var cause string var cause string
u := structuralType(x.typ) u := coreType(x.typ)
switch t := u.(type) { switch t := u.(type) {
case nil: case nil:
cause = check.sprintf("%s has no structural type", x.typ) cause = check.sprintf("%s has no core type", x.typ)
case *Chan: case *Chan:
if s.Value != nil { if s.Value != nil {
check.softErrorf(s.Value, _InvalidIterVar, "range over %s permits only one iteration variable", &x) check.softErrorf(s.Value, _InvalidIterVar, "range over %s permits only one iteration variable", &x)

View File

@ -148,7 +148,7 @@ func _[
_ = make /* ERROR expects 2 or 3 arguments */ (S1) _ = make /* ERROR expects 2 or 3 arguments */ (S1)
_ = make(S1, 10, 20) _ = make(S1, 10, 20)
_ = make /* ERROR expects 2 or 3 arguments */ (S1, 10, 20, 30) _ = make /* ERROR expects 2 or 3 arguments */ (S1, 10, 20, 30)
_ = make(S2 /* ERROR cannot make S2: no structural type */ , 10) _ = make(S2 /* ERROR cannot make S2: no core type */ , 10)
type M0 map[string]int type M0 map[string]int
_ = make(map[string]int) _ = make(map[string]int)
@ -156,7 +156,7 @@ func _[
_ = make(M1) _ = make(M1)
_ = make(M1, 10) _ = make(M1, 10)
_ = make/* ERROR expects 1 or 2 arguments */(M1, 10, 20) _ = make/* ERROR expects 1 or 2 arguments */(M1, 10, 20)
_ = make(M2 /* ERROR cannot make M2: no structural type */ ) _ = make(M2 /* ERROR cannot make M2: no core type */ )
type C0 chan int type C0 chan int
_ = make(chan int) _ = make(chan int)
@ -164,7 +164,7 @@ func _[
_ = make(C1) _ = make(C1)
_ = make(C1, 10) _ = make(C1, 10)
_ = make/* ERROR expects 1 or 2 arguments */(C1, 10, 20) _ = make/* ERROR expects 1 or 2 arguments */(C1, 10, 20)
_ = make(C2 /* ERROR cannot make C2: no structural type */ ) _ = make(C2 /* ERROR cannot make C2: no core type */ )
_ = make(C3) _ = make(C3)
} }

View File

@ -134,11 +134,11 @@ func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x[i:j:k /* ERROR 3
type myByte1 []byte type myByte1 []byte
type myByte2 []byte type myByte2 []byte
func _[T interface{ []byte | myByte1 | myByte2 }] (x T, i, j, k int) { var _ T = x[i:j:k] } func _[T interface{ []byte | myByte1 | myByte2 }] (x T, i, j, k int) { var _ T = x[i:j:k] }
func _[T interface{ []byte | myByte1 | []int }] (x T, i, j, k int) { var _ T = x /* ERROR no structural type */ [i:j:k] } func _[T interface{ []byte | myByte1 | []int }] (x T, i, j, k int) { var _ T = x /* ERROR no core type */ [i:j:k] }
func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x[i:j] } func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x[i:j] }
func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x[i:j:k /* ERROR 3-index slice of string */ ] } func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x[i:j:k /* ERROR 3-index slice of string */ ] }
func _[T interface{ []byte | myByte1 | []int | string }] (x T, i, j, k int) { var _ T = x /* ERROR no structural type */ [i:j] } func _[T interface{ []byte | myByte1 | []int | string }] (x T, i, j, k int) { var _ T = x /* ERROR no core type */ [i:j] }
// len/cap built-ins // len/cap built-ins
@ -230,7 +230,7 @@ func _[
for _, _ = range s1 {} for _, _ = range s1 {}
var s2 S2 var s2 S2
for range s2 /* ERROR cannot range over s2.*no structural type */ {} for range s2 /* ERROR cannot range over s2.*no core type */ {}
var a0 []int var a0 []int
for range a0 {} for range a0 {}
@ -243,7 +243,7 @@ func _[
for _, _ = range a1 {} for _, _ = range a1 {}
var a2 A2 var a2 A2
for range a2 /* ERROR cannot range over a2.*no structural type */ {} for range a2 /* ERROR cannot range over a2.*no core type */ {}
var p0 *[10]int var p0 *[10]int
for range p0 {} for range p0 {}
@ -256,7 +256,7 @@ func _[
for _, _ = range p1 {} for _, _ = range p1 {}
var p2 P2 var p2 P2
for range p2 /* ERROR cannot range over p2.*no structural type */ {} for range p2 /* ERROR cannot range over p2.*no core type */ {}
var m0 map[string]int var m0 map[string]int
for range m0 {} for range m0 {}
@ -269,7 +269,7 @@ func _[
for _, _ = range m1 {} for _, _ = range m1 {}
var m2 M2 var m2 M2
for range m2 /* ERROR cannot range over m2.*no structural type */ {} for range m2 /* ERROR cannot range over m2.*no core type */ {}
} }
// type inference checks // type inference checks

View File

@ -113,7 +113,7 @@ func _() {
// from the first one through constraint type inference. // from the first one through constraint type inference.
related3[int]() related3[int]()
// The inferred type is the structural type of the Slice // The inferred type is the core type of the Slice
// type parameter. // type parameter.
var _ []int = related3[int]() var _ []int = related3[int]()

View File

@ -298,7 +298,7 @@ func _[T interface {~int|~float64}]() {
// It is possible to create composite literals of type parameter // It is possible to create composite literals of type parameter
// type as long as it's possible to create a composite literal // type as long as it's possible to create a composite literal
// of the structural type of the type parameter's constraint. // of the core type of the type parameter's constraint.
func _[P interface{ ~[]int }]() P { func _[P interface{ ~[]int }]() P {
return P{} return P{}
return P{1, 2, 3} return P{1, 2, 3}
@ -313,7 +313,7 @@ func _[P interface{ ~[]E }, E interface{ map[string]P } ]() P {
} }
// This is a degenerate case with a singleton type set, but we can create // This is a degenerate case with a singleton type set, but we can create
// composite literals even if the structural type is a defined type. // composite literals even if the core type is a defined type.
type MyInts []int type MyInts []int
func _[P MyInts]() P { func _[P MyInts]() P {

View File

@ -12,7 +12,7 @@ type C4 interface{ chan int | chan<- int }
type C5[T any] interface{ ~chan T | <-chan T } type C5[T any] interface{ ~chan T | <-chan T }
func _[T any](ch T) { func _[T any](ch T) {
<-ch // ERROR cannot receive from ch .* no structural type <-ch // ERROR cannot receive from ch .* no core type
} }
func _[T C0](ch T) { func _[T C0](ch T) {
@ -28,7 +28,7 @@ func _[T C2](ch T) {
} }
func _[T C3](ch T) { func _[T C3](ch T) {
<-ch // ERROR cannot receive from ch .* no structural type <-ch // ERROR cannot receive from ch .* no core type
} }
func _[T C4](ch T) { func _[T C4](ch T) {

View File

@ -12,7 +12,7 @@ type C4 interface{ chan int | chan<- int }
type C5[T any] interface{ ~chan T | chan<- T } type C5[T any] interface{ ~chan T | chan<- T }
func _[T any](ch T) { func _[T any](ch T) {
ch <- /* ERROR cannot send to ch .* no structural type */ 0 ch <- /* ERROR cannot send to ch .* no core type */ 0
} }
func _[T C0](ch T) { func _[T C0](ch T) {
@ -28,7 +28,7 @@ func _[T C2](ch T) {
} }
func _[T C3](ch T) { func _[T C3](ch T) {
ch <- /* ERROR cannot send to ch .* no structural type */ 0 ch <- /* ERROR cannot send to ch .* no core type */ 0
} }
func _[T C4](ch T) { func _[T C4](ch T) {

View File

@ -6,6 +6,6 @@ package p
func _[P1 any, P2 ~byte](s1 P1, s2 P2) { func _[P1 any, P2 ~byte](s1 P1, s2 P2) {
_ = append(nil /* ERROR first argument to append must be a slice; have untyped nil */ , 0) _ = append(nil /* ERROR first argument to append must be a slice; have untyped nil */ , 0)
_ = append(s1 /* ERROR s1 .* has no structural type */ , 0) _ = append(s1 /* ERROR s1 .* has no core type */ , 0)
_ = append(s2 /* ERROR s2 .* has structural type byte */ , 0) _ = append(s2 /* ERROR s2 .* has core type byte */ , 0)
} }

View File

@ -51,7 +51,7 @@ func f2[P interface{ Sfm; m() }](p P) {
var _ = f2[Sfm] var _ = f2[Sfm]
// special case: structural type is a named pointer type // special case: core type is a named pointer type
type PSfm *Sfm type PSfm *Sfm

View File

@ -27,13 +27,13 @@ func under(t Type) Type {
return t.Underlying() return t.Underlying()
} }
// If t is not a type parameter, structuralType returns the underlying type. // If t is not a type parameter, coreType returns the underlying type.
// If t is a type parameter, structuralType returns the single underlying // If t is a type parameter, coreType returns the single underlying
// type of all types in its type set if it exists, or nil otherwise. If the // type of all types in its type set if it exists, or nil otherwise. If the
// type set contains only unrestricted and restricted channel types (with // type set contains only unrestricted and restricted channel types (with
// identical element types), the single underlying type is the restricted // identical element types), the single underlying type is the restricted
// channel type if the restrictions are always the same, or nil otherwise. // channel type if the restrictions are always the same, or nil otherwise.
func structuralType(t Type) Type { func coreType(t Type) Type {
tpar, _ := t.(*TypeParam) tpar, _ := t.(*TypeParam)
if tpar == nil { if tpar == nil {
return under(t) return under(t)
@ -59,10 +59,10 @@ func structuralType(t Type) Type {
return nil return nil
} }
// structuralString is like structuralType but also considers []byte // coreString is like coreType but also considers []byte
// and strings as identical. In this case, if successful and we saw // and strings as identical. In this case, if successful and we saw
// a string, the result is of type (possibly untyped) string. // a string, the result is of type (possibly untyped) string.
func structuralString(t Type) Type { func coreString(t Type) Type {
tpar, _ := t.(*TypeParam) tpar, _ := t.(*TypeParam)
if tpar == nil { if tpar == nil {
return under(t) // string or untyped string return under(t) // string or untyped string

View File

@ -57,7 +57,7 @@ func f2[P interface {
var _ = f2[Sfm] var _ = f2[Sfm]
// special case: structural type is a named pointer type // special case: core type is a named pointer type
type PSfm *Sfm type PSfm *Sfm
@ -68,7 +68,7 @@ func f3[P interface{ PSfm }](p P) {
var _ = f3[PSfm] var _ = f3[PSfm]
// special case: structural type is an unnamed pointer type // special case: core type is an unnamed pointer type
func f4[P interface{ *Sfm }](p P) { func f4[P interface{ *Sfm }](p P) {
_ = p.f _ = p.f

View File

@ -4,7 +4,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// This file tests type lists & structural constraints. // This file tests type lists & constraints with core types.
// Note: This test has been adjusted to use the new // Note: This test has been adjusted to use the new
// type set notation rather than type lists. // type set notation rather than type lists.
@ -30,28 +30,28 @@ func _[T interface{ ~int }](x T) {
var _ T = 42 var _ T = 42
var _ T = T(myint(42)) var _ T = T(myint(42))
} }
// TODO: put this type declaration back inside the above function when issue 47631 is fixed. // TODO: put this type declaration back inside the above function when issue 47631 is fixed.
type myint int type myint int
// Indexing a generic type which has a structural contraints to be an array. // Indexing a generic type which has a an array as core type.
func _[T interface{ ~[10]int }](x T) { func _[T interface{ ~[10]int }](x T) {
_ = x[9] // ok _ = x[9] // ok
} }
// Dereference of a generic type which has a structural contraint to be a pointer. // Dereference of a generic type which has a pointer as core type.
func _[T interface{ ~*int }](p T) int { func _[T interface{ ~*int }](p T) int {
return *p return *p
} }
// Channel send and receive on a generic type which has a structural constraint to // Channel send and receive on a generic type which has a channel as core type.
// be a channel.
func _[T interface{ ~chan int }](ch T) int { func _[T interface{ ~chan int }](ch T) int {
// This would deadlock if executed (but ok for a compile test) // This would deadlock if executed (but ok for a compile test)
ch <- 0 ch <- 0
return <-ch return <-ch
} }
// Calling of a generic type which has a structural constraint to be a function. // Calling of a generic type which has a function as core type.
func _[T interface{ ~func() }](f T) { func _[T interface{ ~func() }](f T) {
f() f()
go f() go f()
@ -62,7 +62,7 @@ func _[T interface{ ~func(string) int }](f T) int {
return f("hello") return f("hello")
} }
// Map access of a generic type which has a structural constraint to be a map. // Map access of a generic type which has a map as core type.
func _[V any, T interface{ ~map[string]V }](p T) V { func _[V any, T interface{ ~map[string]V }](p T) V {
return p["test"] return p["test"]
} }
@ -122,7 +122,9 @@ func f5[A interface {
b B b B
c C c C
} }
}, B any, C interface{ ~*B }](x B) A { panic(0) } }, B any, C interface{ ~*B }](x B) A {
panic(0)
}
func f5x() { func f5x() {
x := f5(1.2) x := f5(1.2)
var _ float64 = x.b var _ float64 = x.b