mirror of
https://github.com/golang/go
synced 2024-10-14 11:53:56 +00:00
cmd/compile: fix case where g.curDecl should be saved/restored
When we set g.curDecl for the type params created during fillinMethods for an instantiated type, we need to save/restore its value, because fillinMethods() may be called while processing a typeDecl. We want the value of g.curDecl to continue to be correct for type params created in the typeDecl. Because of ordering issues, not restoring g.curDecl happens to cause problems (which don't always show up visibly) exactly when a type param is not actually used in a type declaration. Cleared g.curDecl to "" at the later points in typeDecl() and funcDecl(). This allows adding asserts that g.curDecl is always empty ("") when we set it in typeDecl() and funcDecl(), and always non-empty when we use it in typ0(). Fixes #49893 Change-Id: Ic2fb1df791585bd257f2b86ffaae0453c31705c5 Reviewed-on: https://go-review.googlesource.com/c/go/+/368454 Trust: Dan Scales <danscales@google.com> Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
1b2930d70c
commit
d34051bf16
|
@ -86,6 +86,7 @@ func (g *irgen) constDecl(out *ir.Nodes, decl *syntax.ConstDecl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) {
|
func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) {
|
||||||
|
assert(g.curDecl == "")
|
||||||
// Set g.curDecl to the function name, as context for the type params declared
|
// Set g.curDecl to the function name, as context for the type params declared
|
||||||
// during types2-to-types1 translation if this is a generic function.
|
// during types2-to-types1 translation if this is a generic function.
|
||||||
g.curDecl = decl.Name.Value
|
g.curDecl = decl.Name.Value
|
||||||
|
@ -133,6 +134,7 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
haveEmbed := g.haveEmbed
|
haveEmbed := g.haveEmbed
|
||||||
|
g.curDecl = ""
|
||||||
g.later(func() {
|
g.later(func() {
|
||||||
defer func(b bool) { g.haveEmbed = b }(g.haveEmbed)
|
defer func(b bool) { g.haveEmbed = b }(g.haveEmbed)
|
||||||
|
|
||||||
|
@ -158,6 +160,7 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) {
|
func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) {
|
||||||
|
assert(g.curDecl == "")
|
||||||
// Set g.curDecl to the type name, as context for the type params declared
|
// Set g.curDecl to the type name, as context for the type params declared
|
||||||
// during types2-to-types1 translation if this is a generic type.
|
// during types2-to-types1 translation if this is a generic type.
|
||||||
g.curDecl = decl.Name.Value
|
g.curDecl = decl.Name.Value
|
||||||
|
@ -167,6 +170,7 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) {
|
||||||
assert(name.Alias()) // should be set by irgen.obj
|
assert(name.Alias()) // should be set by irgen.obj
|
||||||
|
|
||||||
out.Append(ir.NewDecl(g.pos(decl), ir.ODCLTYPE, name))
|
out.Append(ir.NewDecl(g.pos(decl), ir.ODCLTYPE, name))
|
||||||
|
g.curDecl = ""
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,6 +223,7 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) {
|
||||||
}
|
}
|
||||||
types.ResumeCheckSize()
|
types.ResumeCheckSize()
|
||||||
|
|
||||||
|
g.curDecl = ""
|
||||||
if otyp, ok := otyp.(*types2.Named); ok && otyp.NumMethods() != 0 {
|
if otyp, ok := otyp.(*types2.Named); ok && otyp.NumMethods() != 0 {
|
||||||
methods := make([]*types.Field, otyp.NumMethods())
|
methods := make([]*types.Field, otyp.NumMethods())
|
||||||
for i := range methods {
|
for i := range methods {
|
||||||
|
@ -229,6 +234,7 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) {
|
||||||
meth := g.obj(m)
|
meth := g.obj(m)
|
||||||
methods[i] = types.NewField(meth.Pos(), g.selector(m), meth.Type())
|
methods[i] = types.NewField(meth.Pos(), g.selector(m), meth.Type())
|
||||||
methods[i].Nname = meth
|
methods[i].Nname = meth
|
||||||
|
g.curDecl = ""
|
||||||
}
|
}
|
||||||
ntyp.Methods().Set(methods)
|
ntyp.Methods().Set(methods)
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,6 +229,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
|
||||||
pkg := g.tpkg(typ)
|
pkg := g.tpkg(typ)
|
||||||
// Create the unique types1 name for a type param, using its context with a
|
// Create the unique types1 name for a type param, using its context with a
|
||||||
// function, type, or method declaration.
|
// function, type, or method declaration.
|
||||||
|
assert(g.curDecl != "")
|
||||||
nm := g.curDecl + "." + typ.Obj().Name()
|
nm := g.curDecl + "." + typ.Obj().Name()
|
||||||
sym := pkg.Lookup(nm)
|
sym := pkg.Lookup(nm)
|
||||||
if sym.Def != nil {
|
if sym.Def != nil {
|
||||||
|
@ -331,11 +332,15 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) {
|
||||||
tparams := make([]*types.Type, rparams.Len())
|
tparams := make([]*types.Type, rparams.Len())
|
||||||
// Set g.curDecl to be the method context, so type
|
// Set g.curDecl to be the method context, so type
|
||||||
// params in the receiver of the method that we are
|
// params in the receiver of the method that we are
|
||||||
// translating gets the right unique name.
|
// translating gets the right unique name. We could
|
||||||
|
// be in a top-level typeDecl, so save and restore
|
||||||
|
// the current contents of g.curDecl.
|
||||||
|
savedCurDecl := g.curDecl
|
||||||
g.curDecl = typ.Obj().Name() + "." + m.Name()
|
g.curDecl = typ.Obj().Name() + "." + m.Name()
|
||||||
for i := range tparams {
|
for i := range tparams {
|
||||||
tparams[i] = g.typ1(rparams.At(i))
|
tparams[i] = g.typ1(rparams.At(i))
|
||||||
}
|
}
|
||||||
|
g.curDecl = savedCurDecl
|
||||||
assert(len(tparams) == len(targs))
|
assert(len(tparams) == len(targs))
|
||||||
ts := typecheck.Tsubster{
|
ts := typecheck.Tsubster{
|
||||||
Tparams: tparams,
|
Tparams: tparams,
|
||||||
|
|
15
test/typeparam/issue49893.dir/a.go
Normal file
15
test/typeparam/issue49893.dir/a.go
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package a
|
||||||
|
|
||||||
|
type Option[T any] interface {
|
||||||
|
ToSeq() Seq[T]
|
||||||
|
}
|
||||||
|
|
||||||
|
type Seq[T any] []T
|
||||||
|
|
||||||
|
func (r Seq[T]) Find(p func(v T) bool) Option[T] {
|
||||||
|
panic("")
|
||||||
|
}
|
15
test/typeparam/issue49893.dir/b.go
Normal file
15
test/typeparam/issue49893.dir/b.go
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package b
|
||||||
|
|
||||||
|
import "a"
|
||||||
|
|
||||||
|
type Ap1[A, B any] struct {
|
||||||
|
opt a.Option[A]
|
||||||
|
}
|
||||||
|
|
||||||
|
type Ap2[A, B any] struct {
|
||||||
|
opt a.Option[A]
|
||||||
|
}
|
15
test/typeparam/issue49893.dir/main.go
Normal file
15
test/typeparam/issue49893.dir/main.go
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"b"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
opt := b.Ap1[string, string]{}
|
||||||
|
fmt.Println(opt)
|
||||||
|
}
|
7
test/typeparam/issue49893.go
Normal file
7
test/typeparam/issue49893.go
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
// compiledir -G=3
|
||||||
|
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ignored
|
Loading…
Reference in a new issue