Skip to content

Commit cfa233d

Browse files
committed
cmd/compile: remove unneeded early transforms, with dictionary change
Now that we are computing the dictionary format on the instantiated functions, we can remove the early transformation code that was needed to create the implicit CONVIFACE nodes in the generic function. Change-Id: I1695484e7d59bccbfb757994f3e40e84288759a5 Reviewed-on: https://go-review.googlesource.com/c/go/+/349614 Run-TryBot: Dan Scales <[email protected]> TryBot-Result: Go Bot <[email protected]> Trust: Dan Scales <[email protected]> Reviewed-by: Keith Randall <[email protected]>
1 parent 59a9a03 commit cfa233d

File tree

5 files changed

+26
-119
lines changed

5 files changed

+26
-119
lines changed

src/cmd/compile/internal/noder/expr.go

-38
Original file line numberDiff line numberDiff line change
@@ -250,44 +250,6 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto
250250
// only be fully transformed once it has an instantiated type.
251251
n := ir.NewSelectorExpr(pos, ir.OXDOT, x, typecheck.Lookup(expr.Sel.Value))
252252
typed(g.typ(typ), n)
253-
254-
// Fill in n.Selection for a generic method reference or a bound
255-
// interface method, even though we won't use it directly, since it
256-
// is useful for analysis. Specifically do not fill in for fields or
257-
// other interfaces methods (method call on an interface value), so
258-
// n.Selection being non-nil means a method reference for a generic
259-
// type or a method reference due to a bound.
260-
obj2 := g.info.Selections[expr].Obj()
261-
sig := types2.AsSignature(obj2.Type())
262-
if sig == nil || sig.Recv() == nil {
263-
return n
264-
}
265-
index := g.info.Selections[expr].Index()
266-
last := index[len(index)-1]
267-
// recvType is the receiver of the method being called. Because of the
268-
// way methods are imported, g.obj(obj2) doesn't work across
269-
// packages, so we have to lookup the method via the receiver type.
270-
recvType := deref2(sig.Recv().Type())
271-
if types2.AsInterface(recvType.Underlying()) != nil {
272-
fieldType := n.X.Type()
273-
for _, ix := range index[:len(index)-1] {
274-
fieldType = deref(fieldType).Field(ix).Type
275-
}
276-
if fieldType.Kind() == types.TTYPEPARAM {
277-
n.Selection = fieldType.Bound().AllMethods().Index(last)
278-
//fmt.Printf(">>>>> %v: Bound call %v\n", base.FmtPos(pos), n.Sel)
279-
} else {
280-
assert(fieldType.Kind() == types.TINTER)
281-
//fmt.Printf(">>>>> %v: Interface call %v\n", base.FmtPos(pos), n.Sel)
282-
}
283-
return n
284-
}
285-
286-
recvObj := types2.AsNamed(recvType).Obj()
287-
recv := g.pkg(recvObj.Pkg()).Lookup(recvObj.Name()).Def
288-
n.Selection = recv.Type().Methods().Index(last)
289-
//fmt.Printf(">>>>> %v: Method call %v\n", base.FmtPos(pos), n.Sel)
290-
291253
return n
292254
}
293255

src/cmd/compile/internal/noder/helpers.go

-11
Original file line numberDiff line numberDiff line change
@@ -189,17 +189,6 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool)
189189
// A function instantiation (even if fully concrete) shouldn't be
190190
// transformed yet, because we need to add the dictionary during the
191191
// transformation.
192-
//
193-
// However, if we have a function type (even though it is
194-
// parameterized), then we can add in any needed CONVIFACE nodes via
195-
// typecheckaste(). We need to call transformArgs() to deal first
196-
// with the f(g(()) case where g returns multiple return values. We
197-
// can't do anything if fun is a type param (which is probably
198-
// described by a structural constraint)
199-
if fun.Type().Kind() == types.TFUNC {
200-
transformArgs(n)
201-
typecheckaste(ir.OCALL, fun, n.IsDDD, fun.Type().Params(), n.Args, true)
202-
}
203192
return typed(typ, n)
204193
}
205194

src/cmd/compile/internal/noder/stmt.go

-9
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,6 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node {
101101
n.Def = initDefn(n, names)
102102

103103
if delay {
104-
earlyTransformAssign(n, lhs, rhs)
105-
n.X, n.Y = lhs[0], rhs[0]
106104
n.SetTypecheck(3)
107105
return n
108106
}
@@ -117,7 +115,6 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node {
117115
n := ir.NewAssignListStmt(g.pos(stmt), ir.OAS2, lhs, rhs)
118116
n.Def = initDefn(n, names)
119117
if delay {
120-
earlyTransformAssign(n, lhs, rhs)
121118
n.SetTypecheck(3)
122119
return n
123120
}
@@ -135,12 +132,6 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node {
135132
if e.Type().HasTParam() {
136133
// Delay transforming the return statement if any of the
137134
// return values have a type param.
138-
if !ir.HasNamedResults(ir.CurFunc) {
139-
transformArgs(n)
140-
// But add CONVIFACE nodes where needed if
141-
// any of the return values have interface type.
142-
typecheckaste(ir.ORETURN, nil, false, ir.CurFunc.Type().Results(), n.Results, true)
143-
}
144135
n.SetTypecheck(3)
145136
return n
146137
}

src/cmd/compile/internal/noder/transform.go

+23-61
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ func transformCall(n *ir.CallExpr) {
157157
n.SetOp(ir.OCALLFUNC)
158158
}
159159

160-
typecheckaste(ir.OCALL, n.X, n.IsDDD, t.Params(), n.Args, false)
160+
typecheckaste(ir.OCALL, n.X, n.IsDDD, t.Params(), n.Args)
161161
if l.Op() == ir.ODOTMETH && len(deref(n.X.Type().Recv().Type).RParams()) == 0 {
162162
typecheck.FixMethodCall(n)
163163
}
@@ -365,59 +365,6 @@ assignOK:
365365
}
366366
}
367367

368-
// Version of transformAssign that can run on generic code that adds CONVIFACE calls
369-
// as needed (and rewrites multi-value calls).
370-
func earlyTransformAssign(stmt ir.Node, lhs, rhs []ir.Node) {
371-
cr := len(rhs)
372-
if len(rhs) == 1 {
373-
if rtyp := rhs[0].Type(); rtyp != nil && rtyp.IsFuncArgStruct() {
374-
cr = rtyp.NumFields()
375-
}
376-
}
377-
378-
// x,y,z = f()
379-
_, isCallExpr := rhs[0].(*ir.CallExpr)
380-
if isCallExpr && cr > len(rhs) {
381-
stmt := stmt.(*ir.AssignListStmt)
382-
stmt.SetOp(ir.OAS2FUNC)
383-
r := rhs[0].(*ir.CallExpr)
384-
rtyp := r.Type()
385-
386-
mismatched := false
387-
failed := false
388-
for i := range lhs {
389-
result := rtyp.Field(i).Type
390-
391-
if lhs[i].Type() == nil || result == nil {
392-
failed = true
393-
} else if lhs[i] != ir.BlankNode && !types.Identical(lhs[i].Type(), result) {
394-
mismatched = true
395-
}
396-
}
397-
if mismatched && !failed {
398-
typecheck.RewriteMultiValueCall(stmt, r)
399-
}
400-
return
401-
}
402-
403-
// x, ok = y
404-
if len(lhs) != len(rhs) {
405-
assert(len(lhs) == 2 && len(rhs) == 1)
406-
// TODO(danscales): deal with case where x or ok is an interface
407-
// type. We want to add CONVIFACE now, but that is tricky, because
408-
// the rhs may be AS2MAPR, AS2RECV, etc. which has two result values,
409-
// and that is not rewritten until the order phase (o.stmt, as2ok).
410-
return
411-
}
412-
413-
// Check for interface conversion on each assignment
414-
for i, r := range rhs {
415-
if lhs[i].Type() != nil && lhs[i].Type().IsInterface() {
416-
rhs[i] = assignconvfn(r, lhs[i].Type())
417-
}
418-
}
419-
}
420-
421368
// Corresponds to typecheck.typecheckargs. Really just deals with multi-value calls.
422369
func transformArgs(n ir.InitNode) {
423370
var list []ir.Node
@@ -457,11 +404,11 @@ func assignconvfn(n ir.Node, t *types.Type) ir.Node {
457404
return n
458405
}
459406

460-
if types.Identical(n.Type(), t) {
407+
if types.IdenticalStrict(n.Type(), t) {
461408
return n
462409
}
463410

464-
op, why := typecheck.Assignop(n.Type(), t)
411+
op, why := Assignop(n.Type(), t)
465412
if op == ir.OXXX {
466413
base.Fatalf("found illegal assignment %+v -> %+v; %s", n.Type(), t, why)
467414
}
@@ -472,11 +419,26 @@ func assignconvfn(n ir.Node, t *types.Type) ir.Node {
472419
return r
473420
}
474421

422+
func Assignop(src, dst *types.Type) (ir.Op, string) {
423+
if src == dst {
424+
return ir.OCONVNOP, ""
425+
}
426+
if src == nil || dst == nil || src.Kind() == types.TFORW || dst.Kind() == types.TFORW || src.Underlying() == nil || dst.Underlying() == nil {
427+
return ir.OXXX, ""
428+
}
429+
430+
// 1. src type is identical to dst.
431+
if types.IdenticalStrict(src, dst) {
432+
return ir.OCONVNOP, ""
433+
}
434+
return typecheck.Assignop1(src, dst)
435+
}
436+
475437
// Corresponds to typecheck.typecheckaste, but we add an extra flag convifaceOnly
476438
// only. If convifaceOnly is true, we only do interface conversion. We use this to do
477439
// early insertion of CONVIFACE nodes during noder2, when the function or args may
478440
// have typeparams.
479-
func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl ir.Nodes, convifaceOnly bool) {
441+
func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl ir.Nodes) {
480442
var t *types.Type
481443
var i int
482444

@@ -495,7 +457,7 @@ func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl i
495457
if isddd {
496458
n = nl[i]
497459
ir.SetPos(n)
498-
if n.Type() != nil && (!convifaceOnly || t.IsInterface()) {
460+
if n.Type() != nil {
499461
nl[i] = assignconvfn(n, t)
500462
}
501463
return
@@ -505,7 +467,7 @@ func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl i
505467
for ; i < len(nl); i++ {
506468
n = nl[i]
507469
ir.SetPos(n)
508-
if n.Type() != nil && (!convifaceOnly || t.IsInterface()) {
470+
if n.Type() != nil {
509471
nl[i] = assignconvfn(n, t.Elem())
510472
}
511473
}
@@ -514,7 +476,7 @@ func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl i
514476

515477
n = nl[i]
516478
ir.SetPos(n)
517-
if n.Type() != nil && (!convifaceOnly || t.IsInterface()) {
479+
if n.Type() != nil {
518480
nl[i] = assignconvfn(n, t)
519481
}
520482
i++
@@ -536,7 +498,7 @@ func transformReturn(rs *ir.ReturnStmt) {
536498
return
537499
}
538500

539-
typecheckaste(ir.ORETURN, nil, false, ir.CurFunc.Type().Results(), nl, false)
501+
typecheckaste(ir.ORETURN, nil, false, ir.CurFunc.Type().Results(), nl)
540502
}
541503

542504
// transformSelect transforms a select node, creating an assignment list as needed

src/cmd/compile/internal/typecheck/subr.go

+3
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,10 @@ func Assignop(src, dst *types.Type) (ir.Op, string) {
352352
if types.Identical(src, dst) {
353353
return ir.OCONVNOP, ""
354354
}
355+
return Assignop1(src, dst)
356+
}
355357

358+
func Assignop1(src, dst *types.Type) (ir.Op, string) {
356359
// 2. src and dst have identical underlying types and
357360
// a. either src or dst is not a named type, or
358361
// b. both are empty interface types, or

0 commit comments

Comments
 (0)