mirror of
https://github.com/golang/go
synced 2024-11-23 18:00:06 -07:00
[dev.unified] cmd/compile/internal/noder: start writing implicit conversions
This CL adds support for implicit conversions to the unified IR export data format, and starts inserting them in a few low-hanging places (send statements, index expressions). Subsequentl CLs will handle the remaining trickier cases. Change-Id: Iaea9d1c5df8432b61bd82578ab2ef02adaf26367 Reviewed-on: https://go-review.googlesource.com/c/go/+/413396 Run-TryBot: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: David Chase <drchase@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
9cb784ac69
commit
5f5422a2dd
@ -1782,6 +1782,7 @@ func (r *reader) expr() (res ir.Node) {
|
||||
return typecheck.Expr(ir.NewUnaryExpr(pos, ir.ONEW, typ))
|
||||
|
||||
case exprConvert:
|
||||
implicit := r.Bool()
|
||||
typ := r.typ()
|
||||
pos := r.pos()
|
||||
x := r.expr()
|
||||
@ -1799,7 +1800,11 @@ func (r *reader) expr() (res ir.Node) {
|
||||
base.ErrorExit() // harsh, but prevents constructing invalid IR
|
||||
}
|
||||
|
||||
return typecheck.Expr(ir.NewConvExpr(pos, ir.OCONV, typ, x))
|
||||
n := typecheck.Expr(ir.NewConvExpr(pos, ir.OCONV, typ, x))
|
||||
if implicit && n.Op() != ir.OLITERAL {
|
||||
n.(ImplicitNode).SetImplicit(true)
|
||||
}
|
||||
return n
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1079,13 +1079,18 @@ func (w *writer) stmt1(stmt syntax.Stmt) {
|
||||
w.op(binOps[stmt.Op])
|
||||
w.expr(stmt.Lhs)
|
||||
w.pos(stmt)
|
||||
w.expr(stmt.Rhs)
|
||||
|
||||
var typ types2.Type
|
||||
if stmt.Op != syntax.Shl && stmt.Op != syntax.Shr {
|
||||
typ = w.p.typeOf(stmt.Lhs)
|
||||
}
|
||||
w.implicitExpr(stmt, typ, stmt.Rhs)
|
||||
|
||||
default:
|
||||
w.Code(stmtAssign)
|
||||
w.pos(stmt)
|
||||
w.assignList(stmt.Lhs)
|
||||
w.exprList(stmt.Rhs)
|
||||
w.exprList(stmt.Rhs) // TODO(mdempsky): Implicit conversions to Lhs types.
|
||||
}
|
||||
|
||||
case *syntax.BlockStmt:
|
||||
@ -1130,17 +1135,19 @@ func (w *writer) stmt1(stmt syntax.Stmt) {
|
||||
case *syntax.ReturnStmt:
|
||||
w.Code(stmtReturn)
|
||||
w.pos(stmt)
|
||||
w.exprList(stmt.Results)
|
||||
w.exprList(stmt.Results) // TODO(mdempsky): Implicit conversions to result types.
|
||||
|
||||
case *syntax.SelectStmt:
|
||||
w.Code(stmtSelect)
|
||||
w.selectStmt(stmt)
|
||||
|
||||
case *syntax.SendStmt:
|
||||
chanType := types2.CoreType(w.p.typeOf(stmt.Chan)).(*types2.Chan)
|
||||
|
||||
w.Code(stmtSend)
|
||||
w.pos(stmt)
|
||||
w.expr(stmt.Chan)
|
||||
w.expr(stmt.Value)
|
||||
w.implicitExpr(stmt, chanType.Elem(), stmt.Value)
|
||||
|
||||
case *syntax.SwitchStmt:
|
||||
w.Code(stmtSwitch)
|
||||
@ -1196,7 +1203,7 @@ func (w *writer) declStmt(decl syntax.Decl) {
|
||||
w.Code(stmtAssign)
|
||||
w.pos(decl)
|
||||
w.assignList(namesAsExpr(decl.NameList))
|
||||
w.exprList(decl.Values)
|
||||
w.exprList(decl.Values) // TODO(mdempsky): Implicit conversions to Lhs types.
|
||||
}
|
||||
}
|
||||
|
||||
@ -1213,6 +1220,11 @@ func (w *writer) forStmt(stmt *syntax.ForStmt) {
|
||||
|
||||
if rang, ok := stmt.Init.(*syntax.RangeClause); w.Bool(ok) {
|
||||
w.pos(rang)
|
||||
// TODO(mdempsky): For !rang.Def, we need to handle implicit
|
||||
// conversions; e.g., see #53328.
|
||||
//
|
||||
// This is tricky, because the assignments aren't introduced until
|
||||
// lowering in walk.
|
||||
w.assignList(rang.Lhs)
|
||||
w.expr(rang.X)
|
||||
} else {
|
||||
@ -1294,6 +1306,7 @@ func (w *writer) switchStmt(stmt *syntax.SwitchStmt) {
|
||||
w.exprType(iface, cas, true)
|
||||
}
|
||||
} else {
|
||||
// TODO(mdempsky): Implicit conversions to tagType, if appropriate.
|
||||
w.exprList(clause.Cases)
|
||||
}
|
||||
|
||||
@ -1418,10 +1431,15 @@ func (w *writer) expr(expr syntax.Expr) {
|
||||
case *syntax.IndexExpr:
|
||||
_ = w.p.typeOf(expr.Index) // ensure this is an index expression, not an instantiation
|
||||
|
||||
var keyType types2.Type
|
||||
if mapType, ok := types2.CoreType(w.p.typeOf(expr.X)).(*types2.Map); ok {
|
||||
keyType = mapType.Key()
|
||||
}
|
||||
|
||||
w.Code(exprIndex)
|
||||
w.expr(expr.X)
|
||||
w.pos(expr)
|
||||
w.expr(expr.Index)
|
||||
w.implicitExpr(expr, keyType, expr.Index)
|
||||
|
||||
case *syntax.SliceExpr:
|
||||
w.Code(exprSlice)
|
||||
@ -1448,6 +1466,7 @@ func (w *writer) expr(expr syntax.Expr) {
|
||||
break
|
||||
}
|
||||
|
||||
// TODO(mdempsky): Implicit conversions to common type.
|
||||
w.Code(exprBinaryOp)
|
||||
w.op(binOps[expr.Op])
|
||||
w.expr(expr.X)
|
||||
@ -1462,6 +1481,7 @@ func (w *writer) expr(expr syntax.Expr) {
|
||||
assert(!expr.HasDots)
|
||||
|
||||
w.Code(exprConvert)
|
||||
w.Bool(false) // explicit
|
||||
w.typ(tv.Type)
|
||||
w.pos(expr)
|
||||
w.expr(expr.ArgList[0])
|
||||
@ -1512,9 +1532,9 @@ func (w *writer) expr(expr syntax.Expr) {
|
||||
if w.Bool(len(expr.ArgList) == 1 && isMultiValueExpr(w.p.info, expr.ArgList[0])) {
|
||||
// f(g()) call
|
||||
assert(!expr.HasDots)
|
||||
w.expr(expr.ArgList[0])
|
||||
w.expr(expr.ArgList[0]) // TODO(mdempsky): Implicit conversions to parameter types.
|
||||
} else {
|
||||
w.exprs(expr.ArgList)
|
||||
w.exprs(expr.ArgList) // TODO(mdempsky): Implicit conversions to parameter types.
|
||||
w.Bool(expr.HasDots)
|
||||
}
|
||||
}
|
||||
@ -1526,6 +1546,24 @@ func (w *writer) optExpr(expr syntax.Expr) {
|
||||
}
|
||||
}
|
||||
|
||||
// implicitExpr is like expr, but if dst is non-nil and different from
|
||||
// expr's type, then an implicit conversion operation is inserted at
|
||||
// pos.
|
||||
func (w *writer) implicitExpr(pos poser, dst types2.Type, expr syntax.Expr) {
|
||||
src := w.p.typeOf(expr)
|
||||
if dst != nil && !types2.Identical(src, dst) {
|
||||
if !types2.AssignableTo(src, dst) {
|
||||
w.p.fatalf(pos, "%v is not assignable to %v", src, dst)
|
||||
}
|
||||
w.Code(exprConvert)
|
||||
w.Bool(true) // implicit
|
||||
w.typ(dst)
|
||||
w.pos(pos)
|
||||
// fallthrough
|
||||
}
|
||||
w.expr(expr)
|
||||
}
|
||||
|
||||
func (w *writer) compLit(lit *syntax.CompositeLit) {
|
||||
typ := w.p.typeOf(lit)
|
||||
|
||||
@ -1554,12 +1592,12 @@ func (w *writer) compLit(lit *syntax.CompositeLit) {
|
||||
if kv, ok := elem.(*syntax.KeyValueExpr); w.Bool(ok) {
|
||||
// use position of expr.Key rather than of elem (which has position of ':')
|
||||
w.pos(kv.Key)
|
||||
w.expr(kv.Key)
|
||||
w.expr(kv.Key) // TODO(mdempsky): Implicit conversion to (map) key type.
|
||||
elem = kv.Value
|
||||
}
|
||||
}
|
||||
w.pos(elem)
|
||||
w.expr(elem)
|
||||
w.expr(elem) // TODO(mdempsky): Implicit conversion to element type.
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user