aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Freeman <mark@golang.org>2026-01-20 14:23:19 -0500
committerGopher Robot <gobot@golang.org>2026-01-27 07:52:07 -0800
commita977717393fd779921ca258988230dbc741f5912 (patch)
treea12ac0383308094d631da9adb5acb19b5cffca5a
parent8ca47fab421e99306afb6f7a0941d85f579ae3c0 (diff)
downloadgo-a977717393fd779921ca258988230dbc741f5912.tar.xz
go/types, types2: add check for map value completeness in IndexExpr
An index expression can also go from map[K]V to V. Since V could be incomplete (due to some admittedly contrived syntax), we need a check. Change-Id: I03ffbfc0e5bcc9129591d60dfbaa5fafcf8fb183 Reviewed-on: https://go-review.googlesource.com/c/go/+/737620 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Robert Griesemer <gri@google.com> Auto-Submit: Mark Freeman <markfreeman@google.com>
-rw-r--r--src/cmd/compile/internal/types2/index.go20
-rw-r--r--src/go/types/index.go20
-rw-r--r--src/internal/types/testdata/check/cycles6.go2
3 files changed, 32 insertions, 10 deletions
diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go
index 98d83833c8..5b52cea837 100644
--- a/src/cmd/compile/internal/types2/index.go
+++ b/src/cmd/compile/internal/types2/index.go
@@ -52,11 +52,21 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo
x.mode = invalid
return false
}
- // Additionally, if x.typ is a pointer to an array type, indexing implicitly dereferences the value, meaning
- // its base type must also be complete.
- if p, ok := x.typ.Underlying().(*Pointer); ok && !check.isComplete(p.base) {
- x.mode = invalid
- return false
+ switch typ := x.typ.Underlying().(type) {
+ case *Pointer:
+ // Additionally, if x.typ is a pointer to an array type, indexing implicitly dereferences the value, meaning
+ // its base type must also be complete.
+ if !check.isComplete(typ.base) {
+ x.mode = invalid
+ return false
+ }
+ case *Map:
+ // Lastly, if x.typ is a map type, indexing must produce a value of a complete type, meaning
+ // its element type must also be complete.
+ if !check.isComplete(typ.elem) {
+ x.mode = invalid
+ return false
+ }
}
// ordinary index expression
diff --git a/src/go/types/index.go b/src/go/types/index.go
index 720cbbf0ea..9089092e52 100644
--- a/src/go/types/index.go
+++ b/src/go/types/index.go
@@ -53,11 +53,21 @@ func (check *Checker) indexExpr(x *operand, e *indexedExpr) (isFuncInst bool) {
x.mode = invalid
return false
}
- // Additionally, if x.typ is a pointer to an array type, indexing implicitly dereferences the value, meaning
- // its base type must also be complete.
- if p, ok := x.typ.Underlying().(*Pointer); ok && !check.isComplete(p.base) {
- x.mode = invalid
- return false
+ switch typ := x.typ.Underlying().(type) {
+ case *Pointer:
+ // Additionally, if x.typ is a pointer to an array type, indexing implicitly dereferences the value, meaning
+ // its base type must also be complete.
+ if !check.isComplete(typ.base) {
+ x.mode = invalid
+ return false
+ }
+ case *Map:
+ // Lastly, if x.typ is a map type, indexing must produce a value of a complete type, meaning
+ // its element type must also be complete.
+ if !check.isComplete(typ.elem) {
+ x.mode = invalid
+ return false
+ }
}
// ordinary index expression
diff --git a/src/internal/types/testdata/check/cycles6.go b/src/internal/types/testdata/check/cycles6.go
index e5635ed456..7c627749a4 100644
--- a/src/internal/types/testdata/check/cycles6.go
+++ b/src/internal/types/testdata/check/cycles6.go
@@ -69,3 +69,5 @@ type T11 /* ERROR "invalid recursive type" */ [unsafe.Sizeof(new(T11)[:])]int
type T12 /* ERROR "invalid recursive type" */ [unsafe.Sizeof(T12{}[42])]int
// index on pointer (case 3)
type T13 /* ERROR "invalid recursive type" */ [unsafe.Sizeof(new(T13)[42])]int
+// index on map (case 1)
+type T14 /* ERROR "invalid recursive type" */ [unsafe.Sizeof((*new(map[int]T14))[42])]int