go: go/types: add Object.Origin [freeze exception]
I propose to add the following methods to types.Var and types.Func:
// Origin returns the canonical object for its receiver, i.e. the object
// recorded in Info.Defs.
//
// For instantiated variables Origin returns the type-parameterized object from
// which the receiver was created. For all other variables Origin returns the
// receiver.
func (obj *Var) Origin() *Var
// Origin returns the canonical object for its receiver, i.e. the object
// recorded in Info.Defs.
//
// For instantiated functions Origin returns the type-parameterized object from
// which the receiver was created. For all other functions, Origin returns
// receiver.
func (obj *Func) Origin() *Func
While instantiating types, we necessarily have to create instantiated copies of their methods/fields/parameters/etc. However, as we work on updating tools for generics, an emerging theme is that is useful to be able to answer the following two questions:
- Is this object canonical?
- What is the canonical object corresponding to this object?
Right now, these are not easy questions to answer. For methods, these can be answered by a lookup on the receiver base origin type. For fields / parameters / etc., it is more difficult and may require finding the relevant *ast.Ident and looking in Info.Defs.
Adding an Origin method to these types answers both of these questions trivially, at the cost of a pointer per object. If the added memory is a concern, there are several internal fields on types.object used during type-checking that may be externalized to free memory.
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 3
- Comments: 20 (19 by maintainers)
This freeze exemption has been approved. Nothing else is required for the exemption request.
CC @golang/release
This issue was filed early in the dev cycle, but due to ongoing discussion and the abbreviated cycle, was not accepted until a few days before the freeze. With other priorities in go/types (particularly the urgent https://go.dev/issue/52715), I didn’t get to the implementation of this feature before the freeze.
I’d like to request a freeze exception to land this proposal for 1.19, as it allows us to redefine a ‘canonical’ invariant that was broken with generics. Certain types of static analysis (such as https://github.com/dominikh/go-tools/issues/1215 or some Google-internal analyses) would be facilitated by these new APIs.
Please let me know if you’d like me to file a new issue for the freeze exception request, or if you need any other information to help make a determination.
Discussed this with @griesemer, and it seems like the arguments for concrete result types are compelling:
On the other hand, we wouldn’t be able to pass around
interface{ Origin() Object }as @dominikh suggests, but it would of course be easy to write a helperfunc originObject(Object) Object.By way of analogy, we document that
Type()of a*Funcis always*Signature, yet I have seen many places inx/toolswhere we use a commaok type assertion and handle the case that theType()of a*Funcis not a*Signature. I would guess that returningObjectwill lead to similar misuse.