]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.23] types2, go/types: fix instantiation of named type with generi...
authorCuong Manh Le <cuong.manhle.vn@gmail.com>
Thu, 25 Jul 2024 10:17:44 +0000 (17:17 +0700)
committerGopher Robot <gobot@golang.org>
Fri, 26 Jul 2024 16:35:29 +0000 (16:35 +0000)
The typechecker is assuming that alias instances cannot be reached from
a named type. However, when type parameters on aliases are permited, it
can happen.

This CL changes the typechecker to propagate the correct named instance
is being expanded.

Updates #46477
Fixes #68580

Change-Id: Id0879021f4640c0fefe277701d5096c649413811
Reviewed-on: https://go-review.googlesource.com/c/go/+/601115
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/601116

src/cmd/compile/internal/types2/alias.go
src/cmd/compile/internal/types2/instantiate.go
src/cmd/compile/internal/types2/subst.go
src/go/types/alias.go
src/go/types/instantiate.go
src/go/types/subst.go
test/fixedbugs/issue68580.go [new file with mode: 0644]

index 5148d5db03414231298b5680c0979f0758c3aa99..07f35b1854acafdad8d7fd1ea4763be23fe21928 100644 (file)
@@ -134,10 +134,10 @@ func (check *Checker) newAlias(obj *TypeName, rhs Type) *Alias {
 // newAliasInstance creates a new alias instance for the given origin and type
 // arguments, recording pos as the position of its synthetic object (for error
 // reporting).
-func (check *Checker) newAliasInstance(pos syntax.Pos, orig *Alias, targs []Type, ctxt *Context) *Alias {
+func (check *Checker) newAliasInstance(pos syntax.Pos, orig *Alias, targs []Type, expanding *Named, ctxt *Context) *Alias {
        assert(len(targs) > 0)
        obj := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
-       rhs := check.subst(pos, orig.fromRHS, makeSubstMap(orig.TypeParams().list(), targs), nil, ctxt)
+       rhs := check.subst(pos, orig.fromRHS, makeSubstMap(orig.TypeParams().list(), targs), expanding, ctxt)
        res := check.newAlias(obj, rhs)
        res.orig = orig
        res.tparams = orig.tparams
index 72227ab12256dd867b58fe86ce60dd9f0400d727..308d1f550ad4fabe3fe1079b3209e0dc88ad9f18 100644 (file)
@@ -11,6 +11,7 @@ import (
        "cmd/compile/internal/syntax"
        "errors"
        "fmt"
+       "internal/buildcfg"
        . "internal/types/errors"
 )
 
@@ -126,8 +127,9 @@ func (check *Checker) instance(pos syntax.Pos, orig genericType, targs []Type, e
                res = check.newNamedInstance(pos, orig, targs, expanding) // substituted lazily
 
        case *Alias:
-               // TODO(gri) is this correct?
-               assert(expanding == nil) // Alias instances cannot be reached from Named types
+               if !buildcfg.Experiment.AliasTypeParams {
+                       assert(expanding == nil) // Alias instances cannot be reached from Named types
+               }
 
                tparams := orig.TypeParams()
                // TODO(gri) investigate if this is needed (type argument and parameter count seem to be correct here)
@@ -138,7 +140,7 @@ func (check *Checker) instance(pos syntax.Pos, orig genericType, targs []Type, e
                        return orig // nothing to do (minor optimization)
                }
 
-               return check.newAliasInstance(pos, orig, targs, ctxt)
+               return check.newAliasInstance(pos, orig, targs, expanding, ctxt)
 
        case *Signature:
                assert(expanding == nil) // function instances cannot be reached from Named types
index 650ae846a61e85dd62a40be52991a9f14e7d6948..7c4cd732501e43a5553f626d910a89950a58e74b 100644 (file)
@@ -115,7 +115,7 @@ func (subst *subster) typ(typ Type) Type {
                // that has a type argument for it.
                targs, updated := subst.typeList(t.TypeArgs().list())
                if updated {
-                       return subst.check.newAliasInstance(subst.pos, t.orig, targs, subst.ctxt)
+                       return subst.check.newAliasInstance(subst.pos, t.orig, targs, subst.expanding, subst.ctxt)
                }
 
        case *Array:
index af43471a324176a30053c91104bded71ba001719..7adb3deb58bbc75d352d120db4bc7c3bc43a2d4a 100644 (file)
@@ -137,10 +137,10 @@ func (check *Checker) newAlias(obj *TypeName, rhs Type) *Alias {
 // newAliasInstance creates a new alias instance for the given origin and type
 // arguments, recording pos as the position of its synthetic object (for error
 // reporting).
-func (check *Checker) newAliasInstance(pos token.Pos, orig *Alias, targs []Type, ctxt *Context) *Alias {
+func (check *Checker) newAliasInstance(pos token.Pos, orig *Alias, targs []Type, expanding *Named, ctxt *Context) *Alias {
        assert(len(targs) > 0)
        obj := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
-       rhs := check.subst(pos, orig.fromRHS, makeSubstMap(orig.TypeParams().list(), targs), nil, ctxt)
+       rhs := check.subst(pos, orig.fromRHS, makeSubstMap(orig.TypeParams().list(), targs), expanding, ctxt)
        res := check.newAlias(obj, rhs)
        res.orig = orig
        res.tparams = orig.tparams
index 7bec790b5586ad4081da6b47b136adf251bd4c9e..0435f2bf261647f38c4b4e6c8270f22d7a346ee5 100644 (file)
@@ -14,6 +14,7 @@ import (
        "errors"
        "fmt"
        "go/token"
+       "internal/buildcfg"
        . "internal/types/errors"
 )
 
@@ -129,8 +130,9 @@ func (check *Checker) instance(pos token.Pos, orig genericType, targs []Type, ex
                res = check.newNamedInstance(pos, orig, targs, expanding) // substituted lazily
 
        case *Alias:
-               // TODO(gri) is this correct?
-               assert(expanding == nil) // Alias instances cannot be reached from Named types
+               if !buildcfg.Experiment.AliasTypeParams {
+                       assert(expanding == nil) // Alias instances cannot be reached from Named types
+               }
 
                tparams := orig.TypeParams()
                // TODO(gri) investigate if this is needed (type argument and parameter count seem to be correct here)
@@ -141,7 +143,7 @@ func (check *Checker) instance(pos token.Pos, orig genericType, targs []Type, ex
                        return orig // nothing to do (minor optimization)
                }
 
-               return check.newAliasInstance(pos, orig, targs, ctxt)
+               return check.newAliasInstance(pos, orig, targs, expanding, ctxt)
 
        case *Signature:
                assert(expanding == nil) // function instances cannot be reached from Named types
index 5ad2ff61eb1d30ea9f0cc62c4dea37abf321826e..6be106d3aa99d6ae78a68569239f36c7ac03eef6 100644 (file)
@@ -118,7 +118,7 @@ func (subst *subster) typ(typ Type) Type {
                // that has a type argument for it.
                targs, updated := subst.typeList(t.TypeArgs().list())
                if updated {
-                       return subst.check.newAliasInstance(subst.pos, t.orig, targs, subst.ctxt)
+                       return subst.check.newAliasInstance(subst.pos, t.orig, targs, subst.expanding, subst.ctxt)
                }
 
        case *Array:
diff --git a/test/fixedbugs/issue68580.go b/test/fixedbugs/issue68580.go
new file mode 100644 (file)
index 0000000..b60a744
--- /dev/null
@@ -0,0 +1,15 @@
+// compile -goexperiment aliastypeparams
+
+// Copyright 2024 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
+
+type A[P any] = struct{ _ P }
+
+type N[P any] A[P]
+
+func f[P any](N[P]) {}
+
+var _ = f[int]