diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index d4463bc4b09..549d94615bc 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -91,6 +91,17 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // to type []byte with a second argument of string type followed by ... . // This form appends the bytes of the string." + // In either case, the first argument must be a slice; in particular it + // cannot be the predeclared nil value. Note that nil is not excluded by + // the assignability requirement alone for the special case (go.dev/issue/76220). + // spec: "If S is a type parameter, all types in its type set + // must have the same underlying slice type []E." + E, err := sliceElem(x) + if err != nil { + check.errorf(x, InvalidAppend, "invalid append: %s", err.format(check)) + return + } + // Handle append(bytes, y...) special case, where // the type set of y is {string} or {string, []byte}. var sig *Signature @@ -119,13 +130,6 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // general case if sig == nil { - // spec: "If S is a type parameter, all types in its type set - // must have the same underlying slice type []E." - E, err := sliceElem(x) - if err != nil { - check.errorf(x, InvalidAppend, "invalid append: %s", err.format(check)) - return - } // check arguments by creating custom signature sig = makeSig(x.typ, x.typ, NewSlice(E)) // []E required for variadic signature sig.variadic = true diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 04d294db0c1..90a3b4a901f 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -94,6 +94,17 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // to type []byte with a second argument of string type followed by ... . // This form appends the bytes of the string." + // In either case, the first argument must be a slice; in particular it + // cannot be the predeclared nil value. Note that nil is not excluded by + // the assignability requirement alone for the special case (go.dev/issue/76220). + // spec: "If S is a type parameter, all types in its type set + // must have the same underlying slice type []E." + E, err := sliceElem(x) + if err != nil { + check.errorf(x, InvalidAppend, "invalid append: %s", err.format(check)) + return + } + // Handle append(bytes, y...) special case, where // the type set of y is {string} or {string, []byte}. var sig *Signature @@ -122,13 +133,6 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // general case if sig == nil { - // spec: "If S is a type parameter, all types in its type set - // must have the same underlying slice type []E." - E, err := sliceElem(x) - if err != nil { - check.errorf(x, InvalidAppend, "invalid append: %s", err.format(check)) - return - } // check arguments by creating custom signature sig = makeSig(x.typ, x.typ, NewSlice(E)) // []E required for variadic signature sig.variadic = true diff --git a/src/internal/types/testdata/fixedbugs/issue76220.go b/src/internal/types/testdata/fixedbugs/issue76220.go new file mode 100644 index 00000000000..ad465010a05 --- /dev/null +++ b/src/internal/types/testdata/fixedbugs/issue76220.go @@ -0,0 +1,17 @@ +// 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 + +func _() { + append(nil /* ERROR "argument must be a slice; have untyped nil" */, ""...) +} + +// test case from issue + +func main() { + s := "hello" + msg := append(nil /* ERROR "argument must be a slice; have untyped nil" */, s...) + print(msg) +}