Skip to content

Commit a4c4beb

Browse files
authored
Fix copying TypeParams (#5)
There was a bug where the TypeParams weren't being properly copied but rather continuing the use the source value. The code: ``` cp := *x if typeParams := typeparams.ForFuncType(x); typeParams != nil { *typeparams.ForFuncType(&cp) = *FieldList(typeParams) } ``` cp.TypeParams which typeparams.ForFyncType returns is still x.TypeParams. Then the `*typeparams.ForFuncType(&cp)` overwrites it a copy thus modifying the original slice. This issue causes a data race which showed up in golangci-lint and often caused a panic. The only way around this I found was to have copies of the function for different versions of Go since the typeparam package doesn't have a way to set the TypeParams field.
1 parent 6984600 commit a4c4beb

File tree

3 files changed

+66
-32
lines changed

3 files changed

+66
-32
lines changed

astcopy.go

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -346,21 +346,6 @@ func FieldList(x *ast.FieldList) *ast.FieldList {
346346
return &cp
347347
}
348348

349-
// FuncType returns x deep copy.
350-
// Copy of nil argument is nil.
351-
func FuncType(x *ast.FuncType) *ast.FuncType {
352-
if x == nil {
353-
return nil
354-
}
355-
cp := *x
356-
cp.Params = FieldList(x.Params)
357-
cp.Results = FieldList(x.Results)
358-
if typeParams := typeparams.ForFuncType(x); typeParams != nil {
359-
*typeparams.ForFuncType(&cp) = *FieldList(typeParams)
360-
}
361-
return &cp
362-
}
363-
364349
// InterfaceType returns x deep copy.
365350
// Copy of nil argument is nil.
366351
func InterfaceType(x *ast.InterfaceType) *ast.InterfaceType {
@@ -435,23 +420,6 @@ func ValueSpec(x *ast.ValueSpec) *ast.ValueSpec {
435420
return &cp
436421
}
437422

438-
// TypeSpec returns x deep copy.
439-
// Copy of nil argument is nil.
440-
func TypeSpec(x *ast.TypeSpec) *ast.TypeSpec {
441-
if x == nil {
442-
return nil
443-
}
444-
cp := *x
445-
cp.Name = Ident(x.Name)
446-
cp.Type = copyExpr(x.Type)
447-
cp.Doc = CommentGroup(x.Doc)
448-
cp.Comment = CommentGroup(x.Comment)
449-
if typeParams := typeparams.ForTypeSpec(x); typeParams != nil {
450-
*typeparams.ForTypeSpec(&cp) = *FieldList(typeParams)
451-
}
452-
return &cp
453-
}
454-
455423
// Spec returns x deep copy.
456424
// Copy of nil argument is nil.
457425
func Spec(x ast.Spec) ast.Spec {

astcopy_go117.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//go:build !go1.18
2+
// +build !go1.18
3+
4+
package astcopy
5+
6+
// FuncType returns x deep copy.
7+
// Copy of nil argument is nil.
8+
func FuncType(x *ast.FuncType) *ast.FuncType {
9+
if x == nil {
10+
return nil
11+
}
12+
cp := *x
13+
cp.Params = FieldList(x.Params)
14+
cp.Results = FieldList(x.Results)
15+
return &cp
16+
}
17+
18+
// TypeSpec returns x deep copy.
19+
// Copy of nil argument is nil.
20+
func TypeSpec(x *ast.TypeSpec) *ast.TypeSpec {
21+
if x == nil {
22+
return nil
23+
}
24+
cp := *x
25+
cp.Name = Ident(x.Name)
26+
cp.Type = copyExpr(x.Type)
27+
cp.Doc = CommentGroup(x.Doc)
28+
cp.Comment = CommentGroup(x.Comment)
29+
return &cp
30+
}

astcopy_go118.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//go:build go1.18
2+
// +build go1.18
3+
4+
package astcopy
5+
6+
import (
7+
"go/ast"
8+
)
9+
10+
// FuncType returns x deep copy.
11+
// Copy of nil argument is nil.
12+
func FuncType(x *ast.FuncType) *ast.FuncType {
13+
if x == nil {
14+
return nil
15+
}
16+
cp := *x
17+
cp.Params = FieldList(x.Params)
18+
cp.Results = FieldList(x.Results)
19+
cp.TypeParams = FieldList(x.TypeParams)
20+
return &cp
21+
}
22+
23+
// TypeSpec returns x deep copy.
24+
// Copy of nil argument is nil.
25+
func TypeSpec(x *ast.TypeSpec) *ast.TypeSpec {
26+
if x == nil {
27+
return nil
28+
}
29+
cp := *x
30+
cp.Name = Ident(x.Name)
31+
cp.Type = copyExpr(x.Type)
32+
cp.Doc = CommentGroup(x.Doc)
33+
cp.Comment = CommentGroup(x.Comment)
34+
cp.TypeParams = FieldList(x.TypeParams)
35+
return &cp
36+
}

0 commit comments

Comments
 (0)