1
0
mirror of https://github.com/golang/go synced 2024-11-14 15:00:27 -07:00

[dev.unified] cmd/compile/internal/noder: stop handling type expressions as expressions

There are two places currently where we rely on type expressions as
generic expressions: the first argument to "make" and "new", and the
selectable operand within a method expression.

This CL makes that code responsible for handling the type expressions
directly. Longer term, this will be relevant to appropriately handling
derived types, because it will provide additional context about how
the derived type is to be used.

Change-Id: I9d7dcf9d32dada032ff411cd103b9df413c298a5
Reviewed-on: https://go-review.googlesource.com/c/go/+/410101
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Matthew Dempsky 2022-06-03 14:30:04 -07:00
parent 1a6c96bb9b
commit 8ef8b60e18
3 changed files with 58 additions and 21 deletions

View File

@ -39,7 +39,6 @@ func (c codeExpr) Value() int { return int(c) }
// TODO(mdempsky): Split expr into addr, for lvalues. // TODO(mdempsky): Split expr into addr, for lvalues.
const ( const (
exprConst codeExpr = iota exprConst codeExpr = iota
exprType // type expression
exprLocal // local variable exprLocal // local variable
exprGlobal // global variable or function exprGlobal // global variable or function
exprCompLit exprCompLit
@ -52,6 +51,8 @@ const (
exprBinaryOp exprBinaryOp
exprCall exprCall
exprConvert exprConvert
exprNew
exprMake
) )
type codeAssign int type codeAssign int

View File

@ -1567,9 +1567,6 @@ func (r *reader) expr() (res ir.Node) {
// TODO(mdempsky): Handle builtins directly in exprCall, like method calls? // TODO(mdempsky): Handle builtins directly in exprCall, like method calls?
return typecheck.Callee(r.obj()) return typecheck.Callee(r.obj())
case exprType:
return r.exprType(false)
case exprConst: case exprConst:
pos := r.pos() pos := r.pos()
typ := r.typ() typ := r.typ()
@ -1585,9 +1582,9 @@ func (r *reader) expr() (res ir.Node) {
return r.funcLit() return r.funcLit()
case exprSelector: case exprSelector:
x := r.expr() var x ir.Node
pos := r.pos() if r.Bool() { // MethodExpr
_, sym := r.selector() x = r.exprType(false)
// Method expression with derived receiver type. // Method expression with derived receiver type.
if x.Op() == ir.ODYNAMICTYPE { if x.Op() == ir.ODYNAMICTYPE {
@ -1596,6 +1593,11 @@ func (r *reader) expr() (res ir.Node) {
n.SetTypecheck(1) n.SetTypecheck(1)
x = n x = n
} }
} else { // FieldVal, MethodVal
x = r.expr()
}
pos := r.pos()
_, sym := r.selector()
n := typecheck.Expr(ir.NewSelectorExpr(pos, ir.OXDOT, x, sym)).(*ir.SelectorExpr) n := typecheck.Expr(ir.NewSelectorExpr(pos, ir.OXDOT, x, sym)).(*ir.SelectorExpr)
if n.Op() == ir.OMETHVALUE { if n.Op() == ir.OMETHVALUE {
@ -1679,6 +1681,17 @@ func (r *reader) expr() (res ir.Node) {
dots := r.Bool() dots := r.Bool()
return typecheck.Call(pos, fun, args, dots) return typecheck.Call(pos, fun, args, dots)
case exprMake:
pos := r.pos()
typ := r.exprType(false)
extra := r.exprs()
return typecheck.Expr(ir.NewCallExpr(pos, ir.OMAKE, nil, append([]ir.Node{typ}, extra...)))
case exprNew:
pos := r.pos()
typ := r.exprType(false)
return typecheck.Expr(ir.NewUnaryExpr(pos, ir.ONEW, typ))
case exprConvert: case exprConvert:
typ := r.typ() typ := r.typ()
pos := r.pos() pos := r.pos()

View File

@ -619,6 +619,8 @@ func (w *writer) doObj(wext *writer, obj types2.Object) pkgbits.CodeObj {
} }
// typExpr writes the type represented by the given expression. // typExpr writes the type represented by the given expression.
//
// TODO(mdempsky): Document how this differs from exprType.
func (w *writer) typExpr(expr syntax.Expr) { func (w *writer) typExpr(expr syntax.Expr) {
tv, ok := w.p.info.Types[expr] tv, ok := w.p.info.Types[expr]
assert(ok) assert(ok)
@ -1228,9 +1230,7 @@ func (w *writer) expr(expr syntax.Expr) {
} }
if tv.IsType() { if tv.IsType() {
w.Code(exprType) w.p.fatalf(expr, "unexpected type expression %v", syntax.String(expr))
w.exprType(nil, expr, false)
return
} }
if tv.Value != nil { if tv.Value != nil {
@ -1280,7 +1280,11 @@ func (w *writer) expr(expr syntax.Expr) {
assert(ok) assert(ok)
w.Code(exprSelector) w.Code(exprSelector)
if w.Bool(sel.Kind() == types2.MethodExpr) {
w.exprType(nil, expr.X, false)
} else {
w.expr(expr.X) w.expr(expr.X)
}
w.pos(expr) w.pos(expr)
w.selector(sel.Obj()) w.selector(sel.Obj())
@ -1339,6 +1343,29 @@ func (w *writer) expr(expr syntax.Expr) {
break break
} }
if name, ok := unparen(expr.Fun).(*syntax.Name); ok && tv.IsBuiltin() {
switch name.Value {
case "make":
assert(len(expr.ArgList) >= 1)
assert(!expr.HasDots)
w.Code(exprMake)
w.pos(expr)
w.exprType(nil, expr.ArgList[0], false)
w.exprs(expr.ArgList[1:])
return
case "new":
assert(len(expr.ArgList) == 1)
assert(!expr.HasDots)
w.Code(exprNew)
w.pos(expr)
w.exprType(nil, expr.ArgList[0], false)
return
}
}
writeFunExpr := func() { writeFunExpr := func() {
if selector, ok := unparen(expr.Fun).(*syntax.SelectorExpr); ok { if selector, ok := unparen(expr.Fun).(*syntax.SelectorExpr); ok {
if sel, ok := w.p.info.Selections[selector]; ok && sel.Kind() == types2.MethodVal { if sel, ok := w.p.info.Selections[selector]; ok && sel.Kind() == types2.MethodVal {
@ -1438,10 +1465,6 @@ func (w *writer) exprList(expr syntax.Expr) {
} }
func (w *writer) exprs(exprs []syntax.Expr) { func (w *writer) exprs(exprs []syntax.Expr) {
if len(exprs) == 0 {
assert(exprs == nil)
}
w.Sync(pkgbits.SyncExprs) w.Sync(pkgbits.SyncExprs)
w.Len(len(exprs)) w.Len(len(exprs))
for _, expr := range exprs { for _, expr := range exprs {