@@ -265,7 +265,8 @@ func TranspileExpressionContext(out *strings.Builder, expr ast.Expr, ctx ExprCon
265265 }
266266 out .WriteString (fieldInfo .FieldName )
267267 } else {
268- out .WriteString ("(*(*" )
268+ // RValue context - need to unwrap the field value too
269+ out .WriteString ("(*(*(*" )
269270 out .WriteString (ident .Name )
270271 WriteBorrowMethod (out , false )
271272 out .WriteString (".as_ref().unwrap())." )
@@ -279,16 +280,32 @@ func TranspileExpressionContext(out *strings.Builder, expr ast.Expr, ctx ExprCon
279280 }
280281 }
281282 out .WriteString (fieldInfo .FieldName )
283+ WriteBorrowMethod (out , false )
284+ out .WriteString (".as_ref().unwrap())" )
282285 }
283286 } else {
284- // Unwrapped variable with promoted field
285- out .WriteString (ident .Name )
286- for _ , embedded := range fieldInfo .EmbeddedPath {
287+ // Unwrapped variable (e.g., range variable) with promoted field
288+ // The field itself is still wrapped, so unwrap it in RValue context
289+ if ctx == RValue {
290+ out .WriteString ("(*" )
291+ out .WriteString (ident .Name )
292+ for _ , embedded := range fieldInfo .EmbeddedPath {
293+ out .WriteString ("." )
294+ out .WriteString (ToSnakeCase (embedded ))
295+ }
287296 out .WriteString ("." )
288- out .WriteString (ToSnakeCase (embedded ))
297+ out .WriteString (fieldInfo .FieldName )
298+ WriteBorrowMethod (out , false )
299+ out .WriteString (".as_ref().unwrap())" )
300+ } else {
301+ out .WriteString (ident .Name )
302+ for _ , embedded := range fieldInfo .EmbeddedPath {
303+ out .WriteString ("." )
304+ out .WriteString (ToSnakeCase (embedded ))
305+ }
306+ out .WriteString ("." )
307+ out .WriteString (fieldInfo .FieldName )
289308 }
290- out .WriteString ("." )
291- out .WriteString (fieldInfo .FieldName )
292309 }
293310 } else {
294311 // Direct field access
@@ -303,17 +320,31 @@ func TranspileExpressionContext(out *strings.Builder, expr ast.Expr, ctx ExprCon
303320 out .WriteString (fieldInfo .FieldName )
304321 } else {
305322 // For reading, we need immutable access
306- out .WriteString ("(*" )
323+ // Also unwrap the field itself in RValue context
324+ out .WriteString ("(*(*" )
307325 out .WriteString (ident .Name )
308326 WriteBorrowMethod (out , false )
309327 out .WriteString (".as_ref().unwrap())." )
310328 out .WriteString (fieldInfo .FieldName )
329+ WriteBorrowMethod (out , false )
330+ out .WriteString (".as_ref().unwrap())" )
311331 }
312332 } else {
313- // Not wrapped - direct access
314- out .WriteString (ident .Name )
315- out .WriteString ("." )
316- out .WriteString (fieldInfo .FieldName )
333+ // Not wrapped (e.g., range variable) - but field itself is wrapped
334+ if ctx == RValue {
335+ // Unwrap the field in RValue context
336+ out .WriteString ("(*" )
337+ out .WriteString (ident .Name )
338+ out .WriteString ("." )
339+ out .WriteString (fieldInfo .FieldName )
340+ WriteBorrowMethod (out , false )
341+ out .WriteString (".as_ref().unwrap())" )
342+ } else {
343+ // Direct access in LValue context
344+ out .WriteString (ident .Name )
345+ out .WriteString ("." )
346+ out .WriteString (fieldInfo .FieldName )
347+ }
317348 }
318349 }
319350 }
@@ -350,20 +381,71 @@ func TranspileExpressionContext(out *strings.Builder, expr ast.Expr, ctx ExprCon
350381 if fieldInfo .IsPromoted {
351382 // Accessing promoted field through embedded struct(s)
352383 // We need to unwrap each embedded struct in the path
353- TranspileExpressionContext (out , e .X , LValue )
354- for _ , embedded := range fieldInfo .EmbeddedPath {
384+ if ctx == RValue {
385+ // In RValue context, unwrap the final field too
386+ out .WriteString ("(*" )
387+ TranspileExpressionContext (out , e .X , LValue )
388+ for _ , embedded := range fieldInfo .EmbeddedPath {
389+ out .WriteString ("." )
390+ out .WriteString (ToSnakeCase (embedded ))
391+ WriteBorrowMethod (out , false )
392+ out .WriteString (".as_ref().unwrap()" )
393+ }
355394 out .WriteString ("." )
356- out .WriteString (ToSnakeCase ( embedded ) )
395+ out .WriteString (fieldInfo . FieldName )
357396 WriteBorrowMethod (out , false )
358- out .WriteString (".as_ref().unwrap()" )
397+ out .WriteString (".as_ref().unwrap())" )
398+ } else {
399+ // In LValue context, don't unwrap the final field
400+ TranspileExpressionContext (out , e .X , LValue )
401+ for _ , embedded := range fieldInfo .EmbeddedPath {
402+ out .WriteString ("." )
403+ out .WriteString (ToSnakeCase (embedded ))
404+ WriteBorrowMethod (out , false )
405+ out .WriteString (".as_ref().unwrap()" )
406+ }
407+ out .WriteString ("." )
408+ out .WriteString (fieldInfo .FieldName )
359409 }
360- out .WriteString ("." )
361- out .WriteString (fieldInfo .FieldName )
362410 } else {
363411 // Direct field access
364- TranspileExpressionContext (out , e .X , LValue )
365- out .WriteString ("." )
366- out .WriteString (fieldInfo .FieldName )
412+ // Check if e.X is a selector expression that returns a wrapped struct field
413+ if _ , isSelector := e .X .(* ast.SelectorExpr ); isSelector {
414+ // e.X is a field access that returns a wrapped value, need to unwrap it
415+ if ctx == RValue {
416+ // In RValue context, unwrap both the struct and the final field
417+ out .WriteString ("(*(*" )
418+ TranspileExpressionContext (out , e .X , LValue )
419+ WriteBorrowMethod (out , false )
420+ out .WriteString (".as_ref().unwrap())." )
421+ out .WriteString (fieldInfo .FieldName )
422+ WriteBorrowMethod (out , false )
423+ out .WriteString (".as_ref().unwrap())" )
424+ } else {
425+ // In LValue context, just unwrap the struct to access the field
426+ out .WriteString ("(*" )
427+ TranspileExpressionContext (out , e .X , LValue )
428+ WriteBorrowMethod (out , false )
429+ out .WriteString (".as_ref().unwrap())." )
430+ out .WriteString (fieldInfo .FieldName )
431+ }
432+ } else {
433+ // e.X is not a selector, use normal handling
434+ if ctx == RValue {
435+ // In RValue context, field needs to be unwrapped
436+ out .WriteString ("(*" )
437+ TranspileExpressionContext (out , e .X , LValue )
438+ out .WriteString ("." )
439+ out .WriteString (fieldInfo .FieldName )
440+ WriteBorrowMethod (out , false )
441+ out .WriteString (".as_ref().unwrap())" )
442+ } else {
443+ // In LValue context, just access the field
444+ TranspileExpressionContext (out , e .X , LValue )
445+ out .WriteString ("." )
446+ out .WriteString (fieldInfo .FieldName )
447+ }
448+ }
367449 }
368450 }
369451
@@ -643,6 +725,81 @@ func TranspileExpressionContext(out *strings.Builder, expr ast.Expr, ctx ExprCon
643725 WriteWrapperSuffix (out )
644726
645727 case * ast.CompositeLit :
728+ // When Type is nil, try to infer from TypeInfo
729+ if e .Type == nil {
730+ typeInfo := GetTypeInfo ()
731+ if typeInfo != nil {
732+ if typ := typeInfo .GetType (e ); typ != nil {
733+ // We have the actual type from go/types
734+ switch typ .Underlying ().(type ) {
735+ case * types.Slice :
736+ // Handle slice with inferred element type
737+ WriteWrapperPrefix (out )
738+ out .WriteString ("vec![" )
739+ for i , elt := range e .Elts {
740+ if i > 0 {
741+ out .WriteString (", " )
742+ }
743+ // Recursively transpile elements
744+ TranspileExpression (out , elt )
745+ }
746+ out .WriteString ("]" )
747+ WriteWrapperSuffix (out )
748+ return
749+ case * types.Struct :
750+ // Handle struct literal with inferred type
751+ // Try to get the struct name from the named type
752+ if named , ok := typ .(* types.Named ); ok {
753+ out .WriteString (named .Obj ().Name ())
754+ } else {
755+ // Anonymous struct - we'd need to generate a type
756+ out .WriteString ("/* Anonymous struct literal */" )
757+ out .WriteString ("unimplemented!()" )
758+ return
759+ }
760+ out .WriteString (" { " )
761+
762+ // Output the fields
763+ for i , elt := range e .Elts {
764+ if i > 0 {
765+ out .WriteString (", " )
766+ }
767+ if kv , ok := elt .(* ast.KeyValueExpr ); ok {
768+ if key , ok := kv .Key .(* ast.Ident ); ok {
769+ out .WriteString (ToSnakeCase (key .Name ))
770+ out .WriteString (": " )
771+ // Check if the value is an identifier (parameter/variable)
772+ if valIdent , ok := kv .Value .(* ast.Ident ); ok {
773+ // Check if it's a literal (true, false, nil) that doesn't need cloning
774+ if valIdent .Name == "true" || valIdent .Name == "false" || valIdent .Name == "nil" {
775+ // Wrap literal values
776+ WriteWrapperPrefix (out )
777+ TranspileExpression (out , kv .Value )
778+ WriteWrapperSuffix (out )
779+ } else {
780+ // It's already wrapped, just clone it
781+ out .WriteString (valIdent .Name )
782+ out .WriteString (".clone()" )
783+ }
784+ } else {
785+ // Wrap field values
786+ WriteWrapperPrefix (out )
787+ TranspileExpression (out , kv .Value )
788+ WriteWrapperSuffix (out )
789+ }
790+ }
791+ }
792+ }
793+ out .WriteString (" }" )
794+ return
795+ }
796+ }
797+ }
798+ // If we can't infer, output an error comment
799+ out .WriteString ("/* ERROR: CompositeLit with nil Type - type inference failed */" )
800+ out .WriteString ("unimplemented!()" )
801+ return
802+ }
646803 // Handle array/slice literals
647804 if arrayType , ok := e .Type .(* ast.ArrayType ); ok {
648805 // Check if element type is interface{}
@@ -718,9 +875,17 @@ func TranspileExpressionContext(out *strings.Builder, expr ast.Expr, ctx ExprCon
718875 out .WriteString (": " )
719876 // Check if the value is an identifier (parameter/variable)
720877 if valIdent , ok := kv .Value .(* ast.Ident ); ok {
721- // It's already wrapped, just clone it
722- out .WriteString (valIdent .Name )
723- out .WriteString (".clone()" )
878+ // Check if it's a literal (true, false, nil) that doesn't need cloning
879+ if valIdent .Name == "true" || valIdent .Name == "false" || valIdent .Name == "nil" {
880+ // Wrap literal values
881+ WriteWrapperPrefix (out )
882+ TranspileExpression (out , kv .Value )
883+ WriteWrapperSuffix (out )
884+ } else {
885+ // It's already wrapped, just clone it
886+ out .WriteString (valIdent .Name )
887+ out .WriteString (".clone()" )
888+ }
724889 } else {
725890 // Wrap field values in Arc<Mutex<Option<T>>>
726891 WriteWrapperPrefix (out )
@@ -766,9 +931,17 @@ func TranspileExpressionContext(out *strings.Builder, expr ast.Expr, ctx ExprCon
766931 out .WriteString (": " )
767932 // Check if the value is an identifier (parameter/variable)
768933 if valIdent , ok := kv .Value .(* ast.Ident ); ok {
769- // It's already wrapped, just clone it
770- out .WriteString (valIdent .Name )
771- out .WriteString (".clone()" )
934+ // Check if it's a literal (true, false, nil) that doesn't need cloning
935+ if valIdent .Name == "true" || valIdent .Name == "false" || valIdent .Name == "nil" {
936+ // Wrap literal values
937+ WriteWrapperPrefix (out )
938+ TranspileExpression (out , kv .Value )
939+ WriteWrapperSuffix (out )
940+ } else {
941+ // It's already wrapped, just clone it
942+ out .WriteString (valIdent .Name )
943+ out .WriteString (".clone()" )
944+ }
772945 } else {
773946 // Wrap field values in Arc<Mutex<Option<T>>>
774947 WriteWrapperPrefix (out )
0 commit comments