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

Comments

Projects
None yet
4 participants
@guangda-hu
Copy link

commented Jan 2, 2018

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

This comment has been minimized.

Copy link
Member

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 label Jan 2, 2018

@odeke-em odeke-em added this to the Go1.11 milestone Jan 2, 2018

@odeke-em

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link
Author

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

This comment has been minimized.

Copy link

commented Jan 13, 2018

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

This comment has been minimized.

Copy link
Member

commented Jan 14, 2018

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

@odeke-em

This comment has been minimized.

Copy link
Member

commented Jan 14, 2018

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

@gopherbot gopherbot closed this in bcb563f Feb 15, 2018

@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.
You can’t perform that action at this time.