[go] types2, go/types: fix conversion error for pointer to type param

2 views
Skip to first unread message

Chencheng Jiang (Gerrit)

unread,
Jun 6, 2026, 7:19:45 PM (6 hours ago) Jun 6
to goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

Chencheng Jiang has uploaded the change for review

Commit message

types2, go/types: fix conversion error for pointer to type param

During conversion checking, assignableTo probes interface targets to
produce the helpful pointer-to-interface diagnostic. Because type
parameters have interface underlying types, that probe also matched
targets such as *A where A is a type parameter, leaking an assignability
error into generic conversion diagnostics.

Limit the pointer-to-interface probe to pointers whose base is a
non-type-parameter interface, and use interfacePtrError for consistency.
Add a fixedbugs test for conversions to *A.

Fixes #79883
Change-Id: Ie2c5860b6a13a782442716eac6276a97310f6ee3

Change diff

diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go
index 3c4044e..fb7c553 100644
--- a/src/cmd/compile/internal/types2/instantiate.go
+++ b/src/cmd/compile/internal/types2/instantiate.go
@@ -245,7 +245,7 @@
if cause != nil {
var detail string
if isInterfacePtr(Tu) {
- detail = check.sprintf("type %s is pointer to interface, not interface", T)
+ detail = check.interfacePtrError(T)
} else {
detail = check.sprintf("%s is not an interface", T)
}
diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go
index 107101f..b9744b4 100644
--- a/src/cmd/compile/internal/types2/lookup.go
+++ b/src/cmd/compile/internal/types2/lookup.go
@@ -564,6 +564,11 @@
return p != nil && IsInterface(p.base)
}

+func isNonTypeParamInterfacePtr(T Type) bool {
+ p, _ := T.Underlying().(*Pointer)
+ return p != nil && isNonTypeParamInterface(p.base)
+}
+
// check may be nil.
func (check *Checker) interfacePtrError(T Type) string {
assert(isInterfacePtr(T))
diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go
index 0e8aa24..26598c0 100644
--- a/src/cmd/compile/internal/types2/operand.go
+++ b/src/cmd/compile/internal/types2/operand.go
@@ -370,9 +370,9 @@
}

// T is an interface type, but not a type parameter, and V implements T.
- // Also handle the case where T is a pointer to an interface so that we get
- // the Checker.implements error cause.
- if _, ok := Tu.(*Interface); ok && Tp == nil || isInterfacePtr(Tu) {
+ // Also handle the case where T is a pointer to a non-type-parameter
+ // interface so that we get the Checker.implements error cause.
+ if _, ok := Tu.(*Interface); ok && Tp == nil || isNonTypeParamInterfacePtr(Tu) {
if check.implements(V, T, false, cause) {
return true, 0
}
diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go
index 6488494..b0df7b9 100644
--- a/src/go/types/instantiate.go
+++ b/src/go/types/instantiate.go
@@ -248,7 +248,7 @@
if cause != nil {
var detail string
if isInterfacePtr(Tu) {
- detail = check.sprintf("type %s is pointer to interface, not interface", T)
+ detail = check.interfacePtrError(T)
} else {
detail = check.sprintf("%s is not an interface", T)
}
diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go
index 0d056e7..5f9b54b 100644
--- a/src/go/types/lookup.go
+++ b/src/go/types/lookup.go
@@ -567,6 +567,11 @@
return p != nil && IsInterface(p.base)
}

+func isNonTypeParamInterfacePtr(T Type) bool {
+ p, _ := T.Underlying().(*Pointer)
+ return p != nil && isNonTypeParamInterface(p.base)
+}
+
// check may be nil.
func (check *Checker) interfacePtrError(T Type) string {
assert(isInterfacePtr(T))
diff --git a/src/go/types/operand.go b/src/go/types/operand.go
index 860611a..7386b64 100644
--- a/src/go/types/operand.go
+++ b/src/go/types/operand.go
@@ -374,9 +374,9 @@
}

// T is an interface type, but not a type parameter, and V implements T.
- // Also handle the case where T is a pointer to an interface so that we get
- // the Checker.implements error cause.
- if _, ok := Tu.(*Interface); ok && Tp == nil || isInterfacePtr(Tu) {
+ // Also handle the case where T is a pointer to a non-type-parameter
+ // interface so that we get the Checker.implements error cause.
+ if _, ok := Tu.(*Interface); ok && Tp == nil || isNonTypeParamInterfacePtr(Tu) {
if check.implements(V, T, false, cause) {
return true, 0
}
diff --git a/src/internal/types/testdata/fixedbugs/issue79883.go b/src/internal/types/testdata/fixedbugs/issue79883.go
new file mode 100644
index 0000000..fe97955
--- /dev/null
+++ b/src/internal/types/testdata/fixedbugs/issue79883.go
@@ -0,0 +1,14 @@
+// Copyright 2026 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
+
+func _[A [1]int]() {
+ var s string
+ _ = (*A)(s /* ERRORx `^cannot convert s \(variable of type string\) to type \*A$` */)
+}
+
+func _[A [1]int](p *[1]int) {
+ _ = (*A)(p /* ERRORx `^cannot convert p \(variable of type \*\[1\]int\) to type \*A$` */)
+}

Change information

Files:
  • M src/cmd/compile/internal/types2/instantiate.go
  • M src/cmd/compile/internal/types2/lookup.go
  • M src/cmd/compile/internal/types2/operand.go
  • M src/go/types/instantiate.go
  • M src/go/types/lookup.go
  • M src/go/types/operand.go
  • A src/internal/types/testdata/fixedbugs/issue79883.go
Change size: S
Delta: 7 files changed, 32 insertions(+), 8 deletions(-)
Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: newchange
Gerrit-Project: go
Gerrit-Branch: master
Gerrit-Change-Id: Ie2c5860b6a13a782442716eac6276a97310f6ee3
Gerrit-Change-Number: 787900
Gerrit-PatchSet: 1
Gerrit-Owner: Chencheng Jiang <dorb...@gmail.com>
unsatisfied_requirement
satisfied_requirement
open
diffy

qiu laidongfeng (Gerrit)

unread,
12:02 AM (2 hours ago) 12:02 AM
to Chencheng Jiang, goph...@pubsubhelper.golang.org, Robert Findley, Robert Griesemer, Gopher Robot, golang-co...@googlegroups.com
Attention needed from Chencheng Jiang, Robert Findley and Robert Griesemer

qiu laidongfeng voted Commit-Queue+1

Commit-Queue+1
Open in Gerrit

Related details

Attention is currently required from:
  • Chencheng Jiang
  • Robert Findley
  • Robert Griesemer
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: go
Gerrit-Branch: master
Gerrit-Change-Id: Ie2c5860b6a13a782442716eac6276a97310f6ee3
Gerrit-Change-Number: 787900
Gerrit-PatchSet: 1
Gerrit-Owner: Chencheng Jiang <dorb...@gmail.com>
Gerrit-Reviewer: Robert Findley <rfin...@golang.org>
Gerrit-Reviewer: Robert Griesemer <g...@golang.org>
Gerrit-Reviewer: qiu laidongfeng <26454...@qq.com>
Gerrit-CC: Gopher Robot <go...@golang.org>
Gerrit-Attention: Robert Griesemer <g...@golang.org>
Gerrit-Attention: Chencheng Jiang <dorb...@gmail.com>
Gerrit-Attention: Robert Findley <rfin...@golang.org>
Gerrit-Comment-Date: Sun, 07 Jun 2026 04:02:34 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
unsatisfied_requirement
satisfied_requirement
open
diffy
Reply all
Reply to author
Forward
0 new messages