Documentation ¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var Analyzer = SCAnalyzer.Analyzer
View Source
var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{ Analyzer: &analysis.Analyzer{ Name: "SA4020", Run: run, Requires: []*analysis.Analyzer{inspect.Analyzer}, }, Doc: &lint.RawDocumentation{ Title: `Unreachable case clause in a type switch`, Text: `In a type switch like the following type T struct{} func (T) Read(b []byte) (int, error) { return 0, nil } var v interface{} = T{} switch v.(type) { case io.Reader: // ... case T: // unreachable } the second case clause can never be reached because \'T\' implements \'io.Reader\' and case clauses are evaluated in source order. Another example: type T struct{} func (T) Read(b []byte) (int, error) { return 0, nil } func (T) Close() error { return nil } var v interface{} = T{} switch v.(type) { case io.Reader: // ... case io.ReadCloser: // unreachable } Even though \'T\' has a \'Close\' method and thus implements \'io.ReadCloser\', \'io.Reader\' will always match first. The method set of \'io.Reader\' is a subset of \'io.ReadCloser\'. Thus it is impossible to match the second case without matching the first case. Structurally equivalent interfaces A special case of the previous example are structurally identical interfaces. Given these declarations type T error type V error func doSomething() error { err, ok := doAnotherThing() if ok { return T(err) } return U(err) } the following type switch will have an unreachable case clause: switch doSomething().(type) { case T: // ... case V: // unreachable } \'T\' will always match before V because they are structurally equivalent and therefore \'doSomething()\''s return value implements both.`, Since: "2019.2", Severity: lint.SeverityWarning, MergeIf: lint.MergeIfAll, }, })
Functions ¶
This section is empty.
Types ¶
This section is empty.
Click to show internal directories.
Click to hide internal directories.