// cap(x)
// len(x)
mode := invalid
- var typ Type
var val constant.Value
- switch typ = arrayPtrDeref(under(x.typ)); t := typ.(type) {
+ switch t := arrayPtrDeref(under(x.typ)).(type) {
case *Basic:
if isString(t) && id == _Len {
if x.mode == constant_ {
}
}
- if mode == invalid && typ != Typ[Invalid] {
+ if mode == invalid && under(x.typ) != Typ[Invalid] {
check.errorf(x, invalidArg+"%s for %s", x, bin.name)
return
}
+ // record the signature before changing x.typ
+ if check.Types != nil && mode != constant_ {
+ check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ))
+ }
+
x.mode = mode
x.typ = Typ[Int]
x.val = val
- if check.Types != nil && mode != constant_ {
- check.recordBuiltinType(call.Fun, makeSig(x.typ, typ))
- }
case _Close:
// close(c)
{"cap", `var s [10]int; _ = cap(&s)`, `invalid type`}, // constant
{"cap", `var s []int64; _ = cap(s)`, `func([]int64) int`},
{"cap", `var c chan<-bool; _ = cap(c)`, `func(chan<- bool) int`},
+ {"cap", `type S []byte; var s S; _ = cap(s)`, `func(p.S) int`},
+ {"cap", `var s P; _ = cap(s)`, `func(P) int`},
{"len", `_ = len("foo")`, `invalid type`}, // constant
{"len", `var s string; _ = len(s)`, `func(string) int`},
{"len", `var s []int64; _ = len(s)`, `func([]int64) int`},
{"len", `var c chan<-bool; _ = len(c)`, `func(chan<- bool) int`},
{"len", `var m map[string]float32; _ = len(m)`, `func(map[string]float32) int`},
+ {"len", `type S []byte; var s S; _ = len(s)`, `func(p.S) int`},
+ {"len", `var s P; _ = len(s)`, `func(P) int`},
{"close", `var c chan int; close(c)`, `func(chan int)`},
{"close", `var c chan<- chan string; close(c)`, `func(chan<- chan string)`},
}
func testBuiltinSignature(t *testing.T, name, src0, want string) {
- src := fmt.Sprintf(`package p; import "unsafe"; type _ unsafe.Pointer /* use unsafe */; func _[P any]() { %s }`, src0)
+ src := fmt.Sprintf(`package p; import "unsafe"; type _ unsafe.Pointer /* use unsafe */; func _[P ~[]byte]() { %s }`, src0)
f, err := parseGenericSrc("", src)
if err != nil {
t.Errorf("%s: %s", src0, err)
// cap(x)
// len(x)
mode := invalid
- var typ Type
var val constant.Value
- switch typ = arrayPtrDeref(under(x.typ)); t := typ.(type) {
+ switch t := arrayPtrDeref(under(x.typ)).(type) {
case *Basic:
if isString(t) && id == _Len {
if x.mode == constant_ {
}
}
- if mode == invalid && typ != Typ[Invalid] {
+ if mode == invalid && under(x.typ) != Typ[Invalid] {
code := _InvalidCap
if id == _Len {
code = _InvalidLen
return
}
+ // record the signature before changing x.typ
+ if check.Types != nil && mode != constant_ {
+ check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ))
+ }
+
x.mode = mode
x.typ = Typ[Int]
x.val = val
- if check.Types != nil && mode != constant_ {
- check.recordBuiltinType(call.Fun, makeSig(x.typ, typ))
- }
case _Close:
// close(c)
{"cap", `var s [10]int; _ = cap(&s)`, `invalid type`}, // constant
{"cap", `var s []int64; _ = cap(s)`, `func([]int64) int`},
{"cap", `var c chan<-bool; _ = cap(c)`, `func(chan<- bool) int`},
+ {"cap", `type S []byte; var s S; _ = cap(s)`, `func(p.S) int`},
+ {"cap", `var s P; _ = cap(s)`, `func(P) int`},
{"len", `_ = len("foo")`, `invalid type`}, // constant
{"len", `var s string; _ = len(s)`, `func(string) int`},
{"len", `var s []int64; _ = len(s)`, `func([]int64) int`},
{"len", `var c chan<-bool; _ = len(c)`, `func(chan<- bool) int`},
{"len", `var m map[string]float32; _ = len(m)`, `func(map[string]float32) int`},
+ {"len", `type S []byte; var s S; _ = len(s)`, `func(p.S) int`},
+ {"len", `var s P; _ = len(s)`, `func(P) int`},
{"close", `var c chan int; close(c)`, `func(chan int)`},
{"close", `var c chan<- chan string; close(c)`, `func(chan<- chan string)`},
// parseGenericSrc in types2 is not necessary. We can just parse in testBuiltinSignature below.
func testBuiltinSignature(t *testing.T, name, src0, want string) {
- src := fmt.Sprintf(`package p; import "unsafe"; type _ unsafe.Pointer /* use unsafe */; func _[P any]() { %s }`, src0)
+ src := fmt.Sprintf(`package p; import "unsafe"; type _ unsafe.Pointer /* use unsafe */; func _[P ~[]byte]() { %s }`, src0)
f, err := parser.ParseFile(fset, "", src, 0)
if err != nil {
t.Errorf("%s: %s", src0, err)
//
// Types and Values of each expression:
// 4: 8 | string | type : string
- // 6:15 | len | builtin : func(string) int
+ // 6:15 | len | builtin : func(fib.S) int
// 6:15 | len(b) | value : int
// 6:19 | b | var : fib.S
// 6:23 | S | type : fib.S