goscript 0.2.6 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/cmd/goscript/cmd-compile.go +7 -0
  2. package/cmd/goscript/cmd_compile_test.go +83 -0
  3. package/compiler/compile-request.go +3 -0
  4. package/compiler/compiler-cache.go +828 -0
  5. package/compiler/compiler-cache_test.go +705 -0
  6. package/compiler/config.go +2 -0
  7. package/compiler/index.test.ts +26 -1
  8. package/compiler/index.ts +5 -0
  9. package/compiler/lowered-program.go +31 -20
  10. package/compiler/lowering.go +349 -93
  11. package/compiler/lowering_bench_test.go +1 -0
  12. package/compiler/override-facts.go +309 -8
  13. package/compiler/override-parity-verifier.go +45 -1
  14. package/compiler/override-parity-verifier_test.go +100 -0
  15. package/compiler/override-registry_test.go +1 -0
  16. package/compiler/package-graph.go +40 -12
  17. package/compiler/package-graph_test.go +29 -0
  18. package/compiler/runtime-contract.go +8 -0
  19. package/compiler/service.go +98 -11
  20. package/compiler/skeleton_test.go +110 -14
  21. package/compiler/typescript-emitter.go +120 -23
  22. package/dist/compiler/index.d.ts +2 -0
  23. package/dist/compiler/index.js +3 -0
  24. package/dist/compiler/index.js.map +1 -1
  25. package/dist/gs/builtin/builtin.d.ts +24 -33
  26. package/dist/gs/builtin/builtin.js +54 -61
  27. package/dist/gs/builtin/builtin.js.map +1 -1
  28. package/dist/gs/builtin/hostio.d.ts +1 -0
  29. package/dist/gs/builtin/hostio.js +1 -1
  30. package/dist/gs/builtin/hostio.js.map +1 -1
  31. package/dist/gs/builtin/index.d.ts +1 -0
  32. package/dist/gs/builtin/index.js +1 -0
  33. package/dist/gs/builtin/index.js.map +1 -1
  34. package/dist/gs/builtin/panic.d.ts +18 -0
  35. package/dist/gs/builtin/panic.js +98 -0
  36. package/dist/gs/builtin/panic.js.map +1 -0
  37. package/dist/gs/builtin/slice.d.ts +10 -0
  38. package/dist/gs/builtin/slice.js +110 -53
  39. package/dist/gs/builtin/slice.js.map +1 -1
  40. package/dist/gs/builtin/type.js +15 -3
  41. package/dist/gs/builtin/type.js.map +1 -1
  42. package/dist/gs/builtin/varRef.d.ts +1 -1
  43. package/dist/gs/builtin/varRef.js +3 -2
  44. package/dist/gs/builtin/varRef.js.map +1 -1
  45. package/dist/gs/bytes/bytes.gs.js +51 -38
  46. package/dist/gs/bytes/bytes.gs.js.map +1 -1
  47. package/dist/gs/bytes/reader.gs.d.ts +1 -1
  48. package/dist/gs/bytes/reader.gs.js +6 -7
  49. package/dist/gs/bytes/reader.gs.js.map +1 -1
  50. package/dist/gs/cmp/index.d.ts +1 -1
  51. package/dist/gs/cmp/index.js +43 -10
  52. package/dist/gs/cmp/index.js.map +1 -1
  53. package/dist/gs/context/context.d.ts +2 -2
  54. package/dist/gs/context/context.js +1 -1
  55. package/dist/gs/context/context.js.map +1 -1
  56. package/dist/gs/embed/index.js +1 -1
  57. package/dist/gs/embed/index.js.map +1 -1
  58. package/dist/gs/encoding/binary/index.js +201 -8
  59. package/dist/gs/encoding/binary/index.js.map +1 -1
  60. package/dist/gs/encoding/json/index.d.ts +5 -0
  61. package/dist/gs/encoding/json/index.js +388 -25
  62. package/dist/gs/encoding/json/index.js.map +1 -1
  63. package/dist/gs/errors/errors.js +17 -24
  64. package/dist/gs/errors/errors.js.map +1 -1
  65. package/dist/gs/fmt/fmt.js +129 -35
  66. package/dist/gs/fmt/fmt.js.map +1 -1
  67. package/dist/gs/golang.org/x/crypto/cryptobyte/index.js +1 -1
  68. package/dist/gs/golang.org/x/crypto/cryptobyte/index.js.map +1 -1
  69. package/dist/gs/internal/bytealg/index.js +43 -8
  70. package/dist/gs/internal/bytealg/index.js.map +1 -1
  71. package/dist/gs/internal/byteorder/index.d.ts +2 -2
  72. package/dist/gs/internal/byteorder/index.js +2 -2
  73. package/dist/gs/internal/byteorder/index.js.map +1 -1
  74. package/dist/gs/io/fs/format.js +2 -2
  75. package/dist/gs/io/fs/format.js.map +1 -1
  76. package/dist/gs/io/fs/fs.d.ts +1 -1
  77. package/dist/gs/io/fs/fs.js +1 -1
  78. package/dist/gs/io/fs/fs.js.map +1 -1
  79. package/dist/gs/io/io.d.ts +21 -21
  80. package/dist/gs/io/io.js +49 -50
  81. package/dist/gs/io/io.js.map +1 -1
  82. package/dist/gs/math/bits/index.js +26 -8
  83. package/dist/gs/math/bits/index.js.map +1 -1
  84. package/dist/gs/math/copysign.gs.js +10 -17
  85. package/dist/gs/math/copysign.gs.js.map +1 -1
  86. package/dist/gs/math/pow.gs.js +5 -0
  87. package/dist/gs/math/pow.gs.js.map +1 -1
  88. package/dist/gs/math/signbit.gs.js +6 -2
  89. package/dist/gs/math/signbit.gs.js.map +1 -1
  90. package/dist/gs/mime/index.js +1 -0
  91. package/dist/gs/mime/index.js.map +1 -1
  92. package/dist/gs/net/http/index.d.ts +6 -6
  93. package/dist/gs/net/http/index.js +507 -43
  94. package/dist/gs/net/http/index.js.map +1 -1
  95. package/dist/gs/os/stat.gs.d.ts +2 -2
  96. package/dist/gs/os/types.gs.d.ts +1 -1
  97. package/dist/gs/os/types.gs.js +1 -1
  98. package/dist/gs/os/types.gs.js.map +1 -1
  99. package/dist/gs/os/types_js.gs.d.ts +1 -1
  100. package/dist/gs/os/types_js.gs.js +7 -7
  101. package/dist/gs/os/types_js.gs.js.map +1 -1
  102. package/dist/gs/os/types_unix.gs.d.ts +1 -1
  103. package/dist/gs/os/types_unix.gs.js +1 -1
  104. package/dist/gs/os/types_unix.gs.js.map +1 -1
  105. package/dist/gs/os/zero_copy_posix.gs.d.ts +1 -1
  106. package/dist/gs/os/zero_copy_posix.gs.js +1 -1
  107. package/dist/gs/os/zero_copy_posix.gs.js.map +1 -1
  108. package/dist/gs/path/filepath/match.js +8 -4
  109. package/dist/gs/path/filepath/match.js.map +1 -1
  110. package/dist/gs/path/filepath/path.js +216 -42
  111. package/dist/gs/path/filepath/path.js.map +1 -1
  112. package/dist/gs/path/match.js +6 -3
  113. package/dist/gs/path/match.js.map +1 -1
  114. package/dist/gs/reflect/type.d.ts +5 -4
  115. package/dist/gs/reflect/type.js +29 -11
  116. package/dist/gs/reflect/type.js.map +1 -1
  117. package/dist/gs/slices/slices.js +11 -11
  118. package/dist/gs/slices/slices.js.map +1 -1
  119. package/dist/gs/strconv/atof.gs.js +156 -43
  120. package/dist/gs/strconv/atof.gs.js.map +1 -1
  121. package/dist/gs/strconv/atoi.gs.d.ts +3 -2
  122. package/dist/gs/strconv/atoi.gs.js +86 -67
  123. package/dist/gs/strconv/atoi.gs.js.map +1 -1
  124. package/dist/gs/strconv/ftoa.gs.js +73 -3
  125. package/dist/gs/strconv/ftoa.gs.js.map +1 -1
  126. package/dist/gs/strconv/itoa.gs.d.ts +4 -4
  127. package/dist/gs/strconv/itoa.gs.js +5 -4
  128. package/dist/gs/strconv/itoa.gs.js.map +1 -1
  129. package/dist/gs/strconv/quote.gs.d.ts +1 -1
  130. package/dist/gs/strconv/quote.gs.js +311 -103
  131. package/dist/gs/strconv/quote.gs.js.map +1 -1
  132. package/dist/gs/strings/reader.d.ts +1 -1
  133. package/dist/gs/strings/reader.js +8 -8
  134. package/dist/gs/strings/reader.js.map +1 -1
  135. package/dist/gs/strings/strings.js +87 -61
  136. package/dist/gs/strings/strings.js.map +1 -1
  137. package/dist/gs/sync/atomic/doc_64.gs.d.ts +14 -14
  138. package/dist/gs/sync/atomic/doc_64.gs.js +10 -10
  139. package/dist/gs/sync/atomic/doc_64.gs.js.map +1 -1
  140. package/dist/gs/sync/atomic/type.gs.d.ts +22 -22
  141. package/dist/gs/sync/atomic/type.gs.js +4 -4
  142. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  143. package/dist/gs/sync/sync.js +50 -12
  144. package/dist/gs/sync/sync.js.map +1 -1
  145. package/dist/gs/syscall/fs.d.ts +6 -6
  146. package/dist/gs/syscall/fs.js +1 -1
  147. package/dist/gs/syscall/fs.js.map +1 -1
  148. package/dist/gs/time/time.d.ts +18 -18
  149. package/dist/gs/time/time.js +58 -55
  150. package/dist/gs/time/time.js.map +1 -1
  151. package/dist/gs/unicode/tables.d.ts +11 -0
  152. package/dist/gs/unicode/tables.js +635 -0
  153. package/dist/gs/unicode/tables.js.map +1 -0
  154. package/dist/gs/unicode/unicode.d.ts +58 -38
  155. package/dist/gs/unicode/unicode.js +362 -278
  156. package/dist/gs/unicode/unicode.js.map +1 -1
  157. package/go.sum +13 -0
  158. package/gs/builtin/builtin.ts +83 -93
  159. package/gs/builtin/hostio.ts +1 -1
  160. package/gs/builtin/index.ts +1 -0
  161. package/gs/builtin/panic.test.ts +189 -0
  162. package/gs/builtin/panic.ts +107 -0
  163. package/gs/builtin/runtime-contract.test.ts +5 -5
  164. package/gs/builtin/slice.test.ts +23 -0
  165. package/gs/builtin/slice.ts +133 -95
  166. package/gs/builtin/type.ts +16 -3
  167. package/gs/builtin/varRef.ts +4 -2
  168. package/gs/builtin/wide-int.test.ts +41 -0
  169. package/gs/bytes/bytes.gs.ts +54 -41
  170. package/gs/bytes/bytes.test.ts +18 -1
  171. package/gs/bytes/reader.gs.ts +7 -8
  172. package/gs/cmp/index.test.ts +55 -0
  173. package/gs/cmp/index.ts +45 -9
  174. package/gs/context/context.ts +3 -3
  175. package/gs/embed/index.ts +2 -2
  176. package/gs/encoding/binary/index.test.ts +104 -0
  177. package/gs/encoding/binary/index.ts +259 -11
  178. package/gs/encoding/json/index.test.ts +107 -0
  179. package/gs/encoding/json/index.ts +400 -29
  180. package/gs/errors/errors.test.ts +44 -1
  181. package/gs/errors/errors.ts +15 -31
  182. package/gs/fmt/fmt.test.ts +70 -2
  183. package/gs/fmt/fmt.ts +128 -34
  184. package/gs/golang.org/x/crypto/cryptobyte/index.ts +1 -1
  185. package/gs/internal/bytealg/index.test.ts +26 -1
  186. package/gs/internal/bytealg/index.ts +44 -8
  187. package/gs/internal/byteorder/index.ts +6 -4
  188. package/gs/io/fs/format.ts +2 -2
  189. package/gs/io/fs/fs.ts +2 -2
  190. package/gs/io/fs/stat.test.ts +2 -2
  191. package/gs/io/fs/sub.test.ts +2 -2
  192. package/gs/io/fs/walk.test.ts +2 -2
  193. package/gs/io/io.test.ts +47 -5
  194. package/gs/io/io.ts +73 -73
  195. package/gs/io/limit.test.ts +103 -0
  196. package/gs/math/bits/index.test.ts +128 -0
  197. package/gs/math/bits/index.ts +26 -8
  198. package/gs/math/copysign.gs.test.ts +3 -1
  199. package/gs/math/copysign.gs.ts +10 -22
  200. package/gs/math/pow.gs.test.ts +4 -5
  201. package/gs/math/pow.gs.ts +5 -0
  202. package/gs/math/signbit.gs.test.ts +2 -1
  203. package/gs/math/signbit.gs.ts +6 -3
  204. package/gs/mime/index.ts +1 -0
  205. package/gs/net/http/index.test.ts +683 -2
  206. package/gs/net/http/index.ts +598 -57
  207. package/gs/net/http/meta.json +3 -0
  208. package/gs/os/stat.gs.ts +2 -2
  209. package/gs/os/types.gs.ts +2 -2
  210. package/gs/os/types_js.gs.ts +9 -9
  211. package/gs/os/types_unix.gs.ts +2 -2
  212. package/gs/os/zero_copy_posix.gs.ts +2 -2
  213. package/gs/path/filepath/match.test.ts +16 -0
  214. package/gs/path/filepath/match.ts +8 -4
  215. package/gs/path/filepath/path.test.ts +91 -9
  216. package/gs/path/filepath/path.ts +223 -49
  217. package/gs/path/match.test.ts +32 -0
  218. package/gs/path/match.ts +6 -3
  219. package/gs/reflect/deepequal.test.ts +1 -1
  220. package/gs/reflect/field.test.ts +1 -1
  221. package/gs/reflect/function-types.test.ts +6 -6
  222. package/gs/reflect/sliceat.test.ts +13 -13
  223. package/gs/reflect/structof.test.ts +4 -4
  224. package/gs/reflect/type.ts +34 -14
  225. package/gs/reflect/typefor.test.ts +5 -5
  226. package/gs/runtime/pprof/index.test.ts +20 -0
  227. package/gs/runtime/trace/index.test.ts +3 -0
  228. package/gs/slices/slices.test.ts +31 -0
  229. package/gs/slices/slices.ts +11 -11
  230. package/gs/strconv/append.test.ts +99 -0
  231. package/gs/strconv/atof.gs.ts +156 -42
  232. package/gs/strconv/atof.test.ts +45 -0
  233. package/gs/strconv/atoi.gs.ts +87 -69
  234. package/gs/strconv/atoi.test.ts +49 -0
  235. package/gs/strconv/ftoa.gs.ts +85 -10
  236. package/gs/strconv/ftoa.test.ts +43 -0
  237. package/gs/strconv/itoa.gs.ts +10 -9
  238. package/gs/strconv/quote.gs.ts +335 -108
  239. package/gs/strconv/quote.test.ts +111 -0
  240. package/gs/strings/reader.test.ts +10 -10
  241. package/gs/strings/reader.ts +9 -9
  242. package/gs/strings/strings.test.ts +18 -5
  243. package/gs/strings/strings.ts +81 -68
  244. package/gs/sync/atomic/doc_64.gs.ts +24 -24
  245. package/gs/sync/atomic/doc_64.test.ts +5 -5
  246. package/gs/sync/atomic/type.gs.ts +28 -28
  247. package/gs/sync/sync.test.ts +109 -1
  248. package/gs/sync/sync.ts +46 -12
  249. package/gs/syscall/fs.ts +8 -8
  250. package/gs/syscall/net.test.ts +1 -1
  251. package/gs/time/parse.test.ts +45 -0
  252. package/gs/time/time.test.ts +46 -23
  253. package/gs/time/time.ts +69 -66
  254. package/gs/unicode/gen.go +198 -0
  255. package/gs/unicode/tables.ts +646 -0
  256. package/gs/unicode/unicode.test.ts +69 -0
  257. package/gs/unicode/unicode.ts +396 -312
  258. package/package.json +1 -1
  259. package/dist/gs/github.com/aperturerobotics/util/conc/index.d.ts +0 -20
  260. package/dist/gs/github.com/aperturerobotics/util/conc/index.js +0 -134
  261. package/dist/gs/github.com/aperturerobotics/util/conc/index.js.map +0 -1
  262. package/gs/github.com/aperturerobotics/util/conc/index.test.ts +0 -30
  263. package/gs/github.com/aperturerobotics/util/conc/index.ts +0 -172
  264. package/gs/github.com/aperturerobotics/util/conc/meta.json +0 -9
@@ -36,6 +36,8 @@ type LoweringOptions struct {
36
36
  OutputPath string
37
37
  // ProtobufTypeScriptBinding binds .pb.go files to sibling .pb.ts files.
38
38
  ProtobufTypeScriptBinding bool
39
+ // TrimTypeInfo drops metadata used only by reflect from named type registration payloads.
40
+ TrimTypeInfo bool
39
41
  }
40
42
 
41
43
  // NewLoweringOwner creates the lowering owner.
@@ -74,7 +76,7 @@ func (o *LoweringOwner) Build(ctx context.Context, model *SemanticModel, opts ..
74
76
  options = opts[0]
75
77
  }
76
78
 
77
- program := &LoweredProgram{}
79
+ program := &LoweredProgram{trimTypeInfo: options.TrimTypeInfo}
78
80
  lazyPackageVars := make(map[string]map[types.Object]bool, len(model.packages))
79
81
  asyncLazyFunctionCache := make(map[*types.Func]bool)
80
82
  asyncLazyFunctionVisiting := make(map[*types.Func]bool)
@@ -159,6 +161,7 @@ func (o *LoweringOwner) lowerPackage(
159
161
  asyncLazyFunctionVisiting,
160
162
  runtimeMethodSets,
161
163
  protobufAdapter,
164
+ options.TrimTypeInfo,
162
165
  options.DisplayRoot,
163
166
  )
164
167
  diagnostics = append(diagnostics, fileDiagnostics...)
@@ -181,6 +184,7 @@ func (o *LoweringOwner) lowerPackage(
181
184
  asyncLazyFunctionVisiting,
182
185
  runtimeMethodSets,
183
186
  false,
187
+ options.TrimTypeInfo,
184
188
  options.DisplayRoot,
185
189
  )
186
190
  diagnostics = append(diagnostics, fileDiagnostics...)
@@ -219,6 +223,7 @@ func (o *LoweringOwner) lowerFile(
219
223
  asyncLazyFunctionVisiting map[*types.Func]bool,
220
224
  runtimeMethodSets runtimeMethodSetCache,
221
225
  protobufTypeScriptAdapter bool,
226
+ trimTypeInfo bool,
222
227
  displayRoot string,
223
228
  ) (*loweredFile, []Diagnostic) {
224
229
  associatedMethods := o.methodDeclsForFileTypes(semPkg, file)
@@ -342,6 +347,7 @@ func (o *LoweringOwner) lowerFile(
342
347
  tempNames: newTempNameOwner(),
343
348
  topLevel: true,
344
349
  protobufTSAdapter: protobufTypeScriptAdapter,
350
+ trimTypeInfo: trimTypeInfo,
345
351
  displayRoot: displayRoot,
346
352
  }
347
353
  var diagnostics []Diagnostic
@@ -1150,6 +1156,7 @@ type lowerFileContext struct {
1150
1156
  switchBreak bool
1151
1157
  topLevel bool
1152
1158
  protobufTSAdapter bool
1159
+ trimTypeInfo bool
1153
1160
  displayRoot string
1154
1161
  }
1155
1162
 
@@ -1311,7 +1318,7 @@ func (o *LoweringOwner) lowerGenDecl(ctx lowerFileContext, decl *ast.GenDecl) ([
1311
1318
  }
1312
1319
  value := o.lowerDeclarationZeroValueExpr(ctx, obj.Type())
1313
1320
  if constObj, ok := obj.(*types.Const); ok {
1314
- if constValue, ok := lowerConstantValue(constObj.Val()); ok {
1321
+ if constValue, ok := lowerConstantValueForType(constObj.Val(), constObj.Type()); ok {
1315
1322
  value = constValue
1316
1323
  }
1317
1324
  } else if idx < len(typed.Values) {
@@ -2575,6 +2582,17 @@ func lowerLargeIntegerConstantValue(value constant.Value) (string, bool) {
2575
2582
  return value.ExactString(), true
2576
2583
  }
2577
2584
 
2585
+ // lowerConstantValueForType lowers an integer constant to a bigint literal when
2586
+ // its declared type is bigint-backed (int64/uint64 and named types over them),
2587
+ // so that const declarations and inlined const references carry the same
2588
+ // representation as the values they participate in arithmetic with.
2589
+ func lowerConstantValueForType(value constant.Value, typ types.Type) (string, bool) {
2590
+ if value != nil && value.Kind() == constant.Int && isBigIntBackedType(typ) {
2591
+ return value.ExactString() + "n", true
2592
+ }
2593
+ return lowerConstantValue(value)
2594
+ }
2595
+
2578
2596
  func lowerWideIntegerConstantValue(value constant.Value) (string, bool) {
2579
2597
  if value == nil || value.Kind() != constant.Int || constant.BitLen(value) <= 53 {
2580
2598
  return "", false
@@ -2918,9 +2936,13 @@ func (o *LoweringOwner) lowerInterfaceType(ctx lowerFileContext, semType *semant
2918
2936
  typeIndexExport = typeName
2919
2937
  }
2920
2938
  }
2939
+ methodSignatures := o.runtimeMethodSignatures(iface)
2940
+ if ctx.trimTypeInfo {
2941
+ methodSignatures = o.runtimeTrimmedMethodSignatures(iface)
2942
+ }
2921
2943
  code = code + "\n\n" + o.runtimeOwner.QualifiedHelper(RuntimeHelperRegisterInterfaceType) +
2922
2944
  "(\n\t" + strconv.Quote(runtimeNamedTypeName(semType.named)) +
2923
- ",\n\tnull,\n\t" + o.runtimeMethodSignatures(iface) + "\n);"
2945
+ ",\n\tnull,\n\t" + methodSignatures + "\n);"
2924
2946
  return loweredDecl{code: code, typeIndexExport: typeIndexExport, sideEffect: true}
2925
2947
  }
2926
2948
 
@@ -2957,6 +2979,18 @@ func (o *LoweringOwner) runtimeMethodSignaturesWithSeen(iface *types.Interface,
2957
2979
  return "[" + strings.Join(methods, ", ") + "]"
2958
2980
  }
2959
2981
 
2982
+ func (o *LoweringOwner) runtimeTrimmedMethodSignatures(iface *types.Interface) string {
2983
+ return o.runtimeTrimmedMethodSignaturesWithSeen(iface, make(map[types.Type]bool))
2984
+ }
2985
+
2986
+ func (o *LoweringOwner) runtimeTrimmedMethodSignaturesWithSeen(iface *types.Interface, seen map[types.Type]bool) string {
2987
+ methods := make([]string, 0, iface.NumMethods())
2988
+ for method := range iface.Methods() {
2989
+ methods = append(methods, o.runtimeTrimmedMethodSignature(method, seen))
2990
+ }
2991
+ return "[" + strings.Join(methods, ", ") + "]"
2992
+ }
2993
+
2960
2994
  func (o *LoweringOwner) runtimeMethodAssertSignaturesWithSeen(ctx lowerFileContext, iface *types.Interface, seen map[types.Type]bool) string {
2961
2995
  methods := make([]string, 0, iface.NumMethods())
2962
2996
  for method := range iface.Methods() {
@@ -2975,6 +3009,16 @@ func (o *LoweringOwner) runtimeMethodSignature(method *types.Func, seen map[type
2975
3009
  ", returns: " + o.runtimeMethodReturns(signature.Results(), seen) + " }"
2976
3010
  }
2977
3011
 
3012
+ func (o *LoweringOwner) runtimeTrimmedMethodSignature(method *types.Func, seen map[types.Type]bool) string {
3013
+ signature, _ := method.Type().(*types.Signature)
3014
+ if signature == nil {
3015
+ return "{ name: " + strconv.Quote(method.Name()) + ", args: [], returns: [] }"
3016
+ }
3017
+ return "{ name: " + strconv.Quote(method.Name()) +
3018
+ ", args: " + o.runtimeTrimmedMethodArgs(signature.Params()) +
3019
+ ", returns: " + o.runtimeTrimmedMethodReturns(signature.Results(), seen) + " }"
3020
+ }
3021
+
2978
3022
  func (o *LoweringOwner) runtimeMethodAssertSignature(ctx lowerFileContext, method *types.Func, seen map[types.Type]bool) string {
2979
3023
  signature, _ := method.Type().(*types.Signature)
2980
3024
  if signature == nil {
@@ -3001,6 +3045,19 @@ func (o *LoweringOwner) runtimeMethodArgs(tuple *types.Tuple, seen map[types.Typ
3001
3045
  return "[" + strings.Join(args, ", ") + "]"
3002
3046
  }
3003
3047
 
3048
+ func (o *LoweringOwner) runtimeTrimmedMethodArgs(tuple *types.Tuple) string {
3049
+ if tuple == nil || tuple.Len() == 0 {
3050
+ return "[]"
3051
+ }
3052
+ typeKind := o.runtimeOwner.QualifiedHelper(RuntimeHelperTypeKind)
3053
+ arg := "{ type: { kind: " + typeKind + ".Basic, name: \"unknown\" } }"
3054
+ args := make([]string, 0, tuple.Len())
3055
+ for range tuple.Len() {
3056
+ args = append(args, arg)
3057
+ }
3058
+ return "[" + strings.Join(args, ", ") + "]"
3059
+ }
3060
+
3004
3061
  func (o *LoweringOwner) runtimeMethodAssertArgs(ctx lowerFileContext, tuple *types.Tuple, seen map[types.Type]bool) string {
3005
3062
  if tuple == nil || tuple.Len() == 0 {
3006
3063
  return "[]"
@@ -3033,6 +3090,17 @@ func (o *LoweringOwner) runtimeMethodReturns(tuple *types.Tuple, seen map[types.
3033
3090
  return "[" + strings.Join(results, ", ") + "]"
3034
3091
  }
3035
3092
 
3093
+ func (o *LoweringOwner) runtimeTrimmedMethodReturns(tuple *types.Tuple, seen map[types.Type]bool) string {
3094
+ if tuple == nil || tuple.Len() == 0 {
3095
+ return "[]"
3096
+ }
3097
+ results := make([]string, 0, tuple.Len())
3098
+ for result := range tuple.Variables() {
3099
+ results = append(results, "{ type: "+o.runtimeTypeInfoExprWithSeen(result.Type(), seen)+" }")
3100
+ }
3101
+ return "[" + strings.Join(results, ", ") + "]"
3102
+ }
3103
+
3036
3104
  func (o *LoweringOwner) runtimeMethodAssertReturns(ctx lowerFileContext, tuple *types.Tuple, seen map[types.Type]bool) string {
3037
3105
  if tuple == nil || tuple.Len() == 0 {
3038
3106
  return "[]"
@@ -3291,13 +3359,14 @@ func (o *LoweringOwner) lowerEmbeddedMethodForwarders(
3291
3359
  async := o.functionAsync(ctx, method)
3292
3360
  targetType := o.tsEmbeddedForwarderTargetType(ctx, field.typ)
3293
3361
  lowered := loweredFunction{
3294
- async: async,
3295
- sourcePath: ctx.sourcePath,
3296
- name: methodMemberName(method.Name()),
3297
- runtimeName: method.Name(),
3298
- runtimeSignature: o.runtimeMethodSignature(method, make(map[types.Type]bool)),
3299
- result: asyncResultType("any", async),
3300
- deferState: &loweredDeferState{},
3362
+ async: async,
3363
+ sourcePath: ctx.sourcePath,
3364
+ name: methodMemberName(method.Name()),
3365
+ runtimeName: method.Name(),
3366
+ runtimeSignature: o.runtimeMethodSignature(method, make(map[types.Type]bool)),
3367
+ runtimeTrimmedSignature: o.runtimeTrimmedMethodSignature(method, make(map[types.Type]bool)),
3368
+ result: asyncResultType("any", async),
3369
+ deferState: &loweredDeferState{},
3301
3370
  }
3302
3371
  args := make([]string, 0, signature.Params().Len())
3303
3372
  for idx := range signature.Params().Len() {
@@ -3462,8 +3531,13 @@ func (o *LoweringOwner) lowerNamedReceiverMethodDecl(
3462
3531
  lowered.params, lowered.paramBindings = o.appendLoweredParam(ctx, lowered.params, lowered.paramBindings, param, idx, decl.Body == nil || async)
3463
3532
  }
3464
3533
  if decl.Body != nil {
3465
- body, diagnostics := o.lowerBlock(ctx.withSignature(signature).withAsyncFunction(async).withDeferState(deferState), decl.Body)
3534
+ bodyCtx := ctx.withSignature(signature).withAsyncFunction(async).withDeferState(deferState)
3535
+ body, diagnostics := o.lowerBlock(bodyCtx, decl.Body)
3466
3536
  lowered.body = body
3537
+ if deferState.used && funcBodyUsesRecover(bodyCtx, decl.Body) {
3538
+ deferState.recover = true
3539
+ lowered.recoverReturn = o.recoverReturnStmt(bodyCtx, signature)
3540
+ }
3467
3541
  if deferState.async && !lowered.async {
3468
3542
  lowered.async = true
3469
3543
  lowered.result = asyncResultType(o.tsSignatureResultFor(ctx.withAsyncFunction(true), signature), true)
@@ -3520,6 +3594,7 @@ func (o *LoweringOwner) lowerFuncDecl(ctx lowerFileContext, decl *ast.FuncDecl)
3520
3594
  }
3521
3595
  if decl.Recv != nil {
3522
3596
  lowered.runtimeSignature = o.runtimeMethodSignature(fnObj, make(map[types.Type]bool))
3597
+ lowered.runtimeTrimmedSignature = o.runtimeTrimmedMethodSignature(fnObj, make(map[types.Type]bool))
3523
3598
  }
3524
3599
  if signature.TypeParams() != nil && signature.TypeParams().Len() != 0 {
3525
3600
  lowered.typeParams = signatureTypeParamNames(signature)
@@ -3550,8 +3625,13 @@ func (o *LoweringOwner) lowerFuncDecl(ctx lowerFileContext, decl *ast.FuncDecl)
3550
3625
  lowered.params, lowered.paramBindings = o.appendLoweredParam(functionCtx, lowered.params, lowered.paramBindings, param, idx, decl.Body == nil || async)
3551
3626
  }
3552
3627
  if decl.Body != nil {
3553
- body, diagnostics := o.lowerBlock(functionCtx.withAsyncFunction(async).withDeferState(deferState), decl.Body)
3628
+ bodyCtx := functionCtx.withAsyncFunction(async).withDeferState(deferState)
3629
+ body, diagnostics := o.lowerBlock(bodyCtx, decl.Body)
3554
3630
  lowered.body = body
3631
+ if deferState.used && funcBodyUsesRecover(bodyCtx, decl.Body) {
3632
+ deferState.recover = true
3633
+ lowered.recoverReturn = o.recoverReturnStmt(bodyCtx, signature)
3634
+ }
3555
3635
  if deferState.async && !lowered.async {
3556
3636
  lowered.async = true
3557
3637
  lowered.result = asyncResultType(o.tsSignatureResultFor(functionCtx.withAsyncFunction(true), signature), true)
@@ -3863,7 +3943,7 @@ func (o *LoweringOwner) lowerStmtInto(ctx lowerFileContext, stmt ast.Stmt, out [
3863
3943
  }
3864
3944
  if decl.structType != nil {
3865
3945
  var b strings.Builder
3866
- renderStruct(&b, decl.structType, o.runtimeOwner)
3946
+ renderStruct(&b, decl.structType, o.runtimeOwner, ctx.trimTypeInfo)
3867
3947
  stmts = append(stmts, loweredStmt{text: strings.TrimRight(b.String(), "\n")})
3868
3948
  }
3869
3949
  }
@@ -3955,17 +4035,22 @@ func (o *LoweringOwner) lowerStmtInto(ctx lowerFileContext, stmt ast.Stmt, out [
3955
4035
  }
3956
4036
  return append(out, lowered...), diagnostics
3957
4037
  case *ast.IncDecStmt:
4038
+ // A bigint-backed operand (int64/uint64) needs a bigint step literal so
4039
+ // the generated +/- does not mix bigint and number.
4040
+ oneLiteral := "1"
4041
+ if isBigIntBackedType(ctx.semPkg.source.TypesInfo.TypeOf(typed.X)) {
4042
+ oneLiteral = "1n"
4043
+ }
3958
4044
  if star, ok := unwrapParenExpr(typed.X).(*ast.StarExpr); ok {
3959
4045
  expr, diagnostics := o.lowerPointerStorageExpr(ctx, star.X)
3960
4046
  return append(out, loweredStmt{text: expr + typed.Tok.String()}), diagnostics
3961
4047
  }
3962
4048
  if index, ok := unwrapParenExpr(typed.X).(*ast.IndexExpr); ok && isMapType(ctx.semPkg.source.TypesInfo.TypeOf(index.X)) {
3963
- right := "1"
3964
4049
  tok := token.ADD_ASSIGN
3965
4050
  if typed.Tok == token.DEC {
3966
4051
  tok = token.SUB_ASSIGN
3967
4052
  }
3968
- stmts, diagnostics := o.lowerMapIndexUpdateStmts(ctx, index, tok, right, ctx.semPkg.source.TypesInfo.TypeOf(typed.X))
4053
+ stmts, diagnostics := o.lowerMapIndexUpdateStmts(ctx, index, tok, oneLiteral, ctx.semPkg.source.TypesInfo.TypeOf(typed.X))
3969
4054
  return append(out, stmts...), diagnostics
3970
4055
  }
3971
4056
  if setter, ok := o.packageVarSetterForAssignment(ctx, typed.X); ok {
@@ -3974,7 +4059,14 @@ func (o *LoweringOwner) lowerStmtInto(ctx lowerFileContext, stmt ast.Stmt, out [
3974
4059
  if typed.Tok == token.DEC {
3975
4060
  op = "-"
3976
4061
  }
3977
- return append(out, loweredStmt{text: setter + "(" + expr + " " + op + " 1)"}), diagnostics
4062
+ return append(out, loweredStmt{text: setter + "(" + expr + " " + op + " " + oneLiteral + ")"}), diagnostics
4063
+ }
4064
+ if _, ok := unwrapParenExpr(typed.X).(*ast.IndexExpr); ok {
4065
+ // Array/slice index increment needs the assignable target[index] form;
4066
+ // the read path wraps indexing in a bounds-checked helper that cannot be
4067
+ // an increment operand. Map index increment is handled above.
4068
+ target, diagnostics := o.lowerAssignmentTarget(ctx, typed.X, false)
4069
+ return append(out, loweredStmt{text: target + typed.Tok.String()}), diagnostics
3978
4070
  }
3979
4071
  expr, diagnostics := o.lowerExpr(ctx, typed.X)
3980
4072
  return append(out, loweredStmt{text: expr + typed.Tok.String()}), diagnostics
@@ -4896,7 +4988,8 @@ func (o *LoweringOwner) lowerAssignStmt(ctx lowerFileContext, stmt *ast.AssignSt
4896
4988
  continue
4897
4989
  }
4898
4990
  if helper, ok := wideIntegerAssignHelper(targetType, stmt.Tok); ok {
4899
- stmts = append(stmts, loweredStmt{text: left + " = " + o.runtimeOwner.QualifiedHelper(helper) + "(" + left + ", " + right + ")"})
4991
+ call := coerceWideHelperResult(o.runtimeOwner, targetType, o.runtimeOwner.QualifiedHelper(helper)+"("+left+", "+right+")")
4992
+ stmts = append(stmts, loweredStmt{text: left + " = " + call})
4900
4993
  continue
4901
4994
  }
4902
4995
  if value, ok := integerQuotientAssignExpr(targetType, left, right, stmt.Tok); ok {
@@ -4951,7 +5044,7 @@ func lowerCompoundAssignValue(
4951
5044
  tok token.Token,
4952
5045
  ) string {
4953
5046
  if helper, ok := wideIntegerAssignHelper(targetType, tok); ok {
4954
- return runtimeOwner.QualifiedHelper(helper) + "(" + left + ", " + right + ")"
5047
+ return coerceWideHelperResult(runtimeOwner, targetType, runtimeOwner.QualifiedHelper(helper)+"("+left+", "+right+")")
4955
5048
  }
4956
5049
  if value, ok := integerQuotientAssignValueExpr(targetType, left, right, tok); ok {
4957
5050
  return value
@@ -6099,6 +6192,23 @@ func (o *LoweringOwner) lowerNamedResultReturn(ctx lowerFileContext) (string, bo
6099
6192
  return "[" + strings.Join(parts, ", ") + "]", true
6100
6193
  }
6101
6194
 
6195
+ // recoverReturnStmt builds the return statement a defer+recover function runs
6196
+ // after its deferred recover() swallows a panic: the named results, the zero
6197
+ // values for unnamed results, or an empty string for a void function (which
6198
+ // falls through and returns undefined).
6199
+ func (o *LoweringOwner) recoverReturnStmt(ctx lowerFileContext, signature *types.Signature) string {
6200
+ if signature == nil || signature.Results() == nil || signature.Results().Len() == 0 {
6201
+ return ""
6202
+ }
6203
+ if expr, ok := o.lowerNamedResultReturn(ctx); ok {
6204
+ return "return " + expr
6205
+ }
6206
+ if zeroReturn, ok := o.lowerBodylessReturnStmt(ctx, signature); ok {
6207
+ return zeroReturn
6208
+ }
6209
+ return ""
6210
+ }
6211
+
6102
6212
  func (o *LoweringOwner) lowerForStmt(ctx lowerFileContext, stmt *ast.ForStmt) (loweredStmt, []Diagnostic) {
6103
6213
  bodyCtx := ctx.withoutRangeLoopBranches().withoutLoopLabel()
6104
6214
  loopLabel := ""
@@ -7042,8 +7152,7 @@ func isFunctionType(typ types.Type) bool {
7042
7152
  }
7043
7153
 
7044
7154
  func isBoolType(typ types.Type) bool {
7045
- basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
7046
- return ok && basic.Kind() == types.Bool
7155
+ return basicKind(typ, types.Bool)
7047
7156
  }
7048
7157
 
7049
7158
  func isUntypedNilType(typ types.Type) bool {
@@ -7326,17 +7435,22 @@ func (o *LoweringOwner) lowerExpr(ctx lowerFileContext, expr ast.Expr) (string,
7326
7435
  return lowerPrefixUnaryExpr(typed.Op, value), diagnostics
7327
7436
  }
7328
7437
  if typed.Op == token.XOR {
7329
- if bits, ok := unsignedIntegerBits(ctx.semPkg.source.TypesInfo.TypeOf(typed)); ok {
7438
+ resultType := ctx.semPkg.source.TypesInfo.TypeOf(typed)
7439
+ // The int64*/uint64* family returns bigint; number-typed wide results
7440
+ // (uint, uintptr) keep full 64-bit width through coerceWideHelperResult.
7441
+ wideComplement := func(helper RuntimeHelper) string {
7442
+ return coerceWideHelperResult(o.runtimeOwner, resultType,
7443
+ o.runtimeOwner.QualifiedHelper(helper)+"("+value+", -1n)")
7444
+ }
7445
+ if bits, ok := unsignedIntegerBits(resultType); ok {
7330
7446
  if bits <= 32 {
7331
7447
  return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint) +
7332
7448
  "(~" + value + ", " + strconv.Itoa(bits) + ")", diagnostics
7333
7449
  }
7334
- return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint64Xor) +
7335
- "(" + value + ", -1n)", diagnostics
7450
+ return wideComplement(RuntimeHelperUint64Xor), diagnostics
7336
7451
  }
7337
- if bits, ok := signedIntegerBits(ctx.semPkg.source.TypesInfo.TypeOf(typed)); ok && bits > 32 {
7338
- return o.runtimeOwner.QualifiedHelper(RuntimeHelperInt64Xor) +
7339
- "(" + value + ", -1n)", diagnostics
7452
+ if bits, ok := signedIntegerBits(resultType); ok && bits > 32 {
7453
+ return wideComplement(RuntimeHelperInt64Xor), diagnostics
7340
7454
  }
7341
7455
  return "~" + value, diagnostics
7342
7456
  }
@@ -7470,11 +7584,15 @@ func (o *LoweringOwner) lowerFuncLitArrowWithAsyncCalls(
7470
7584
  }
7471
7585
  }
7472
7586
  body, diagnostics := o.lowerBlock(bodyCtx, lit.Body)
7587
+ litFn := &loweredFunction{body: body, deferState: deferState}
7588
+ if deferState.used && funcBodyUsesRecover(bodyCtx, lit.Body) {
7589
+ deferState.recover = true
7590
+ litFn.recoverReturn = o.recoverReturnStmt(bodyCtx, signature)
7591
+ }
7473
7592
  var rendered strings.Builder
7474
7593
  renderStmts(&rendered, paramBindings, 1)
7475
7594
  renderNamedResults(&rendered, o.lowerNamedResults(ctx, signature), 1)
7476
- renderDeferStack(&rendered, deferState, 1)
7477
- renderStmts(&rendered, body, 1)
7595
+ renderBodyWithDefer(&rendered, litFn, 1)
7478
7596
  async := bodyCtx.asyncFunction || stmtsContainAwait(body) || deferState.async
7479
7597
  prefix := ""
7480
7598
  if async {
@@ -7578,7 +7696,7 @@ func (o *LoweringOwner) lowerIdent(ctx lowerFileContext, ident *ast.Ident, raw b
7578
7696
  return alias
7579
7697
  }
7580
7698
  if constObj, ok := obj.(*types.Const); ok && !raw {
7581
- if constValue, ok := lowerConstantValue(constObj.Val()); ok {
7699
+ if constValue, ok := lowerConstantValueForType(constObj.Val(), constObj.Type()); ok {
7582
7700
  return constValue
7583
7701
  }
7584
7702
  }
@@ -8173,6 +8291,34 @@ func isBuiltinCallTarget(ctx lowerFileContext, expr ast.Expr) bool {
8173
8291
  return ok
8174
8292
  }
8175
8293
 
8294
+ // funcBodyUsesRecover reports whether body lexically contains a call to the
8295
+ // builtin recover. The scan descends into nested function literals because a
8296
+ // recover() inside a deferred func literal recovers the enclosing function's
8297
+ // panic, so that enclosing function is the one that needs the recover-aware
8298
+ // emission.
8299
+ func funcBodyUsesRecover(ctx lowerFileContext, body ast.Node) bool {
8300
+ found := false
8301
+ ast.Inspect(body, func(node ast.Node) bool {
8302
+ if found {
8303
+ return false
8304
+ }
8305
+ call, ok := node.(*ast.CallExpr)
8306
+ if !ok {
8307
+ return true
8308
+ }
8309
+ ident, ok := call.Fun.(*ast.Ident)
8310
+ if !ok || ident.Name != "recover" {
8311
+ return true
8312
+ }
8313
+ if _, ok := objectForIdent(ctx, ident).(*types.Builtin); ok {
8314
+ found = true
8315
+ return false
8316
+ }
8317
+ return true
8318
+ })
8319
+ return found
8320
+ }
8321
+
8176
8322
  func (o *LoweringOwner) callUsesOverridePackage(ctx lowerFileContext, expr ast.Expr) bool {
8177
8323
  if o.overrideOwner == nil || ctx.semPkg == nil || ctx.semPkg.source == nil {
8178
8324
  return false
@@ -8219,11 +8365,13 @@ func (o *LoweringOwner) lowerMakeExpr(ctx lowerFileContext, expr *ast.CallExpr)
8219
8365
  if len(expr.Args) >= 2 {
8220
8366
  var lengthDiagnostics []Diagnostic
8221
8367
  length, lengthDiagnostics = o.lowerExpr(ctx, expr.Args[1])
8368
+ length = o.lowerNumberIndexValue(ctx, expr.Args[1], length)
8222
8369
  diagnostics = append(diagnostics, lengthDiagnostics...)
8223
8370
  }
8224
8371
  if len(expr.Args) >= 3 {
8225
8372
  var capacityDiagnostics []Diagnostic
8226
8373
  capacity, capacityDiagnostics = o.lowerExpr(ctx, expr.Args[2])
8374
+ capacity = o.lowerNumberIndexValue(ctx, expr.Args[2], capacity)
8227
8375
  diagnostics = append(diagnostics, capacityDiagnostics...)
8228
8376
  }
8229
8377
  args := []string{length}
@@ -8256,6 +8404,7 @@ func (o *LoweringOwner) lowerMakeExpr(ctx lowerFileContext, expr *ast.CallExpr)
8256
8404
  if len(expr.Args) >= 2 {
8257
8405
  var capacityDiagnostics []Diagnostic
8258
8406
  capacity, capacityDiagnostics = o.lowerExpr(ctx, expr.Args[1])
8407
+ capacity = o.lowerNumberIndexValue(ctx, expr.Args[1], capacity)
8259
8408
  diagnostics = append(diagnostics, capacityDiagnostics...)
8260
8409
  }
8261
8410
  return o.runtimeOwner.QualifiedHelper(RuntimeHelperMakeChannel) +
@@ -8400,8 +8549,18 @@ func (o *LoweringOwner) lowerConversionExpr(
8400
8549
  }
8401
8550
  if isNumericType(targetType) {
8402
8551
  if isFloatType(targetType) {
8552
+ if isBigIntBackedType(sourceType) {
8553
+ return "Number(" + value + ")", diagnostics
8554
+ }
8403
8555
  return value, diagnostics
8404
8556
  }
8557
+ if isBigIntBackedType(targetType) {
8558
+ helper := RuntimeHelperInt64
8559
+ if _, ok := unsignedIntegerBits(targetType); ok {
8560
+ helper = RuntimeHelperUint64
8561
+ }
8562
+ return o.runtimeOwner.QualifiedHelper(helper) + "(" + value + ")", diagnostics
8563
+ }
8405
8564
  if bits, ok := unsignedIntegerBits(targetType); ok {
8406
8565
  return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint) +
8407
8566
  "(" + value + ", " + strconv.Itoa(bits) + ")", diagnostics
@@ -8415,14 +8574,39 @@ func (o *LoweringOwner) lowerConversionExpr(
8415
8574
  return value, diagnostics
8416
8575
  }
8417
8576
 
8577
+ // coerceWideHelperResult coerces a bigint result from the int64*/uint64* runtime
8578
+ // family back to resultType's representation. int64/uint64 results stay bigint.
8579
+ // Unsigned number-typed wide results (uint, uintptr) flow through $.uint(_, 64),
8580
+ // which keeps values above 2^53 as a runtime bigint so full 64-bit width
8581
+ // survives; a precision-losing Number() wrap would truncate values like
8582
+ // ^uint(0). Signed platform int coerces with Number (accepted precision loss
8583
+ // above 2^53, matching Model A's int->number mapping): $.uint on a signed value
8584
+ // would reinterpret its sign bit as magnitude.
8585
+ func coerceWideHelperResult(runtimeOwner *RuntimeContractOwner, resultType types.Type, call string) string {
8586
+ if isBigIntBackedType(resultType) {
8587
+ return call
8588
+ }
8589
+ if _, ok := unsignedIntegerBits(resultType); ok {
8590
+ return runtimeOwner.QualifiedHelper(RuntimeHelperUint) + "(" + call + ", 64)"
8591
+ }
8592
+ return "Number(" + call + ")"
8593
+ }
8594
+
8418
8595
  func (o *LoweringOwner) lowerWideIntegerBinaryExpr(ctx lowerFileContext, expr *ast.BinaryExpr, left string, right string) (string, bool) {
8419
- resultWide := isRuntimeWideIntegerType(ctx.semPkg.source.TypesInfo.TypeOf(expr))
8596
+ resultType := ctx.semPkg.source.TypesInfo.TypeOf(expr)
8597
+ resultWide := isRuntimeWideIntegerType(resultType)
8420
8598
  leftWide := isRuntimeWideIntegerType(ctx.semPkg.source.TypesInfo.TypeOf(expr.X))
8421
8599
  if !resultWide && !leftWide {
8422
8600
  return "", false
8423
8601
  }
8424
- signed := isFixedSignedWideIntegerType(ctx.semPkg.source.TypesInfo.TypeOf(expr)) ||
8602
+ signed := isFixedSignedWideIntegerType(resultType) ||
8425
8603
  isFixedSignedWideIntegerType(ctx.semPkg.source.TypesInfo.TypeOf(expr.X))
8604
+ wrap := func(call string) string {
8605
+ return coerceWideHelperResult(o.runtimeOwner, resultType, call)
8606
+ }
8607
+ helperCall := func(helper RuntimeHelper) string {
8608
+ return wrap(o.runtimeOwner.QualifiedHelper(helper) + "(" + left + ", " + right + ")")
8609
+ }
8426
8610
  switch expr.Op {
8427
8611
  case token.SHL, token.SHR:
8428
8612
  helper := RuntimeHelperUint64Shr
@@ -8436,27 +8620,27 @@ func (o *LoweringOwner) lowerWideIntegerBinaryExpr(ctx lowerFileContext, expr *a
8436
8620
  }
8437
8621
  }
8438
8622
  if _, ok := constantShiftAmount(ctx, expr.Y); !ok {
8439
- return o.runtimeOwner.QualifiedHelper(helper) + "(" + left + ", " + right + ")", true
8623
+ return helperCall(helper), true
8440
8624
  }
8441
8625
  amount, ok := constantShiftAmount(ctx, expr.Y)
8442
8626
  if ok && amount >= 32 && expr.Op == token.SHL && !signed {
8443
8627
  base := o.lowerWideShiftLeftOperand(ctx, expr.X, left)
8444
- return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint64Mul) +
8445
- "(" + base + ", " + shiftMultiplier(amount) + ")", true
8628
+ return wrap(o.runtimeOwner.QualifiedHelper(RuntimeHelperUint64Mul) +
8629
+ "(" + base + ", " + shiftMultiplier(amount) + ")"), true
8446
8630
  }
8447
- return o.runtimeOwner.QualifiedHelper(helper) + "(" + left + ", " + right + ")", true
8631
+ return helperCall(helper), true
8448
8632
  case token.MUL:
8449
- return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64Mul, RuntimeHelperInt64Mul)) + "(" + left + ", " + right + ")", true
8633
+ return helperCall(wideIntegerHelper(signed, RuntimeHelperUint64Mul, RuntimeHelperInt64Mul)), true
8450
8634
  case token.QUO:
8451
- return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64Div, RuntimeHelperInt64Div)) + "(" + left + ", " + right + ")", true
8635
+ return helperCall(wideIntegerHelper(signed, RuntimeHelperUint64Div, RuntimeHelperInt64Div)), true
8452
8636
  case token.REM:
8453
- return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64Mod, RuntimeHelperInt64Mod)) + "(" + left + ", " + right + ")", true
8637
+ return helperCall(wideIntegerHelper(signed, RuntimeHelperUint64Mod, RuntimeHelperInt64Mod)), true
8454
8638
  case token.ADD:
8455
- return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64Add, RuntimeHelperInt64Add)) + "(" + left + ", " + right + ")", true
8639
+ return helperCall(wideIntegerHelper(signed, RuntimeHelperUint64Add, RuntimeHelperInt64Add)), true
8456
8640
  case token.SUB:
8457
- return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64Sub, RuntimeHelperInt64Sub)) + "(" + left + ", " + right + ")", true
8641
+ return helperCall(wideIntegerHelper(signed, RuntimeHelperUint64Sub, RuntimeHelperInt64Sub)), true
8458
8642
  case token.AND:
8459
- return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64And, RuntimeHelperInt64And)) + "(" + left + ", " + right + ")", true
8643
+ return helperCall(wideIntegerHelper(signed, RuntimeHelperUint64And, RuntimeHelperInt64And)), true
8460
8644
  case token.XOR:
8461
8645
  if isZeroIntegerExpr(ctx, expr.Y) {
8462
8646
  return left, true
@@ -8464,15 +8648,15 @@ func (o *LoweringOwner) lowerWideIntegerBinaryExpr(ctx lowerFileContext, expr *a
8464
8648
  if isZeroIntegerExpr(ctx, expr.X) {
8465
8649
  return right, true
8466
8650
  }
8467
- return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64Xor, RuntimeHelperInt64Xor)) + "(" + left + ", " + right + ")", true
8651
+ return helperCall(wideIntegerHelper(signed, RuntimeHelperUint64Xor, RuntimeHelperInt64Xor)), true
8468
8652
  case token.OR:
8469
8653
  shift, ok := wideLeftShiftExpr(ctx, expr.X)
8470
8654
  if ok && !signed {
8471
8655
  if bits, ok := lowIntegerBits(ctx, expr.Y); ok && bits <= shift {
8472
- return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint64Add) + "(" + left + ", " + right + ")", true
8656
+ return helperCall(RuntimeHelperUint64Add), true
8473
8657
  }
8474
8658
  }
8475
- return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64Or, RuntimeHelperInt64Or)) + "(" + left + ", " + right + ")", true
8659
+ return helperCall(wideIntegerHelper(signed, RuntimeHelperUint64Or, RuntimeHelperInt64Or)), true
8476
8660
  default:
8477
8661
  return "", false
8478
8662
  }
@@ -8965,7 +9149,7 @@ func (o *LoweringOwner) packageVarAssignmentValue(
8965
9149
  return left + " & ~(" + right + ")", true
8966
9150
  }
8967
9151
  if helper, ok := wideIntegerAssignHelper(targetType, tok); ok {
8968
- return o.runtimeOwner.QualifiedHelper(helper) + "(" + left + ", " + right + ")", true
9152
+ return coerceWideHelperResult(o.runtimeOwner, targetType, o.runtimeOwner.QualifiedHelper(helper)+"("+left+", "+right+")"), true
8969
9153
  }
8970
9154
  if value, ok := integerQuotientAssignValueExpr(targetType, left, right, tok); ok {
8971
9155
  return value, true
@@ -9336,6 +9520,18 @@ func (o *LoweringOwner) lowerAssignmentTarget(
9336
9520
  return o.lowerIdent(ctx, typed, false), nil
9337
9521
  case *ast.StarExpr:
9338
9522
  return o.lowerPointerValueExpr(ctx, typed.X)
9523
+ case *ast.IndexExpr:
9524
+ // Assignment targets need an assignable JS reference (target[index]); the
9525
+ // read path wraps array/slice indexing in a bounds-checked helper, which
9526
+ // is not assignable. Map and string targets keep their own paths.
9527
+ targetType := ctx.semPkg.source.TypesInfo.TypeOf(typed.X)
9528
+ if isStringType(targetType) || isMapType(targetType) {
9529
+ return o.lowerExpr(ctx, expr)
9530
+ }
9531
+ target, targetDiagnostics := o.lowerExpr(ctx, typed.X)
9532
+ index, indexDiagnostics := o.lowerExpr(ctx, typed.Index)
9533
+ diagnostics := append(targetDiagnostics, indexDiagnostics...)
9534
+ return o.lowerIndexTarget(ctx, target, targetType) + "[" + o.lowerNumberIndexValue(ctx, typed.Index, index) + "]", diagnostics
9339
9535
  default:
9340
9536
  return o.lowerExpr(ctx, expr)
9341
9537
  }
@@ -9428,7 +9624,7 @@ func (o *LoweringOwner) lowerIndexAddressExpr(ctx lowerFileContext, expr *ast.In
9428
9624
  if isStringType(targetType) || isMapType(targetType) {
9429
9625
  return "undefined", append(diagnostics, loweringUnsupportedAt(ctx, expr, "expression", ctx.semPkg.pkgPath, "unsupported address expression"))
9430
9626
  }
9431
- return o.runtimeOwner.QualifiedHelper(RuntimeHelperIndexRef) + "(" + o.lowerIndexTarget(ctx, target, targetType) + ", " + index + ")", diagnostics
9627
+ return o.runtimeOwner.QualifiedHelper(RuntimeHelperIndexRef) + "(" + o.lowerIndexTarget(ctx, target, targetType) + ", " + o.lowerNumberIndexValue(ctx, expr.Index, index) + ")", diagnostics
9432
9628
  }
9433
9629
 
9434
9630
  func (o *LoweringOwner) lowerAddressEqualityExpr(
@@ -9506,7 +9702,7 @@ func (o *LoweringOwner) lowerIndexAddressIntegerExpr(
9506
9702
  return "", diagnostics, false
9507
9703
  }
9508
9704
  return o.runtimeOwner.QualifiedHelper(RuntimeHelperIndexAddress) +
9509
- "(" + o.lowerIndexTarget(ctx, target, targetType) + ", " + index + ")", diagnostics, true
9705
+ "(" + o.lowerIndexTarget(ctx, target, targetType) + ", " + o.lowerNumberIndexValue(ctx, indexExpr.Index, index) + ")", diagnostics, true
9510
9706
  }
9511
9707
 
9512
9708
  func (o *LoweringOwner) lowerIndexByteAddressIntegerExpr(
@@ -9530,7 +9726,7 @@ func (o *LoweringOwner) lowerIndexByteAddressIntegerExpr(
9530
9726
  }
9531
9727
  elementSize := goScriptElementByteSize(ctx, indexElementType(targetType))
9532
9728
  return o.runtimeOwner.QualifiedHelper(RuntimeHelperIndexByteAddress) +
9533
- "(" + o.lowerIndexTarget(ctx, target, targetType) + ", " + index + ", " + strconv.FormatInt(elementSize, 10) + ")", diagnostics, true
9729
+ "(" + o.lowerIndexTarget(ctx, target, targetType) + ", " + o.lowerNumberIndexValue(ctx, indexExpr.Index, index) + ", " + strconv.FormatInt(elementSize, 10) + ")", diagnostics, true
9534
9730
  }
9535
9731
 
9536
9732
  func (o *LoweringOwner) lowerPointerValueExpr(ctx lowerFileContext, expr ast.Expr) (string, []Diagnostic) {
@@ -10037,14 +10233,27 @@ func (o *LoweringOwner) lowerIndexExpr(ctx lowerFileContext, expr *ast.IndexExpr
10037
10233
  targetType := ctx.semPkg.source.TypesInfo.TypeOf(expr.X)
10038
10234
  switch {
10039
10235
  case isStringType(targetType):
10040
- return o.runtimeOwner.QualifiedHelper(RuntimeHelperIndexStringOrBytes) + "(" + target + ", " + index + ")", diagnostics
10236
+ return o.runtimeOwner.QualifiedHelper(RuntimeHelperIndexStringOrBytes) + "(" + target + ", " + o.lowerNumberIndexValue(ctx, expr.Index, index) + ")", diagnostics
10041
10237
  case isMapType(targetType):
10042
10238
  return o.lowerMapGetValue(ctx, expr, target, index), diagnostics
10043
10239
  default:
10044
- return o.lowerIndexTarget(ctx, target, targetType) + "[" + index + "]", diagnostics
10240
+ return o.runtimeOwner.QualifiedHelper(RuntimeHelperArrayIndex) + "(" + o.lowerIndexTarget(ctx, target, targetType) + ", " + o.lowerNumberIndexValue(ctx, expr.Index, index) + ")", diagnostics
10045
10241
  }
10046
10242
  }
10047
10243
 
10244
+ // lowerNumberIndexValue coerces an index or size expression to a JS number when
10245
+ // its Go type is bigint-backed (int64/uint64/uint/uintptr). Array indices, slice
10246
+ // bounds, string/byte offsets, and make/len sizes must be number, not bigint.
10247
+ func (o *LoweringOwner) lowerNumberIndexValue(ctx lowerFileContext, expr ast.Expr, value string) string {
10248
+ if expr == nil {
10249
+ return value
10250
+ }
10251
+ if isBigIntBackedType(ctx.semPkg.source.TypesInfo.TypeOf(expr)) {
10252
+ return "Number(" + value + ")"
10253
+ }
10254
+ return value
10255
+ }
10256
+
10048
10257
  func (o *LoweringOwner) lowerGenericFunctionValue(
10049
10258
  ctx lowerFileContext,
10050
10259
  callee ast.Expr,
@@ -10103,6 +10312,9 @@ func (o *LoweringOwner) lowerSliceExpr(ctx lowerFileContext, expr *ast.SliceExpr
10103
10312
  low, lowDiagnostics := o.lowerOptionalExpr(ctx, expr.Low)
10104
10313
  high, highDiagnostics := o.lowerOptionalExpr(ctx, expr.High)
10105
10314
  max, maxDiagnostics := o.lowerOptionalExpr(ctx, expr.Max)
10315
+ low = o.lowerNumberIndexValue(ctx, expr.Low, low)
10316
+ high = o.lowerNumberIndexValue(ctx, expr.High, high)
10317
+ max = o.lowerNumberIndexValue(ctx, expr.Max, max)
10106
10318
  diagnostics = append(diagnostics, lowDiagnostics...)
10107
10319
  diagnostics = append(diagnostics, highDiagnostics...)
10108
10320
  diagnostics = append(diagnostics, maxDiagnostics...)
@@ -10530,6 +10742,9 @@ func (o *LoweringOwner) lowerNumericConstantExprForTarget(ctx lowerFileContext,
10530
10742
  }
10531
10743
  tv, ok := ctx.semPkg.source.TypesInfo.Types[expr]
10532
10744
  if ok && tv.Value != nil {
10745
+ if isBigIntBackedType(targetType) && tv.Value.Kind() == constant.Int {
10746
+ return tv.Value.ExactString() + "n", true
10747
+ }
10533
10748
  if bits, ok := unsignedIntegerBits(targetType); ok && bits >= 64 {
10534
10749
  if value, ok := lowerWideIntegerConstantValue(tv.Value); ok {
10535
10750
  return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint) + "(" +
@@ -10616,6 +10831,16 @@ func (o *LoweringOwner) lowerValueForTargetTypes(
10616
10831
  return o.lowerStructClone(value)
10617
10832
  }
10618
10833
  if isIntegerType(targetType) && isIntegerType(sourceType) {
10834
+ if isBigIntBackedType(targetType) {
10835
+ if isBigIntBackedType(sourceType) {
10836
+ return value
10837
+ }
10838
+ helper := RuntimeHelperInt64
10839
+ if _, ok := unsignedIntegerBits(targetType); ok {
10840
+ helper = RuntimeHelperUint64
10841
+ }
10842
+ return o.runtimeOwner.QualifiedHelper(helper) + "(" + value + ")"
10843
+ }
10619
10844
  if isBasicFixedWideIntegerType(targetType) {
10620
10845
  if bits, ok := unsignedIntegerBits(targetType); ok {
10621
10846
  return o.runtimeOwner.QualifiedHelper(RuntimeHelperUint) +
@@ -10761,6 +10986,10 @@ func (o *LoweringOwner) lowerZeroValueExprFor(ctx lowerFileContext, typ types.Ty
10761
10986
  return "\"\""
10762
10987
  }
10763
10988
  if typed.Info()&types.IsNumeric != 0 {
10989
+ switch typed.Kind() {
10990
+ case types.Int64, types.Uint64:
10991
+ return "0n"
10992
+ }
10764
10993
  return "0"
10765
10994
  }
10766
10995
  return "undefined"
@@ -10813,6 +11042,13 @@ func (o *LoweringOwner) runtimeTypeAssertInfoExpr(ctx lowerFileContext, typ type
10813
11042
  return o.runtimeTypeAssertInfoExprWithSeen(ctx, typ, make(map[types.Type]bool))
10814
11043
  }
10815
11044
 
11045
+ // runtimeTypeAssertInfoExprWithSeen renders the runtime type descriptor for a
11046
+ // type-assertion or type-switch target. It mirrors runtimeTypeInfoExprWithSeen
11047
+ // but threads ctx so a type parameter in scope resolves to its runtime
11048
+ // __typeArgs entry. Keep the two structurally in sync: the named-type checks,
11049
+ // the underlying switch arms, and the leaf cases must stay parallel; the only
11050
+ // intended differences are the type-parameter prefix and the ctx-threaded
11051
+ // recursion.
10816
11052
  func (o *LoweringOwner) runtimeTypeAssertInfoExprWithSeen(ctx lowerFileContext, typ types.Type, seen map[types.Type]bool) string {
10817
11053
  typeParam, ok := types.Unalias(typ).(*types.TypeParam)
10818
11054
  if ok && typeParamInScope(ctx, typeParam) {
@@ -10832,12 +11068,12 @@ func (o *LoweringOwner) runtimeTypeAssertInfoExprWithSeen(ctx lowerFileContext,
10832
11068
  seen[typeKey] = true
10833
11069
  defer delete(seen, typeKey)
10834
11070
  }
10835
- if named := namedFunctionType(typ); named != nil {
10836
- return o.runtimeFunctionTypeAssertInfoWithSeen(ctx, named.Underlying().(*types.Signature), runtimeNamedTypeName(named), seen)
10837
- }
10838
11071
  if named := namedStructType(typ); named != nil {
10839
11072
  return strconv.Quote(runtimeNamedTypeName(named))
10840
11073
  }
11074
+ if named := namedFunctionType(typ); named != nil {
11075
+ return o.runtimeFunctionTypeAssertInfoWithSeen(ctx, named.Underlying().(*types.Signature), runtimeNamedTypeName(named), seen)
11076
+ }
10841
11077
  if named := namedNonStructType(typ); named != nil {
10842
11078
  if basic, ok := types.Unalias(named.Underlying()).(*types.Basic); ok {
10843
11079
  return runtimeBasicTypeInfoExpr(typeKind, basic, runtimeNamedTypeName(named))
@@ -10845,6 +11081,8 @@ func (o *LoweringOwner) runtimeTypeAssertInfoExprWithSeen(ctx lowerFileContext,
10845
11081
  return strconv.Quote(runtimeNamedTypeName(named))
10846
11082
  }
10847
11083
  switch typed := types.Unalias(typ).Underlying().(type) {
11084
+ case *types.Basic:
11085
+ return runtimeBasicTypeInfoExpr(typeKind, typed, "")
10848
11086
  case *types.Pointer:
10849
11087
  return "{ kind: " + typeKind + ".Pointer, elemType: " + o.runtimeTypeAssertInfoExprWithSeen(ctx, typed.Elem(), seen) + " }"
10850
11088
  case *types.Struct:
@@ -10867,6 +11105,8 @@ func (o *LoweringOwner) runtimeTypeAssertInfoExprWithSeen(ctx lowerFileContext,
10867
11105
  }
10868
11106
  }
10869
11107
 
11108
+ // runtimeTypeInfoExprWithSeen renders the runtime type descriptor for typ. Keep
11109
+ // it structurally in sync with runtimeTypeAssertInfoExprWithSeen.
10870
11110
  func (o *LoweringOwner) runtimeTypeInfoExprWithSeen(typ types.Type, seen map[types.Type]bool) string {
10871
11111
  typeKind := o.runtimeOwner.QualifiedHelper(RuntimeHelperTypeKind)
10872
11112
  if typ == nil {
@@ -11353,6 +11593,10 @@ func (o *LoweringOwner) tsTypeFor(ctx lowerFileContext, typ types.Type) string {
11353
11593
  return "string"
11354
11594
  }
11355
11595
  if typed.Info()&types.IsNumeric != 0 {
11596
+ switch typed.Kind() {
11597
+ case types.Int64, types.Uint64:
11598
+ return "bigint"
11599
+ }
11356
11600
  return "number"
11357
11601
  }
11358
11602
  return "unknown"
@@ -11517,6 +11761,10 @@ func zeroValueExpr(typ types.Type) string {
11517
11761
  return "\"\""
11518
11762
  }
11519
11763
  if typed.Info()&types.IsNumeric != 0 {
11764
+ switch typed.Kind() {
11765
+ case types.Int64, types.Uint64:
11766
+ return "0n"
11767
+ }
11520
11768
  return "0"
11521
11769
  }
11522
11770
  return "undefined"
@@ -11836,12 +12084,28 @@ func isChannelType(typ types.Type) bool {
11836
12084
  return ok
11837
12085
  }
11838
12086
 
11839
- func isComplexType(typ types.Type) bool {
12087
+ // basicKind reports whether typ's underlying type is a basic type of the given
12088
+ // kind. It is nil-safe and returns false for a nil type.
12089
+ func basicKind(typ types.Type, kind types.BasicKind) bool {
11840
12090
  if typ == nil {
11841
12091
  return false
11842
12092
  }
11843
12093
  basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
11844
- return ok && basic.Info()&types.IsComplex != 0
12094
+ return ok && basic.Kind() == kind
12095
+ }
12096
+
12097
+ // basicInfo reports whether typ's underlying type is a basic type whose info
12098
+ // flags include the given flag. It is nil-safe and returns false for a nil type.
12099
+ func basicInfo(typ types.Type, flag types.BasicInfo) bool {
12100
+ if typ == nil {
12101
+ return false
12102
+ }
12103
+ basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
12104
+ return ok && basic.Info()&flag != 0
12105
+ }
12106
+
12107
+ func isComplexType(typ types.Type) bool {
12108
+ return basicInfo(typ, types.IsComplex)
11845
12109
  }
11846
12110
 
11847
12111
  func isPointerType(typ types.Type) bool {
@@ -11853,19 +12117,11 @@ func isPointerType(typ types.Type) bool {
11853
12117
  }
11854
12118
 
11855
12119
  func isUnsafePointerType(typ types.Type) bool {
11856
- if typ == nil {
11857
- return false
11858
- }
11859
- basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
11860
- return ok && basic.Kind() == types.UnsafePointer
12120
+ return basicKind(typ, types.UnsafePointer)
11861
12121
  }
11862
12122
 
11863
12123
  func isUintptrType(typ types.Type) bool {
11864
- if typ == nil {
11865
- return false
11866
- }
11867
- basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
11868
- return ok && basic.Kind() == types.Uintptr
12124
+ return basicKind(typ, types.Uintptr)
11869
12125
  }
11870
12126
 
11871
12127
  func channelDirectionString(dir types.ChanDir) string {
@@ -11895,35 +12151,19 @@ func unwrapParenExpr(expr ast.Expr) ast.Expr {
11895
12151
  }
11896
12152
 
11897
12153
  func isStringType(typ types.Type) bool {
11898
- if typ == nil {
11899
- return false
11900
- }
11901
- basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
11902
- return ok && basic.Info()&types.IsString != 0
12154
+ return basicInfo(typ, types.IsString)
11903
12155
  }
11904
12156
 
11905
12157
  func isNumericType(typ types.Type) bool {
11906
- if typ == nil {
11907
- return false
11908
- }
11909
- basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
11910
- return ok && basic.Info()&types.IsNumeric != 0
12158
+ return basicInfo(typ, types.IsNumeric)
11911
12159
  }
11912
12160
 
11913
12161
  func isIntegerType(typ types.Type) bool {
11914
- if typ == nil {
11915
- return false
11916
- }
11917
- basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
11918
- return ok && basic.Info()&types.IsInteger != 0
12162
+ return basicInfo(typ, types.IsInteger)
11919
12163
  }
11920
12164
 
11921
12165
  func isFloatType(typ types.Type) bool {
11922
- if typ == nil {
11923
- return false
11924
- }
11925
- basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
11926
- return ok && basic.Info()&types.IsFloat != 0
12166
+ return basicInfo(typ, types.IsFloat)
11927
12167
  }
11928
12168
 
11929
12169
  func unsignedIntegerBits(typ types.Type) (int, bool) {
@@ -11994,12 +12234,30 @@ func isFixedWideIntegerType(typ types.Type) bool {
11994
12234
  }
11995
12235
  }
11996
12236
 
11997
- func isFixedSignedWideIntegerType(typ types.Type) bool {
11998
- if typ == nil {
12237
+ // isBigIntBackedType reports whether typ lowers to a TypeScript bigint. Only the
12238
+ // fixed 64-bit Go integer types int64 and uint64 are represented as bigint to
12239
+ // preserve full-width precision and Go overflow semantics. The platform-width
12240
+ // uint and uintptr, plain int, and the narrower fixed-width integers stay number
12241
+ // so they remain usable as array indices; uint/uintptr arithmetic still routes
12242
+ // through the int64/uint64 runtime helpers and the result flows through
12243
+ // coerceWideHelperResult, which keeps values above 2^53 as a runtime bigint to
12244
+ // preserve full 64-bit width, matching design/SPEC_DIFFERENCES.md which maps
12245
+ // int64/uint64 to bigint and uint/uintptr to the number representation.
12246
+ func isBigIntBackedType(typ types.Type) bool {
12247
+ basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
12248
+ if !ok {
12249
+ return false
12250
+ }
12251
+ switch basic.Kind() {
12252
+ case types.Int64, types.Uint64:
12253
+ return true
12254
+ default:
11999
12255
  return false
12000
12256
  }
12001
- basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
12002
- return ok && basic.Kind() == types.Int64
12257
+ }
12258
+
12259
+ func isFixedSignedWideIntegerType(typ types.Type) bool {
12260
+ return basicKind(typ, types.Int64)
12003
12261
  }
12004
12262
 
12005
12263
  func isRuntimeWideIntegerType(typ types.Type) bool {
@@ -12021,13 +12279,11 @@ func isByteSliceType(typ types.Type) bool {
12021
12279
  }
12022
12280
 
12023
12281
  func isRuneType(typ types.Type) bool {
12024
- basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
12025
- return ok && basic.Kind() == types.Int32
12282
+ return basicKind(typ, types.Int32)
12026
12283
  }
12027
12284
 
12028
12285
  func isByteType(typ types.Type) bool {
12029
- basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
12030
- return ok && basic.Kind() == types.Uint8
12286
+ return basicKind(typ, types.Uint8)
12031
12287
  }
12032
12288
 
12033
12289
  func sliceTypeHint(typ types.Type) string {