Skip to content

Commit 032ef4b

Browse files
committed
cmd/compile: fix creation of named generic types (setting of t.nod)
The correct setting of t.nod is needed when exporting types. Make sure we create instantiated named types correctly so t.nod is set. New test file interfacearg.go that tests this (by instantiating a type with an interface). Also has tests for various kinds of method expressions. Change-Id: Ia7fd9debd495336b73788af9e35d72331bb7d2b5 Reviewed-on: https://go-review.googlesource.com/c/go/+/305730 Run-TryBot: Dan Scales <[email protected]> TryBot-Result: Go Bot <[email protected]> Trust: Dan Scales <[email protected]> Trust: Robert Griesemer <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
1 parent bb2fc21 commit 032ef4b

File tree

4 files changed

+64
-13
lines changed

4 files changed

+64
-13
lines changed

src/cmd/compile/internal/noder/stencil.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -715,12 +715,10 @@ func (subst *subster) typ(t *types.Type) *types.Type {
715715
return newsym.Def.Type()
716716
}
717717

718-
// In order to deal with recursive generic types, create a TFORW type
719-
// initially and set its Def field, so it can be found if this type
720-
// appears recursively within the type.
721-
forw = types.New(types.TFORW)
722-
forw.SetSym(newsym)
723-
newsym.Def = ir.TypeNode(forw)
718+
// In order to deal with recursive generic types, create a TFORW
719+
// type initially and set the Def field of its sym, so it can be
720+
// found if this type appears recursively within the type.
721+
forw = newNamedTypeWithSym(t.Pos(), newsym)
724722
//println("Creating new type by sub", newsym.Name, forw.HasTParam())
725723
forw.SetRParams(neededTargs)
726724
}
@@ -894,3 +892,13 @@ func deref(t *types.Type) *types.Type {
894892
}
895893
return t
896894
}
895+
896+
// newNamedTypeWithSym returns a TFORW type t with name specified by sym, such
897+
// that t.nod and sym.Def are set correctly.
898+
func newNamedTypeWithSym(pos src.XPos, sym *types.Sym) *types.Type {
899+
name := ir.NewDeclNameAt(pos, ir.OTYPE, sym)
900+
forw := types.NewNamed(name)
901+
name.SetType(forw)
902+
sym.Def = name
903+
return forw
904+
}

src/cmd/compile/internal/noder/types.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,8 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
120120
// which may set HasTParam) before translating the
121121
// underlying type itself, so we handle recursion
122122
// correctly, including via method signatures.
123-
ntyp := types.New(types.TFORW)
123+
ntyp := newNamedTypeWithSym(g.pos(typ.Obj().Pos()), s)
124124
g.typs[typ] = ntyp
125-
ntyp.SetSym(s)
126-
s.Def = ir.TypeNode(ntyp)
127125

128126
// If ntyp still has type params, then we must be
129127
// referencing something like 'value[T2]', as when

src/cmd/compile/internal/types/type.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,9 @@ type Type struct {
160160
methods Fields
161161
allMethods Fields
162162

163-
nod Object // canonical OTYPE node
164-
underlying *Type // original type (type literal or predefined type)
163+
// canonical OTYPE node for a named type (should be an ir.Name node with same sym)
164+
nod Object
165+
underlying *Type // original type (type literal or predefined type)
165166

166167
// Cache of composite types, with this type being the element type.
167168
cache struct {
@@ -1642,15 +1643,15 @@ var (
16421643
TypeResultMem = newResults([]*Type{TypeMem})
16431644
)
16441645

1645-
// NewNamed returns a new named type for the given type name.
1646+
// NewNamed returns a new named type for the given type name. obj should be an ir.Name.
16461647
func NewNamed(obj Object) *Type {
16471648
t := New(TFORW)
16481649
t.sym = obj.Sym()
16491650
t.nod = obj
16501651
return t
16511652
}
16521653

1653-
// Obj returns the type name for the named type t.
1654+
// Obj returns the canonical type name node for a named type t, nil for an unnamed type.
16541655
func (t *Type) Obj() Object {
16551656
if t.sym != nil {
16561657
return t.nod

test/typeparam/interfacearg.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// run -gcflags=-G=3
2+
3+
// Copyright 2021 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
package main
8+
9+
type I interface{}
10+
11+
type _S[T any] struct {
12+
*T
13+
}
14+
15+
// F is a non-generic function, but has a type _S[I] which is instantiated from a
16+
// generic type. Test that _S[I] is successfully exported.
17+
func F() {
18+
v := _S[I]{}
19+
if v.T != nil {
20+
panic(v)
21+
}
22+
}
23+
24+
// Testing the various combinations of method expressions.
25+
type S1 struct{}
26+
func (*S1) M() {}
27+
28+
type S2 struct{}
29+
func (S2) M() {}
30+
31+
func _F1[T interface{ M() }](t T) {
32+
_ = T.M
33+
}
34+
35+
func F2() {
36+
_F1(&S1{})
37+
_F1(S2{})
38+
_F1(&S2{})
39+
}
40+
41+
func main() {
42+
F()
43+
F2()
44+
}

0 commit comments

Comments
 (0)