golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
124.25k stars 17.7k forks source link

x/tools/internal/refactor/inline: avoid unnecessary interface conversions #68554

Open adonovan opened 4 months ago

adonovan commented 4 months ago

This contrived example demonstrates that the source-level inliner (activated through gopls' refactor.inline code action) adds conversions to interface types even when they are not necessary:

func f(d discard) {
    g(d) // inlining this => fmt.Println(io.Writer(d)), where fmt.Println(d) would do
}

func g(w io.Writer) { fmt.Println(w) }

var d discard
type discard struct{}
func (discard) Write(p []byte) (int, error) { return len(p), nil }

Because fmt.Println's arguments are each converted to any, the implicit conversion from discard to io.Writer is not significant within the body of g and could be omitted. By contrast, were fmt.Println replaced by panic, the conversion would not be safe to remove, because in general panic(x) is not equivalent to panic(any(x)).

The inliner should detect, for each interface-typed parameter of the callee, whether all its uses in the callee's body are converted explicitly or implicitly to an interface type, so that the caller-side interface conversion may be safely omitted.

Googlers: see internal issue b/354664998

gopherbot commented 5 days ago

Change https://go.dev/cl/629875 mentions this issue: internal/refactor/inline: avoid unnecessary interface conversions