mirror of
https://github.com/golang/go.git
synced 2025-10-19 19:13: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:
|
case _New:
|
||||||
// new(T)
|
// new(T) or new(expr)
|
||||||
// (no argument evaluated yet)
|
// (no argument evaluated yet)
|
||||||
T := check.varType(argList[0])
|
arg := argList[0]
|
||||||
if !isValid(T) {
|
check.exprOrType(x, arg, true)
|
||||||
return
|
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.mode = value
|
||||||
|
|
|
@ -43,6 +43,7 @@ var (
|
||||||
go1_21 = asGoVersion("go1.21")
|
go1_21 = asGoVersion("go1.21")
|
||||||
go1_22 = asGoVersion("go1.22")
|
go1_22 = asGoVersion("go1.22")
|
||||||
go1_23 = asGoVersion("go1.23")
|
go1_23 = asGoVersion("go1.23")
|
||||||
|
go1_26 = asGoVersion("go1.26")
|
||||||
|
|
||||||
// current (deployed) Go version
|
// current (deployed) Go version
|
||||||
go_current = asGoVersion(fmt.Sprintf("go1.%d", goversion.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:
|
case _New:
|
||||||
// new(T)
|
// new(T) or new(expr)
|
||||||
// (no argument evaluated yet)
|
// (no argument evaluated yet)
|
||||||
T := check.varType(argList[0])
|
arg := argList[0]
|
||||||
if !isValid(T) {
|
check.exprOrType(x, arg, true)
|
||||||
return
|
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.mode = value
|
||||||
|
|
|
@ -43,6 +43,7 @@ var (
|
||||||
go1_21 = asGoVersion("go1.21")
|
go1_21 = asGoVersion("go1.21")
|
||||||
go1_22 = asGoVersion("go1.22")
|
go1_22 = asGoVersion("go1.22")
|
||||||
go1_23 = asGoVersion("go1.23")
|
go1_23 = asGoVersion("go1.23")
|
||||||
|
go1_26 = asGoVersion("go1.26")
|
||||||
|
|
||||||
// current (deployed) Go version
|
// current (deployed) Go version
|
||||||
go_current = asGoVersion(fmt.Sprintf("go1.%d", goversion.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() {
|
func newInvalid() {
|
||||||
_ = new() // ERROR "not enough arguments"
|
f2 := func() (x, y int) { return }
|
||||||
_ = 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() // 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 }
|
f1 := func() (x []int) { return }
|
||||||
_ = new(f0 /* ERROR "not a type" */ ())
|
var (
|
||||||
_ = new(f1 /* ERROR "not a type" */ ())
|
_ *[]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() {
|
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"
|
unsafe.Sizeof(t) // ERROR "unsafe.Sizeof\(t\) .* not used"
|
||||||
_ = int // ERROR "type int is not an expression|not an expression"
|
_ = int // ERROR "type int is not an expression|not an expression"
|
||||||
(x) // ERROR "x .* not used|not used"
|
(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.
|
// Disabled due to issue #43125.
|
||||||
// _ = new(1 + 1) // DISABLED "1 \+ 1 is not a type"
|
// _ = new(1 + 1) // DISABLED "1 \+ 1 is not a type"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue