diff --git a/src/cmd/compile/internal/types2/alias.go b/src/cmd/compile/internal/types2/alias.go index 5148d5db034..07f35b1854a 100644 --- a/src/cmd/compile/internal/types2/alias.go +++ b/src/cmd/compile/internal/types2/alias.go @@ -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 diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 72227ab1225..308d1f550ad 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -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 diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 650ae846a61..7c4cd732501 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -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: diff --git a/src/go/types/alias.go b/src/go/types/alias.go index af43471a324..7adb3deb58b 100644 --- a/src/go/types/alias.go +++ b/src/go/types/alias.go @@ -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 diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 7bec790b558..0435f2bf261 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -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 diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 5ad2ff61eb1..6be106d3aa9 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -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 index 00000000000..b60a7447aaa --- /dev/null +++ b/test/fixedbugs/issue68580.go @@ -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]