|
| 1 | +# Type Assertion Duplicate Vars Issue Analysis |
| 2 | + |
| 3 | +## Problem Summary |
| 4 | +The `type_assertion_duplicate_vars` compliance test is failing because type assertions are incorrectly returning `true` for both assertions when only one should succeed. |
| 5 | + |
| 6 | +## Test Details |
| 7 | +In the test: |
| 8 | +```go |
| 9 | +var iface Interface = ConcreteA{} |
| 10 | + |
| 11 | +// Multiple type assertions that should generate unique variable names |
| 12 | +_, c.hasA = iface.(ConcreteA) |
| 13 | +_, c.hasB = iface.(ConcreteB) |
| 14 | +``` |
| 15 | + |
| 16 | +Expected output: |
| 17 | +``` |
| 18 | +hasA: true |
| 19 | +hasB: false |
| 20 | +``` |
| 21 | + |
| 22 | +Actual output: |
| 23 | +``` |
| 24 | +hasA: true |
| 25 | +hasB: true |
| 26 | +``` |
| 27 | + |
| 28 | +## Generated TypeScript Analysis |
| 29 | +The generated TypeScript correctly creates unique temporary variables: |
| 30 | +```typescript |
| 31 | +let _gs_ta_val_418_: ConcreteA |
| 32 | +let _gs_ta_ok_418_: boolean |
| 33 | +({ value: _gs_ta_val_418_, ok: _gs_ta_ok_418_ } = $.typeAssert<ConcreteA>(iface, 'ConcreteA')) |
| 34 | +c.hasA = _gs_ta_ok_418_ |
| 35 | + |
| 36 | +let _gs_ta_val_449_: ConcreteB |
| 37 | +let _gs_ta_ok_449_: boolean |
| 38 | +({ value: _gs_ta_val_449_, ok: _gs_ta_ok_449_ } = $.typeAssert<ConcreteB>(iface, 'ConcreteB')) |
| 39 | +c.hasB = _gs_ta_ok_449_ |
| 40 | +``` |
| 41 | + |
| 42 | +The variable naming is correct and unique based on AST position. The issue is NOT with duplicate variables. |
| 43 | + |
| 44 | +## Root Cause Identified |
| 45 | +The issue is in the `$.typeAssert` function in `gs/builtin/type.ts`. Specifically in the `matchesStructType` function around lines 465-467: |
| 46 | + |
| 47 | +```typescript |
| 48 | +// For structs, use instanceof with the constructor |
| 49 | +if (info.ctor && value instanceof info.ctor) { |
| 50 | + return true |
| 51 | +} |
| 52 | +``` |
| 53 | + |
| 54 | +The problem appears to be that the type checking logic is not working correctly for struct type assertions. Either: |
| 55 | + |
| 56 | +1. The `info.ctor` is not being set correctly for the type info |
| 57 | +2. The `instanceof` check is passing when it shouldn't |
| 58 | +3. There's a fallback case that's always returning true |
| 59 | + |
| 60 | +## Investigation Needed |
| 61 | +1. Check how type information is being passed to `$.typeAssert` calls |
| 62 | +2. Verify the constructor registration for `ConcreteA` and `ConcreteB` |
| 63 | +3. Look at whether there's a fallback that incorrectly returns `ok: true` |
| 64 | + |
| 65 | +## Next Steps |
| 66 | +1. Check the type registration code in the generated TypeScript |
| 67 | +2. Examine the actual runtime behavior of the `$.typeAssert` function |
| 68 | +3. Debug why `ConcreteA` instance is matching `ConcreteB` type |
| 69 | + |
| 70 | +# Variadic Interface Method Issue Analysis |
| 71 | + |
| 72 | +## Problem Description |
| 73 | + |
| 74 | +When an interface declares a method with variadic parameters, the Go-to-TypeScript compiler incorrectly generates the TypeScript interface signature. |
| 75 | + |
| 76 | +**Go Source:** |
| 77 | +```go |
| 78 | +type Basic interface { |
| 79 | + Join(elem ...string) string |
| 80 | +} |
| 81 | +``` |
| 82 | + |
| 83 | +**Current TypeScript Output:** |
| 84 | +```typescript |
| 85 | +export type Basic = null | { |
| 86 | + Join(elem: $.Slice<string>): string |
| 87 | +} |
| 88 | +``` |
| 89 | +
|
| 90 | +**Expected TypeScript Output:** |
| 91 | +```typescript |
| 92 | +export type Basic = null | { |
| 93 | + Join(...elem: string[]): string |
| 94 | +} |
| 95 | +``` |
| 96 | +
|
| 97 | +## Root Cause Analysis |
| 98 | +
|
| 99 | +The issue is in the interface method parameter handling in `compiler/type.go`. When processing interface methods in the `writeInterfaceStructure` function (around lines 570-580), the code correctly handles regular parameters but does not properly detect and handle variadic parameters. |
| 100 | +
|
| 101 | +Looking at the code in `writeInterfaceStructure`: |
| 102 | +
|
| 103 | +1. It iterates through interface methods using `iface.ExplicitMethod(i)` |
| 104 | +2. For each method, it gets the signature using `method.Type().(*types.Signature)` |
| 105 | +3. It processes parameters using `sig.Params()` but doesn't check if the signature is variadic |
| 106 | +4. It doesn't use the variadic-aware parameter writing logic that exists in `field.go` |
| 107 | +
|
| 108 | +## Comparison with Working Implementation |
| 109 | +
|
| 110 | +The struct method implementation correctly generates `public Join(...elem: string[]): string` because it uses the `WriteFieldList` function in `field.go` which has proper variadic handling (lines 31-81). |
| 111 | +
|
| 112 | +However, the interface method generation in `type.go` bypasses this logic and manually processes parameters without checking for variadic signatures. |
| 113 | +
|
| 114 | +## Solution Plan |
| 115 | +
|
| 116 | +1. **Modify `writeInterfaceStructure` in `compiler/type.go`**: |
| 117 | + - Check if the method signature is variadic using `sig.Variadic()` |
| 118 | + - For variadic methods, handle the last parameter specially by: |
| 119 | + - Adding the `...` prefix to the parameter name |
| 120 | + - Converting the slice type to element type with `[]` suffix |
| 121 | + - Using `GoTypeContextVariadicParam` context to avoid the `null |` prefix |
| 122 | +
|
| 123 | +2. **Test the fix**: |
| 124 | + - Run the `variadic_interface_method` compliance test |
| 125 | + - Verify the generated TypeScript interface matches the expected output |
| 126 | + - Ensure the implementation and interface signatures are compatible |
| 127 | +
|
| 128 | +## Expected Changes |
| 129 | +
|
| 130 | +After the fix, the interface should generate: |
| 131 | +```typescript |
| 132 | +export type Basic = null | { |
| 133 | + Join(...elem: string[]): string |
| 134 | +} |
| 135 | +``` |
| 136 | +
|
| 137 | +This will make the interface signature compatible with the implementation signature, resolving the TypeScript compilation errors. |
| 138 | +
|
| 139 | +## Implementation Details |
| 140 | +
|
| 141 | +### Changes Made |
| 142 | +
|
| 143 | +**File: `compiler/type.go`** |
| 144 | +- Modified the `writeInterfaceStructure` function (lines ~568-579) |
| 145 | +- Added variadic parameter detection using `sig.Variadic()` |
| 146 | +- Split parameter processing into two phases: |
| 147 | + 1. Regular parameters (all params for non-variadic, all but last for variadic) |
| 148 | + 2. Variadic parameter handling (if present) |
| 149 | +- For variadic parameters: |
| 150 | + - Added `...` prefix to parameter name |
| 151 | + - Used `GoTypeContextVariadicParam` context to avoid `null |` prefix |
| 152 | + - Extracted element type from slice type and added `[]` suffix |
| 153 | +
|
| 154 | +### Test Results |
| 155 | +
|
| 156 | +✅ **Created compliance test**: `compliance/tests/variadic_interface_method/` |
| 157 | +✅ **Test passes**: `go test -timeout 30s -run ^TestCompliance/variadic_interface_method$ ./compiler` |
| 158 | +✅ **Generated correct TypeScript**: |
| 159 | +```typescript |
| 160 | +export type Basic = null | { |
| 161 | + Join(...elem: string[]): string |
| 162 | +} |
| 163 | +``` |
| 164 | +✅ **Interface and implementation signatures match** |
| 165 | +✅ **No regressions**: Other interface and method tests still pass |
| 166 | +
|
| 167 | +### Before and After |
| 168 | +
|
| 169 | +**Before (incorrect):** |
| 170 | +```typescript |
| 171 | +export type Basic = null | { |
| 172 | + Join(elem: $.Slice<string>): string // ❌ Wrong signature |
| 173 | +} |
| 174 | + |
| 175 | +export class PathJoiner { |
| 176 | + public Join(...elem: string[]): string { /* ... */ } // ✅ Correct implementation |
| 177 | +} |
| 178 | +``` |
| 179 | + |
| 180 | +**After (correct):** |
| 181 | +```typescript |
| 182 | +export type Basic = null | { |
| 183 | + Join(...elem: string[]): string // ✅ Now matches implementation |
| 184 | +} |
| 185 | + |
| 186 | +export class PathJoiner { |
| 187 | + public Join(...elem: string[]): string { /* ... */ } // ✅ Correct implementation |
| 188 | +} |
| 189 | +``` |
| 190 | + |
| 191 | +## Status: ✅ COMPLETED |
| 192 | + |
| 193 | +The variadic interface method issue has been successfully resolved. The Go-to-TypeScript compiler now correctly generates TypeScript interface signatures for methods with variadic parameters, ensuring compatibility between interface declarations and their implementations. |
0 commit comments