Skip to content

unused: introduce objects for instantiated functions #1199

@dominikh

Description

@dominikh

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
Loading

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions