Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/compile: converting to slice of runes fails, from defined type derived from string of non-const instance when inside a function #23298

Closed
guangda-hu opened this issue Jan 2, 2018 · 6 comments
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@guangda-hu
Copy link

This is the second item in #23297.

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

go version go1.9.2 linux/amd64
and the compiler used by the Go playground

What did you do?

The string->[]rune conversion does not work for non-constant user defined string type:

type MyString string
[]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 seems no such problem with constant, []byte, or the other converting direction.

What did you expect to see?

I think this should compile. From https://golang.org/ref/spec#Conversions, Version of June 28, 2017:

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}

What did you see instead?

Compile error:
cannot use a (type MyString) as type string in argument to runtime.stringtoslicerune

@odeke-em odeke-em changed the title cmd/compile: Converting string to slice of runes cmd/compile: converting defined type derived from string to slice of runes fails Jan 2, 2018
@odeke-em
Copy link
Member

odeke-em commented Jan 2, 2018

Nice catch, thank you for reporting this @guangda-hu! As @ianlancetaylor reported in that issue, that code works alright with gccgo.

/cc @griesemer @mdempsky.

@odeke-em odeke-em changed the title cmd/compile: converting defined type derived from string to slice of runes fails cmd/compile: converting to slice of runes fails, from defined type derived from string Jan 2, 2018
@odeke-em odeke-em added the NeedsFix The path to resolution is known, but the work has not been done. label Jan 2, 2018
@odeke-em odeke-em added this to the Go1.11 milestone Jan 2, 2018
@odeke-em
Copy link
Member

odeke-em commented Jan 2, 2018

Okay now an interesting permutation of this bug passes when the example is NOT in a function i.e

Passing 1

package p
type T string
var _ = []rune(T("T"))

Passing 2

package p
type T string
var t = T("T")
var _ = []rune(t)

Passing 3 based off Passing 1

package p
type T string
func foo() {
	var _ = []rune(T("T"))
}

Failing 1 based off Passing 2, but in function

package p
type T string
func foo() {
        var t = T("T") 
        var _ = []rune(t)
}
$ go tool compile fail.go 
fail.go:7:16: cannot use t (type T) as type string in argument to runtime.stringtoslicerune

@odeke-em odeke-em changed the title cmd/compile: converting to slice of runes fails, from defined type derived from string cmd/compile: converting to slice of runes fails, from defined type derived from string when inside a function Jan 2, 2018
@guangda-hu
Copy link
Author

guangda-hu commented Jan 2, 2018

My guess was that the problem is only with non-constant (I actually briefly mentioned this at the end of "What did you do?", and the example []rune(MyString("白鵬翔")) provided by the spec works).
In your failing example, it would pass if you change var t to const t.

Edit: Nevermind. Your second example shows it's actually related to whether it's inside a function.

Edit again: Your second example will fail if you don't use '_': https://play.golang.org/p/h4ZAslGQ8eN
Probably the var declaration is just ignored if you use the blank identifier. I don't know.

@odeke-em odeke-em changed the title cmd/compile: converting to slice of runes fails, from defined type derived from string when inside a function cmd/compile: converting to slice of runes fails, from defined type derived from string of non-const instance when inside a function Jan 2, 2018
@gopherbot
Copy link

Change https://golang.org/cl/87695 mentions this issue: cmd/compile: make slice of runes accept to be converted from defined type derived from string

@namusyaka
Copy link
Member

@guangda-hu @odeke-em I've tried to fix the issue. Could you take a look at the CL?

@odeke-em
Copy link
Member

Thank you @namusyaka and Happy New Year! It'll be for Go1.11 :)

@golang golang locked and limited conversation to collaborators Feb 15, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

4 participants