Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unused: introduce objects for instantiated functions #1199

Closed
dominikh opened this issue Mar 7, 2022 · 0 comments
Closed

unused: introduce objects for instantiated functions #1199

dominikh opened this issue Mar 7, 2022 · 0 comments
Labels
false-negative started Issues we've started working on

Comments

@dominikh
Copy link
Owner

dominikh commented Mar 7, 2022

In go/types, instantiated functions do not have an associated types.Object. For

func Fn1[T any](x T) {}
func Fn2() {
    Fn1[int](0)
}

in Fn2, info.ObjectOf(Fn1) will return the parameterized Fn1. info.Instances[Fn1] will give us the type argument (int) and the resulting signature (func(int)) but no types.Object for this instantiation. It is essentially an anonymous function.

This is problematic for unused, because unused's graph consists of values from the go/types type system (so that we can serialize it and only need type information, not the IR).

Consider this example, which leads to a false negative:

type c1 struct{}
func Fn[T any]() {}
func uncalled() {
    Fn[c1]()
}

In go/ir, we have three functions: Fn, uncalled, and a wrapper that calls Fn generically, with the type argument c1. But because we have no types.Object for the instance, the wrapper's Object is Fn. Thus, when we analyze the wrapper and see the use of c1, we associate that use with Fn, not with the wrapper. Thus, even though uncalled is unused, and Fn is never instantiated with c1, we still consider c1 used, because Fn is exported, and thus used.

We end up with the following graph, where the node (*types.Func) func command-line-arguments.Fn6[T any]() contains edges for both Fn and the wrapper representing Fn[c1].

graph TD
    n1("Root") 
    n1 -->|edgeExportedFunction| n2
    n2("(*types.Func) func command-line-arguments.Fn6[T any]()")
    n2 -->|edgeFunctionArgument| n6
    n2 -->|edgeType| n6
    n2 -->|edgeInstructionOperand| n2
    n2 -->|edgeTypeArg| n5
    n3("(*types.Func) func command-line-arguments.uncalled()")
    n3 -->|edgeInstructionOperand| n2
    n4("(*types.TypeName) type command-line-arguments.c8 struct{}")
    n4 -->|edgeNamedType| n5
    n7("(*types.TypeName) type parameter T any")
    n7 -->|edgeNamedType| n6
    n6("(*types.TypeParam) T")
    n6 -->|edgeTypeName| n7
    n5("(*types.Named) command-line-arguments.c8")
    n5 -->|edgeTypeName| n4
    style n2 stroke:lime
    style n4 stroke:lime
    style n7 stroke:lime
    style n5 stroke:lime
    style n3 stroke:red
@dominikh dominikh added the started Issues we've started working on label Jun 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
false-negative started Issues we've started working on
Projects
None yet
Development

No branches or pull requests

1 participant