]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile: use types2.Constraint() rather than types2.Bound()
authorDan Scales <danscales@google.com>
Sun, 8 Aug 2021 05:26:46 +0000 (22:26 -0700)
committerDan Scales <danscales@google.com>
Mon, 9 Aug 2021 20:08:06 +0000 (20:08 +0000)
types2.Constraint() returns the top-level constraint type, including any
unions or other interface elements. Because of that, we needed to
add/fix some code in the type substituter and generic type instantiater
in the importer to deal with unions and non-method members of an
interface. Also, NewUnion was not correctly setting the HasTParam flag.

I also added a better error message when a symbol is not found in
(*deadcodePass).decodeIfaceMethod().

Change-Id: Id3668dc596dce63690fa05a9e5e42295b5e2bbb5
Reviewed-on: https://go-review.googlesource.com/c/go/+/340670
Trust: Dan Scales <danscales@google.com>
Run-TryBot: Dan Scales <danscales@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/noder/types.go
src/cmd/compile/internal/typecheck/iimport.go
src/cmd/compile/internal/typecheck/subr.go
src/cmd/compile/internal/types/type.go
src/cmd/link/internal/ld/deadcode.go

index 4e80b1a0ffe3e567ed0a0e8809a0af4cc9b84ea6..8d596e599ed172a0f23d96eea0170c08737f4a36 100644 (file)
@@ -227,7 +227,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
                // Set g.typs[typ] in case the bound methods reference typ.
                g.typs[typ] = tp
 
-               bound := g.typ1(typ.Bound())
+               bound := g.typ1(typ.Constraint())
                tp.SetBound(bound)
                return tp
 
index 2e8b18c0b7cd335d846169e06e6f3f7618f078ce..d5f4bba98b2b0e2b5ef2f51614976338e6d20c90 100644 (file)
@@ -1858,18 +1858,26 @@ func substInstType(t *types.Type, baseType *types.Type, targs []*types.Type) {
 
        newfields := make([]*types.Field, baseType.Methods().Len())
        for i, f := range baseType.Methods().Slice() {
+               if !f.IsMethod() || types.IsInterfaceMethod(f.Type) {
+                       // Do a normal substitution if this is a non-method (which
+                       // means this must be an interface used as a constraint) or
+                       // an interface method.
+                       t2 := subst.Typ(f.Type)
+                       newfields[i] = types.NewField(f.Pos, f.Sym, t2)
+                       continue
+               }
                recvType := f.Type.Recv().Type
                if recvType.IsPtr() {
                        recvType = recvType.Elem()
                }
                // Substitute in the method using the type params used in the
                // method (not the type params in the definition of the generic type).
-               subst := Tsubster{
+               msubst := Tsubster{
                        Tparams:       recvType.RParams(),
                        Targs:         targs,
                        SubstForwFunc: doInst,
                }
-               t2 := subst.Typ(f.Type)
+               t2 := msubst.Typ(f.Type)
                oldsym := f.Nname.Sym()
                newsym := MakeInstName(oldsym, targs, true)
                var nname *ir.Name
index e840df56dc2ea9ac4d434384f3860a0ddf546981..e86c4c6bca7e39d9e78dffcffa6399de0c9a452d 100644 (file)
@@ -1165,7 +1165,7 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type {
 
        case types.TINTER:
                newt = ts.tinter(t)
-               if newt == t {
+               if newt == t && !targsChanged {
                        newt = nil
                }
 
@@ -1197,6 +1197,24 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type {
                types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64,
                types.TUINTPTR, types.TBOOL, types.TSTRING, types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128:
                newt = t.Underlying()
+       case types.TUNION:
+               nt := t.NumTerms()
+               newterms := make([]*types.Type, nt)
+               tildes := make([]bool, nt)
+               changed := false
+               for i := 0; i < nt; i++ {
+                       term, tilde := t.Term(i)
+                       tildes[i] = tilde
+                       newterms[i] = ts.Typ(term)
+                       if newterms[i] != term {
+                               changed = true
+                       }
+               }
+               if changed {
+                       newt = types.NewUnion(newterms, tildes)
+               }
+       default:
+               panic(fmt.Sprintf("Bad type in (*TSubster).Typ: %v", t.Kind()))
        }
        if newt == nil {
                // Even though there were typeparams in the type, there may be no
index 099080f48f3c6aba98d217f77c302fc46fe170e0..875b0ba82f1ec5407d3b7fd82063a55b09412b08 100644 (file)
@@ -1912,6 +1912,15 @@ func NewUnion(terms []*Type, tildes []bool) *Type {
        }
        t.Extra.(*Union).terms = terms
        t.Extra.(*Union).tildes = tildes
+       nt := len(terms)
+       for i := 0; i < nt; i++ {
+               if terms[i].HasTParam() {
+                       t.SetHasTParam(true)
+               }
+               if terms[i].HasShape() {
+                       t.SetHasShape(true)
+               }
+       }
        return t
 }
 
index 416e5da39838fe73a68f663c6914869571a444ba..dd5dafc21b2361346c862c2a5af5a5abdb5b1a46 100644 (file)
@@ -408,6 +408,9 @@ func (d *deadcodePass) decodeMethodSig(ldr *loader.Loader, arch *sys.Arch, symId
 // Decode the method of interface type symbol symIdx at offset off.
 func (d *deadcodePass) decodeIfaceMethod(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, off int64) methodsig {
        p := ldr.Data(symIdx)
+       if p == nil {
+               panic(fmt.Sprintf("missing symbol %q", ldr.SymName(symIdx)))
+       }
        if decodetypeKind(arch, p)&kindMask != kindInterface {
                panic(fmt.Sprintf("symbol %q is not an interface", ldr.SymName(symIdx)))
        }