1
0
mirror of https://github.com/golang/go synced 2024-11-18 14:54:40 -07:00

Revert "go/analysis: add pass to check for impossible interface-to-interface type assertions"

This reverts commit 7a72f3f8e9.

Reason for revert: The 1.15 tree is not open yet.

Change-Id: I5b3e458748bb3d69950f6331672e8c883d6234fb
Reviewed-on: https://go-review.googlesource.com/c/tools/+/219119
Run-TryBot: Andrew Bonventre <andybons@golang.org>
Reviewed-by: Alan Donovan <adonovan@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Andrew Bonventre 2020-02-11 20:35:28 +00:00
parent 6822f1ada4
commit 11eff242d1
4 changed files with 0 additions and 171 deletions

View File

@ -1,13 +0,0 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// The ifaceassert command runs the ifaceassert analyzer.
package main
import (
"golang.org/x/tools/go/analysis/passes/ifaceassert"
"golang.org/x/tools/go/analysis/singlechecker"
)
func main() { singlechecker.Main(ifaceassert.Analyzer) }

View File

@ -1,101 +0,0 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package ifaceassert defines an Analyzer that flags
// impossible interface-interface type assertions.
package ifaceassert
import (
"go/ast"
"go/types"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
"golang.org/x/tools/go/ast/inspector"
)
const Doc = `detect impossible interface-to-interface type assertions
This checker flags type assertions v.(T) and corresponding type-switch cases
in which the static type V of v is an interface that cannot possibly implement
the target interface T. This occurs when V and T contain methods with the same
name but different signatures. Example:
var v interface {
Read()
}
_ = v.(io.Reader)
The Read method in v has a different signature than the Read method in
io.Reader, so this assertion cannot succeed.
`
var Analyzer = &analysis.Analyzer{
Name: "ifaceassert",
Doc: Doc,
Requires: []*analysis.Analyzer{inspect.Analyzer},
Run: run,
}
// assertableTo checks whether interface v can be asserted into t. It returns
// nil on success, or the first conflicting method on failure.
func assertableTo(v, t types.Type) *types.Func {
// ensure that v and t are interfaces
V, _ := v.Underlying().(*types.Interface)
T, _ := t.Underlying().(*types.Interface)
if V == nil || T == nil {
return nil
}
if f, wrongType := types.MissingMethod(V, T, false); wrongType {
return f
}
return nil
}
func run(pass *analysis.Pass) (interface{}, error) {
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
nodeFilter := []ast.Node{
(*ast.TypeAssertExpr)(nil),
(*ast.TypeSwitchStmt)(nil),
}
inspect.Preorder(nodeFilter, func(n ast.Node) {
var (
assert *ast.TypeAssertExpr // v.(T) expression
targets []ast.Expr // interfaces T in v.(T)
)
switch n := n.(type) {
case *ast.TypeAssertExpr:
// take care of v.(type) in *ast.TypeSwitchStmt
if n.Type == nil {
return
}
assert = n
targets = append(targets, n.Type)
case *ast.TypeSwitchStmt:
// retrieve type assertion from type switch's 'assign' field
switch t := n.Assign.(type) {
case *ast.ExprStmt:
assert = t.X.(*ast.TypeAssertExpr)
case *ast.AssignStmt:
assert = t.Rhs[0].(*ast.TypeAssertExpr)
}
// gather target types from case clauses
for _, c := range n.Body.List {
targets = append(targets, c.(*ast.CaseClause).List...)
}
}
V := pass.TypesInfo.TypeOf(assert.X)
for _, target := range targets {
T := pass.TypesInfo.TypeOf(target)
if f := assertableTo(V, T); f != nil {
pass.Reportf(
target.Pos(),
"impossible type assertion: no type can implement both %v and %v (conflicting types for %v method)",
V, T, f.Name(),
)
}
}
})
return nil, nil
}

View File

@ -1,17 +0,0 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ifaceassert_test
import (
"testing"
"golang.org/x/tools/go/analysis/analysistest"
"golang.org/x/tools/go/analysis/passes/ifaceassert"
)
func Test(t *testing.T) {
testdata := analysistest.TestData()
analysistest.Run(t, testdata, ifaceassert.Analyzer, "a")
}

View File

@ -1,40 +0,0 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file contains tests for the ifaceassert checker.
package a
import "io"
func InterfaceAssertionTest() {
var (
a io.ReadWriteSeeker
b interface {
Read()
Write()
}
)
_ = a.(io.Reader)
_ = a.(io.ReadWriter)
_ = b.(io.Reader) // want `^impossible type assertion: no type can implement both interface{Read\(\); Write\(\)} and io.Reader \(conflicting types for Read method\)$`
_ = b.(interface { // want `^impossible type assertion: no type can implement both interface{Read\(\); Write\(\)} and interface{Read\(p \[\]byte\) \(n int, err error\)} \(conflicting types for Read method\)$`
Read(p []byte) (n int, err error)
})
switch a.(type) {
case io.ReadWriter:
case interface { // want `^impossible type assertion: no type can implement both io.ReadWriteSeeker and interface{Write\(\)} \(conflicting types for Write method\)$`
Write()
}:
default:
}
switch b := b.(type) {
case io.ReadWriter, interface{ Read() }: // want `^impossible type assertion: no type can implement both interface{Read\(\); Write\(\)} and io.ReadWriter \(conflicting types for Read method\)$`
case io.Writer: // want `^impossible type assertion: no type can implement both interface{Read\(\); Write\(\)} and io.Writer \(conflicting types for Write method\)$`
default:
_ = b
}
}