-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Description
I noticed some issues with the "Conversions" section in the official spec (https://golang.org/ref/spec#Conversions, Version of June 28, 2017):
1. Conversions between pointers
The spec says:
A non-constant value x can be converted to type T in any of these cases:
...
- ignoring struct tags (see below), x's type and T are pointer types that are not defined types, and their pointer base types have identical underlying types.
...
However, it seems conversion is also allowed for defined types (i.e. the clause "that are not defined types" seems unnecessary):
type MyPointer1 *struct{}
type MyPointer2 *struct{}
var p1 MyPointer1
var p2 MyPointer2
p2 = MyPointer2(p1)
This is valid on the playground: https://play.golang.org/p/fSrWN-bB3Zr
2. Conversion between string and slice of runes
In the same paragraph:
A non-constant value x can be converted to type T in any of these cases:
...
- x is an integer or a slice of bytes or runes and T is a string type.
- x is a string and T is a slice of bytes or runes.
Based on the following examples provided in the spec, it seems the phrases "string", "slice of bytes", "slice of runes" include defined types as well as the plane "string", "[]byte", "[]rune" types:
// Examples provided in the same section of the spec:
type MyString string
MyString(0x65e5) // "\u65e5" == "日" == "\xe6\x97\xa5"
type MyBytes []byte
string(MyBytes{'h', 'e', 'l', 'l', '\xc3', '\xb8'}) // "hellø"
type MyRunes []rune
string(MyRunes{0x767d, 0x9d6c, 0x7fd4}) // "\u767d\u9d6c\u7fd4" == "白鵬翔"
MyBytes("hellø") // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}
[]rune(MyString("白鵬翔")) // []rune{0x767d, 0x9d6c, 0x7fd4}
MyRunes("白鵬翔") // []rune{0x767d, 0x9d6c, 0x7fd4}
However, at least for the complier used by the playground, the MyString->[]rune conversion does not work for non-constant:
[]rune(MyString("白鵬翔")) // legal, example provided by spec
a := MyString("sss")
b := []rune(a) // compile error: cannot use a (type MyString) as type string in argument to runtime.stringtoslicerune
See https://play.golang.org/p/gunMmHAxytT. There is no such problem with constant, []byte, or the other converting direction.
Ambiguity of "type"
As a side-note, I think when the spec mentions a type, it usually (if not always) means the "underlying type" instead of the type identity. For example, there are phrases like "struct type", "slice type" everywhere (composite literals, operators, len, cap etc work for values of user defined types as well as values of the plane type literals), and "string", "slice of bytes", "slice of runes" mentioned above.
However, I don't seem to see this is clearly stated in the spec. Perhaps I'm missing something. In fact, the ambiguity of "type" is what made me dig into the language spec.
3. Which conversions involve "representation change"
The last sentence in the following paragraph is suspicious:
Specific rules apply to (non-constant) conversions between numeric types or to and from a string type. These conversions may change the representation of x and incur a run-time cost. All other conversions only change the type but not the representation of x.
Does "all other conversions" include floating point conversions? When a round happens, doesn't the representation change as well?