From a27261c42fcebf601587725714b9ef53c47b06b3 Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Wed, 17 Sep 2025 22:17:41 -0400 Subject: [PATCH] go/types,types2: allow new(expr) For #45624 Change-Id: I6d77a2a1d6095cac0edc36060cbf98c72b749404 Reviewed-on: https://go-review.googlesource.com/c/go/+/704935 Auto-Submit: Alan Donovan Reviewed-by: Robert Findley LUCI-TryBot-Result: Go LUCI --- src/cmd/compile/internal/types2/builtins.go | 27 +++++++++-- src/cmd/compile/internal/types2/version.go | 1 + src/go/types/builtins.go | 27 +++++++++-- src/go/types/version.go | 1 + .../types/testdata/check/builtins0.go | 46 ++++++++++++++----- src/internal/types/testdata/check/go1_25.go | 13 ++++++ .../types/testdata/fixedbugs/issue43125.go | 8 ---- test/used.go | 2 +- 8 files changed, 97 insertions(+), 28 deletions(-) create mode 100644 src/internal/types/testdata/check/go1_25.go delete mode 100644 src/internal/types/testdata/fixedbugs/issue43125.go diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 4bb2135755..3de2857ed4 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -636,11 +636,30 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( } case _New: - // new(T) + // new(T) or new(expr) // (no argument evaluated yet) - T := check.varType(argList[0]) - if !isValid(T) { - return + arg := argList[0] + check.exprOrType(x, arg, true) + var T Type + switch x.mode { + case builtin: + check.errorf(x, UncalledBuiltin, "%s must be called", x) + x.mode = invalid + case typexpr: + // new(T) + T = x.typ + if !isValid(T) { + return + } + default: + // new(expr) + check.verifyVersionf(call.Fun, go1_26, "new(expr)") + T = Default(x.typ) + if T != x.typ { + // untyped constant: check for overflow. + check.assignment(x, T, "argument to new") + } + check.validVarType(arg, T) } x.mode = value diff --git a/src/cmd/compile/internal/types2/version.go b/src/cmd/compile/internal/types2/version.go index b555f398da..765b0f7e9a 100644 --- a/src/cmd/compile/internal/types2/version.go +++ b/src/cmd/compile/internal/types2/version.go @@ -43,6 +43,7 @@ var ( go1_21 = asGoVersion("go1.21") go1_22 = asGoVersion("go1.22") go1_23 = asGoVersion("go1.23") + go1_26 = asGoVersion("go1.26") // current (deployed) Go version go_current = asGoVersion(fmt.Sprintf("go1.%d", goversion.Version)) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index e9f2b3e21d..1163321ecd 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -639,11 +639,30 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b } case _New: - // new(T) + // new(T) or new(expr) // (no argument evaluated yet) - T := check.varType(argList[0]) - if !isValid(T) { - return + arg := argList[0] + check.exprOrType(x, arg, true) + var T Type + switch x.mode { + case builtin: + check.errorf(x, UncalledBuiltin, "%s must be called", x) + x.mode = invalid + case typexpr: + // new(T) + T = x.typ + if !isValid(T) { + return + } + default: + // new(expr) + check.verifyVersionf(call.Fun, go1_26, "new(expr)") + T = Default(x.typ) + if T != x.typ { + // untyped constant: check for overflow. + check.assignment(x, T, "argument to new") + } + check.validVarType(arg, T) } x.mode = value diff --git a/src/go/types/version.go b/src/go/types/version.go index 2a2d341205..8133110398 100644 --- a/src/go/types/version.go +++ b/src/go/types/version.go @@ -43,6 +43,7 @@ var ( go1_21 = asGoVersion("go1.21") go1_22 = asGoVersion("go1.22") go1_23 = asGoVersion("go1.23") + go1_26 = asGoVersion("go1.26") // current (deployed) Go version go_current = asGoVersion(fmt.Sprintf("go1.%d", goversion.Version)) diff --git a/src/internal/types/testdata/check/builtins0.go b/src/internal/types/testdata/check/builtins0.go index ea30fbcbe7..e326b92ac7 100644 --- a/src/internal/types/testdata/check/builtins0.go +++ b/src/internal/types/testdata/check/builtins0.go @@ -609,24 +609,48 @@ func min2() { ) } -func new1() { - _ = new() // ERROR "not enough arguments" +func newInvalid() { + f2 := func() (x, y int) { return } + + _ = new() // ERROR "not enough arguments" _ = new(1, 2) // ERROR "too many arguments" - _ = new("foo" /* ERROR "not a type" */) - p := new(float64) + new /* ERROR "not used" */ (int) + _ = &new /* ERROR "cannot take address" */ (int) + _ = new(int... /* ERROR "invalid use of ..." */) + _ = new(f0 /* ERROR "f0() (no value) used as value or type" */ ()) + _ = new(len /* ERROR "len (built-in) must be called" */) + _ = new(1 /* ERROR "argument to new (overflows)" */ << 70) + _ = new(f2 /* ERRORx "multiple-value.*in single-value context" */ ()) +} + +// new(T) +func newType() { _ = new(struct{ x, y int }) + + p := new(float64) q := new(*float64) _ = *p == **q - new /* ERROR "not used" */ (int) - _ = &new /* ERROR "cannot take address" */ (int) - - _ = new(int... /* ERROR "invalid use of ..." */ ) } -func new2() { +// new(expr), added in go1.26 +func newExpr() { f1 := func() (x []int) { return } - _ = new(f0 /* ERROR "not a type" */ ()) - _ = new(f1 /* ERROR "not a type" */ ()) + var ( + _ *[]int = new(f1()) + _ *func() []int = new(f1) + _ *bool = new(false) + _ *int = new(123) + _ *float64 = new(1.0) + _ *uint = new(uint(3)) + _ *rune = new('a') + _ *string = new("A") + _ *struct{} = new(struct{}{}) + _ *any = new(any) + + // from issue 43125 + _ = new(-1) + _ = new(1 + 1) + ) } func panic1() { diff --git a/src/internal/types/testdata/check/go1_25.go b/src/internal/types/testdata/check/go1_25.go new file mode 100644 index 0000000000..b2ace83343 --- /dev/null +++ b/src/internal/types/testdata/check/go1_25.go @@ -0,0 +1,13 @@ +// -lang=go1.25 + +// 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. + +// Check Go language version-specific errors. + +//go:build go1.25 + +package p + +var _ = new /* ERROR "new(expr) requires go1.26 or later" */ (123) diff --git a/src/internal/types/testdata/fixedbugs/issue43125.go b/src/internal/types/testdata/fixedbugs/issue43125.go deleted file mode 100644 index d0d6feb2a8..0000000000 --- a/src/internal/types/testdata/fixedbugs/issue43125.go +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2021 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 - -var _ = new(- /* ERROR "not a type" */ 1) -var _ = new(1 /* ERROR "not a type" */ + 1) diff --git a/test/used.go b/test/used.go index 5bdc5a7318..516f5968a8 100644 --- a/test/used.go +++ b/test/used.go @@ -139,7 +139,7 @@ func _() { unsafe.Sizeof(t) // ERROR "unsafe.Sizeof\(t\) .* not used" _ = int // ERROR "type int is not an expression|not an expression" (x) // ERROR "x .* not used|not used" - _ = new(x2) // ERROR "x2 is not a type|not a type" + _ = new(len) // ERROR "len.*must be called" // Disabled due to issue #43125. // _ = new(1 + 1) // DISABLED "1 \+ 1 is not a type" } -- 2.52.0