@@ -39,6 +39,62 @@ func isReferenceType(typeStr string) bool {
3939 return strings .HasPrefix (typeStr , "Slice<" ) || strings .HasPrefix (typeStr , "Map<" )
4040}
4141
42+ // liftReflectionDecodeParams returns (specs, nil) when not whitelisted or no
43+ // `interface{}` params are liftable; the index map encodes per-param Ref<T>
44+ // rewrites for the caller to apply during the param loop.
45+ func (c * Converter ) liftReflectionDecodeParams (
46+ sig * types.Signature ,
47+ qualifiedName string ,
48+ specs TypeParamSpecs ,
49+ ) (TypeParamSpecs , map [int ]string ) {
50+ if ! c .cfg .IsReflectionDecode (c .currentPkgPath , qualifiedName ) {
51+ return specs , nil
52+ }
53+ used := make (map [string ]bool , len (specs ))
54+ for _ , s := range specs {
55+ used [s .Name ] = true
56+ }
57+ var overrides map [int ]string
58+ params := sig .Params ()
59+ for i := 0 ; i < params .Len (); i ++ {
60+ if sig .Variadic () && i == params .Len ()- 1 {
61+ continue
62+ }
63+ t := params .At (i ).Type ()
64+ for {
65+ alias , ok := t .(* types.Alias )
66+ if ! ok {
67+ break
68+ }
69+ t = alias .Rhs ()
70+ }
71+ iface , ok := t .(* types.Interface )
72+ if ! ok || ! iface .Empty () || isErrorInterface (iface ) {
73+ continue
74+ }
75+ name := freshTypeParamName (used )
76+ used [name ] = true
77+ specs = append (specs , TypeParamSpec {Name : name })
78+ if overrides == nil {
79+ overrides = make (map [int ]string )
80+ }
81+ overrides [i ] = fmt .Sprintf ("Ref<%s>" , name )
82+ }
83+ return specs , overrides
84+ }
85+
86+ func freshTypeParamName (used map [string ]bool ) string {
87+ if ! used ["T" ] {
88+ return "T"
89+ }
90+ for n := 2 ; ; n ++ {
91+ candidate := fmt .Sprintf ("T%d" , n )
92+ if ! used [candidate ] {
93+ return candidate
94+ }
95+ }
96+ }
97+
4298func (c * Converter ) convertFunction (result * ConvertResult , symbolExport extract.SymbolExport ) {
4399 signature , ok := symbolExport .GoType .(* types.Signature )
44100 if ! ok {
@@ -58,6 +114,9 @@ func (c *Converter) convertFunction(result *ConvertResult, symbolExport extract.
58114 c .typeParamSubstitutions = substitutions
59115 defer func () { c .typeParamSubstitutions = prevSubs }()
60116
117+ liftedSpecs , paramOverrides := c .liftReflectionDecodeParams (signature , result .Name , result .TypeParams )
118+ result .TypeParams = liftedSpecs
119+
61120 mutParams := c .cfg .MutatingParams (c .currentPkgPath , result .Name )
62121
63122 params := signature .Params ()
@@ -73,6 +132,9 @@ func (c *Converter) convertFunction(result *ConvertResult, symbolExport extract.
73132 if signature .Variadic () && i == params .Len ()- 1 {
74133 typeStr = sliceToVarArgs (typeStr )
75134 }
135+ if override , ok := paramOverrides [i ]; ok {
136+ typeStr = override
137+ }
76138
77139 name := param .Name ()
78140 if name == "" {
@@ -204,6 +266,13 @@ func (c *Converter) convertMethod(result *ConvertResult, symbolExport extract.Sy
204266 qualifiedName = result .Receiver .BaseTypeName + "." + result .Name
205267 }
206268
269+ methodSpecs , _ , skip := collectTypeParams (signature .TypeParams (), false , c )
270+ if skip != nil {
271+ result .SkipReason = skip
272+ return
273+ }
274+ liftedSpecs , paramOverrides := c .liftReflectionDecodeParams (signature , qualifiedName , methodSpecs )
275+
207276 mutParams := c .cfg .MutatingParams (c .currentPkgPath , qualifiedName )
208277
209278 params := signature .Params ()
@@ -219,6 +288,9 @@ func (c *Converter) convertMethod(result *ConvertResult, symbolExport extract.Sy
219288 if signature .Variadic () && i == params .Len ()- 1 {
220289 typeStr = sliceToVarArgs (typeStr )
221290 }
291+ if override , ok := paramOverrides [i ]; ok {
292+ typeStr = override
293+ }
222294
223295 name := param .Name ()
224296 if name == "" {
@@ -290,12 +362,7 @@ func (c *Converter) convertMethod(result *ConvertResult, symbolExport extract.Sy
290362 }
291363 }
292364
293- methodSpecs , _ , skip := collectTypeParams (signature .TypeParams (), false , c )
294- if skip != nil {
295- result .SkipReason = skip
296- return
297- }
298- result .TypeParams = methodSpecs
365+ result .TypeParams = liftedSpecs
299366
300367 if isFluentBuilderCandidate (result , symbolExport , signature ) {
301368 if fn := c .findFuncDecl (symbolExport .Obj ); fn != nil && isFluentMethod (fn , ncGetReceiverName (fn )) {
0 commit comments