Skip to content

Commit a27261c

Browse files
committed
go/types,types2: allow new(expr)
For golang#45624 Change-Id: I6d77a2a1d6095cac0edc36060cbf98c72b749404 Reviewed-on: https://go-review.googlesource.com/c/go/+/704935 Auto-Submit: Alan Donovan <[email protected]> Reviewed-by: Robert Findley <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent e93f439 commit a27261c

File tree

8 files changed

+97
-28
lines changed

8 files changed

+97
-28
lines changed

src/cmd/compile/internal/types2/builtins.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -636,11 +636,30 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
636636
}
637637

638638
case _New:
639-
// new(T)
639+
// new(T) or new(expr)
640640
// (no argument evaluated yet)
641-
T := check.varType(argList[0])
642-
if !isValid(T) {
643-
return
641+
arg := argList[0]
642+
check.exprOrType(x, arg, true)
643+
var T Type
644+
switch x.mode {
645+
case builtin:
646+
check.errorf(x, UncalledBuiltin, "%s must be called", x)
647+
x.mode = invalid
648+
case typexpr:
649+
// new(T)
650+
T = x.typ
651+
if !isValid(T) {
652+
return
653+
}
654+
default:
655+
// new(expr)
656+
check.verifyVersionf(call.Fun, go1_26, "new(expr)")
657+
T = Default(x.typ)
658+
if T != x.typ {
659+
// untyped constant: check for overflow.
660+
check.assignment(x, T, "argument to new")
661+
}
662+
check.validVarType(arg, T)
644663
}
645664

646665
x.mode = value

src/cmd/compile/internal/types2/version.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ var (
4343
go1_21 = asGoVersion("go1.21")
4444
go1_22 = asGoVersion("go1.22")
4545
go1_23 = asGoVersion("go1.23")
46+
go1_26 = asGoVersion("go1.26")
4647

4748
// current (deployed) Go version
4849
go_current = asGoVersion(fmt.Sprintf("go1.%d", goversion.Version))

src/go/types/builtins.go

Lines changed: 23 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/go/types/version.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ var (
4343
go1_21 = asGoVersion("go1.21")
4444
go1_22 = asGoVersion("go1.22")
4545
go1_23 = asGoVersion("go1.23")
46+
go1_26 = asGoVersion("go1.26")
4647

4748
// current (deployed) Go version
4849
go_current = asGoVersion(fmt.Sprintf("go1.%d", goversion.Version))

src/internal/types/testdata/check/builtins0.go

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -609,24 +609,48 @@ func min2() {
609609
)
610610
}
611611

612-
func new1() {
613-
_ = new() // ERROR "not enough arguments"
612+
func newInvalid() {
613+
f2 := func() (x, y int) { return }
614+
615+
_ = new() // ERROR "not enough arguments"
614616
_ = new(1, 2) // ERROR "too many arguments"
615-
_ = new("foo" /* ERROR "not a type" */)
616-
p := new(float64)
617+
new /* ERROR "not used" */ (int)
618+
_ = &new /* ERROR "cannot take address" */ (int)
619+
_ = new(int... /* ERROR "invalid use of ..." */)
620+
_ = new(f0 /* ERROR "f0() (no value) used as value or type" */ ())
621+
_ = new(len /* ERROR "len (built-in) must be called" */)
622+
_ = new(1 /* ERROR "argument to new (overflows)" */ << 70)
623+
_ = new(f2 /* ERRORx "multiple-value.*in single-value context" */ ())
624+
}
625+
626+
// new(T)
627+
func newType() {
617628
_ = new(struct{ x, y int })
629+
630+
p := new(float64)
618631
q := new(*float64)
619632
_ = *p == **q
620-
new /* ERROR "not used" */ (int)
621-
_ = &new /* ERROR "cannot take address" */ (int)
622-
623-
_ = new(int... /* ERROR "invalid use of ..." */ )
624633
}
625634

626-
func new2() {
635+
// new(expr), added in go1.26
636+
func newExpr() {
627637
f1 := func() (x []int) { return }
628-
_ = new(f0 /* ERROR "not a type" */ ())
629-
_ = new(f1 /* ERROR "not a type" */ ())
638+
var (
639+
_ *[]int = new(f1())
640+
_ *func() []int = new(f1)
641+
_ *bool = new(false)
642+
_ *int = new(123)
643+
_ *float64 = new(1.0)
644+
_ *uint = new(uint(3))
645+
_ *rune = new('a')
646+
_ *string = new("A")
647+
_ *struct{} = new(struct{}{})
648+
_ *any = new(any)
649+
650+
// from issue 43125
651+
_ = new(-1)
652+
_ = new(1 + 1)
653+
)
630654
}
631655

632656
func panic1() {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// -lang=go1.25
2+
3+
// Copyright 2025 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
// Check Go language version-specific errors.
8+
9+
//go:build go1.25
10+
11+
package p
12+
13+
var _ = new /* ERROR "new(expr) requires go1.26 or later" */ (123)

src/internal/types/testdata/fixedbugs/issue43125.go

Lines changed: 0 additions & 8 deletions
This file was deleted.

test/used.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ func _() {
139139
unsafe.Sizeof(t) // ERROR "unsafe.Sizeof\(t\) .* not used"
140140
_ = int // ERROR "type int is not an expression|not an expression"
141141
(x) // ERROR "x .* not used|not used"
142-
_ = new(x2) // ERROR "x2 is not a type|not a type"
142+
_ = new(len) // ERROR "len.*must be called"
143143
// Disabled due to issue #43125.
144144
// _ = new(1 + 1) // DISABLED "1 \+ 1 is not a type"
145145
}

0 commit comments

Comments
 (0)