Skip to content

spec: Some issues with https://golang.org/ref/spec#Conversions #23297

@guangda-hu

Description

@guangda-hu

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?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions