Skip to content

Commit 06e57e6

Browse files
Robert Griesemergopherbot
authored andcommitted
go/types, types2: only report version errors if new(expr) is ok otherwise
If new(expr) is used before Go 1.26, don't report version errors if there are other problems with the expression. While at it, implement multiple missing type checks for new(expr) and add corresponding test cases that were missed in CL 704935 (tests for no value expressions, generic types, untyped nil). Reorganize/rename builtins0.go tests for new to match existing test case patterns again. Fixes #75986. For #45624. Change-Id: I39e5516d3f8d191cc390a4d8b9911c312bbb177c Reviewed-on: https://go-review.googlesource.com/c/go/+/713241 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Mark Freeman <markfreeman@google.com> Reviewed-by: Robert Griesemer <gri@google.com> Auto-Submit: Robert Griesemer <gri@google.com>
1 parent 6c3d0d2 commit 06e57e6

File tree

5 files changed

+91
-48
lines changed

5 files changed

+91
-48
lines changed

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

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -639,31 +639,31 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
639639
// new(T) or new(expr)
640640
// (no argument evaluated yet)
641641
arg := argList[0]
642-
check.exprOrType(x, arg, true)
643-
var T Type
642+
check.exprOrType(x, arg, false)
643+
check.exclude(x, 1<<novalue|1<<builtin)
644644
switch x.mode {
645-
case builtin:
646-
check.errorf(x, UncalledBuiltin, "%s must be called", x)
647-
x.mode = invalid
645+
case invalid:
646+
return
648647
case typexpr:
649648
// new(T)
650-
T = x.typ
651-
if !isValid(T) {
652-
return
653-
}
649+
check.validVarType(arg, x.typ)
654650
default:
655651
// 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")
652+
if isUntyped(x.typ) {
653+
// check for overflow and untyped nil
654+
check.assignment(x, nil, "argument to new")
655+
if x.mode == invalid {
656+
return
657+
}
658+
assert(isTyped(x.typ))
661659
}
662-
check.validVarType(arg, T)
660+
// report version error only if there are no other errors
661+
check.verifyVersionf(call.Fun, go1_26, "new(%s)", arg)
663662
}
664663

664+
T := x.typ
665665
x.mode = value
666-
x.typ = &Pointer{base: T}
666+
x.typ = NewPointer(T)
667667
if check.recordTypes() {
668668
check.recordBuiltinType(call.Fun, makeSig(x.typ, T))
669669
}

src/go/types/builtins.go

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

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

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -609,36 +609,38 @@ func min2() {
609609
)
610610
}
611611

612-
func newInvalid() {
613-
f2 := func() (x, y int) { return }
614612

613+
func new1() {
615614
_ = new() // ERROR "not enough arguments"
616615
_ = new(1, 2) // ERROR "too many arguments"
616+
_ = new(unsafe /* ERROR "use of package unsafe not in selector" */ )
617+
618+
_ = new(struct{ x, y int })
619+
p := new(float64)
620+
q := new(*float64)
621+
_ = *p == **q
622+
623+
type G[P any] struct{}
624+
_ = new(G[int])
625+
_ = new(G /* ERROR "cannot use generic type G without instantiation" */ )
626+
617627
new /* ERROR "not used" */ (int)
618628
_ = &new /* ERROR "cannot take address" */ (int)
619629
_ = new(int... /* ERROR "invalid use of ..." */)
620630
_ = new(f0 /* ERROR "f0() (no value) used as value or type" */ ())
621631
_ = new(len /* ERROR "len (built-in) must be called" */)
622632
_ = new(1 /* ERROR "argument to new (overflows)" */ << 70)
623-
_ = new(f2 /* ERRORx "multiple-value.*in single-value context" */ ())
624633
}
625634

626-
// new(T)
627-
func newType() {
628-
_ = new(struct{ x, y int })
629-
630-
p := new(float64)
631-
q := new(*float64)
632-
_ = *p == **q
633-
}
634-
635-
// new(expr), added in go1.26
636-
func newExpr() {
637-
f1 := func() (x []int) { return }
635+
func new2() {
636+
// new(expr), added in go1.26
637+
f1 := func() []int { panic(0) }
638+
f2 := func() (int, int) { panic(0) }
638639
var (
639640
_ *[]int = new(f1())
640641
_ *func() []int = new(f1)
641642
_ *bool = new(false)
643+
_ *bool = new(1 < 2)
642644
_ *int = new(123)
643645
_ *float64 = new(1.0)
644646
_ *uint = new(uint(3))
@@ -647,6 +649,14 @@ func newExpr() {
647649
_ *struct{} = new(struct{}{})
648650
_ *any = new(any)
649651

652+
_ = new(f2 /* ERRORx "multiple-value.*in single-value context" */ ())
653+
_ = new(1 << /* ERROR "constant shift overflow" */ 1000)
654+
_ = new(1e10000 /* ERROR "cannot use 1e10000 (untyped float constant 1e+10000) as float64 value in argument to new (overflows)" */ )
655+
_ = new(nil /* ERROR "use of untyped nil in argument to new" */ )
656+
_ = new(comparable /* ERROR "cannot use type comparable outside a type constraint" */ )
657+
_ = new(new /* ERROR "new (built-in) must be called" */ )
658+
_ = new(panic /* ERROR "panic(0) (no value) used as value or type" */ (0))
659+
650660
// from issue 43125
651661
_ = new(-1)
652662
_ = new(1 + 1)

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,9 @@
1010

1111
package p
1212

13-
var _ = new /* ERROR "new(expr) requires go1.26 or later" */ (123)
13+
func f(x int) {
14+
_ = new /* ERROR "new(123) requires go1.26 or later" */ (123)
15+
_ = new /* ERROR "new(x) requires go1.26 or later" */ (x)
16+
_ = new /* ERROR "new(f) requires go1.26 or later" */ (f)
17+
_ = new /* ERROR "new(1 < 2) requires go1.26 or later" */ (1 < 2)
18+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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+
package p
8+
9+
import "strings"
10+
11+
type T int
12+
type G[P any] struct{}
13+
14+
var x T
15+
16+
// Verify that we don't get a version error when there's another error present in new(expr).
17+
18+
func f() {
19+
_ = new(U /* ERROR "undefined: U" */)
20+
_ = new(strings.BUILDER /* ERROR "undefined: strings.BUILDER (but have Builder)" */)
21+
_ = new(T) // ok
22+
_ = new(G[int]) // ok
23+
_ = new(G /* ERROR "cannot use generic type G without instantiation" */)
24+
_ = new(nil /* ERROR "use of untyped nil in argument to new" */)
25+
_ = new(comparable /* ERROR "cannot use type comparable outside a type constraint" */)
26+
_ = new(new /* ERROR "new (built-in) must be called" */)
27+
_ = new(panic /* ERROR "panic(0) (no value) used as value or type" */ (0))
28+
}

0 commit comments

Comments
 (0)