mirror of
https://github.com/golang/go
synced 2024-11-26 06:27:58 -07:00
[dev.typeparams] cmd/compile: use types2.Constraint() rather than types2.Bound()
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>
This commit is contained in:
parent
9f4d6a8359
commit
f5f79c47f9
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user