go: go/types: incorrect behavior for string conversions of byte slices

What version of Go are you using (go version)?

go version go1.9.2 linux/amd64

Does this issue reproduce with the latest release?

yes

What did you do?

It looks the definitions for slice of bytes are not consistent between spec and the builtin docs.

In spec

A non-constant value x can be converted to type T in any of these cases: 
...
* x is a string and T is a slice of bytes or runes. 

In he builtin docs

The copy built-in function .... 
(As a special case, it also will copy bytes from a string to a slice of bytes.)

However:

package main

type T byte

func main() {
	var x []T
	str := "abc"
	x = []T(str) // okay
	copy(x, str) // arguments to copy have different element types: []T and string
	_ = append(x, str...) // cannot use <node SPTR> (type *uint8) as type *T in argument to runtime.memmove
}

[edit] It looks []T is treated as a slice of bytes in x = []T(str), but not in the copy and append calls.

What did you expect to see?

all fail to compile or all compile okay.

What did you see instead?

non-consistent behavior

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 27 (18 by maintainers)

Commits related to this issue

Most upvoted comments

@griesemer Yeah, I added some notes/comments about this issue just a few weeks ago at https://github.com/golang/go/issues/23814#issuecomment-536082226.

TL;DR: I think we should be liberal in interpreting “slice of bytes” and “slice of runes” to mean any slice type whose element type has underlying type byte or rune (respectively).

More cases:

	x1 := []byte("foo")
	_ = string(x1)

	type T byte
	x2 := []T("foo")
	_ = string(x2)

	type S1 []byte
	x3 := S1("foo")
	_ = string(x3)

	type S2 []T
	x4 := S2("foo")
	_ = string(x4)

go/types accepts all of them. gc complains twice:

x.go:9:12: cannot use x2 (type []T) as type []byte in argument to runtime.slicebytetostring
x.go:17:12: cannot use x4 (type S2) as type []byte in argument to runtime.slicebytetostring

It looks to me that the spec is pretty clear with specific examples (https://tip.golang.org/ref/spec#Conversions). It does appear that gc is correct: A “slice of bytes” means any type whose underlying type is []byte in this case. go/types on the other hand accepts any slice type where the slice element type’s underlying type is a byte, which seems incorrect according to the spec. (Whether the spec rule is too tight is a different question).