diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index 0143fd3d45..027c8598fd 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -86,6 +86,7 @@ func (g *irgen) constDecl(out *ir.Nodes, decl *syntax.ConstDecl) { } 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 // during types2-to-types1 translation if this is a generic function. g.curDecl = decl.Name.Value @@ -133,6 +134,7 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) { } haveEmbed := g.haveEmbed + g.curDecl = "" g.later(func() { 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) { + assert(g.curDecl == "") // 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. 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 out.Append(ir.NewDecl(g.pos(decl), ir.ODCLTYPE, name)) + g.curDecl = "" return } @@ -219,6 +223,7 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) { } types.ResumeCheckSize() + g.curDecl = "" if otyp, ok := otyp.(*types2.Named); ok && otyp.NumMethods() != 0 { methods := make([]*types.Field, otyp.NumMethods()) for i := range methods { @@ -229,6 +234,7 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) { meth := g.obj(m) methods[i] = types.NewField(meth.Pos(), g.selector(m), meth.Type()) methods[i].Nname = meth + g.curDecl = "" } ntyp.Methods().Set(methods) } diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index fa24ab1844..4f6d828720 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -229,6 +229,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { pkg := g.tpkg(typ) // Create the unique types1 name for a type param, using its context with a // function, type, or method declaration. + assert(g.curDecl != "") nm := g.curDecl + "." + typ.Obj().Name() sym := pkg.Lookup(nm) if sym.Def != nil { @@ -331,11 +332,15 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { tparams := make([]*types.Type, rparams.Len()) // Set g.curDecl to be the method context, so type // 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() for i := range tparams { tparams[i] = g.typ1(rparams.At(i)) } + g.curDecl = savedCurDecl assert(len(tparams) == len(targs)) ts := typecheck.Tsubster{ Tparams: tparams, diff --git a/test/typeparam/issue49893.dir/a.go b/test/typeparam/issue49893.dir/a.go new file mode 100644 index 0000000000..bc810cd3dd --- /dev/null +++ b/test/typeparam/issue49893.dir/a.go @@ -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("") +} diff --git a/test/typeparam/issue49893.dir/b.go b/test/typeparam/issue49893.dir/b.go new file mode 100644 index 0000000000..b36f6bddf0 --- /dev/null +++ b/test/typeparam/issue49893.dir/b.go @@ -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] +} diff --git a/test/typeparam/issue49893.dir/main.go b/test/typeparam/issue49893.dir/main.go new file mode 100644 index 0000000000..8b5b3bdad7 --- /dev/null +++ b/test/typeparam/issue49893.dir/main.go @@ -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) +} diff --git a/test/typeparam/issue49893.go b/test/typeparam/issue49893.go new file mode 100644 index 0000000000..87b4ff46c1 --- /dev/null +++ b/test/typeparam/issue49893.go @@ -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