]> Cypherpunks repositories - gostls13.git/commitdiff
spec: adjust rule for type parameter on RHS of alias declaration
authorRobert Griesemer <gri@google.com>
Tue, 18 Nov 2025 23:47:44 +0000 (15:47 -0800)
committerGopher Robot <gobot@golang.org>
Thu, 20 Nov 2025 18:25:17 +0000 (10:25 -0800)
Per discussion on issue #75885, a type parameter on the RHS of an alias
declaration must not be declared in the same declaration (but it may be
declared by an enclosing function). This relaxes the spec slightly and
allows for (pre-existing) test cases.

Add a corresponding check to the type checker (there was no check for
type parameters on the RHS of alias declarations at all, before).

Fixes #75884.
Fixes #75885.

Change-Id: I1e5675978e6423d626c068829d4bf5e90035ea82
Reviewed-on: https://go-review.googlesource.com/c/go/+/721820
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-by: Mark Freeman <markfreeman@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

doc/go_spec.html
src/cmd/compile/internal/types2/decl.go
src/go/types/decl.go
src/internal/types/testdata/fixedbugs/issue75885.go [new file with mode: 0644]

index 77400ad210ebb60481fa77cd7e35288601a22614..b75845372da3769e1ad0d080cd65287151cce9f4 100644 (file)
@@ -1,6 +1,6 @@
 <!--{
        "Title": "The Go Programming Language Specification",
-       "Subtitle": "Language version go1.26 (Nov 12, 2025)",
+       "Subtitle": "Language version go1.26 (Nov 18, 2025)",
        "Path": "/ref/spec"
 }-->
 
@@ -2487,11 +2487,15 @@ type set[P comparable] = map[P]bool
 </pre>
 
 <p>
-In an alias declaration the given type cannot be a type parameter.
+In an alias declaration the given type cannot be a type parameter declared in the same declaration.
 </p>
 
 <pre>
-type A[P any] = P    // illegal: P is a type parameter
+type A[P any] = P   // illegal: P is a type parameter declared in the declaration of A
+
+func f[P any]() {
+       type A = P  // ok: T is a type parameter declared by the enclosing function
+}
 </pre>
 
 <h4 id="Type_definitions">Type definitions</h4>
@@ -2601,8 +2605,8 @@ In a type definition the given type cannot be a type parameter.
 <pre>
 type T[P any] P    // illegal: P is a type parameter
 
-func f[T any]() {
-       type L T   // illegal: T is a type parameter declared by the enclosing function
+func f[P any]() {
+       type L P   // illegal: P is a type parameter declared by the enclosing function
 }
 </pre>
 
index 60371651ab0b687de9bc7efa89b0bcfe64445600..5cb52fdbe45641778d7d71ddf0211a93cee84b1f 100644 (file)
@@ -497,9 +497,14 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *TypeN
 
                        rhs = check.declaredType(tdecl.Type, obj)
                        assert(rhs != nil)
-
                        alias.fromRHS = rhs
-                       unalias(alias) // populate alias.actual
+
+                       // spec: In an alias declaration the given type cannot be a type parameter declared in the same declaration."
+                       // (see also go.dev/issue/75884, go.dev/issue/#75885)
+                       if tpar, ok := rhs.(*TypeParam); ok && alias.tparams != nil && slices.Index(alias.tparams.list(), tpar) >= 0 {
+                               check.error(tdecl.Type, MisplacedTypeParam, "cannot use type parameter declared in alias declaration as RHS")
+                               alias.fromRHS = Typ[Invalid]
+                       }
                } else {
                        if !versionErr && tparam0 != nil {
                                check.error(tdecl, UnsupportedFeature, "generic type alias requires GODEBUG=gotypesalias=1 or unset")
index 4b374fb66dfa147b7bf6177ef28628995598b067..fffcb590e605c0f73cedf4c992ab912444850235 100644 (file)
@@ -572,9 +572,14 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *TypeName
 
                        rhs = check.declaredType(tdecl.Type, obj)
                        assert(rhs != nil)
-
                        alias.fromRHS = rhs
-                       unalias(alias) // populate alias.actual
+
+                       // spec: In an alias declaration the given type cannot be a type parameter declared in the same declaration."
+                       // (see also go.dev/issue/75884, go.dev/issue/#75885)
+                       if tpar, ok := rhs.(*TypeParam); ok && alias.tparams != nil && slices.Index(alias.tparams.list(), tpar) >= 0 {
+                               check.error(tdecl.Type, MisplacedTypeParam, "cannot use type parameter declared in alias declaration as RHS")
+                               alias.fromRHS = Typ[Invalid]
+                       }
                } else {
                        // With Go1.23, the default behavior is to use Alias nodes,
                        // reflected by check.enableAlias. Signal non-default behavior.
diff --git a/src/internal/types/testdata/fixedbugs/issue75885.go b/src/internal/types/testdata/fixedbugs/issue75885.go
new file mode 100644 (file)
index 0000000..f0cf4a6
--- /dev/null
@@ -0,0 +1,15 @@
+// -gotypesalias=1
+
+// Copyright 2025 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 p
+
+type A[P any] = P // ERROR "cannot use type parameter declared in alias declaration as RHS"
+
+func _[P any]() {
+       type A[P any] = P // ERROR "cannot use type parameter declared in alias declaration as RHS"
+       type B = P
+       type C[Q any] = P
+}