cmd/compile: replace Type.OrigSym with Type.OrigType

First law of cmd/compile frontend development: thou shalt not rely on
types.Sym.

This CL replaces Type.OrigSym with Type.OrigType, which semantically
matches what all of the uses within the frontend actually care about,
and avoids using types.Sym, which invariably leads to mistakes because
symbol scoping in the frontend doesn't work how anyone intuitively
expects it to.

Fixes #51765.

Change-Id: I4affe6ee0718103ce5006ab68aa7e1bb0cac6881
Reviewed-on: https://go-review.googlesource.com/c/go/+/394274
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Matthew Dempsky 2022-03-21 10:06:48 -07:00
parent 29866aa2b6
commit adae6ec542
10 changed files with 47 additions and 34 deletions

View file

@ -114,11 +114,11 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) {
// the Fields to represent the receiver's method set. // the Fields to represent the receiver's method set.
if recv := fn.Type().Recv(); recv != nil { if recv := fn.Type().Recv(); recv != nil {
typ := types.ReceiverBaseType(recv.Type) typ := types.ReceiverBaseType(recv.Type)
if typ.OrigSym() != nil { if orig := typ.OrigType(); orig != nil {
// For a generic method, we mark the methods on the // For a generic method, we mark the methods on the
// base generic type, since those are the methods // base generic type, since those are the methods
// that will be stenciled. // that will be stenciled.
typ = typ.OrigSym().Def.Type() typ = orig
} }
meth := typecheck.Lookdot1(fn, typecheck.Lookup(decl.Name.Value), typ, typ.Methods(), 0) meth := typecheck.Lookdot1(fn, typecheck.Lookup(decl.Name.Value), typ, typ.Methods(), 0)
meth.SetNointerface(true) meth.SetNointerface(true)

View file

@ -193,8 +193,7 @@ func (g *genInst) scanForGenCalls(decl ir.Node) {
targs := deref(meth.Type().Recv().Type).RParams() targs := deref(meth.Type().Recv().Type).RParams()
t := meth.X.Type() t := meth.X.Type()
baseSym := deref(t).OrigSym() baseType := deref(t).OrigType()
baseType := baseSym.Def.(*ir.Name).Type()
var gf *ir.Name var gf *ir.Name
for _, m := range baseType.Methods().Slice() { for _, m := range baseType.Methods().Slice() {
if meth.Sel == m.Sym { if meth.Sel == m.Sym {
@ -348,7 +347,7 @@ func (g *genInst) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
// actually generic, so no need to build a closure. // actually generic, so no need to build a closure.
return x return x
} }
baseType := recv.OrigSym().Def.Type() baseType := recv.OrigType()
var gf *ir.Name var gf *ir.Name
for _, m := range baseType.Methods().Slice() { for _, m := range baseType.Methods().Slice() {
if se.Sel == m.Sym { if se.Sel == m.Sym {
@ -543,8 +542,7 @@ func (g *genInst) instantiateMethods() {
typecheck.NeedRuntimeType(typ) typecheck.NeedRuntimeType(typ)
// Lookup the method on the base generic type, since methods may // Lookup the method on the base generic type, since methods may
// not be set on imported instantiated types. // not be set on imported instantiated types.
baseSym := typ.OrigSym() baseType := typ.OrigType()
baseType := baseSym.Def.(*ir.Name).Type()
for j, _ := range typ.Methods().Slice() { for j, _ := range typ.Methods().Slice() {
if baseType.Methods().Slice()[j].Nointerface() { if baseType.Methods().Slice()[j].Nointerface() {
typ.Methods().Slice()[j].SetNointerface(true) typ.Methods().Slice()[j].SetNointerface(true)
@ -644,7 +642,7 @@ func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMe
if recvType.IsFullyInstantiated() { if recvType.IsFullyInstantiated() {
// Get the type of the base generic type, so we get // Get the type of the base generic type, so we get
// its original typeparams. // its original typeparams.
recvType = recvType.OrigSym().Def.(*ir.Name).Type() recvType = recvType.OrigType()
} }
tparams = recvType.RParams() tparams = recvType.RParams()
} else { } else {
@ -1628,7 +1626,7 @@ func (g *genInst) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool
// instantiated type, so we need a // instantiated type, so we need a
// sub-dictionary. // sub-dictionary.
targs := recvType.RParams() targs := recvType.RParams()
genRecvType := recvType.OrigSym().Def.Type() genRecvType := recvType.OrigType()
nameNode = typecheck.Lookdot1(call.X, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name) nameNode = typecheck.Lookdot1(call.X, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name)
sym = g.getDictionarySym(nameNode, targs, true) sym = g.getDictionarySym(nameNode, targs, true)
} else { } else {
@ -1707,7 +1705,7 @@ func (g *genInst) getSymForMethodCall(se *ir.SelectorExpr, subst *typecheck.Tsub
// also give the receiver type. For method expressions with embedded types, we // also give the receiver type. For method expressions with embedded types, we
// need to look at the type of the selection to get the final receiver type. // need to look at the type of the selection to get the final receiver type.
recvType := deref(se.Selection.Type.Recv().Type) recvType := deref(se.Selection.Type.Recv().Type)
genRecvType := recvType.OrigSym().Def.Type() genRecvType := recvType.OrigType()
nameNode := typecheck.Lookdot1(se, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name) nameNode := typecheck.Lookdot1(se, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name)
subtargs := recvType.RParams() subtargs := recvType.RParams()
s2targs := make([]*types.Type, len(subtargs)) s2targs := make([]*types.Type, len(subtargs))

View file

@ -166,7 +166,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
//fmt.Printf("Saw new type %v %v\n", instName, ntyp.HasTParam()) //fmt.Printf("Saw new type %v %v\n", instName, ntyp.HasTParam())
// Save the symbol for the base generic type. // Save the symbol for the base generic type.
ntyp.SetOrigSym(g.pkg(typ.Obj().Pkg()).Lookup(typ.Obj().Name())) ntyp.SetOrigType(base.Type())
ntyp.SetUnderlying(g.typ1(typ.Underlying())) ntyp.SetUnderlying(g.typ1(typ.Underlying()))
if typ.NumMethods() != 0 { if typ.NumMethods() != 0 {
// Save a delayed call to g.fillinMethods() (once // Save a delayed call to g.fillinMethods() (once

View file

@ -1920,7 +1920,7 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy
// Target method uses shaped names. // Target method uses shaped names.
targs2 := make([]*types.Type, len(targs)) targs2 := make([]*types.Type, len(targs))
origRParams := deref(orig).OrigSym().Def.(*ir.Name).Type().RParams() origRParams := deref(orig).OrigType().RParams()
for i, t := range targs { for i, t := range targs {
targs2[i] = typecheck.Shapify(t, i, origRParams[i]) targs2[i] = typecheck.Shapify(t, i, origRParams[i])
} }

View file

@ -66,9 +66,9 @@ func (p *crawler) markObject(n *ir.Name) {
// inline bodies may be needed. For instantiated generic types, it visits the base // inline bodies may be needed. For instantiated generic types, it visits the base
// generic type, which has the relevant methods. // generic type, which has the relevant methods.
func (p *crawler) markType(t *types.Type) { func (p *crawler) markType(t *types.Type) {
if t.OrigSym() != nil { if orig := t.OrigType(); orig != nil {
// Convert to the base generic type. // Convert to the base generic type.
t = t.OrigSym().Def.Type() t = orig
} }
if p.marked[t] { if p.marked[t] {
return return
@ -154,9 +154,9 @@ func (p *crawler) markEmbed(t *types.Type) {
t = t.Elem() t = t.Elem()
} }
if t.OrigSym() != nil { if orig := t.OrigType(); orig != nil {
// Convert to the base generic type. // Convert to the base generic type.
t = t.OrigSym().Def.Type() t = orig
} }
if p.embedded[t] { if p.embedded[t] {
@ -194,9 +194,9 @@ func (p *crawler) markGeneric(t *types.Type) {
if t.IsPtr() { if t.IsPtr() {
t = t.Elem() t = t.Elem()
} }
if t.OrigSym() != nil { if orig := t.OrigType(); orig != nil {
// Convert to the base generic type. // Convert to the base generic type.
t = t.OrigSym().Def.Type() t = orig
} }
if p.generic[t] { if p.generic[t] {
return return
@ -229,7 +229,7 @@ func (p *crawler) checkForFullyInst(t *types.Type) {
// them available for import, and so will not need // them available for import, and so will not need
// another round of method and dictionary // another round of method and dictionary
// instantiation after inlining. // instantiation after inlining.
baseType := t.OrigSym().Def.(*ir.Name).Type() baseType := t.OrigType()
shapes := make([]*types.Type, len(t.RParams())) shapes := make([]*types.Type, len(t.RParams()))
for i, t1 := range t.RParams() { for i, t1 := range t.RParams() {
shapes[i] = Shapify(t1, i, baseType.RParams()[i]) shapes[i] = Shapify(t1, i, baseType.RParams()[i])

View file

@ -948,7 +948,7 @@ func (w *exportWriter) startType(k itag) {
func (w *exportWriter) doTyp(t *types.Type) { func (w *exportWriter) doTyp(t *types.Type) {
s := t.Sym() s := t.Sym()
if s != nil && t.OrigSym() != nil { if s != nil && t.OrigType() != nil {
// This is an instantiated type - could be a re-instantiation like // This is an instantiated type - could be a re-instantiation like
// Value[T2] or a full instantiation like Value[int]. // Value[T2] or a full instantiation like Value[int].
if strings.Index(s.Name, "[") < 0 { if strings.Index(s.Name, "[") < 0 {
@ -964,7 +964,7 @@ func (w *exportWriter) doTyp(t *types.Type) {
// types or existing typeparams from the function/method header. // types or existing typeparams from the function/method header.
w.typeList(t.RParams()) w.typeList(t.RParams())
// Export a reference to the base type. // Export a reference to the base type.
baseType := t.OrigSym().Def.(*ir.Name).Type() baseType := t.OrigType()
w.typ(baseType) w.typ(baseType)
return return
} }

View file

@ -761,7 +761,7 @@ func (p *iimporter) typAt(off uint64) *types.Type {
// No need to calc sizes for re-instantiated generic types, and // No need to calc sizes for re-instantiated generic types, and
// they are not necessarily resolved until the top-level type is // they are not necessarily resolved until the top-level type is
// defined (because of recursive types). // defined (because of recursive types).
if t.OrigSym() == nil || !t.HasTParam() { if t.OrigType() == nil || !t.HasTParam() {
types.CheckSize(t) types.CheckSize(t)
} }
p.typCache[off] = t p.typCache[off] = t
@ -1482,7 +1482,7 @@ func (r *importReader) node() ir.Node {
} else { } else {
genType := types.ReceiverBaseType(n1.X.Type()) genType := types.ReceiverBaseType(n1.X.Type())
if genType.IsInstantiatedGeneric() { if genType.IsInstantiatedGeneric() {
genType = genType.OrigSym().Def.Type() genType = genType.OrigType()
} }
m = Lookdot1(n1, sel, genType, genType.Methods(), 1) m = Lookdot1(n1, sel, genType, genType.Methods(), 1)
} }
@ -1913,7 +1913,7 @@ func Instantiate(pos src.XPos, baseType *types.Type, targs []*types.Type) *types
t := NewIncompleteNamedType(baseType.Pos(), instSym) t := NewIncompleteNamedType(baseType.Pos(), instSym)
t.SetRParams(targs) t.SetRParams(targs)
t.SetOrigSym(baseSym) t.SetOrigType(baseType)
// baseType may still be TFORW or its methods may not be fully filled in // baseType may still be TFORW or its methods may not be fully filled in
// (since we are in the middle of importing it). So, delay call to // (since we are in the middle of importing it). So, delay call to
@ -1938,7 +1938,7 @@ func resumeDoInst() {
for len(deferredInstStack) > 0 { for len(deferredInstStack) > 0 {
t := deferredInstStack[0] t := deferredInstStack[0]
deferredInstStack = deferredInstStack[1:] deferredInstStack = deferredInstStack[1:]
substInstType(t, t.OrigSym().Def.(*ir.Name).Type(), t.RParams()) substInstType(t, t.OrigType(), t.RParams())
} }
} }
deferInst-- deferInst--
@ -1950,7 +1950,7 @@ func resumeDoInst() {
// instantiations of mutually recursive types. // instantiations of mutually recursive types.
func doInst(t *types.Type) *types.Type { func doInst(t *types.Type) *types.Type {
assert(t.Kind() == types.TFORW) assert(t.Kind() == types.TFORW)
return Instantiate(t.Pos(), t.OrigSym().Def.(*ir.Name).Type(), t.RParams()) return Instantiate(t.Pos(), t.OrigType(), t.RParams())
} }
// substInstType completes the instantiation of a generic type by doing a // substInstType completes the instantiation of a generic type by doing a

View file

@ -1108,10 +1108,10 @@ func (ts *Tsubster) typ1(t *types.Type) *types.Type {
forw = NewIncompleteNamedType(t.Pos(), newsym) forw = NewIncompleteNamedType(t.Pos(), newsym)
//println("Creating new type by sub", newsym.Name, forw.HasTParam()) //println("Creating new type by sub", newsym.Name, forw.HasTParam())
forw.SetRParams(neededTargs) forw.SetRParams(neededTargs)
// Copy the OrigSym from the re-instantiated type (which is the sym of // Copy the OrigType from the re-instantiated type (which is the sym of
// the base generic type). // the base generic type).
assert(t.OrigSym() != nil) assert(t.OrigType() != nil)
forw.SetOrigSym(t.OrigSym()) forw.SetOrigType(t.OrigType())
} }
var newt *types.Type var newt *types.Type

View file

@ -202,10 +202,10 @@ type Type struct {
// TODO(danscales): choose a better name. // TODO(danscales): choose a better name.
rparams *[]*Type rparams *[]*Type
// For an instantiated generic type, the symbol for the base generic type. // For an instantiated generic type, the base generic type.
// This backpointer is useful, because the base type is the type that has // This backpointer is useful, because the base type is the type that has
// the method bodies. // the method bodies.
origSym *Sym origType *Type
} }
func (*Type) CanBeAnSSAAux() {} func (*Type) CanBeAnSSAAux() {}
@ -248,10 +248,10 @@ func (t *Type) Kind() Kind { return t.kind }
func (t *Type) Sym() *Sym { return t.sym } func (t *Type) Sym() *Sym { return t.sym }
func (t *Type) SetSym(sym *Sym) { t.sym = sym } func (t *Type) SetSym(sym *Sym) { t.sym = sym }
// OrigSym returns the name of the original generic type that t is an // OrigType returns the original generic type that t is an
// instantiation of, if any. // instantiation of, if any.
func (t *Type) OrigSym() *Sym { return t.origSym } func (t *Type) OrigType() *Type { return t.origType }
func (t *Type) SetOrigSym(sym *Sym) { t.origSym = sym } func (t *Type) SetOrigType(orig *Type) { t.origType = orig }
// Underlying returns the underlying type of type t. // Underlying returns the underlying type of type t.
func (t *Type) Underlying() *Type { return t.underlying } func (t *Type) Underlying() *Type { return t.underlying }

View file

@ -0,0 +1,15 @@
// compile
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package p
type empty[T any] struct{}
func (this *empty[T]) Next() (empty T, _ error) {
return empty, nil
}
var _ = &empty[string]{}