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

encoding/json: panic: reflect.Set: value of type []uint8 is not assignable to type []main.Uint8 #12921

Closed
kshvakov opened this issue Oct 13, 2015 · 10 comments
Milestone

Comments

@kshvakov
Copy link

go version go1.5 darwin/amd64
go version go1.5.1 linux/amd64

package main

import (
    "encoding/json"
)

type Uint8 uint8

func main() {

    var sliceIn, sliceOut []Uint8

    for i := 0; i < 20; i++ {

        sliceIn = append(sliceIn, Uint8(i))
    }

    j, _ := json.Marshal(sliceIn)

    json.Unmarshal(j, &sliceOut)
}

output

panic: reflect.Set: value of type []uint8 is not assignable to type []main.Uint8 [recovered]
    panic: interface conversion: string is not error: missing method Error

goroutine 1 [running]:
encoding/json.(*decodeState).unmarshal.func1(0x820275e40)
    /usr/local/go/src/encoding/json/decode.go:145 +0xba
reflect.Value.assignTo(0xdf2c0, 0x8202ae0c0, 0x57, 0x13d0e0, 0xb, 0xde2a0, 0x0, 0x0, 0x0, 0x0)
    /usr/local/go/src/reflect/value.go:2158 +0x3be
reflect.Value.Set(0xde2a0, 0x8202ae000, 0xd7, 0xdf2c0, 0x8202ae0c0, 0x57)
    /usr/local/go/src/reflect/value.go:1327 +0x95
encoding/json.(*decodeState).literalStore(0x8202ba000, 0x8202b0024, 0x1e, 0x40, 0xde2a0, 0x8202ae000, 0xd7, 0x0)
    /usr/local/go/src/encoding/json/decode.go:760 +0x14ee
encoding/json.(*decodeState).literal(0x8202ba000, 0xd81e0, 0x8202ae000, 0x16)
    /usr/local/go/src/encoding/json/decode.go:646 +0xe9
encoding/json.(*decodeState).value(0x8202ba000, 0xd81e0, 0x8202ae000, 0x16)
    /usr/local/go/src/encoding/json/decode.go:299 +0x397
encoding/json.(*decodeState).unmarshal(0x8202ba000, 0xd81e0, 0x8202ae000, 0x0, 0x0)
    /usr/local/go/src/encoding/json/decode.go:157 +0x196
encoding/json.Unmarshal(0x8202b0024, 0x1e, 0x40, 0xd81e0, 0x8202ae000, 0x0, 0x0)
    /usr/local/go/src/encoding/json/decode.go:85 +0x12b
main.main()
    /Users/kshvakov/unmarshal_bug.go:20 +0x168
exit status 2

http://play.golang.org/p/ZFlbNkI0H3

@kshvakov kshvakov changed the title encoding/json: reflect.Set: value of type []uint8 is not assignable to type []main.Uint8 encoding/json: panic: reflect.Set: value of type []uint8 is not assignable to type []main.Uint8 Oct 13, 2015
@ianlancetaylor ianlancetaylor added this to the Go1.6 milestone Oct 13, 2015
@freeformz
Copy link

FWIW: This worked on go 1.4.2

@adg
Copy link
Contributor

adg commented Oct 13, 2015

Confirmed that it works under Go 1.4, so this is a regression.

Not sure what to do about this, though, because you according to the language spec you can't assign []T to []S, even if T and S have the same underlying type. The reflect package is supposed to enforce the language spec.

cc @rsc @ianlancetaylor @griesemer

@kshvakov
Copy link
Author

@adg this problem only occurs with type uint8

https://golang.org/src/encoding/json/decode.go?s=#L749

example

package main

import (
    "encoding/json"
    "fmt"
)

type MyType int8

func main() {

    var sliceIn, sliceOut []MyType

    for i := 0; i < 20; i++ {

        sliceIn = append(sliceIn, MyType(i))
    }

    j, _ := json.Marshal(sliceIn)

    json.Unmarshal(j, &sliceOut)

    fmt.Printf("%#v\n", sliceOut)
}

output

[]main.MyType{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}

http://play.golang.org/p/ZTIYhhnbVI

@adg
Copy link
Contributor

adg commented Oct 13, 2015

Well, that's weird.

@kshvakov
Copy link
Author

@adg

package main

import (
    "encoding/json"
    "fmt"
)

type Uint8 uint8

func main() {

    var sliceIn []Uint8

    for i := 0; i < 20; i++ {

        sliceIn = append(sliceIn, Uint8(i))
    }

    j, _ := json.Marshal(sliceIn)

    fmt.Println(string(j))
}

output

"AAECAwQFBgcICQoLDA0ODxAREhM="

@adg
Copy link
Contributor

adg commented Oct 13, 2015

I guess it's related to encoding/json's special handling of []byte.

On 14 October 2015 at 09:04, Kirill Shvakov notifications@github.com
wrote:

@adg https://github.com/adg

package main
import (
"encoding/json"
"fmt"
)
type Uint8 uint8
func main() {

var sliceIn []Uint8

for i := 0; i < 20; i++ {

    sliceIn = append(sliceIn, Uint8(i))
}

j, _ := json.Marshal(sliceIn)

fmt.Println(string(j))

}

output

"AAECAwQFBgcICQoLDA0ODxAREhM="


Reply to this email directly or view it on GitHub
#12921 (comment).

@kshvakov
Copy link
Author

it seems that 4302fd0 ?

@adg
Copy link
Contributor

adg commented Oct 13, 2015

Yeah, it's the fix to #8962 but it's debatable as to whether we fixed it in the right direction.

@gopherbot
Copy link

CL https://golang.org/cl/16303 mentions this issue.

@dsturrock
Copy link

I don't think it was introduced in encoding/json, just tried adding the same type declaration and managed to replicate it myself:

panic: reflect.Set: value of type []uint8 is not assignable to type []main.Uint8 [recovered]
    panic: reflect.Set: value of type []uint8 is not assignable to type []main.Uint8

goroutine 5 [running]:
testing.tRunner.func1(0xc8200921b0)
    /usr/local/go/src/testing/testing.go:450 +0x171
reflect.Value.assignTo(0x6c88c0, 0xc82000ebe0, 0x57, 0x7e8f90, 0xb, 0x6c5f80, 0x0, 0x0, 0x0, 0x0)
    /usr/local/go/src/reflect/value.go:2158 +0x3be
reflect.Value.Set(0x6c5f80, 0xc82000eba0, 0xd7, 0x6c88c0, 0xc82000ebe0, 0x57)
    /usr/local/go/src/reflect/value.go:1327 +0x95
database/sql.convertAssign(0x6b6c20, 0xc82000eba0, 0x6c88c0, 0xc82000ebe0, 0x0, 0x0)
    /usr/local/go/src/database/sql/convert.go:207 +0x7ca
database/sql.(*Rows).Scan(0xc82001e540, 0xc82000b340, 0x1, 0x1, 0x0, 0x0)
    /usr/local/go/src/database/sql/sql.go:1692 +0x47a

@golang golang locked and limited conversation to collaborators Nov 16, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants