]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile: get rid of concretify use for bounds.
authorDan Scales <danscales@google.com>
Sat, 24 Jul 2021 00:19:51 +0000 (17:19 -0700)
committerDan Scales <danscales@google.com>
Sat, 24 Jul 2021 17:47:08 +0000 (17:47 +0000)
We just need to substitute from the typeparams to the shapes for the dst
type of the bound.

Removed concretify substituter, not used anymore. Also removed
shape2params, not needed anymore.

However, since the dst type is now not concrete, this gives more cases
where the linker can't find a method.

I realized that we need to call MarkUsedIfaceMethod to mark a method as
used on a particular interface, else a type's method can be still
deadcoded even though MarkTypeUsedInInterface has been called on the
concrete type. I added a new version MarkUsedIfaceMethodIndex to fit my
use case.

Change-Id: Id67b72b350889dd3688b42739c337d5d79a0d1a2
Reviewed-on: https://go-review.googlesource.com/c/go/+/337230
Trust: Dan Scales <danscales@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/noder/stencil.go
src/cmd/compile/internal/reflectdata/reflect.go

index e308dd7a05b788be6202b6d5fbb9daa130574a0c..f1de1152c5505da971d22a4342ba93d59b6e4178 100644 (file)
@@ -855,13 +855,9 @@ type subster struct {
        ts       typecheck.Tsubster
        info     *instInfo // Place to put extra info in the instantiation
 
-       // Which type parameter the shape type came from.
-       shape2param map[*types.Type]*types.Type
-
        // unshapeify maps from shape types to the concrete types they represent.
        // TODO: remove when we no longer need it.
-       unshapify  typecheck.Tsubster
-       concretify typecheck.Tsubster
+       unshapify typecheck.Tsubster
 
        // TODO: some sort of map from <shape type, interface type> to index in the
        // dictionary where a *runtime.itab for the corresponding <concrete type,
@@ -920,23 +916,11 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes, targs
                        Targs:   shapes,
                        Vars:    make(map[*ir.Name]*ir.Name),
                },
-               shape2param: map[*types.Type]*types.Type{},
                unshapify: typecheck.Tsubster{
                        Tparams: shapes,
                        Targs:   targs,
                        Vars:    make(map[*ir.Name]*ir.Name),
                },
-               concretify: typecheck.Tsubster{
-                       Tparams: tparams,
-                       Targs:   targs,
-                       Vars:    make(map[*ir.Name]*ir.Name),
-               },
-       }
-       for i := range shapes {
-               if !shapes[i].IsShape() {
-                       panic("must be a shape type")
-               }
-               subst.shape2param[shapes[i]] = tparams[i]
        }
 
        newf.Dcl = make([]*ir.Name, 0, len(gf.Dcl)+1)
@@ -992,7 +976,6 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes, targs
        // g.instTypeList.
        g.instTypeList = append(g.instTypeList, subst.ts.InstTypeList...)
        g.instTypeList = append(g.instTypeList, subst.unshapify.InstTypeList...)
-       g.instTypeList = append(g.instTypeList, subst.concretify.InstTypeList...)
 
        if doubleCheck {
                okConvs := map[ir.Node]bool{}
@@ -1258,7 +1241,10 @@ func (subst *subster) node(n ir.Node) ir.Node {
                                        //  1) convert x to the bound interface
                                        //  2) call M on that interface
                                        gsrc := x.(*ir.SelectorExpr).X.Type()
-                                       dst := subst.concretify.Typ(gsrc.Bound())
+                                       dst := gsrc.Bound()
+                                       if dst.HasTParam() {
+                                               dst = subst.ts.Typ(dst)
+                                       }
                                        mse.X = subst.convertUsingDictionary(m.Pos(), mse.X, x, dst, gsrc)
                                }
                        }
@@ -1714,6 +1700,18 @@ func (g *irgen) finalizeSyms() {
                                se := n.(*ir.SelectorExpr)
                                srctype = subst.Typ(se.X.Type())
                                dsttype = subst.Typ(se.X.Type().Bound())
+                               found := false
+                               for i, m := range dsttype.AllMethods().Slice() {
+                                       if se.Sel == m.Sym {
+                                               // Mark that this method se.Sel is
+                                               // used for the dsttype interface, so
+                                               // it won't get deadcoded.
+                                               reflectdata.MarkUsedIfaceMethodIndex(lsym, dsttype, i)
+                                               found = true
+                                               break
+                                       }
+                               }
+                               assert(found)
                        } else {
                                assert(n.Op() == ir.OCONVIFACE)
                                srctype = subst.Typ(n.(*ir.ConvExpr).X.Type())
index 7eba5fb41e47cf984be2e93051eeb1b8d4c2efbb..3bf248a7ade2a8e90b46129d75b7596fb6c83c85 100644 (file)
@@ -2006,13 +2006,23 @@ func MarkUsedIfaceMethod(n *ir.CallExpr) {
        tsym := TypeLinksym(ityp)
        r := obj.Addrel(ir.CurFunc.LSym)
        r.Sym = tsym
-       // dot.Xoffset is the method index * PtrSize (the offset of code pointer
+       // dot.Offset() is the method index * PtrSize (the offset of code pointer
        // in itab).
        midx := dot.Offset() / int64(types.PtrSize)
        r.Add = InterfaceMethodOffset(ityp, midx)
        r.Type = objabi.R_USEIFACEMETHOD
 }
 
+// MarkUsedIfaceMethodIndex marks that that method number ix (in the AllMethods list)
+// of interface type ityp is used, and should be attached to lsym.
+func MarkUsedIfaceMethodIndex(lsym *obj.LSym, ityp *types.Type, ix int) {
+       tsym := TypeLinksym(ityp)
+       r := obj.Addrel(lsym)
+       r.Sym = tsym
+       r.Add = InterfaceMethodOffset(ityp, int64(ix))
+       r.Type = objabi.R_USEIFACEMETHOD
+}
+
 // getDictionary returns the dictionary for the given named generic function
 // or method, with the given type arguments.
 func getDictionary(gf *types.Sym, targs []*types.Type) ir.Node {