mirror of
https://github.com/golang/go
synced 2024-09-05 07:54:46 +00: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.
|
// Set g.typs[typ] in case the bound methods reference typ.
|
||||||
g.typs[typ] = tp
|
g.typs[typ] = tp
|
||||||
|
|
||||||
bound := g.typ1(typ.Bound())
|
bound := g.typ1(typ.Constraint())
|
||||||
tp.SetBound(bound)
|
tp.SetBound(bound)
|
||||||
return tp
|
return tp
|
||||||
|
|
||||||
|
|
|
@ -1858,18 +1858,26 @@ func substInstType(t *types.Type, baseType *types.Type, targs []*types.Type) {
|
||||||
|
|
||||||
newfields := make([]*types.Field, baseType.Methods().Len())
|
newfields := make([]*types.Field, baseType.Methods().Len())
|
||||||
for i, f := range baseType.Methods().Slice() {
|
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
|
recvType := f.Type.Recv().Type
|
||||||
if recvType.IsPtr() {
|
if recvType.IsPtr() {
|
||||||
recvType = recvType.Elem()
|
recvType = recvType.Elem()
|
||||||
}
|
}
|
||||||
// Substitute in the method using the type params used in the
|
// Substitute in the method using the type params used in the
|
||||||
// method (not the type params in the definition of the generic type).
|
// method (not the type params in the definition of the generic type).
|
||||||
subst := Tsubster{
|
msubst := Tsubster{
|
||||||
Tparams: recvType.RParams(),
|
Tparams: recvType.RParams(),
|
||||||
Targs: targs,
|
Targs: targs,
|
||||||
SubstForwFunc: doInst,
|
SubstForwFunc: doInst,
|
||||||
}
|
}
|
||||||
t2 := subst.Typ(f.Type)
|
t2 := msubst.Typ(f.Type)
|
||||||
oldsym := f.Nname.Sym()
|
oldsym := f.Nname.Sym()
|
||||||
newsym := MakeInstName(oldsym, targs, true)
|
newsym := MakeInstName(oldsym, targs, true)
|
||||||
var nname *ir.Name
|
var nname *ir.Name
|
||||||
|
|
|
@ -1165,7 +1165,7 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type {
|
||||||
|
|
||||||
case types.TINTER:
|
case types.TINTER:
|
||||||
newt = ts.tinter(t)
|
newt = ts.tinter(t)
|
||||||
if newt == t {
|
if newt == t && !targsChanged {
|
||||||
newt = nil
|
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.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64,
|
||||||
types.TUINTPTR, types.TBOOL, types.TSTRING, types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128:
|
types.TUINTPTR, types.TBOOL, types.TSTRING, types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128:
|
||||||
newt = t.Underlying()
|
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 {
|
if newt == nil {
|
||||||
// Even though there were typeparams in the type, there may be no
|
// 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).terms = terms
|
||||||
t.Extra.(*Union).tildes = tildes
|
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
|
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.
|
// 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 {
|
func (d *deadcodePass) decodeIfaceMethod(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, off int64) methodsig {
|
||||||
p := ldr.Data(symIdx)
|
p := ldr.Data(symIdx)
|
||||||
|
if p == nil {
|
||||||
|
panic(fmt.Sprintf("missing symbol %q", ldr.SymName(symIdx)))
|
||||||
|
}
|
||||||
if decodetypeKind(arch, p)&kindMask != kindInterface {
|
if decodetypeKind(arch, p)&kindMask != kindInterface {
|
||||||
panic(fmt.Sprintf("symbol %q is not an interface", ldr.SymName(symIdx)))
|
panic(fmt.Sprintf("symbol %q is not an interface", ldr.SymName(symIdx)))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue