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 <adonovan@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Alan Donovan 2025-09-17 22:17:41 -04:00
parent e93f439ac4
commit a27261c42f
8 changed files with 100 additions and 31 deletions

View file

@ -636,12 +636,31 @@ 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])
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
x.typ = &Pointer{base: T}

View 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))

View file

@ -639,12 +639,31 @@ 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])
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
x.typ = &Pointer{base: T}

View 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))

View file

@ -609,24 +609,48 @@ func min2() {
)
}
func new1() {
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(struct{ x, y int })
q := new(*float64)
_ = *p == **q
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" */ ())
}
func new2() {
// new(T)
func newType() {
_ = new(struct{ x, y int })
p := new(float64)
q := new(*float64)
_ = *p == **q
}
// 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() {

View file

@ -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)

View file

@ -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)

View 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"
}