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

go/types: Info.Selections records unique objects for generic methods #51184

Closed
dominikh opened this issue Feb 14, 2022 · 2 comments
Closed

go/types: Info.Selections records unique objects for generic methods #51184

dominikh opened this issue Feb 14, 2022 · 2 comments
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@dominikh
Copy link
Member

Consider https://gotipplay.golang.org/p/DBMZ9zBIaGB

We have a generic and a normal method named Bar, which result in the following two objects in Info.Defs:

def: Bar = func (pkg.Generic[T]).Bar() [0xc0000699a0]
def: Bar = func (pkg.Normal).Bar() [0xc000069b30]

All calls to Normal.Bar map to the same object in Info.Selections, which is also the object that was recorded in Info.Defs:

use: &{recv Bar} = func (pkg.Normal).Bar() [0xc000069b30]
use: &{recv Bar} = func (pkg.Normal).Bar() [0xc000069b30]
use: &{recv Bar} = func (pkg.Normal).Bar() [0xc000069b30]

However, each call to Generic[T].Bar maps to a different object, none of which matches one in Info.Defs:

use: &{recv Bar} = func (pkg.Generic[T]).Bar() [0xc00013e280]
use: &{recv Bar} = func (pkg.Generic[T]).Bar() [0xc00013e370]
use: &{recv Bar} = func (pkg.Generic[T]).Bar() [0xc00013e460]

(The same behavior can be observed with Info.Uses instead of Info.Selections.)

Is this expected behavior?

/cc @findleyr

@dmitshur dmitshur added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Feb 14, 2022
@dmitshur dmitshur added this to the Go1.18 milestone Feb 14, 2022
@findleyr
Copy link
Contributor

@dominikh yes, this is expected (but rather subtle) behavior. This is also discussed in https://go.dev/issue/50619.

Methods on generic types are a bit strange by construction: their receiver base cannot be the generic type, because we don't allow uses of uninstantated generic types. Instead, the receiver base type is the generic type instantiated with the method's receiver type parameters.

Because we made the decision to have a 1:1 correspondence between type parameter names and type parameter types (for the purpose of better type strings), the receiver type parameters of each method are distinct types. So this means that the receiver base of each method has a distinct identity, and yes, that we have a theoretical N^2 fan-out of methods on a generic type: each method has a distinct instance as its receiver, and each receiver therefore has a distinct method set. Though note that methods are lazily instantiated when they are used.

I believe this is logically consistent, but certainly subtle. For this reason, I hope to upstream helpers like OriginMethod to go/types.

@dominikh
Copy link
Member Author

Thanks for the clarification. That is certainly something for internal/typeparams/example :)

I'm going to close this issue as there doesn't seem to be anything to do here.

@golang golang locked and limited conversation to collaborators Feb 15, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

4 participants