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: problem in typed switch statement (type * has no field or method) #12772

Closed
mislav opened this issue Sep 28, 2015 · 4 comments
Closed

Comments

@mislav
Copy link

mislav commented Sep 28, 2015

I've made 2 custom error types that implement error interface: customErr1 and customErr2. They both have a Message property.

The inspect(error) function checks for types using a typed switch statement and, if the error object is either of customErr or customErr2 type, accesses their Message property.

What I expected to see: typed switch statement compiled.

What I saw instead: compilation error:

prog.go:24: e.Message undefined (type error has no field or method Message)

The problematic line below is

case *customErr1, *customErr2:

What's weird is that the program works if the list is reduced to 1 item, i.e. one of the types is removed. However if the case list contains 2 items, the program doesn't compile and complains that "type error has no field or method Message". It's true that error doesn't implement Message, but that was the purpose of my type check in the first place.

Full example on Go playground, inlined here:

package main

import "fmt"

type customErr1 struct {
    Message string
}

func (err *customErr1) Error() string {
    return "Error() 1"
}

type customErr2 struct {
    Message string
}

func (err *customErr2) Error() string {
    return "Error() 2"
}

func inspect(err error) {
    switch e := err.(type) {
    case *customErr1, *customErr2:    // PROBLEMATIC LINE
        fmt.Println(e.Message)
    default:
        fmt.Println(e.Error())
    }
}

func main() {
    inspect(&customErr1{Message: "hello from error 1"})
    inspect(&customErr2{Message: "hello from error 2"})
}

go version go1.5.1 darwin/amd64

@cznic
Copy link
Contributor

cznic commented Sep 28, 2015

The variable e in the typeswitch cannot have both type *customErr1 and customErr2. That's why it will have type error instead (same like in the default case). The solution is to use only one type per case clause where the e variable is used: http://play.golang.org/p/v7687VMgpR

#WAI

@mislav
Copy link
Author

mislav commented Sep 28, 2015

Thanks for the quick reply. I'm still confused. The Go language spec suggests in its example that such construct is possible:

switch i := x.(type) {
case bool, string:
    printString("type is bool or string")
default:
    printString("don't know the type")
}

Here we see the same case statement for both bool and string. Why wouldn't it be possible for two different types that implement the same interface, like in my example above?

@bradfitz
Copy link
Contributor

https://golang.org/ref/spec#Switch_statements says:

In clauses with a case listing exactly one type, the variable has that type; otherwise, the variable has the type of the expression in the TypeSwitchGuard.

Let's move further discussion to the mailing list. This isn't a bug.

@mislav
Copy link
Author

mislav commented Sep 28, 2015

@bradfitz Thanks, that clears it up!

@golang golang locked and limited conversation to collaborators Sep 27, 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

4 participants