mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile/internal: support new(expr)
This CL adds compiler support for new(expr), a feature of go1.26 that allows the user to specify the initial value of the variable instead of its type. Also, a basic test of dynamic behavior. See CL 704737 for spec change and CL 704935 for type-checker changes. For #45624 Change-Id: I65d27de1ee3aabb819b57cce8ea77f3073447757 Reviewed-on: https://go-review.googlesource.com/c/go/+/705157 Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Mateusz Poliwczak <mpoliwczak34@gmail.com> Auto-Submit: Alan Donovan <adonovan@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
parent
eb78f13c9f
commit
7bc1935db5
6 changed files with 56 additions and 6 deletions
|
|
@ -215,7 +215,7 @@ const (
|
|||
ORSH // X >> Y
|
||||
OAND // X & Y
|
||||
OANDNOT // X &^ Y
|
||||
ONEW // new(X); corresponds to calls to new in source code
|
||||
ONEW // new(X); corresponds to calls to new(T) in source code
|
||||
ONOT // !X
|
||||
OBITNOT // ^X
|
||||
OPLUS // +X
|
||||
|
|
|
|||
|
|
@ -42,6 +42,10 @@ func TypeNode(t *types.Type) Node {
|
|||
|
||||
// A DynamicType represents a type expression whose exact type must be
|
||||
// computed dynamically.
|
||||
//
|
||||
// TODO(adonovan): I think "dynamic" is a misnomer here; it's really a
|
||||
// type with free type parameters that needs to be instantiated to obtain
|
||||
// a ground type for which an rtype can exist.
|
||||
type DynamicType struct {
|
||||
miniExpr
|
||||
|
||||
|
|
|
|||
|
|
@ -2431,8 +2431,16 @@ func (r *reader) expr() (res ir.Node) {
|
|||
|
||||
case exprNew:
|
||||
pos := r.pos()
|
||||
typ := r.exprType()
|
||||
return typecheck.Expr(ir.NewUnaryExpr(pos, ir.ONEW, typ))
|
||||
if r.Bool() {
|
||||
// new(expr) -> tmp := expr; &tmp
|
||||
x := r.expr()
|
||||
var init ir.Nodes
|
||||
addr := ir.NewAddrExpr(pos, r.tempCopy(pos, x, &init))
|
||||
addr.SetInit(init)
|
||||
return typecheck.Expr(addr)
|
||||
}
|
||||
// new(T)
|
||||
return typecheck.Expr(ir.NewUnaryExpr(pos, ir.ONEW, r.exprType()))
|
||||
|
||||
case exprSizeof:
|
||||
return ir.NewUintptr(r.pos(), r.typ().Size())
|
||||
|
|
@ -3239,6 +3247,7 @@ func (r *reader) exprType() ir.Node {
|
|||
var rtype, itab ir.Node
|
||||
|
||||
if r.Bool() {
|
||||
// non-empty interface
|
||||
typ, rtype, _, _, itab = r.itab(pos)
|
||||
if !typ.IsInterface() {
|
||||
rtype = nil // TODO(mdempsky): Leave set?
|
||||
|
|
|
|||
|
|
@ -2035,10 +2035,16 @@ func (w *writer) expr(expr syntax.Expr) {
|
|||
case "new":
|
||||
assert(len(expr.ArgList) == 1)
|
||||
assert(!expr.HasDots)
|
||||
arg := expr.ArgList[0]
|
||||
|
||||
w.Code(exprNew)
|
||||
w.pos(expr)
|
||||
w.exprType(nil, expr.ArgList[0])
|
||||
tv := w.p.typeAndValue(arg)
|
||||
if w.Bool(!tv.IsType()) {
|
||||
w.expr(arg) // new(expr), go1.26
|
||||
} else {
|
||||
w.exprType(nil, arg) // new(T)
|
||||
}
|
||||
return
|
||||
|
||||
case "Sizeof":
|
||||
|
|
|
|||
32
test/newexpr.go
Normal file
32
test/newexpr.go
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// run
|
||||
|
||||
// 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.
|
||||
|
||||
package main
|
||||
|
||||
// Issue #45624 is the proposal to accept new(expr) in go1.26.
|
||||
// Here we test its run-time behavior.
|
||||
func main() {
|
||||
{
|
||||
p := new(123) // untyped constant expr
|
||||
if *p != 123 {
|
||||
panic("wrong value")
|
||||
}
|
||||
}
|
||||
{
|
||||
x := 42
|
||||
p := new(x) // non-constant expr
|
||||
if *p != x {
|
||||
panic("wrong value")
|
||||
}
|
||||
}
|
||||
{
|
||||
x := [2]int{123, 456}
|
||||
p := new(x) // composite value
|
||||
if *p != x {
|
||||
panic("wrong value")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -140,6 +140,5 @@ func _() {
|
|||
_ = int // ERROR "type int is not an expression|not an expression"
|
||||
(x) // ERROR "x .* not used|not used"
|
||||
_ = new(len) // ERROR "len.*must be called"
|
||||
// Disabled due to issue #43125.
|
||||
// _ = new(1 + 1) // DISABLED "1 \+ 1 is not a type"
|
||||
_ = new(1 + 1) // ok
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue