]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile: fix static init inlining for hidden node fields
authorMatthew Dempsky <mdempsky@google.com>
Tue, 17 Jan 2023 18:59:25 +0000 (10:59 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Tue, 17 Jan 2023 22:13:42 +0000 (22:13 +0000)
Unified IR added several new IR fields for holding *runtime._type
expressions. To avoid throwing off any frontend semantics
(particularly inlining cost heuristics), they were marked as
`mknode:"-"` so that code wouldn't visit them.

Unfortunately, this has a bad interaction with the static init
inlining optimization, because the latter relies on ir.EditChildren to
substitute all parameters. This potentially includes dictionary
parameters, which can appear within the new RType fields.

This CL adds a new ir.EditChildrenWithHidden function that also edits
these fields, and switches staticinit to use it. Longer term, we
should unhide the RType fields so that ir.EditChildren visits them
normally, but that's scarier so late in the release cycle.

Fixes #57778.

Change-Id: I98c1e8cf366156dc0c81a0cb79029cc5e59c476f
Reviewed-on: https://go-review.googlesource.com/c/go/+/461686
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
src/cmd/compile/internal/ir/func.go
src/cmd/compile/internal/ir/mknode.go
src/cmd/compile/internal/ir/name.go
src/cmd/compile/internal/ir/node.go
src/cmd/compile/internal/ir/node_gen.go
src/cmd/compile/internal/ir/visit.go
src/cmd/compile/internal/staticinit/sched.go
test/fixedbugs/issue57778.go [new file with mode: 0644]

index 31c11f8297ec19891a7521adb01c9e8dcc9cd342..b0b8da5d18a8f3a504894246b820a3b957d12357 100644 (file)
@@ -147,9 +147,10 @@ func NewFunc(pos src.XPos) *Func {
 
 func (f *Func) isStmt() {}
 
-func (n *Func) copy() Node                         { panic(n.no("copy")) }
-func (n *Func) doChildren(do func(Node) bool) bool { return doNodes(n.Body, do) }
-func (n *Func) editChildren(edit func(Node) Node)  { editNodes(n.Body, edit) }
+func (n *Func) copy() Node                                  { panic(n.no("copy")) }
+func (n *Func) doChildren(do func(Node) bool) bool          { return doNodes(n.Body, do) }
+func (n *Func) editChildren(edit func(Node) Node)           { editNodes(n.Body, edit) }
+func (n *Func) editChildrenWithHidden(edit func(Node) Node) { editNodes(n.Body, edit) }
 
 func (f *Func) Type() *types.Type                { return f.Nname.Type() }
 func (f *Func) Sym() *types.Sym                  { return f.Nname.Sym() }
index caf4ba01358cd8be4dee312488b6028c4cfa7a22..716e84389ff9997db07054af099479ce450a9d8c 100644 (file)
@@ -256,18 +256,24 @@ func processType(t *ast.TypeSpec) {
        var copyBody strings.Builder
        var doChildrenBody strings.Builder
        var editChildrenBody strings.Builder
+       var editChildrenWithHiddenBody strings.Builder
        for _, f := range fields {
+               names := f.Names
+               ft := f.Type
+               hidden := false
                if f.Tag != nil {
                        tag := f.Tag.Value[1 : len(f.Tag.Value)-1]
                        if strings.HasPrefix(tag, "mknode:") {
                                if tag[7:] == "\"-\"" {
-                                       continue
+                                       if !isNamedType(ft, "Node") {
+                                               continue
+                                       }
+                                       hidden = true
+                               } else {
+                                       panic(fmt.Sprintf("unexpected tag value: %s", tag))
                                }
-                               panic(fmt.Sprintf("unexpected tag value: %s", tag))
                        }
                }
-               names := f.Names
-               ft := f.Type
                if isNamedType(ft, "Nodes") {
                        // Nodes == []Node
                        ft = &ast.ArrayType{Elt: &ast.Ident{Name: "Node"}}
@@ -286,6 +292,20 @@ func processType(t *ast.TypeSpec) {
                        continue
                }
                for _, name := range names {
+                       ptr := ""
+                       if isPtr {
+                               ptr = "*"
+                       }
+                       if isSlice {
+                               fmt.Fprintf(&editChildrenWithHiddenBody,
+                                       "edit%ss(n.%s, edit)\n", ft, name)
+                       } else {
+                               fmt.Fprintf(&editChildrenWithHiddenBody,
+                                       "if n.%s != nil {\nn.%s = edit(n.%s).(%s%s)\n}\n", name, name, name, ptr, ft)
+                       }
+                       if hidden {
+                               continue
+                       }
                        if isSlice {
                                fmt.Fprintf(&copyBody, "c.%s = copy%ss(c.%s)\n", name, ft, name)
                                fmt.Fprintf(&doChildrenBody,
@@ -295,10 +315,6 @@ func processType(t *ast.TypeSpec) {
                        } else {
                                fmt.Fprintf(&doChildrenBody,
                                        "if n.%s != nil && do(n.%s) {\nreturn true\n}\n", name, name)
-                               ptr := ""
-                               if isPtr {
-                                       ptr = "*"
-                               }
                                fmt.Fprintf(&editChildrenBody,
                                        "if n.%s != nil {\nn.%s = edit(n.%s).(%s%s)\n}\n", name, name, name, ptr, ft)
                        }
@@ -313,6 +329,9 @@ func processType(t *ast.TypeSpec) {
        fmt.Fprintf(&buf, "func (n *%s) editChildren(edit func(Node) Node) {\n", name)
        buf.WriteString(editChildrenBody.String())
        fmt.Fprintf(&buf, "}\n")
+       fmt.Fprintf(&buf, "func (n *%s) editChildrenWithHidden(edit func(Node) Node) {\n", name)
+       buf.WriteString(editChildrenWithHiddenBody.String())
+       fmt.Fprintf(&buf, "}\n")
 }
 
 func generateHelpers() {
index f537ba49818f6d4dbd51918e0c5321b152c14d86..43aa582e3d18eb9bc121178064440cf3674b2263 100644 (file)
@@ -134,9 +134,10 @@ type Name struct {
 
 func (n *Name) isExpr() {}
 
-func (n *Name) copy() Node                         { panic(n.no("copy")) }
-func (n *Name) doChildren(do func(Node) bool) bool { return false }
-func (n *Name) editChildren(edit func(Node) Node)  {}
+func (n *Name) copy() Node                                  { panic(n.no("copy")) }
+func (n *Name) doChildren(do func(Node) bool) bool          { return false }
+func (n *Name) editChildren(edit func(Node) Node)           {}
+func (n *Name) editChildrenWithHidden(edit func(Node) Node) {}
 
 // RecordFrameOffset records the frame offset for the name.
 // It is used by package types when laying out function arguments.
index bda3957af9561104c43abf962da30ba8363bc30b..b42f914aadd8209c163c13a46441caa2ed1b09e1 100644 (file)
@@ -30,6 +30,7 @@ type Node interface {
 
        doChildren(func(Node) bool) bool
        editChildren(func(Node) Node)
+       editChildrenWithHidden(func(Node) Node)
 
        // Abstract graph structure, for generic traversals.
        Op() Op
index f5d362eef543d18dc25d49498436b569f81f9180..2dda76b1e3f498595e9a1c31be23a8347106badd 100644 (file)
@@ -30,6 +30,13 @@ func (n *AddStringExpr) editChildren(edit func(Node) Node) {
                n.Prealloc = edit(n.Prealloc).(*Name)
        }
 }
+func (n *AddStringExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       editNodes(n.List, edit)
+       if n.Prealloc != nil {
+               n.Prealloc = edit(n.Prealloc).(*Name)
+       }
+}
 
 func (n *AddrExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *AddrExpr) copy() Node {
@@ -58,6 +65,15 @@ func (n *AddrExpr) editChildren(edit func(Node) Node) {
                n.Prealloc = edit(n.Prealloc).(*Name)
        }
 }
+func (n *AddrExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.X != nil {
+               n.X = edit(n.X).(Node)
+       }
+       if n.Prealloc != nil {
+               n.Prealloc = edit(n.Prealloc).(*Name)
+       }
+}
 
 func (n *AssignListStmt) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *AssignListStmt) copy() Node {
@@ -84,6 +100,11 @@ func (n *AssignListStmt) editChildren(edit func(Node) Node) {
        editNodes(n.Lhs, edit)
        editNodes(n.Rhs, edit)
 }
+func (n *AssignListStmt) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       editNodes(n.Lhs, edit)
+       editNodes(n.Rhs, edit)
+}
 
 func (n *AssignOpStmt) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *AssignOpStmt) copy() Node {
@@ -112,6 +133,15 @@ func (n *AssignOpStmt) editChildren(edit func(Node) Node) {
                n.Y = edit(n.Y).(Node)
        }
 }
+func (n *AssignOpStmt) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.X != nil {
+               n.X = edit(n.X).(Node)
+       }
+       if n.Y != nil {
+               n.Y = edit(n.Y).(Node)
+       }
+}
 
 func (n *AssignStmt) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *AssignStmt) copy() Node {
@@ -140,6 +170,15 @@ func (n *AssignStmt) editChildren(edit func(Node) Node) {
                n.Y = edit(n.Y).(Node)
        }
 }
+func (n *AssignStmt) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.X != nil {
+               n.X = edit(n.X).(Node)
+       }
+       if n.Y != nil {
+               n.Y = edit(n.Y).(Node)
+       }
+}
 
 func (n *BasicLit) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *BasicLit) copy() Node {
@@ -156,6 +195,9 @@ func (n *BasicLit) doChildren(do func(Node) bool) bool {
 func (n *BasicLit) editChildren(edit func(Node) Node) {
        editNodes(n.init, edit)
 }
+func (n *BasicLit) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+}
 
 func (n *BinaryExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *BinaryExpr) copy() Node {
@@ -184,6 +226,18 @@ func (n *BinaryExpr) editChildren(edit func(Node) Node) {
                n.Y = edit(n.Y).(Node)
        }
 }
+func (n *BinaryExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.X != nil {
+               n.X = edit(n.X).(Node)
+       }
+       if n.Y != nil {
+               n.Y = edit(n.Y).(Node)
+       }
+       if n.RType != nil {
+               n.RType = edit(n.RType).(Node)
+       }
+}
 
 func (n *BlockStmt) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *BlockStmt) copy() Node {
@@ -205,6 +259,10 @@ func (n *BlockStmt) editChildren(edit func(Node) Node) {
        editNodes(n.init, edit)
        editNodes(n.List, edit)
 }
+func (n *BlockStmt) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       editNodes(n.List, edit)
+}
 
 func (n *BranchStmt) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *BranchStmt) copy() Node {
@@ -221,6 +279,9 @@ func (n *BranchStmt) doChildren(do func(Node) bool) bool {
 func (n *BranchStmt) editChildren(edit func(Node) Node) {
        editNodes(n.init, edit)
 }
+func (n *BranchStmt) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+}
 
 func (n *CallExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *CallExpr) copy() Node {
@@ -253,6 +314,17 @@ func (n *CallExpr) editChildren(edit func(Node) Node) {
        editNodes(n.Args, edit)
        editNames(n.KeepAlive, edit)
 }
+func (n *CallExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.X != nil {
+               n.X = edit(n.X).(Node)
+       }
+       editNodes(n.Args, edit)
+       if n.RType != nil {
+               n.RType = edit(n.RType).(Node)
+       }
+       editNames(n.KeepAlive, edit)
+}
 
 func (n *CaseClause) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *CaseClause) copy() Node {
@@ -290,6 +362,15 @@ func (n *CaseClause) editChildren(edit func(Node) Node) {
        editNodes(n.RTypes, edit)
        editNodes(n.Body, edit)
 }
+func (n *CaseClause) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.Var != nil {
+               n.Var = edit(n.Var).(*Name)
+       }
+       editNodes(n.List, edit)
+       editNodes(n.RTypes, edit)
+       editNodes(n.Body, edit)
+}
 
 func (n *ClosureExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *ClosureExpr) copy() Node {
@@ -312,6 +393,12 @@ func (n *ClosureExpr) editChildren(edit func(Node) Node) {
                n.Prealloc = edit(n.Prealloc).(*Name)
        }
 }
+func (n *ClosureExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.Prealloc != nil {
+               n.Prealloc = edit(n.Prealloc).(*Name)
+       }
+}
 
 func (n *CommClause) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *CommClause) copy() Node {
@@ -339,6 +426,13 @@ func (n *CommClause) editChildren(edit func(Node) Node) {
        }
        editNodes(n.Body, edit)
 }
+func (n *CommClause) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.Comm != nil {
+               n.Comm = edit(n.Comm).(Node)
+       }
+       editNodes(n.Body, edit)
+}
 
 func (n *CompLitExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *CompLitExpr) copy() Node {
@@ -366,6 +460,16 @@ func (n *CompLitExpr) editChildren(edit func(Node) Node) {
                n.Prealloc = edit(n.Prealloc).(*Name)
        }
 }
+func (n *CompLitExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       editNodes(n.List, edit)
+       if n.RType != nil {
+               n.RType = edit(n.RType).(Node)
+       }
+       if n.Prealloc != nil {
+               n.Prealloc = edit(n.Prealloc).(*Name)
+       }
+}
 
 func (n *ConstExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *ConstExpr) copy() Node {
@@ -382,6 +486,9 @@ func (n *ConstExpr) doChildren(do func(Node) bool) bool {
 func (n *ConstExpr) editChildren(edit func(Node) Node) {
        editNodes(n.init, edit)
 }
+func (n *ConstExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+}
 
 func (n *ConvExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *ConvExpr) copy() Node {
@@ -404,6 +511,24 @@ func (n *ConvExpr) editChildren(edit func(Node) Node) {
                n.X = edit(n.X).(Node)
        }
 }
+func (n *ConvExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.X != nil {
+               n.X = edit(n.X).(Node)
+       }
+       if n.TypeWord != nil {
+               n.TypeWord = edit(n.TypeWord).(Node)
+       }
+       if n.SrcRType != nil {
+               n.SrcRType = edit(n.SrcRType).(Node)
+       }
+       if n.ElemRType != nil {
+               n.ElemRType = edit(n.ElemRType).(Node)
+       }
+       if n.ElemElemRType != nil {
+               n.ElemElemRType = edit(n.ElemElemRType).(Node)
+       }
+}
 
 func (n *Decl) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *Decl) copy() Node {
@@ -421,6 +546,11 @@ func (n *Decl) editChildren(edit func(Node) Node) {
                n.X = edit(n.X).(*Name)
        }
 }
+func (n *Decl) editChildrenWithHidden(edit func(Node) Node) {
+       if n.X != nil {
+               n.X = edit(n.X).(*Name)
+       }
+}
 
 func (n *DynamicType) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *DynamicType) copy() Node {
@@ -449,6 +579,15 @@ func (n *DynamicType) editChildren(edit func(Node) Node) {
                n.ITab = edit(n.ITab).(Node)
        }
 }
+func (n *DynamicType) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.RType != nil {
+               n.RType = edit(n.RType).(Node)
+       }
+       if n.ITab != nil {
+               n.ITab = edit(n.ITab).(Node)
+       }
+}
 
 func (n *DynamicTypeAssertExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *DynamicTypeAssertExpr) copy() Node {
@@ -489,6 +628,21 @@ func (n *DynamicTypeAssertExpr) editChildren(edit func(Node) Node) {
                n.ITab = edit(n.ITab).(Node)
        }
 }
+func (n *DynamicTypeAssertExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.X != nil {
+               n.X = edit(n.X).(Node)
+       }
+       if n.SrcRType != nil {
+               n.SrcRType = edit(n.SrcRType).(Node)
+       }
+       if n.RType != nil {
+               n.RType = edit(n.RType).(Node)
+       }
+       if n.ITab != nil {
+               n.ITab = edit(n.ITab).(Node)
+       }
+}
 
 func (n *ForStmt) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *ForStmt) copy() Node {
@@ -522,6 +676,16 @@ func (n *ForStmt) editChildren(edit func(Node) Node) {
        }
        editNodes(n.Body, edit)
 }
+func (n *ForStmt) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.Cond != nil {
+               n.Cond = edit(n.Cond).(Node)
+       }
+       if n.Post != nil {
+               n.Post = edit(n.Post).(Node)
+       }
+       editNodes(n.Body, edit)
+}
 
 func (n *Func) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 
@@ -546,6 +710,12 @@ func (n *GoDeferStmt) editChildren(edit func(Node) Node) {
                n.Call = edit(n.Call).(Node)
        }
 }
+func (n *GoDeferStmt) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.Call != nil {
+               n.Call = edit(n.Call).(Node)
+       }
+}
 
 func (n *Ident) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *Ident) copy() Node {
@@ -562,6 +732,9 @@ func (n *Ident) doChildren(do func(Node) bool) bool {
 func (n *Ident) editChildren(edit func(Node) Node) {
        editNodes(n.init, edit)
 }
+func (n *Ident) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+}
 
 func (n *IfStmt) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *IfStmt) copy() Node {
@@ -594,6 +767,14 @@ func (n *IfStmt) editChildren(edit func(Node) Node) {
        editNodes(n.Body, edit)
        editNodes(n.Else, edit)
 }
+func (n *IfStmt) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.Cond != nil {
+               n.Cond = edit(n.Cond).(Node)
+       }
+       editNodes(n.Body, edit)
+       editNodes(n.Else, edit)
+}
 
 func (n *IndexExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *IndexExpr) copy() Node {
@@ -622,6 +803,18 @@ func (n *IndexExpr) editChildren(edit func(Node) Node) {
                n.Index = edit(n.Index).(Node)
        }
 }
+func (n *IndexExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.X != nil {
+               n.X = edit(n.X).(Node)
+       }
+       if n.Index != nil {
+               n.Index = edit(n.Index).(Node)
+       }
+       if n.RType != nil {
+               n.RType = edit(n.RType).(Node)
+       }
+}
 
 func (n *InlineMarkStmt) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *InlineMarkStmt) copy() Node {
@@ -638,6 +831,9 @@ func (n *InlineMarkStmt) doChildren(do func(Node) bool) bool {
 func (n *InlineMarkStmt) editChildren(edit func(Node) Node) {
        editNodes(n.init, edit)
 }
+func (n *InlineMarkStmt) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+}
 
 func (n *InlinedCallExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *InlinedCallExpr) copy() Node {
@@ -664,6 +860,11 @@ func (n *InlinedCallExpr) editChildren(edit func(Node) Node) {
        editNodes(n.Body, edit)
        editNodes(n.ReturnVars, edit)
 }
+func (n *InlinedCallExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       editNodes(n.Body, edit)
+       editNodes(n.ReturnVars, edit)
+}
 
 func (n *InstExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *InstExpr) copy() Node {
@@ -691,6 +892,13 @@ func (n *InstExpr) editChildren(edit func(Node) Node) {
        }
        editNtypes(n.Targs, edit)
 }
+func (n *InstExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.X != nil {
+               n.X = edit(n.X).(Node)
+       }
+       editNtypes(n.Targs, edit)
+}
 
 func (n *JumpTableStmt) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *JumpTableStmt) copy() Node {
@@ -713,6 +921,12 @@ func (n *JumpTableStmt) editChildren(edit func(Node) Node) {
                n.Idx = edit(n.Idx).(Node)
        }
 }
+func (n *JumpTableStmt) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.Idx != nil {
+               n.Idx = edit(n.Idx).(Node)
+       }
+}
 
 func (n *KeyExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *KeyExpr) copy() Node {
@@ -741,6 +955,15 @@ func (n *KeyExpr) editChildren(edit func(Node) Node) {
                n.Value = edit(n.Value).(Node)
        }
 }
+func (n *KeyExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.Key != nil {
+               n.Key = edit(n.Key).(Node)
+       }
+       if n.Value != nil {
+               n.Value = edit(n.Value).(Node)
+       }
+}
 
 func (n *LabelStmt) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *LabelStmt) copy() Node {
@@ -757,6 +980,9 @@ func (n *LabelStmt) doChildren(do func(Node) bool) bool {
 func (n *LabelStmt) editChildren(edit func(Node) Node) {
        editNodes(n.init, edit)
 }
+func (n *LabelStmt) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+}
 
 func (n *LinksymOffsetExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *LinksymOffsetExpr) copy() Node {
@@ -773,6 +999,9 @@ func (n *LinksymOffsetExpr) doChildren(do func(Node) bool) bool {
 func (n *LinksymOffsetExpr) editChildren(edit func(Node) Node) {
        editNodes(n.init, edit)
 }
+func (n *LinksymOffsetExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+}
 
 func (n *LogicalExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *LogicalExpr) copy() Node {
@@ -801,6 +1030,15 @@ func (n *LogicalExpr) editChildren(edit func(Node) Node) {
                n.Y = edit(n.Y).(Node)
        }
 }
+func (n *LogicalExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.X != nil {
+               n.X = edit(n.X).(Node)
+       }
+       if n.Y != nil {
+               n.Y = edit(n.Y).(Node)
+       }
+}
 
 func (n *MakeExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *MakeExpr) copy() Node {
@@ -829,6 +1067,18 @@ func (n *MakeExpr) editChildren(edit func(Node) Node) {
                n.Cap = edit(n.Cap).(Node)
        }
 }
+func (n *MakeExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.RType != nil {
+               n.RType = edit(n.RType).(Node)
+       }
+       if n.Len != nil {
+               n.Len = edit(n.Len).(Node)
+       }
+       if n.Cap != nil {
+               n.Cap = edit(n.Cap).(Node)
+       }
+}
 
 func (n *Name) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 
@@ -847,6 +1097,9 @@ func (n *NilExpr) doChildren(do func(Node) bool) bool {
 func (n *NilExpr) editChildren(edit func(Node) Node) {
        editNodes(n.init, edit)
 }
+func (n *NilExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+}
 
 func (n *ParenExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *ParenExpr) copy() Node {
@@ -869,6 +1122,12 @@ func (n *ParenExpr) editChildren(edit func(Node) Node) {
                n.X = edit(n.X).(Node)
        }
 }
+func (n *ParenExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.X != nil {
+               n.X = edit(n.X).(Node)
+       }
+}
 
 func (n *RangeStmt) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *RangeStmt) copy() Node {
@@ -914,6 +1173,37 @@ func (n *RangeStmt) editChildren(edit func(Node) Node) {
                n.Prealloc = edit(n.Prealloc).(*Name)
        }
 }
+func (n *RangeStmt) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.X != nil {
+               n.X = edit(n.X).(Node)
+       }
+       if n.RType != nil {
+               n.RType = edit(n.RType).(Node)
+       }
+       if n.Key != nil {
+               n.Key = edit(n.Key).(Node)
+       }
+       if n.Value != nil {
+               n.Value = edit(n.Value).(Node)
+       }
+       editNodes(n.Body, edit)
+       if n.Prealloc != nil {
+               n.Prealloc = edit(n.Prealloc).(*Name)
+       }
+       if n.KeyTypeWord != nil {
+               n.KeyTypeWord = edit(n.KeyTypeWord).(Node)
+       }
+       if n.KeySrcRType != nil {
+               n.KeySrcRType = edit(n.KeySrcRType).(Node)
+       }
+       if n.ValueTypeWord != nil {
+               n.ValueTypeWord = edit(n.ValueTypeWord).(Node)
+       }
+       if n.ValueSrcRType != nil {
+               n.ValueSrcRType = edit(n.ValueSrcRType).(Node)
+       }
+}
 
 func (n *RawOrigExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *RawOrigExpr) copy() Node {
@@ -930,6 +1220,9 @@ func (n *RawOrigExpr) doChildren(do func(Node) bool) bool {
 func (n *RawOrigExpr) editChildren(edit func(Node) Node) {
        editNodes(n.init, edit)
 }
+func (n *RawOrigExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+}
 
 func (n *ResultExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *ResultExpr) copy() Node {
@@ -946,6 +1239,9 @@ func (n *ResultExpr) doChildren(do func(Node) bool) bool {
 func (n *ResultExpr) editChildren(edit func(Node) Node) {
        editNodes(n.init, edit)
 }
+func (n *ResultExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+}
 
 func (n *ReturnStmt) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *ReturnStmt) copy() Node {
@@ -967,6 +1263,10 @@ func (n *ReturnStmt) editChildren(edit func(Node) Node) {
        editNodes(n.init, edit)
        editNodes(n.Results, edit)
 }
+func (n *ReturnStmt) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       editNodes(n.Results, edit)
+}
 
 func (n *SelectStmt) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *SelectStmt) copy() Node {
@@ -993,6 +1293,11 @@ func (n *SelectStmt) editChildren(edit func(Node) Node) {
        editCommClauses(n.Cases, edit)
        editNodes(n.Compiled, edit)
 }
+func (n *SelectStmt) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       editCommClauses(n.Cases, edit)
+       editNodes(n.Compiled, edit)
+}
 
 func (n *SelectorExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *SelectorExpr) copy() Node {
@@ -1021,6 +1326,15 @@ func (n *SelectorExpr) editChildren(edit func(Node) Node) {
                n.Prealloc = edit(n.Prealloc).(*Name)
        }
 }
+func (n *SelectorExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.X != nil {
+               n.X = edit(n.X).(Node)
+       }
+       if n.Prealloc != nil {
+               n.Prealloc = edit(n.Prealloc).(*Name)
+       }
+}
 
 func (n *SendStmt) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *SendStmt) copy() Node {
@@ -1049,6 +1363,15 @@ func (n *SendStmt) editChildren(edit func(Node) Node) {
                n.Value = edit(n.Value).(Node)
        }
 }
+func (n *SendStmt) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.Chan != nil {
+               n.Chan = edit(n.Chan).(Node)
+       }
+       if n.Value != nil {
+               n.Value = edit(n.Value).(Node)
+       }
+}
 
 func (n *SliceExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *SliceExpr) copy() Node {
@@ -1089,6 +1412,21 @@ func (n *SliceExpr) editChildren(edit func(Node) Node) {
                n.Max = edit(n.Max).(Node)
        }
 }
+func (n *SliceExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.X != nil {
+               n.X = edit(n.X).(Node)
+       }
+       if n.Low != nil {
+               n.Low = edit(n.Low).(Node)
+       }
+       if n.High != nil {
+               n.High = edit(n.High).(Node)
+       }
+       if n.Max != nil {
+               n.Max = edit(n.Max).(Node)
+       }
+}
 
 func (n *SliceHeaderExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *SliceHeaderExpr) copy() Node {
@@ -1123,6 +1461,18 @@ func (n *SliceHeaderExpr) editChildren(edit func(Node) Node) {
                n.Cap = edit(n.Cap).(Node)
        }
 }
+func (n *SliceHeaderExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.Ptr != nil {
+               n.Ptr = edit(n.Ptr).(Node)
+       }
+       if n.Len != nil {
+               n.Len = edit(n.Len).(Node)
+       }
+       if n.Cap != nil {
+               n.Cap = edit(n.Cap).(Node)
+       }
+}
 
 func (n *StarExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *StarExpr) copy() Node {
@@ -1145,6 +1495,12 @@ func (n *StarExpr) editChildren(edit func(Node) Node) {
                n.X = edit(n.X).(Node)
        }
 }
+func (n *StarExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.X != nil {
+               n.X = edit(n.X).(Node)
+       }
+}
 
 func (n *StringHeaderExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *StringHeaderExpr) copy() Node {
@@ -1173,6 +1529,15 @@ func (n *StringHeaderExpr) editChildren(edit func(Node) Node) {
                n.Len = edit(n.Len).(Node)
        }
 }
+func (n *StringHeaderExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.Ptr != nil {
+               n.Ptr = edit(n.Ptr).(Node)
+       }
+       if n.Len != nil {
+               n.Len = edit(n.Len).(Node)
+       }
+}
 
 func (n *StructKeyExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *StructKeyExpr) copy() Node {
@@ -1195,6 +1560,12 @@ func (n *StructKeyExpr) editChildren(edit func(Node) Node) {
                n.Value = edit(n.Value).(Node)
        }
 }
+func (n *StructKeyExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.Value != nil {
+               n.Value = edit(n.Value).(Node)
+       }
+}
 
 func (n *SwitchStmt) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *SwitchStmt) copy() Node {
@@ -1227,6 +1598,14 @@ func (n *SwitchStmt) editChildren(edit func(Node) Node) {
        editCaseClauses(n.Cases, edit)
        editNodes(n.Compiled, edit)
 }
+func (n *SwitchStmt) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.Tag != nil {
+               n.Tag = edit(n.Tag).(Node)
+       }
+       editCaseClauses(n.Cases, edit)
+       editNodes(n.Compiled, edit)
+}
 
 func (n *TailCallStmt) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *TailCallStmt) copy() Node {
@@ -1249,6 +1628,12 @@ func (n *TailCallStmt) editChildren(edit func(Node) Node) {
                n.Call = edit(n.Call).(*CallExpr)
        }
 }
+func (n *TailCallStmt) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.Call != nil {
+               n.Call = edit(n.Call).(*CallExpr)
+       }
+}
 
 func (n *TypeAssertExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *TypeAssertExpr) copy() Node {
@@ -1271,6 +1656,15 @@ func (n *TypeAssertExpr) editChildren(edit func(Node) Node) {
                n.X = edit(n.X).(Node)
        }
 }
+func (n *TypeAssertExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.X != nil {
+               n.X = edit(n.X).(Node)
+       }
+       if n.ITab != nil {
+               n.ITab = edit(n.ITab).(Node)
+       }
+}
 
 func (n *TypeSwitchGuard) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *TypeSwitchGuard) copy() Node {
@@ -1294,6 +1688,14 @@ func (n *TypeSwitchGuard) editChildren(edit func(Node) Node) {
                n.X = edit(n.X).(Node)
        }
 }
+func (n *TypeSwitchGuard) editChildrenWithHidden(edit func(Node) Node) {
+       if n.Tag != nil {
+               n.Tag = edit(n.Tag).(*Ident)
+       }
+       if n.X != nil {
+               n.X = edit(n.X).(Node)
+       }
+}
 
 func (n *UnaryExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *UnaryExpr) copy() Node {
@@ -1316,6 +1718,12 @@ func (n *UnaryExpr) editChildren(edit func(Node) Node) {
                n.X = edit(n.X).(Node)
        }
 }
+func (n *UnaryExpr) editChildrenWithHidden(edit func(Node) Node) {
+       editNodes(n.init, edit)
+       if n.X != nil {
+               n.X = edit(n.X).(Node)
+       }
+}
 
 func (n *typeNode) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *typeNode) copy() Node {
@@ -1327,6 +1735,8 @@ func (n *typeNode) doChildren(do func(Node) bool) bool {
 }
 func (n *typeNode) editChildren(edit func(Node) Node) {
 }
+func (n *typeNode) editChildrenWithHidden(edit func(Node) Node) {
+}
 
 func copyCaseClauses(list []*CaseClause) []*CaseClause {
        if list == nil {
index e4aeae352209a7c5b6fe31aa263fc4f598cf3334..016467081e5d9e6ae7d6f1f1a2eb7f9a387a6bd8 100644 (file)
@@ -184,3 +184,15 @@ func EditChildren(n Node, edit func(Node) Node) {
        }
        n.editChildren(edit)
 }
+
+// EditChildrenWithHidden is like EditChildren, but also edits
+// Node-typed fields tagged with `mknode:"-"`.
+//
+// TODO(mdempsky): Remove the `mknode:"-"` tags so this function can
+// go away.
+func EditChildrenWithHidden(n Node, edit func(Node) Node) {
+       if n == nil {
+               return
+       }
+       n.editChildrenWithHidden(edit)
+}
index fde128ec86d4bcc1b3fadf355b4bb0234e3ac861..bd1bf4114d334ce3ac635cb064dba6bcdee660c0 100644 (file)
@@ -838,7 +838,7 @@ func subst(n ir.Node, m map[*ir.Name]ir.Node) (ir.Node, bool) {
                        return x
                }
                x = ir.Copy(x)
-               ir.EditChildren(x, edit)
+               ir.EditChildrenWithHidden(x, edit)
                if x, ok := x.(*ir.ConvExpr); ok && x.X.Op() == ir.OLITERAL {
                        // A conversion of variable or expression involving variables
                        // may become a conversion of constant after inlining the parameters
diff --git a/test/fixedbugs/issue57778.go b/test/fixedbugs/issue57778.go
new file mode 100644 (file)
index 0000000..597eb80
--- /dev/null
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2023 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 p
+
+type FreeListG[T any] struct {
+       freelist []*node[T]
+}
+
+type node[T any] struct{}
+
+func NewFreeListG[T any](size int) *FreeListG[T] {
+       return &FreeListG[T]{freelist: make([]*node[T], 0, size)}
+}
+
+var bf = NewFreeListG[*int](1024)