@@ -100,8 +100,34 @@ func (fc *funcContext) translateExpr(expr ast.Expr) *expression {
100
100
101
101
switch e := expr .(type ) {
102
102
case * ast.CompositeLit :
103
- if ptrType , isPointer := exprType .(* types.Pointer ); isPointer {
104
- exprType = ptrType .Elem ()
103
+ if ptrType , isPointer := exprType .Underlying ().(* types.Pointer ); isPointer {
104
+ // Go automatically treats `[]*T{{}}` as `[]*T{&T{}}`, in which case the
105
+ // inner composite literal `{}` would has a pointer type. To make sure the
106
+ // type conversion is handled correctly, we generate the explicit AST for
107
+ // this.
108
+ var rewritten ast.Expr = fc .setType (& ast.UnaryExpr {
109
+ OpPos : e .Pos (),
110
+ Op : token .AND ,
111
+ X : fc .setType (& ast.CompositeLit {
112
+ Elts : e .Elts ,
113
+ }, ptrType .Elem ()),
114
+ }, ptrType )
115
+
116
+ if exprType , ok := exprType .(* types.Named ); ok {
117
+ // Handle a special case when the pointer type is named, e.g.:
118
+ // type PS *S
119
+ // _ = []PS{{}}
120
+ // In that case the value corresponding to the inner literal `{}` is
121
+ // initialized as `&S{}` and then converted to `PS`: `[]PS{PS(&S{})}`.
122
+ typeCast := fc .setType (& ast.CallExpr {
123
+ Fun : fc .newTypeIdent (exprType .String (), exprType .Obj ()),
124
+ Lparen : e .Lbrace ,
125
+ Args : []ast.Expr {rewritten },
126
+ Rparen : e .Rbrace ,
127
+ }, exprType )
128
+ rewritten = typeCast
129
+ }
130
+ return fc .translateExpr (rewritten )
105
131
}
106
132
107
133
collectIndexedElements := func (elementType types.Type ) []string {
@@ -173,7 +199,7 @@ func (fc *funcContext) translateExpr(expr ast.Expr) *expression {
173
199
}
174
200
return fc .formatExpr ("new %s.ptr(%s)" , fc .typeName (exprType ), strings .Join (elements , ", " ))
175
201
default :
176
- panic (fmt .Sprintf ("Unhandled CompositeLit type: %T \n " , t ))
202
+ panic (fmt .Sprintf ("Unhandled CompositeLit type: %[1]T %[1]v \n " , t ))
177
203
}
178
204
179
205
case * ast.FuncLit :
0 commit comments