@@ -1135,13 +1135,21 @@ func (fc *funcContext) translateConversion(expr ast.Expr, desiredType types.Type
1135
1135
}
1136
1136
}
1137
1137
1138
- switch t := desiredType .Underlying ().(type ) {
1138
+ _ , fromTypeParam := exprType .(* types.TypeParam )
1139
+ _ , toTypeParam := desiredType .(* types.TypeParam )
1140
+ if fromTypeParam || toTypeParam {
1141
+ // Conversion from or to a type param can only be done at runtime, since the
1142
+ // concrete type is not known to the compiler at compile time.
1143
+ return fc .formatExpr ("%s.convertFrom(%s.wrap(%e))" , fc .typeName (desiredType ), fc .typeName (exprType ), expr )
1144
+ }
1145
+
1146
+ switch dst := desiredType .Underlying ().(type ) {
1139
1147
case * types.Basic :
1140
1148
switch {
1141
- case isInteger (t ):
1149
+ case isInteger (dst ):
1142
1150
basicExprType := exprType .Underlying ().(* types.Basic )
1143
1151
switch {
1144
- case is64Bit (t ):
1152
+ case is64Bit (dst ):
1145
1153
if ! is64Bit (basicExprType ) {
1146
1154
if basicExprType .Kind () == types .Uintptr { // this might be an Object returned from reflect.Value.Pointer()
1147
1155
return fc .formatExpr ("new %1s(0, %2e.constructor === Number ? %2e : 1)" , fc .typeName (desiredType ), expr )
@@ -1150,25 +1158,25 @@ func (fc *funcContext) translateConversion(expr ast.Expr, desiredType types.Type
1150
1158
}
1151
1159
return fc .formatExpr ("new %1s(%2h, %2l)" , fc .typeName (desiredType ), expr )
1152
1160
case is64Bit (basicExprType ):
1153
- if ! isUnsigned (t ) && ! isUnsigned (basicExprType ) {
1154
- return fc .fixNumber (fc .formatParenExpr ("%1l + ((%1h >> 31) * 4294967296)" , expr ), t )
1161
+ if ! isUnsigned (dst ) && ! isUnsigned (basicExprType ) {
1162
+ return fc .fixNumber (fc .formatParenExpr ("%1l + ((%1h >> 31) * 4294967296)" , expr ), dst )
1155
1163
}
1156
- return fc .fixNumber (fc .formatExpr ("%s.$low" , fc .translateExpr (expr )), t )
1164
+ return fc .fixNumber (fc .formatExpr ("%s.$low" , fc .translateExpr (expr )), dst )
1157
1165
case isFloat (basicExprType ):
1158
1166
return fc .formatParenExpr ("%e >> 0" , expr )
1159
1167
case types .Identical (exprType , types .Typ [types .UnsafePointer ]):
1160
1168
return fc .translateExpr (expr )
1161
1169
default :
1162
- return fc .fixNumber (fc .translateExpr (expr ), t )
1170
+ return fc .fixNumber (fc .translateExpr (expr ), dst )
1163
1171
}
1164
- case isFloat (t ):
1165
- if t .Kind () == types .Float32 && exprType .Underlying ().(* types.Basic ).Kind () == types .Float64 {
1172
+ case isFloat (dst ):
1173
+ if dst .Kind () == types .Float32 && exprType .Underlying ().(* types.Basic ).Kind () == types .Float64 {
1166
1174
return fc .formatExpr ("$fround(%e)" , expr )
1167
1175
}
1168
1176
return fc .formatExpr ("%f" , expr )
1169
- case isComplex (t ):
1177
+ case isComplex (dst ):
1170
1178
return fc .formatExpr ("new %1s(%2r, %2i)" , fc .typeName (desiredType ), expr )
1171
- case isString (t ):
1179
+ case isString (dst ):
1172
1180
value := fc .translateExpr (expr )
1173
1181
switch et := exprType .Underlying ().(type ) {
1174
1182
case * types.Basic :
@@ -1187,7 +1195,7 @@ func (fc *funcContext) translateConversion(expr ast.Expr, desiredType types.Type
1187
1195
default :
1188
1196
panic (fmt .Sprintf ("Unhandled conversion: %v\n " , et ))
1189
1197
}
1190
- case t .Kind () == types .UnsafePointer :
1198
+ case dst .Kind () == types .UnsafePointer :
1191
1199
if unary , isUnary := expr .(* ast.UnaryExpr ); isUnary && unary .Op == token .AND {
1192
1200
if indexExpr , isIndexExpr := unary .X .(* ast.IndexExpr ); isIndexExpr {
1193
1201
return fc .formatExpr ("$sliceToNativeArray(%s)" , fc .translateConversionToSlice (indexExpr .X , types .NewSlice (types .Typ [types .Uint8 ])))
@@ -1218,7 +1226,7 @@ func (fc *funcContext) translateConversion(expr ast.Expr, desiredType types.Type
1218
1226
switch et := exprType .Underlying ().(type ) {
1219
1227
case * types.Basic :
1220
1228
if isString (et ) {
1221
- if types .Identical (t .Elem ().Underlying (), types .Typ [types .Rune ]) {
1229
+ if types .Identical (dst .Elem ().Underlying (), types .Typ [types .Rune ]) {
1222
1230
return fc .formatExpr ("new %s($stringToRunes(%e))" , fc .typeName (desiredType ), expr )
1223
1231
}
1224
1232
return fc .formatExpr ("new %s($stringToBytes(%e))" , fc .typeName (desiredType ), expr )
@@ -1234,7 +1242,7 @@ func (fc *funcContext) translateConversion(expr ast.Expr, desiredType types.Type
1234
1242
break
1235
1243
}
1236
1244
1237
- switch ptrElType := t .Elem ().Underlying ().(type ) {
1245
+ switch ptrElType := dst .Elem ().Underlying ().(type ) {
1238
1246
case * types.Array : // (*[N]T)(expr) — converting expr to a pointer to an array.
1239
1247
if _ , ok := exprType .Underlying ().(* types.Slice ); ok {
1240
1248
return fc .formatExpr ("$sliceToGoArray(%e, %s)" , expr , fc .typeName (desiredType ))
@@ -1249,7 +1257,7 @@ func (fc *funcContext) translateConversion(expr ast.Expr, desiredType types.Type
1249
1257
// indeed pointing at a byte array.
1250
1258
array := fc .newLocalVariable ("_array" )
1251
1259
target := fc .newLocalVariable ("_struct" )
1252
- return fc .formatExpr ("(%s = %e, %s = %e, %s, %s)" , array , expr , target , fc .zeroValue (t .Elem ()), fc .loadStruct (array , target , ptrElType ), target )
1260
+ return fc .formatExpr ("(%s = %e, %s = %e, %s, %s)" , array , expr , target , fc .zeroValue (dst .Elem ()), fc .loadStruct (array , target , ptrElType ), target )
1253
1261
}
1254
1262
// Convert between structs of different types but identical layouts,
1255
1263
// for example:
@@ -1271,8 +1279,8 @@ func (fc *funcContext) translateConversion(expr ast.Expr, desiredType types.Type
1271
1279
// TODO(nevkontakte): Are there any other cases that fall into this case?
1272
1280
exprTypeElem := exprType .Underlying ().(* types.Pointer ).Elem ()
1273
1281
ptrVar := fc .newLocalVariable ("_ptr" )
1274
- getterConv := fc .translateConversion (fc .setType (& ast.StarExpr {X : fc .newIdent (ptrVar , exprType )}, exprTypeElem ), t .Elem ())
1275
- setterConv := fc .translateConversion (fc .newIdent ("$v" , t .Elem ()), exprTypeElem )
1282
+ getterConv := fc .translateConversion (fc .setType (& ast.StarExpr {X : fc .newIdent (ptrVar , exprType )}, exprTypeElem ), dst .Elem ())
1283
+ setterConv := fc .translateConversion (fc .newIdent ("$v" , dst .Elem ()), exprTypeElem )
1276
1284
return fc .formatExpr ("(%1s = %2e, new %3s(function() { return %4s; }, function($v) { %1s.$set(%5s); }, %1s.$target))" , ptrVar , expr , fc .typeName (desiredType ), getterConv , setterConv )
1277
1285
1278
1286
case * types.Interface :
0 commit comments