Commit 3fbfc83d authored by Daniel Martí's avatar Daniel Martí Committed by Robert Griesemer

cmd/vet: recognise func type conversions

In hasSideEffects, vet has to be taught whether or not a CallExpr is an
actual function call, or just a type conversion.

The previous code knew how to differentiate fn(arg) from int(arg), but
it incorrectly saw (func(T))(fn) as a func call. This edge case is
slightly tricky, since the CallExpr.Fun has a func signature type, just
like in func calls.

However, the difference is that in this case the Fun is a type, not a
value. This information is in types.TypeAndValue, so use it.

Change-Id: I18bb8b23abbe7decc558b726ff2dc31fae2f13d6
Reviewed-on: https://go-review.googlesource.com/111416
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
parent d474f582
...@@ -145,13 +145,14 @@ func hasSideEffects(f *File, e ast.Expr) bool { ...@@ -145,13 +145,14 @@ func hasSideEffects(f *File, e ast.Expr) bool {
// Don't call Type.Underlying(), since its lack // Don't call Type.Underlying(), since its lack
// lets us see the NamedFuncType(x) type // lets us see the NamedFuncType(x) type
// conversion as a *types.Named. // conversion as a *types.Named.
_, ok := f.pkg.types[n.Fun].Type.(*types.Signature) typVal := f.pkg.types[n.Fun]
if ok { _, isSig := typVal.Type.(*types.Signature)
// Conservatively assume that all function and if typVal.IsValue() && isSig {
// method calls have side effects for // If we have a value of unnamed signature type,
// now. This will include func type // this CallExpr is a func call and not a type
// conversions, but it's ok given that // conversion. Conservatively assume that all
// this is the conservative side. // function and method calls have side effects
// for now.
safe = false safe = false
return false return false
} }
......
...@@ -24,8 +24,7 @@ func RatherStupidConditions() { ...@@ -24,8 +24,7 @@ func RatherStupidConditions() {
_ = i == T(2) || i == T(2) // ERROR "redundant or: i == T(2) || i == T(2)" _ = i == T(2) || i == T(2) // ERROR "redundant or: i == T(2) || i == T(2)"
_ = FT(f) == nil || FT(f) == nil // ERROR "redundant or: FT(f) == nil || FT(f) == nil" _ = FT(f) == nil || FT(f) == nil // ERROR "redundant or: FT(f) == nil || FT(f) == nil"
// TODO: distinguish from an actual func call _ = (func() int)(f) == nil || (func() int)(f) == nil // ERROR "redundant or: (func() int)(f) == nil || (func() int)(f) == nil"
_ = (func() int)(f) == nil || (func() int)(f) == nil
var namedFuncVar FT var namedFuncVar FT
_ = namedFuncVar() == namedFuncVar() // OK; still func calls _ = namedFuncVar() == namedFuncVar() // OK; still func calls
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment