mirror of
https://github.com/golang/go.git
synced 2025-10-19 11:03:18 +00:00
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:
parent
e93f439ac4
commit
a27261c42f
8 changed files with 100 additions and 31 deletions
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
52
src/internal/types/testdata/check/builtins0.go
vendored
52
src/internal/types/testdata/check/builtins0.go
vendored
|
@ -609,24 +609,48 @@ func min2() {
|
|||
)
|
||||
}
|
||||
|
||||
func new1() {
|
||||
_ = 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)
|
||||
func newInvalid() {
|
||||
f2 := func() (x, y int) { return }
|
||||
|
||||
_ = new(int... /* ERROR "invalid use of ..." */ )
|
||||
_ = new() // ERROR "not enough arguments"
|
||||
_ = new(1, 2) // ERROR "too many arguments"
|
||||
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() {
|
||||
|
|
13
src/internal/types/testdata/check/go1_25.go
vendored
Normal file
13
src/internal/types/testdata/check/go1_25.go
vendored
Normal 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)
|
|
@ -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)
|
|
@ -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"
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue