Skip to content

Commit 62c8c31

Browse files
CannibalVoxStephen Baynham
andauthored
Use value types to wrap only if a type has at least one method with a value-type receiver (#3)
Somewhere I got the brilliant idea that I could simplify my life by using value-type fields for all wrapped values. Of course this didn't work- lots of stuff breaks if you clone it off (like database/sql.Rows). So now I'm only using value types as the inner field if there's at least one method with a value-type receiver. This should hopefully indicate that it is safe to clone a type off. Having the code handle both pointer and value type inner fields was less complicated than expected, so cheers to me. Co-authored-by: Stephen Baynham <[email protected]>
1 parent ba76cbf commit 62c8c31

File tree

3 files changed

+14
-4
lines changed

3 files changed

+14
-4
lines changed

filegen/file.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ func NewFile(pkgName string, t *types.TypeInfo, db *types.TypeDB) *FileCreate {
3838
// inner [ElementType]
3939
// errorTransformer ErrorTransformer
4040
// }
41-
innerField := jenutils.Type(jen.Id("Inner"), t.TypeId.Type)
41+
innerType := t.TypeId.Type
42+
if !t.RootType.HasDirectReceiver {
43+
innerType = gotypes.NewPointer(innerType)
44+
}
45+
innerField := jenutils.Type(jen.Id("Inner"), innerType)
4246
errTransformerField := jen.Id("ErrorTransformer").Qual("github.com/CannibalVox/errproxy", "ErrorTransformer")
4347

4448
fileCreate.jen.Type().Id(t.RootType.RootType.WrapperTypeName()).Struct(innerField, errTransformerField)
@@ -100,15 +104,15 @@ func (f *FileCreate) AppendType(t *types.TypeInfo) {
100104

101105
funcDeclaration.BlockFunc(func(g *jen.Group) {
102106
// if inner == nil { return nil }
103-
if t.TypeId.PointerDepth > 0 {
107+
if t.TypeId.PointerDepth > 0 || t.TypeId.Mode == types.TypeInterface {
104108
//If this is a pointer type, we'll need to dereference it soon so check if we can
105109
g.If(jen.Id("inner").Op("==").Nil()).Block(jen.Return(jen.Nil()))
106110
g.Line()
107111
}
108112

109113
// If we're accepting a pointer, we need to dereference it before assigning the struct field
110114
innerAssign := jen.Null()
111-
if t.TypeId.PointerDepth > 0 {
115+
if t.TypeId.PointerDepth > 0 && t.RootType.HasDirectReceiver {
112116
innerAssign = jen.Op("*")
113117
}
114118

@@ -217,7 +221,7 @@ func (f *FileCreate) wrapMethod(t *types.TypeInfo, methodInfo *gotypes.Selection
217221

218222
var paramCodes *jen.Statement
219223
doWrap, paramTypeInfo := f.requiresWrap(param.Type(), types.WrapStatusHard)
220-
if doWrap && paramTypeInfo.TypeId.PointerDepth > 0 {
224+
if doWrap && paramTypeInfo.TypeId.PointerDepth > 0 && paramTypeInfo.RootType.HasDirectReceiver {
221225
paramCodes = g.Op("&").Id(paramVal).Dot("Inner")
222226
} else if doWrap {
223227
paramCodes = g.Id(paramVal).Dot("Inner")

types/info.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ type RootTypeInfo struct {
9393
// The value is the type key for the owning type- this is necessary because
9494
// we may assign a method to one type initially but allow another method to steal
9595
// it later
96+
HasDirectReceiver bool // If true, there is a method with a direct non-pointer receiver
9697
}
9798

9899
func (r *RootTypeInfo) CanUseMethod(t gotypes.Type, method string) bool {

types/walker_walk.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ func (state *TypeWalker) walkSingleType(walkType *TypeInfo) {
4343
return
4444
}
4545

46+
// If this is a direct, non-pointered type (root type == type), then that will change how we render the wrapper
47+
if walkType.TypeId.TypeKey == walkType.RootType.RootType.TypeKey {
48+
walkType.RootType.HasDirectReceiver = true
49+
}
50+
4651
// Loop through each method
4752
for _, wrappedMethod := range walkType.MethodToWrap {
4853
sig := wrappedMethod.Type().(*gotypes.Signature)

0 commit comments

Comments
 (0)