]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[release-branch.go1.21] go/types, types2: don't lose position info of interface embed...
authorRobert Griesemer <gri@golang.org>
Wed, 10 Jan 2024 23:49:33 +0000 (15:49 -0800)
committerCherry Mui <cherryyz@google.com>
Thu, 25 Jan 2024 17:49:05 +0000 (17:49 +0000)
Accurate position information for embedded types in interfaces is
crucial to identify the corresponding source file, and with that
the Go language version associated with that file. (The position
information is also important for proper error messages.)

Before this CL, the position information for embedded types was
discarded after type set computation, in the assumption that it
was not needed anymore. However, substitutions that update the
interface may lead to repeated type set computations which then
won't have the correct position information.

This CL does preserve the position information for embedded
types until the end of type checking (cleanup phase), and also
copy the position information during a substitution of the
interface.

The respective bug (#64759) doesn't seem to appear in 1.22 (most
likely because it's hidden by some of the changes made with respect
to the file version logic), but the existing code is still wrong.
The backport of this code to 1.21 and 1.20 fixes the issue in those
releases.

For #64759.
Fixes #65053.

Change-Id: I80f4004c9d79cb02eac6739c324c477706615102
Reviewed-on: https://go-review.googlesource.com/c/go/+/555296
Run-TryBot: Robert Griesemer <gri@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/555415
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/cmd/compile/internal/types2/issues_test.go
src/cmd/compile/internal/types2/subst.go
src/cmd/compile/internal/types2/typeset.go
src/go/types/issues_test.go
src/go/types/subst.go
src/go/types/typeset.go

index 3ac345729b9a51dc8dc3dc5e8c0945456a99f266..9d0adae8df92c418af927aa7723696cf4f23fd1f 100644 (file)
@@ -964,3 +964,20 @@ func f[I *T, T any]() {
                t.Fatalf("types of v and T are not pointer-identical: %p != %p", v.Type().(*TypeParam), T)
        }
 }
+
+func TestIssue64759(t *testing.T) {
+       const src = `
+//go:build go1.18
+package p
+
+func f[S ~[]E, E any](S) {}
+
+func _() {
+       f([]string{})
+}
+`
+       // Per the go:build directive, the source must typecheck
+       // even though the (module) Go version is set to go1.17.
+       conf := Config{GoVersion: "go1.17"}
+       mustTypecheck(src, &conf, nil)
+}
index 74d6294dff03f56e4d8f2d43159367ea7bb1dd16..a75040385589f59e1232bc821e529944725e5bff 100644 (file)
@@ -169,6 +169,7 @@ func (subst *subster) typ(typ Type) Type {
                if mcopied || ecopied {
                        iface := subst.check.newInterface()
                        iface.embeddeds = embeddeds
+                       iface.embedPos = t.embedPos
                        iface.implicit = t.implicit
                        iface.complete = t.complete
                        // If we've changed the interface type, we may need to replace its
index 70b9e36aef7e65bb06bd75ab2793accf48335c1b..8d33597ffd90a6b270d8550d233e7d1b61e24ba3 100644 (file)
@@ -304,7 +304,6 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
                // separately. Here we only need to intersect the term lists and comparable bits.
                allTerms, allComparable = intersectTermLists(allTerms, allComparable, terms, comparable)
        }
-       ityp.embedPos = nil // not needed anymore (errors have been reported)
 
        ityp.tset.comparable = allComparable
        if len(allMethods) != 0 {
index 4a559cbab31581000cb083ce5f9abf636e18408c..282939d64146bc795ca08a5cad7fa354cd44a919 100644 (file)
@@ -974,3 +974,20 @@ func f[I *T, T any]() {
                t.Fatalf("types of v and T are not pointer-identical: %p != %p", v.Type().(*TypeParam), T)
        }
 }
+
+func TestIssue64759(t *testing.T) {
+       const src = `
+//go:build go1.18
+package p
+
+func f[S ~[]E, E any](S) {}
+
+func _() {
+       f([]string{})
+}
+`
+       // Per the go:build directive, the source must typecheck
+       // even though the (module) Go version is set to go1.17.
+       conf := Config{GoVersion: "go1.17"}
+       mustTypecheck(src, &conf, nil)
+}
index 30c48e1badc4bd628010a83e006cbf2892ddae3f..96bc341a5fd00bde97389cb86225630e66801888 100644 (file)
@@ -171,6 +171,7 @@ func (subst *subster) typ(typ Type) Type {
                if mcopied || ecopied {
                        iface := subst.check.newInterface()
                        iface.embeddeds = embeddeds
+                       iface.embedPos = t.embedPos
                        iface.implicit = t.implicit
                        iface.complete = t.complete
                        // If we've changed the interface type, we may need to replace its
index 206aa3da08f78cd57c723b66f73551bee8ca4073..4cd118a2265535f68508ddf3e662d8fc14c398c9 100644 (file)
@@ -302,7 +302,6 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T
                // separately. Here we only need to intersect the term lists and comparable bits.
                allTerms, allComparable = intersectTermLists(allTerms, allComparable, terms, comparable)
        }
-       ityp.embedPos = nil // not needed anymore (errors have been reported)
 
        ityp.tset.comparable = allComparable
        if len(allMethods) != 0 {