]> Cypherpunks repositories - gostls13.git/commitdiff
go/types,types2: allow new(expr)
authorAlan Donovan <adonovan@google.com>
Thu, 18 Sep 2025 02:17:41 +0000 (22:17 -0400)
committerAlan Donovan <adonovan@google.com>
Tue, 23 Sep 2025 18:36:46 +0000 (11:36 -0700)
For #45624

Change-Id: I6d77a2a1d6095cac0edc36060cbf98c72b749404
Reviewed-on: https://go-review.googlesource.com/c/go/+/704935
Auto-Submit: Alan Donovan <adonovan@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/cmd/compile/internal/types2/builtins.go
src/cmd/compile/internal/types2/version.go
src/go/types/builtins.go
src/go/types/version.go
src/internal/types/testdata/check/builtins0.go
src/internal/types/testdata/check/go1_25.go [new file with mode: 0644]
src/internal/types/testdata/fixedbugs/issue43125.go [deleted file]
test/used.go

index 4bb2135755377ae2246f224b7115af354bcb4fce..3de2857ed4828c765218c52a91b334235a51941a 100644 (file)
@@ -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
index b555f398dab734ab13218f8586196d5c7b148c8a..765b0f7e9aba4421f211944341a0e5c453b8eb40 100644 (file)
@@ -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))
index e9f2b3e21d9ea4d0ba3677b480163b255b30591c..1163321ecd756e5f831b2bcdd10acee090277170 100644 (file)
@@ -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
index 2a2d34120526d110a72cecfc542ffb93243b9fd6..81331103980fc7f109f063ff20ce94cb53ece231 100644 (file)
@@ -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))
index ea30fbcbe7d8d39965a4fc0e91effcdc61dcea66..e326b92ac7bbd104c3820d62bd9365cfe1c27e59 100644 (file)
@@ -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 (file)
index 0000000..b2ace83
--- /dev/null
@@ -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 (file)
index d0d6feb..0000000
+++ /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)
index 5bdc5a731886913c393b42177ffc17964fbc4579..516f5968a84110dedc779d4ca4aab6f516aa0b6e 100644 (file)
@@ -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"
 }