Skip to content

Commit 25c5f6f

Browse files
griesemerRobert Griesemer
authored and
Robert Griesemer
committed
go/types, types2: don't lose position info of interface embeddings
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. Change-Id: I80f4004c9d79cb02eac6739c324c477706615102 Reviewed-on: https://go-review.googlesource.com/c/go/+/555296 Run-TryBot: Robert Griesemer <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Robert Findley <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
1 parent d1674cb commit 25c5f6f

File tree

6 files changed

+36
-2
lines changed

6 files changed

+36
-2
lines changed

src/cmd/compile/internal/types2/issues_test.go

+17
Original file line numberDiff line numberDiff line change
@@ -1076,3 +1076,20 @@ func TestIssue59831(t *testing.T) {
10761076
}
10771077
}
10781078
}
1079+
1080+
func TestIssue64759(t *testing.T) {
1081+
const src = `
1082+
//go:build go1.18
1083+
package p
1084+
1085+
func f[S ~[]E, E any](S) {}
1086+
1087+
func _() {
1088+
f([]string{})
1089+
}
1090+
`
1091+
// Per the go:build directive, the source must typecheck
1092+
// even though the (module) Go version is set to go1.17.
1093+
conf := Config{GoVersion: "go1.17"}
1094+
mustTypecheck(src, &conf, nil)
1095+
}

src/cmd/compile/internal/types2/subst.go

+1
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ func (subst *subster) typ(typ Type) Type {
169169
if mcopied || ecopied {
170170
iface := subst.check.newInterface()
171171
iface.embeddeds = embeddeds
172+
iface.embedPos = t.embedPos
172173
iface.implicit = t.implicit
173174
assert(t.complete) // otherwise we are copying incomplete data
174175
iface.complete = t.complete

src/cmd/compile/internal/types2/typeset.go

-1
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,6 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
304304
// separately. Here we only need to intersect the term lists and comparable bits.
305305
allTerms, allComparable = intersectTermLists(allTerms, allComparable, terms, comparable)
306306
}
307-
ityp.embedPos = nil // not needed anymore (errors have been reported)
308307

309308
ityp.tset.comparable = allComparable
310309
if len(allMethods) != 0 {

src/go/types/issues_test.go

+17
Original file line numberDiff line numberDiff line change
@@ -1086,3 +1086,20 @@ func TestIssue59831(t *testing.T) {
10861086
}
10871087
}
10881088
}
1089+
1090+
func TestIssue64759(t *testing.T) {
1091+
const src = `
1092+
//go:build go1.18
1093+
package p
1094+
1095+
func f[S ~[]E, E any](S) {}
1096+
1097+
func _() {
1098+
f([]string{})
1099+
}
1100+
`
1101+
// Per the go:build directive, the source must typecheck
1102+
// even though the (module) Go version is set to go1.17.
1103+
conf := Config{GoVersion: "go1.17"}
1104+
mustTypecheck(src, &conf, nil)
1105+
}

src/go/types/subst.go

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/go/types/typeset.go

-1
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,6 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T
302302
// separately. Here we only need to intersect the term lists and comparable bits.
303303
allTerms, allComparable = intersectTermLists(allTerms, allComparable, terms, comparable)
304304
}
305-
ityp.embedPos = nil // not needed anymore (errors have been reported)
306305

307306
ityp.tset.comparable = allComparable
308307
if len(allMethods) != 0 {

0 commit comments

Comments
 (0)