V8025. The case in a type switch is unreachable. A previous case already covers this type.
The analyzer has detected a case clause that will never be executed in a type switch construct. One of the previous case clauses has already handled the type expected by this case clause.
The example:
type Value interface {
GetValue() string
}
type ConcreteValue struct {
value string
}
func (v *ConcreteValue) GetValue() string {
return v.value
}
....
func foo(x any) {
switch x.(type) {
case Value:
....
case *ConcreteValue: // <=
....
}
}
The first case clause checks whether x implements the Value interface, and the second one checks whether x has the *ConcreteValue type. The Go specification states that the appropriate execution block is determined by traversing the list of types in the case clauses left-to-right and top-to-bottom. Upon the first match, the control flow will pass to the corresponding block. Since the *ConcreteValue type implements the Value interface, objects of this type will be intercepted by the first case clause, rather than the second, as developers intended.
To avoid type-masking issues, always use specific types (or pointers to them) instead of general interfaces:
func foo(x any) {
switch x.(type) {
case *ConcreteValue:
....
case Value:
....
}
}