goscript 0.1.3 → 0.2.0

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 (330) hide show
  1. package/README.md +5 -2
  2. package/cmd/go_js_wasm_exec/main.go +201 -0
  3. package/cmd/go_js_wasm_exec/main_test.go +83 -0
  4. package/cmd/goscript/{cmd_compile.go → cmd-compile.go} +35 -8
  5. package/cmd/goscript/cmd-test.go +14 -0
  6. package/cmd/goscript/cmd-test_test.go +1 -1
  7. package/cmd/goscript/cmd_compile_test.go +105 -6
  8. package/compiler/build-flags.go +9 -10
  9. package/compiler/compile-request.go +12 -9
  10. package/compiler/compliance_test.go +0 -1
  11. package/compiler/config.go +2 -0
  12. package/compiler/gotest/request.go +28 -0
  13. package/compiler/gotest/runner.go +353 -27
  14. package/compiler/gotest/runner_test.go +400 -1
  15. package/compiler/gotest/testdata/browserapi/browserapi_test.go +20 -0
  16. package/compiler/gotest/testdata/browserapi/go.mod +3 -0
  17. package/compiler/lowered-program.go +24 -17
  18. package/compiler/lowering.go +988 -263
  19. package/compiler/lowering_bench_test.go +364 -0
  20. package/compiler/override-facts.go +15 -0
  21. package/compiler/override-parity-verifier.go +450 -0
  22. package/compiler/override-parity.go +122 -0
  23. package/compiler/override-registry_test.go +559 -0
  24. package/compiler/package-graph.go +61 -4
  25. package/compiler/package-graph_test.go +30 -0
  26. package/compiler/protobuf-ts-binding.go +514 -0
  27. package/compiler/protobuf-ts-binding_test.go +172 -0
  28. package/compiler/semantic-model-types.go +17 -4
  29. package/compiler/semantic-model.go +709 -72
  30. package/compiler/semantic-model_test.go +219 -0
  31. package/compiler/service.go +20 -1
  32. package/compiler/skeleton_test.go +1008 -20
  33. package/compiler/typescript-emitter.go +147 -15
  34. package/dist/gs/builtin/builtin.d.ts +2 -2
  35. package/dist/gs/builtin/builtin.js +20 -0
  36. package/dist/gs/builtin/builtin.js.map +1 -1
  37. package/dist/gs/builtin/slice.d.ts +2 -1
  38. package/dist/gs/builtin/slice.js +34 -4
  39. package/dist/gs/builtin/slice.js.map +1 -1
  40. package/dist/gs/builtin/type.d.ts +14 -6
  41. package/dist/gs/builtin/type.js +224 -64
  42. package/dist/gs/builtin/type.js.map +1 -1
  43. package/dist/gs/builtin/varRef.d.ts +11 -0
  44. package/dist/gs/builtin/varRef.js +57 -2
  45. package/dist/gs/builtin/varRef.js.map +1 -1
  46. package/dist/gs/bytes/buffer.gs.js +1 -1
  47. package/dist/gs/bytes/buffer.gs.js.map +1 -1
  48. package/dist/gs/bytes/reader.gs.js +1 -1
  49. package/dist/gs/bytes/reader.gs.js.map +1 -1
  50. package/dist/gs/compress/zlib/index.d.ts +13 -6
  51. package/dist/gs/compress/zlib/index.js +131 -35
  52. package/dist/gs/compress/zlib/index.js.map +1 -1
  53. package/dist/gs/crypto/sha1/index.js +2 -5
  54. package/dist/gs/crypto/sha1/index.js.map +1 -1
  55. package/dist/gs/crypto/sha256/index.js +2 -5
  56. package/dist/gs/crypto/sha256/index.js.map +1 -1
  57. package/dist/gs/crypto/sha512/index.js +2 -5
  58. package/dist/gs/crypto/sha512/index.js.map +1 -1
  59. package/dist/gs/embed/index.d.ts +6 -0
  60. package/dist/gs/embed/index.js +210 -5
  61. package/dist/gs/embed/index.js.map +1 -1
  62. package/dist/gs/encoding/json/index.d.ts +114 -0
  63. package/dist/gs/encoding/json/index.js +544 -36
  64. package/dist/gs/encoding/json/index.js.map +1 -1
  65. package/dist/gs/fmt/fmt.d.ts +3 -3
  66. package/dist/gs/fmt/fmt.js +29 -16
  67. package/dist/gs/fmt/fmt.js.map +1 -1
  68. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +100 -0
  69. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +564 -0
  70. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  71. package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.d.ts +45 -0
  72. package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js +229 -0
  73. package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js.map +1 -0
  74. package/dist/gs/github.com/pkg/errors/errors.js +54 -30
  75. package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
  76. package/dist/gs/go/scanner/index.d.ts +2 -0
  77. package/dist/gs/go/scanner/index.js +29 -5
  78. package/dist/gs/go/scanner/index.js.map +1 -1
  79. package/dist/gs/go/token/index.js +22 -6
  80. package/dist/gs/go/token/index.js.map +1 -1
  81. package/dist/gs/hash/index.d.ts +6 -0
  82. package/dist/gs/hash/index.js +20 -0
  83. package/dist/gs/hash/index.js.map +1 -1
  84. package/dist/gs/internal/goarch/index.d.ts +43 -3
  85. package/dist/gs/internal/goarch/index.js +42 -10
  86. package/dist/gs/internal/goarch/index.js.map +1 -1
  87. package/dist/gs/io/fs/fs.js +26 -14
  88. package/dist/gs/io/fs/fs.js.map +1 -1
  89. package/dist/gs/io/fs/readdir.js +8 -4
  90. package/dist/gs/io/fs/readdir.js.map +1 -1
  91. package/dist/gs/io/fs/sub.js +8 -1
  92. package/dist/gs/io/fs/sub.js.map +1 -1
  93. package/dist/gs/io/io.d.ts +12 -6
  94. package/dist/gs/io/io.js +87 -42
  95. package/dist/gs/io/io.js.map +1 -1
  96. package/dist/gs/math/bits/index.d.ts +31 -5
  97. package/dist/gs/math/bits/index.js +29 -28
  98. package/dist/gs/math/bits/index.js.map +1 -1
  99. package/dist/gs/mime/index.d.ts +16 -0
  100. package/dist/gs/mime/index.js +315 -6
  101. package/dist/gs/mime/index.js.map +1 -1
  102. package/dist/gs/net/http/httptest/index.d.ts +12 -0
  103. package/dist/gs/net/http/httptest/index.js +85 -6
  104. package/dist/gs/net/http/httptest/index.js.map +1 -1
  105. package/dist/gs/net/http/index.d.ts +303 -6
  106. package/dist/gs/net/http/index.js +1615 -58
  107. package/dist/gs/net/http/index.js.map +1 -1
  108. package/dist/gs/os/dir_unix.gs.js +1 -1
  109. package/dist/gs/os/dir_unix.gs.js.map +1 -1
  110. package/dist/gs/os/error.gs.js +1 -1
  111. package/dist/gs/os/error.gs.js.map +1 -1
  112. package/dist/gs/os/exec.gs.d.ts +1 -0
  113. package/dist/gs/os/exec.gs.js +4 -8
  114. package/dist/gs/os/exec.gs.js.map +1 -1
  115. package/dist/gs/os/exec_posix.gs.js +1 -1
  116. package/dist/gs/os/exec_posix.gs.js.map +1 -1
  117. package/dist/gs/os/index.d.ts +1 -1
  118. package/dist/gs/os/index.js +1 -1
  119. package/dist/gs/os/index.js.map +1 -1
  120. package/dist/gs/os/proc.gs.d.ts +4 -0
  121. package/dist/gs/os/proc.gs.js +12 -6
  122. package/dist/gs/os/proc.gs.js.map +1 -1
  123. package/dist/gs/os/root_js.gs.js +1 -1
  124. package/dist/gs/os/root_js.gs.js.map +1 -1
  125. package/dist/gs/os/types.gs.js +1 -1
  126. package/dist/gs/os/types.gs.js.map +1 -1
  127. package/dist/gs/os/types_js.gs.d.ts +6 -2
  128. package/dist/gs/os/types_js.gs.js +170 -9
  129. package/dist/gs/os/types_js.gs.js.map +1 -1
  130. package/dist/gs/os/types_unix.gs.js +1 -1
  131. package/dist/gs/os/types_unix.gs.js.map +1 -1
  132. package/dist/gs/path/path.js +11 -7
  133. package/dist/gs/path/path.js.map +1 -1
  134. package/dist/gs/reflect/index.d.ts +5 -4
  135. package/dist/gs/reflect/index.js +4 -3
  136. package/dist/gs/reflect/index.js.map +1 -1
  137. package/dist/gs/reflect/map.js +15 -0
  138. package/dist/gs/reflect/map.js.map +1 -1
  139. package/dist/gs/reflect/type.d.ts +26 -6
  140. package/dist/gs/reflect/type.js +1498 -279
  141. package/dist/gs/reflect/type.js.map +1 -1
  142. package/dist/gs/reflect/types.d.ts +14 -6
  143. package/dist/gs/reflect/types.js +35 -1
  144. package/dist/gs/reflect/types.js.map +1 -1
  145. package/dist/gs/reflect/value.d.ts +1 -0
  146. package/dist/gs/reflect/value.js +83 -41
  147. package/dist/gs/reflect/value.js.map +1 -1
  148. package/dist/gs/reflect/visiblefields.js +4 -140
  149. package/dist/gs/reflect/visiblefields.js.map +1 -1
  150. package/dist/gs/runtime/pprof/index.d.ts +8 -2
  151. package/dist/gs/runtime/pprof/index.js +50 -30
  152. package/dist/gs/runtime/pprof/index.js.map +1 -1
  153. package/dist/gs/runtime/runtime.js +5 -4
  154. package/dist/gs/runtime/runtime.js.map +1 -1
  155. package/dist/gs/runtime/trace/index.js +5 -19
  156. package/dist/gs/runtime/trace/index.js.map +1 -1
  157. package/dist/gs/strconv/atoi.gs.js +1 -1
  158. package/dist/gs/strconv/atoi.gs.js.map +1 -1
  159. package/dist/gs/strconv/complex.gs.d.ts +3 -0
  160. package/dist/gs/strconv/complex.gs.js +148 -0
  161. package/dist/gs/strconv/complex.gs.js.map +1 -0
  162. package/dist/gs/strconv/index.d.ts +1 -0
  163. package/dist/gs/strconv/index.js +1 -0
  164. package/dist/gs/strconv/index.js.map +1 -1
  165. package/dist/gs/strings/builder.js +1 -1
  166. package/dist/gs/strings/reader.d.ts +1 -1
  167. package/dist/gs/strings/reader.js +11 -7
  168. package/dist/gs/strings/reader.js.map +1 -1
  169. package/dist/gs/strings/replace.js +15 -7
  170. package/dist/gs/strings/replace.js.map +1 -1
  171. package/dist/gs/strings/strings.d.ts +5 -0
  172. package/dist/gs/strings/strings.js +57 -5
  173. package/dist/gs/strings/strings.js.map +1 -1
  174. package/dist/gs/sync/atomic/type.gs.js +9 -9
  175. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  176. package/dist/gs/sync/atomic/value.gs.js +2 -2
  177. package/dist/gs/sync/atomic/value.gs.js.map +1 -1
  178. package/dist/gs/sync/sync.d.ts +2 -1
  179. package/dist/gs/sync/sync.js +37 -16
  180. package/dist/gs/sync/sync.js.map +1 -1
  181. package/dist/gs/syscall/env.js +22 -14
  182. package/dist/gs/syscall/env.js.map +1 -1
  183. package/dist/gs/syscall/js/index.js +9 -0
  184. package/dist/gs/syscall/js/index.js.map +1 -1
  185. package/dist/gs/testing/testing.js +59 -15
  186. package/dist/gs/testing/testing.js.map +1 -1
  187. package/dist/gs/time/time.d.ts +24 -1
  188. package/dist/gs/time/time.js +43 -3
  189. package/dist/gs/time/time.js.map +1 -1
  190. package/dist/gs/unique/index.js +7 -1
  191. package/dist/gs/unique/index.js.map +1 -1
  192. package/go.mod +3 -3
  193. package/go.sum +16 -0
  194. package/gs/builtin/builtin.ts +25 -2
  195. package/gs/builtin/runtime-contract.test.ts +260 -18
  196. package/gs/builtin/slice.ts +51 -4
  197. package/gs/builtin/type.ts +310 -63
  198. package/gs/builtin/varRef.ts +85 -2
  199. package/gs/bytes/buffer.gs.ts +1 -1
  200. package/gs/bytes/reader.gs.ts +1 -1
  201. package/gs/compress/zlib/index.test.ts +159 -1
  202. package/gs/compress/zlib/index.ts +164 -37
  203. package/gs/compress/zlib/meta.json +4 -1
  204. package/gs/compress/zlib/parity.json +51 -0
  205. package/gs/crypto/sha1/index.test.ts +19 -2
  206. package/gs/crypto/sha1/index.ts +3 -6
  207. package/gs/crypto/sha256/index.test.ts +14 -2
  208. package/gs/crypto/sha256/index.ts +3 -6
  209. package/gs/crypto/sha512/index.test.ts +17 -2
  210. package/gs/crypto/sha512/index.ts +3 -6
  211. package/gs/embed/index.test.ts +87 -0
  212. package/gs/embed/index.ts +229 -5
  213. package/gs/encoding/json/index.test.ts +360 -6
  214. package/gs/encoding/json/index.ts +679 -38
  215. package/gs/encoding/json/parity.json +81 -0
  216. package/gs/fmt/fmt.test.ts +41 -3
  217. package/gs/fmt/fmt.ts +40 -17
  218. package/gs/fmt/meta.json +6 -1
  219. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +211 -3
  220. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +857 -1
  221. package/gs/github.com/go-git/go-billy/v6/osfs/index.test.ts +110 -0
  222. package/gs/github.com/go-git/go-billy/v6/osfs/index.ts +280 -0
  223. package/gs/github.com/go-git/go-billy/v6/osfs/meta.json +8 -0
  224. package/gs/github.com/pkg/errors/errors.ts +54 -30
  225. package/gs/go/scanner/index.test.ts +39 -56
  226. package/gs/go/scanner/index.ts +33 -5
  227. package/gs/go/scanner/parity.json +27 -0
  228. package/gs/go/token/index.ts +22 -6
  229. package/gs/hash/index.test.ts +20 -33
  230. package/gs/hash/index.ts +28 -0
  231. package/gs/hash/parity.json +21 -0
  232. package/gs/internal/goarch/index.test.ts +32 -0
  233. package/gs/internal/goarch/index.ts +45 -13
  234. package/gs/internal/goarch/parity.json +144 -0
  235. package/gs/io/fs/fs.ts +26 -14
  236. package/gs/io/fs/readdir.test.ts +38 -0
  237. package/gs/io/fs/readdir.ts +8 -4
  238. package/gs/io/fs/sub.ts +8 -1
  239. package/gs/io/io.test.ts +77 -6
  240. package/gs/io/io.ts +115 -52
  241. package/gs/io/meta.json +7 -1
  242. package/gs/io/parity.json +162 -0
  243. package/gs/math/bits/index.test.ts +14 -1
  244. package/gs/math/bits/index.ts +75 -32
  245. package/gs/math/bits/parity.json +156 -0
  246. package/gs/mime/index.test.ts +90 -0
  247. package/gs/mime/index.ts +369 -6
  248. package/gs/mime/parity.json +36 -0
  249. package/gs/net/http/httptest/index.test.ts +98 -2
  250. package/gs/net/http/httptest/index.ts +101 -6
  251. package/gs/net/http/httptest/parity.json +15 -0
  252. package/gs/net/http/index.test.ts +797 -12
  253. package/gs/net/http/index.ts +1874 -136
  254. package/gs/net/http/meta.json +16 -1
  255. package/gs/net/http/parity.json +193 -0
  256. package/gs/os/dir_unix.gs.ts +1 -1
  257. package/gs/os/error.gs.ts +1 -1
  258. package/gs/os/exec.gs.ts +4 -8
  259. package/gs/os/exec_posix.gs.ts +1 -1
  260. package/gs/os/file_unix_js.test.ts +52 -0
  261. package/gs/os/index.test.ts +9 -0
  262. package/gs/os/index.ts +1 -0
  263. package/gs/os/meta.json +4 -0
  264. package/gs/os/parity.json +9 -0
  265. package/gs/os/proc.gs.ts +18 -5
  266. package/gs/os/proc.test.ts +26 -0
  267. package/gs/os/readdir.test.ts +56 -0
  268. package/gs/os/root_js.gs.ts +1 -1
  269. package/gs/os/types.gs.ts +1 -1
  270. package/gs/os/types_js.gs.ts +170 -9
  271. package/gs/os/types_unix.gs.ts +1 -1
  272. package/gs/path/path.ts +11 -7
  273. package/gs/reflect/deepequal.test.ts +10 -1
  274. package/gs/reflect/field.test.ts +37 -15
  275. package/gs/reflect/function-types.test.ts +518 -22
  276. package/gs/reflect/index.ts +8 -6
  277. package/gs/reflect/map.ts +20 -0
  278. package/gs/reflect/meta.json +6 -4
  279. package/gs/reflect/parity.json +234 -0
  280. package/gs/reflect/sliceat.test.ts +156 -0
  281. package/gs/reflect/structof.test.ts +401 -0
  282. package/gs/reflect/type.ts +1980 -365
  283. package/gs/reflect/typefor.test.ts +540 -10
  284. package/gs/reflect/types.ts +43 -18
  285. package/gs/reflect/value.ts +105 -45
  286. package/gs/reflect/visiblefields.ts +5 -168
  287. package/gs/runtime/parity.json +24 -0
  288. package/gs/runtime/pprof/index.test.ts +29 -7
  289. package/gs/runtime/pprof/index.ts +56 -30
  290. package/gs/runtime/pprof/parity.json +27 -0
  291. package/gs/runtime/runtime.test.ts +3 -1
  292. package/gs/runtime/runtime.ts +4 -3
  293. package/gs/runtime/trace/index.test.ts +5 -3
  294. package/gs/runtime/trace/index.ts +8 -20
  295. package/gs/runtime/trace/parity.json +36 -0
  296. package/gs/strconv/atoi.gs.ts +1 -1
  297. package/gs/strconv/complex.gs.ts +174 -0
  298. package/gs/strconv/complex.test.ts +65 -0
  299. package/gs/strconv/index.ts +1 -0
  300. package/gs/strconv/parity.json +120 -0
  301. package/gs/strings/builder.ts +1 -1
  302. package/gs/strings/meta.json +5 -2
  303. package/gs/strings/parity.json +186 -0
  304. package/gs/strings/reader.test.ts +2 -2
  305. package/gs/strings/reader.ts +11 -7
  306. package/gs/strings/replace.ts +15 -7
  307. package/gs/strings/strings.test.ts +22 -2
  308. package/gs/strings/strings.ts +64 -6
  309. package/gs/sync/atomic/type.gs.ts +9 -9
  310. package/gs/sync/atomic/value.gs.ts +2 -2
  311. package/gs/sync/meta.json +1 -0
  312. package/gs/sync/sync.test.ts +41 -1
  313. package/gs/sync/sync.ts +41 -16
  314. package/gs/syscall/env.ts +29 -14
  315. package/gs/syscall/js/index.test.ts +18 -0
  316. package/gs/syscall/js/index.ts +12 -0
  317. package/gs/testing/testing.test.ts +99 -3
  318. package/gs/testing/testing.ts +95 -24
  319. package/gs/time/parity.json +225 -0
  320. package/gs/time/time.test.ts +20 -2
  321. package/gs/time/time.ts +49 -7
  322. package/gs/unique/index.ts +7 -1
  323. package/package.json +4 -2
  324. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +0 -217
  325. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +0 -814
  326. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +0 -1
  327. package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +0 -31
  328. package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +0 -1233
  329. package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +0 -46
  330. /package/compiler/{wasm_api.go → wasm-api.go} +0 -0
@@ -6,7 +6,6 @@ import (
6
6
  "go/ast"
7
7
  "go/token"
8
8
  "go/types"
9
- "maps"
10
9
  "slices"
11
10
  "strconv"
12
11
  "strings"
@@ -75,6 +74,7 @@ func (o *SemanticModelOwner) Build(ctx context.Context, graph *PackageGraph) (*S
75
74
  return model, diagnostics
76
75
  }
77
76
 
77
+ model.functionCallers = semanticFunctionCallers(model)
78
78
  diagnostics = append(diagnostics, o.propagateFunctionAsync(ctx, model)...)
79
79
  if diagnosticsHaveErrors(diagnostics) {
80
80
  return model, diagnostics
@@ -83,17 +83,31 @@ func (o *SemanticModelOwner) Build(ctx context.Context, graph *PackageGraph) (*S
83
83
  if diagnosticsHaveErrors(diagnostics) {
84
84
  return model, diagnostics
85
85
  }
86
- interfaceGraph, interfaceDiagnostics := o.resolveInterfaceImplementationGraph(ctx, model)
86
+ methodSets, methodSetDiagnostics := o.resolveImplementationMethodSets(ctx, model)
87
+ diagnostics = append(diagnostics, methodSetDiagnostics...)
88
+ if diagnosticsHaveErrors(diagnostics) {
89
+ return model, diagnostics
90
+ }
91
+ interfaceGraph, interfaceDiagnostics := o.resolveInterfaceImplementationGraph(ctx, model, methodSets)
87
92
  diagnostics = append(diagnostics, interfaceDiagnostics...)
88
93
  if diagnosticsHaveErrors(diagnostics) {
89
94
  return model, diagnostics
90
95
  }
96
+ anonymousInterfaceGraph, anonymousInterfaceDiagnostics := o.resolveAnonymousInterfaceImplementationGraph(ctx, model, methodSets)
97
+ diagnostics = append(diagnostics, anonymousInterfaceDiagnostics...)
98
+ if diagnosticsHaveErrors(diagnostics) {
99
+ return model, diagnostics
100
+ }
91
101
  for {
92
102
  asyncCount := semanticAsyncFunctionCount(model)
93
103
  diagnostics = append(diagnostics, o.applyInterfaceAsyncMethods(ctx, model, interfaceGraph)...)
94
104
  if diagnosticsHaveErrors(diagnostics) {
95
105
  return model, diagnostics
96
106
  }
107
+ diagnostics = append(diagnostics, o.applyAnonymousInterfaceAsyncMethods(ctx, model, anonymousInterfaceGraph)...)
108
+ if diagnosticsHaveErrors(diagnostics) {
109
+ return model, diagnostics
110
+ }
97
111
  diagnostics = append(diagnostics, o.propagateFunctionAsync(ctx, model)...)
98
112
  if diagnosticsHaveErrors(diagnostics) {
99
113
  return model, diagnostics
@@ -107,15 +121,20 @@ func (o *SemanticModelOwner) Build(ctx context.Context, graph *PackageGraph) (*S
107
121
 
108
122
  func newSemanticModel() *SemanticModel {
109
123
  return &SemanticModel{
110
- packages: make(map[string]*semanticPackage),
111
- addressTaken: make(map[types.Object]bool),
112
- needsVarRef: make(map[types.Object]bool),
113
- functions: make(map[*types.Func]*semanticFunction),
114
- functionsByFullName: make(map[string]*semanticFunction),
115
- functionLookupMisses: make(map[*types.Func]bool),
116
- types: make(map[*types.Named]*semanticType),
117
- values: make(map[types.Object]*semanticValue),
118
- generatedImports: make(map[string]map[string]bool),
124
+ packages: make(map[string]*semanticPackage),
125
+ addressTaken: make(map[types.Object]bool),
126
+ needsVarRef: make(map[types.Object]bool),
127
+ functions: make(map[*types.Func]*semanticFunction),
128
+ functionCallers: make(map[*types.Func][]*semanticFunction),
129
+ functionsByFullName: make(map[string]*semanticFunction),
130
+ functionLookupMisses: make(map[*types.Func]bool),
131
+ functionFullNames: make(map[*types.Func]string),
132
+ types: make(map[*types.Named]*semanticType),
133
+ values: make(map[types.Object]*semanticValue),
134
+ generatedImports: make(map[string]map[string]bool),
135
+ generatedImportTypes: make(map[string]map[types.Type]bool),
136
+ asyncInterfaceMethods: make(map[string]bool),
137
+ asyncInterfaceMethodObjs: make(map[*types.Func]bool),
119
138
  }
120
139
  }
121
140
 
@@ -207,7 +226,7 @@ func (o *SemanticModelOwner) collectGenDecl(
207
226
  continue
208
227
  }
209
228
  position := sourcePos(pkg, typed.Name.Pos())
210
- o.addType(model, semPkg, obj, position, typed.Type)
229
+ o.addType(model, semPkg, obj, position, typed.Type, pkg.TypesSizes)
211
230
  o.recordGeneratedImports(model, semPkg, position.file, pkg.PkgPath, obj.Type())
212
231
  semPkg.declarations = append(semPkg.declarations, semanticDeclaration{
213
232
  kind: "type",
@@ -342,7 +361,7 @@ func (o *SemanticModelOwner) recordTypeSpec(
342
361
  return
343
362
  }
344
363
  position := sourcePos(pkg, spec.Name.Pos())
345
- o.addType(model, semPkg, obj, position, spec.Type)
364
+ o.addType(model, semPkg, obj, position, spec.Type, pkg.TypesSizes)
346
365
  o.recordGeneratedImports(model, semPkg, position.file, pkg.PkgPath, obj.Type())
347
366
  }
348
367
 
@@ -380,8 +399,9 @@ func (o *SemanticModelOwner) recordCallSignatureImports(
380
399
  return
381
400
  }
382
401
  position := sourcePos(pkg, expr.Pos())
383
- o.recordTupleImports(model, semPkg, position.file, pkg.PkgPath, signature.Params(), make(map[types.Type]bool))
384
- o.recordTupleImports(model, semPkg, position.file, pkg.PkgPath, signature.Results(), make(map[types.Type]bool))
402
+ seen := model.generatedImportSeen(position.file)
403
+ o.recordTupleImports(model, semPkg, position.file, pkg.PkgPath, signature.Params(), seen)
404
+ o.recordTupleImports(model, semPkg, position.file, pkg.PkgPath, signature.Results(), seen)
385
405
  }
386
406
 
387
407
  func (o *SemanticModelOwner) recordAsyncCompatibleFunctionAssignments(
@@ -466,7 +486,7 @@ func (o *SemanticModelOwner) addDefinedObject(
466
486
  o.addValue(model, semPkg, typed, position, false)
467
487
  o.recordGeneratedImports(model, semPkg, position.file, pkg.PkgPath, typed.Type())
468
488
  case *types.TypeName:
469
- o.addType(model, semPkg, typed, sourcePos(pkg, ident.Pos()), nil)
489
+ o.addType(model, semPkg, typed, sourcePos(pkg, ident.Pos()), nil, pkg.TypesSizes)
470
490
  case *types.Func:
471
491
  o.addFunction(model, semPkg, typed, sourcePos(pkg, ident.Pos()))
472
492
  }
@@ -478,6 +498,7 @@ func (o *SemanticModelOwner) addType(
478
498
  obj *types.TypeName,
479
499
  position sourcePosition,
480
500
  typeExpr ast.Expr,
501
+ sizes types.Sizes,
481
502
  ) *semanticType {
482
503
  named, _ := obj.Type().(*types.Named)
483
504
  if named == nil {
@@ -485,7 +506,7 @@ func (o *SemanticModelOwner) addType(
485
506
  }
486
507
  if existing := model.types[named]; existing != nil {
487
508
  if typeExpr != nil && len(existing.fields) == 0 {
488
- existing.fields = semanticFields(named, typeExpr)
509
+ existing.fields = semanticFields(named, typeExpr, sizes)
489
510
  }
490
511
  return existing
491
512
  }
@@ -494,7 +515,7 @@ func (o *SemanticModelOwner) addType(
494
515
  name: obj.Name(),
495
516
  named: named,
496
517
  isInterface: isInterface,
497
- fields: semanticFields(named, typeExpr),
518
+ fields: semanticFields(named, typeExpr, sizes),
498
519
  position: position,
499
520
  }
500
521
  model.types[named] = semType
@@ -555,7 +576,7 @@ func (o *SemanticModelOwner) addFunction(
555
576
  return existing
556
577
  }
557
578
  }
558
- if fullName := fn.FullName(); fullName != "" {
579
+ if fullName := model.functionFullName(fn); fullName != "" {
559
580
  if existing := model.functionsByFullName[fullName]; existing != nil {
560
581
  model.functions[fn] = existing
561
582
  if origin := fn.Origin(); origin != nil {
@@ -583,7 +604,7 @@ func (o *SemanticModelOwner) addFunction(
583
604
  if origin := fn.Origin(); origin != nil {
584
605
  model.functions[origin] = semFn
585
606
  }
586
- if fullName := fn.FullName(); fullName != "" {
607
+ if fullName := model.functionFullName(fn); fullName != "" {
587
608
  if existing := model.functionsByFullName[fullName]; existing == nil {
588
609
  model.functionsByFullName[fullName] = semFn
589
610
  }
@@ -592,7 +613,7 @@ func (o *SemanticModelOwner) addFunction(
592
613
  return semFn
593
614
  }
594
615
 
595
- func semanticFields(named *types.Named, typeExpr ast.Expr) []semanticField {
616
+ func semanticFields(named *types.Named, typeExpr ast.Expr, sizes types.Sizes) []semanticField {
596
617
  if named == nil {
597
618
  return nil
598
619
  }
@@ -602,19 +623,64 @@ func semanticFields(named *types.Named, typeExpr ast.Expr) []semanticField {
602
623
  }
603
624
  docs := structFieldDocs(typeExpr)
604
625
  fields := make([]semanticField, 0, structType.NumFields())
626
+ var vars []*types.Var
627
+ for field := range structType.Fields() {
628
+ vars = append(vars, field)
629
+ }
630
+ offsets := structFieldOffsets(sizes, vars)
605
631
  for i := range structType.NumFields() {
606
632
  field := structType.Field(i)
633
+ pkgPath := ""
634
+ if !field.Exported() && field.Pkg() != nil {
635
+ pkgPath = field.Pkg().Path()
636
+ }
607
637
  fields = append(fields, semanticField{
608
638
  name: field.Name(),
609
639
  typ: field.Type(),
610
640
  doc: docs[field.Name()],
611
641
  tag: structType.Tag(i),
612
642
  embedded: field.Embedded(),
643
+ pkgPath: pkgPath,
644
+ index: []int{i},
645
+ offset: offsets[i],
646
+ exported: field.Exported(),
613
647
  })
614
648
  }
615
649
  return fields
616
650
  }
617
651
 
652
+ func goScriptTypeSizes() types.Sizes {
653
+ if sizes := types.SizesFor("gc", "wasm"); sizes != nil {
654
+ return sizes
655
+ }
656
+ return types.SizesFor("gc", "amd64")
657
+ }
658
+
659
+ func structFieldOffsets(sizes types.Sizes, fields []*types.Var) (offsets []int64) {
660
+ offsets = make([]int64, len(fields))
661
+ if len(fields) == 0 {
662
+ return offsets
663
+ }
664
+ if sizes == nil {
665
+ sizes = goScriptTypeSizes()
666
+ }
667
+ if sizes == nil {
668
+ return offsets
669
+ }
670
+ defer func() {
671
+ if recover() != nil {
672
+ // Generic field layouts do not have concrete target offsets during
673
+ // package-level metadata emission; keep compiling and leave them zero.
674
+ offsets = make([]int64, len(fields))
675
+ }
676
+ }()
677
+ computed := sizes.Offsetsof(fields)
678
+ if len(computed) == len(fields) {
679
+ copy(offsets, computed)
680
+ }
681
+ return offsets
682
+ }
683
+
618
684
  func structFieldDocs(typeExpr ast.Expr) map[string]string {
619
685
  structType, _ := typeExpr.(*ast.StructType)
620
686
  if structType == nil || structType.Fields == nil {
@@ -932,7 +998,7 @@ func semanticFunctionFor(model *SemanticModel, fn *types.Func) *semanticFunction
932
998
  return semFn
933
999
  }
934
1000
  }
935
- if fullName := fn.FullName(); fullName != "" {
1001
+ if fullName := model.functionFullName(fn); fullName != "" {
936
1002
  if semFn := model.functionsByFullName[fullName]; semFn != nil {
937
1003
  model.functions[fn] = semFn
938
1004
  return semFn
@@ -989,6 +1055,8 @@ func callUsesFunctionValue(pkg *packages.Package, expr ast.Expr) bool {
989
1055
  switch typed := expr.(type) {
990
1056
  case *ast.CallExpr:
991
1057
  return true
1058
+ case *ast.TypeAssertExpr:
1059
+ return true
992
1060
  case *ast.SelectorExpr:
993
1061
  selection := pkg.TypesInfo.Selections[typed]
994
1062
  if selection != nil {
@@ -1114,29 +1182,56 @@ func receiverNamedType(typ types.Type) *types.Named {
1114
1182
  }
1115
1183
 
1116
1184
  func (o *SemanticModelOwner) propagateFunctionAsync(ctx context.Context, model *SemanticModel) []Diagnostic {
1117
- changed := true
1118
- for changed {
1185
+ if err := ctx.Err(); err != nil {
1186
+ return []Diagnostic{contextCanceledDiagnostic(err)}
1187
+ }
1188
+ queued := make(map[*types.Func]bool)
1189
+ queue := make([]*types.Func, 0)
1190
+ enqueue := func(fn *types.Func) {
1191
+ fn = functionOriginOrSelf(fn)
1192
+ if fn == nil || queued[fn] {
1193
+ return
1194
+ }
1195
+ queued[fn] = true
1196
+ queue = append(queue, fn)
1197
+ }
1198
+ for called := range model.functionCallers {
1199
+ if model.functionAsync(called) {
1200
+ enqueue(called)
1201
+ }
1202
+ }
1203
+ for len(queue) != 0 {
1119
1204
  if err := ctx.Err(); err != nil {
1120
1205
  return []Diagnostic{contextCanceledDiagnostic(err)}
1121
1206
  }
1122
- changed = false
1123
- for _, semFn := range model.functions {
1207
+ called := queue[0]
1208
+ queue = queue[1:]
1209
+ for _, semFn := range model.functionCallers[called] {
1124
1210
  if err := ctx.Err(); err != nil {
1125
1211
  return []Diagnostic{contextCanceledDiagnostic(err)}
1126
1212
  }
1127
- for called := range semFn.calls {
1128
- calledFn := semanticFunctionFor(model, called)
1129
- if calledFn != nil && calledFn.async {
1130
- if markFunctionAsync(semFn, "call:"+called.FullName()) {
1131
- changed = true
1132
- }
1133
- }
1213
+ if markFunctionAsync(semFn, "call:"+model.functionFullName(called)) {
1214
+ enqueue(semFn.function)
1134
1215
  }
1135
1216
  }
1136
1217
  }
1137
1218
  return nil
1138
1219
  }
1139
1220
 
1221
+ func semanticFunctionCallers(model *SemanticModel) map[*types.Func][]*semanticFunction {
1222
+ callers := make(map[*types.Func][]*semanticFunction)
1223
+ for _, semFn := range model.functions {
1224
+ for called := range semFn.calls {
1225
+ called = functionOriginOrSelf(called)
1226
+ if called == nil {
1227
+ continue
1228
+ }
1229
+ callers[called] = append(callers[called], semFn)
1230
+ }
1231
+ }
1232
+ return callers
1233
+ }
1234
+
1140
1235
  func markFunctionAsync(fn *semanticFunction, reason string) bool {
1141
1236
  if fn == nil {
1142
1237
  return false
@@ -1166,23 +1261,12 @@ func semanticAsyncFunctionCount(model *SemanticModel) int {
1166
1261
  func (o *SemanticModelOwner) resolveInterfaceImplementationGraph(
1167
1262
  ctx context.Context,
1168
1263
  model *SemanticModel,
1264
+ methodSets []semanticImplementationMethodSet,
1169
1265
  ) ([]semanticInterfaceImplementationGraphEntry, []Diagnostic) {
1170
- var interfaces []*types.Named
1171
- var concretes []*types.Named
1172
- for named, semType := range model.types {
1173
- if err := ctx.Err(); err != nil {
1174
- return nil, []Diagnostic{contextCanceledDiagnostic(err)}
1175
- }
1176
- if semType.isInterface {
1177
- interfaces = append(interfaces, named)
1178
- continue
1179
- }
1180
- concretes = append(concretes, named)
1181
- }
1266
+ interfaces := collectInterfaceImplementationCandidates(model)
1182
1267
  sortNamedTypes(interfaces)
1183
- sortNamedTypes(concretes)
1184
- methodSets := implementationMethodSets(concretes)
1185
1268
 
1269
+ methodSetIndexByName := indexImplementationMethodSets(methodSets)
1186
1270
  implementationGraph := make([]semanticInterfaceImplementationGraphEntry, 0)
1187
1271
  for _, ifaceNamed := range interfaces {
1188
1272
  if err := ctx.Err(); err != nil {
@@ -1197,10 +1281,11 @@ func (o *SemanticModelOwner) resolveInterfaceImplementationGraph(
1197
1281
  if len(ifaceMethods) == 0 {
1198
1282
  continue
1199
1283
  }
1200
- for _, methodSet := range methodSets {
1284
+ for _, methodSetIdx := range implementationMethodSetCandidates(methodSetIndexByName, ifaceMethods) {
1201
1285
  if err := ctx.Err(); err != nil {
1202
1286
  return nil, []Diagnostic{contextCanceledDiagnostic(err)}
1203
1287
  }
1288
+ methodSet := methodSets[methodSetIdx]
1204
1289
  if implementation, ok := o.interfaceImplementationGraphEntry(methodSet, ifaceNamed, ifaceMethods); ok {
1205
1290
  implementationGraph = append(implementationGraph, implementation)
1206
1291
  }
@@ -1209,42 +1294,447 @@ func (o *SemanticModelOwner) resolveInterfaceImplementationGraph(
1209
1294
  return implementationGraph, nil
1210
1295
  }
1211
1296
 
1297
+ func (o *SemanticModelOwner) resolveAnonymousInterfaceImplementationGraph(
1298
+ ctx context.Context,
1299
+ model *SemanticModel,
1300
+ methodSets []semanticImplementationMethodSet,
1301
+ ) ([]semanticAnonymousInterfaceImplementation, []Diagnostic) {
1302
+ interfaces := collectAnonymousInterfaceImplementationCandidates(model)
1303
+ for _, namedIface := range collectNamedInterfaceImplementationCandidates(model) {
1304
+ if err := ctx.Err(); err != nil {
1305
+ return nil, []Diagnostic{contextCanceledDiagnostic(err)}
1306
+ }
1307
+ methodSets = append(methodSets, semanticImplementationMethodSet{
1308
+ typ: namedIface,
1309
+ receiver: namedIface,
1310
+ methods: methodSetMap(namedIface),
1311
+ })
1312
+ }
1313
+
1314
+ methodSetIndexByName := indexImplementationMethodSets(methodSets)
1315
+ implementationGraph := make([]semanticAnonymousInterfaceImplementation, 0)
1316
+ for _, iface := range interfaces {
1317
+ if err := ctx.Err(); err != nil {
1318
+ return nil, []Diagnostic{contextCanceledDiagnostic(err)}
1319
+ }
1320
+ iface.Complete()
1321
+ ifaceMethods := interfaceMethodMap(iface)
1322
+ if len(ifaceMethods) == 0 {
1323
+ continue
1324
+ }
1325
+ for _, methodSetIdx := range implementationMethodSetCandidates(methodSetIndexByName, ifaceMethods) {
1326
+ if err := ctx.Err(); err != nil {
1327
+ return nil, []Diagnostic{contextCanceledDiagnostic(err)}
1328
+ }
1329
+ methodSet := methodSets[methodSetIdx]
1330
+ if !implementationHasMethods(methodSet.methods, ifaceMethods) {
1331
+ continue
1332
+ }
1333
+ if !namedTypeHasParams(methodSet.typ) {
1334
+ if matches, exact := implementationHasExactMethodSignatures(methodSet.methods, ifaceMethods); exact {
1335
+ if !matches {
1336
+ continue
1337
+ }
1338
+ implementationGraph = append(implementationGraph, semanticAnonymousInterfaceImplementation{
1339
+ ifaceMethods: ifaceMethods,
1340
+ implMethods: methodSet.methods,
1341
+ })
1342
+ continue
1343
+ }
1344
+ }
1345
+ receiver := methodSet.receiver
1346
+ if (methodSet.typ.TypeArgs() == nil || methodSet.typ.TypeArgs().Len() == 0) &&
1347
+ methodSet.typ.TypeParams() != nil && methodSet.typ.TypeParams().Len() != 0 {
1348
+ args := typeParamTypes(methodSet.typ.TypeParams())
1349
+ if instantiated, err := types.Instantiate(nil, methodSet.typ, args, false); err == nil {
1350
+ receiver = instantiated
1351
+ if methodSet.pointer {
1352
+ receiver = types.NewPointer(instantiated)
1353
+ }
1354
+ }
1355
+ }
1356
+ if !types.Implements(receiver, iface) {
1357
+ continue
1358
+ }
1359
+ implementationGraph = append(implementationGraph, semanticAnonymousInterfaceImplementation{
1360
+ ifaceMethods: ifaceMethods,
1361
+ implMethods: methodSet.methods,
1362
+ })
1363
+ }
1364
+ }
1365
+ return implementationGraph, nil
1366
+ }
1367
+
1368
+ func (o *SemanticModelOwner) resolveImplementationMethodSets(
1369
+ ctx context.Context,
1370
+ model *SemanticModel,
1371
+ ) ([]semanticImplementationMethodSet, []Diagnostic) {
1372
+ var concretes []*types.Named
1373
+ for named, semType := range model.types {
1374
+ if err := ctx.Err(); err != nil {
1375
+ return nil, []Diagnostic{contextCanceledDiagnostic(err)}
1376
+ }
1377
+ if !semType.isInterface {
1378
+ concretes = append(concretes, namedOriginOrSelf(named))
1379
+ }
1380
+ }
1381
+ sortNamedTypes(concretes)
1382
+ return implementationMethodSets(concretes), nil
1383
+ }
1384
+
1385
+ func collectInterfaceImplementationCandidates(model *SemanticModel) []*types.Named {
1386
+ if model == nil {
1387
+ return nil
1388
+ }
1389
+ seen := make(map[string]bool)
1390
+ var interfaces []*types.Named
1391
+ add := func(named *types.Named) {
1392
+ if named == nil || named.Obj() == nil || named.Obj().Pkg() == nil {
1393
+ return
1394
+ }
1395
+ named = namedOriginOrSelf(named)
1396
+ if _, ok := types.Unalias(named.Underlying()).(*types.Interface); !ok {
1397
+ return
1398
+ }
1399
+ key := named.Obj().Pkg().Path() + "." + named.Obj().Name()
1400
+ if seen[key] {
1401
+ return
1402
+ }
1403
+ seen[key] = true
1404
+ interfaces = append(interfaces, named)
1405
+ }
1406
+ var collect func(types.Type)
1407
+ seenTypes := make(map[types.Type]bool)
1408
+ collect = func(typ types.Type) {
1409
+ if typ == nil {
1410
+ return
1411
+ }
1412
+ typ = types.Unalias(typ)
1413
+ if seenTypes[typ] {
1414
+ return
1415
+ }
1416
+ seenTypes[typ] = true
1417
+ switch typed := typ.(type) {
1418
+ case *types.Named:
1419
+ add(typed)
1420
+ collect(typed.Underlying())
1421
+ case *types.Pointer:
1422
+ collect(typed.Elem())
1423
+ case *types.Slice:
1424
+ collect(typed.Elem())
1425
+ case *types.Array:
1426
+ collect(typed.Elem())
1427
+ case *types.Map:
1428
+ collect(typed.Key())
1429
+ collect(typed.Elem())
1430
+ case *types.Chan:
1431
+ collect(typed.Elem())
1432
+ case *types.Struct:
1433
+ for field := range typed.Fields() {
1434
+ collect(field.Type())
1435
+ }
1436
+ case *types.Interface:
1437
+ typed.Complete()
1438
+ for method := range typed.Methods() {
1439
+ collect(method.Type())
1440
+ }
1441
+ case *types.Signature:
1442
+ if typed.Recv() != nil {
1443
+ collect(typed.Recv().Type())
1444
+ }
1445
+ collectTuple(collect, typed.Params())
1446
+ collectTuple(collect, typed.Results())
1447
+ }
1448
+ }
1449
+ for _, semType := range model.types {
1450
+ collect(semType.named)
1451
+ for _, field := range semType.fields {
1452
+ collect(field.typ)
1453
+ }
1454
+ }
1455
+ for _, semFn := range model.functions {
1456
+ collect(semFn.signature)
1457
+ }
1458
+ for _, semValue := range model.values {
1459
+ collect(semValue.typ)
1460
+ }
1461
+ for _, semPkg := range model.packages {
1462
+ for _, assertion := range semPkg.typeAssertions {
1463
+ collect(assertion.source)
1464
+ collect(assertion.target)
1465
+ }
1466
+ for _, fact := range semPkg.nilFacts {
1467
+ collect(fact.typ)
1468
+ }
1469
+ }
1470
+ return interfaces
1471
+ }
1472
+
1473
+ func collectAnonymousInterfaceImplementationCandidates(model *SemanticModel) []*types.Interface {
1474
+ if model == nil {
1475
+ return nil
1476
+ }
1477
+ seen := make(map[*types.Interface]bool)
1478
+ var interfaces []*types.Interface
1479
+ add := func(iface *types.Interface) {
1480
+ if iface == nil || seen[iface] {
1481
+ return
1482
+ }
1483
+ seen[iface] = true
1484
+ interfaces = append(interfaces, iface)
1485
+ }
1486
+ var collect func(types.Type)
1487
+ seenTypes := make(map[types.Type]bool)
1488
+ collect = func(typ types.Type) {
1489
+ if typ == nil {
1490
+ return
1491
+ }
1492
+ typ = types.Unalias(typ)
1493
+ if seenTypes[typ] {
1494
+ return
1495
+ }
1496
+ seenTypes[typ] = true
1497
+ switch typed := typ.(type) {
1498
+ case *types.Named:
1499
+ collect(typed.Underlying())
1500
+ case *types.Pointer:
1501
+ collect(typed.Elem())
1502
+ case *types.Slice:
1503
+ collect(typed.Elem())
1504
+ case *types.Array:
1505
+ collect(typed.Elem())
1506
+ case *types.Map:
1507
+ collect(typed.Key())
1508
+ collect(typed.Elem())
1509
+ case *types.Chan:
1510
+ collect(typed.Elem())
1511
+ case *types.Struct:
1512
+ for field := range typed.Fields() {
1513
+ collect(field.Type())
1514
+ }
1515
+ case *types.Interface:
1516
+ typed.Complete()
1517
+ add(typed)
1518
+ for method := range typed.Methods() {
1519
+ collect(method.Type())
1520
+ }
1521
+ case *types.Signature:
1522
+ if typed.Recv() != nil {
1523
+ collect(typed.Recv().Type())
1524
+ }
1525
+ collectTuple(collect, typed.Params())
1526
+ collectTuple(collect, typed.Results())
1527
+ }
1528
+ }
1529
+ for _, semType := range model.types {
1530
+ collect(semType.named)
1531
+ for _, field := range semType.fields {
1532
+ collect(field.typ)
1533
+ }
1534
+ }
1535
+ for _, semFn := range model.functions {
1536
+ collect(semFn.signature)
1537
+ }
1538
+ for _, semValue := range model.values {
1539
+ collect(semValue.typ)
1540
+ }
1541
+ for _, semPkg := range model.packages {
1542
+ for _, assertion := range semPkg.typeAssertions {
1543
+ collect(assertion.source)
1544
+ collect(assertion.target)
1545
+ }
1546
+ for _, fact := range semPkg.nilFacts {
1547
+ collect(fact.typ)
1548
+ }
1549
+ }
1550
+ return interfaces
1551
+ }
1552
+
1553
+ func collectNamedInterfaceImplementationCandidates(model *SemanticModel) []*types.Named {
1554
+ if model == nil {
1555
+ return nil
1556
+ }
1557
+ seen := make(map[string]bool)
1558
+ var interfaces []*types.Named
1559
+ add := func(named *types.Named) {
1560
+ if named == nil {
1561
+ return
1562
+ }
1563
+ if _, ok := types.Unalias(named.Underlying()).(*types.Interface); !ok {
1564
+ return
1565
+ }
1566
+ key := types.TypeString(named, func(pkg *types.Package) string {
1567
+ if pkg == nil {
1568
+ return ""
1569
+ }
1570
+ return pkg.Path()
1571
+ })
1572
+ if seen[key] {
1573
+ return
1574
+ }
1575
+ seen[key] = true
1576
+ interfaces = append(interfaces, named)
1577
+ }
1578
+ var collect func(types.Type)
1579
+ seenTypes := make(map[types.Type]bool)
1580
+ collect = func(typ types.Type) {
1581
+ if typ == nil {
1582
+ return
1583
+ }
1584
+ typ = types.Unalias(typ)
1585
+ if seenTypes[typ] {
1586
+ return
1587
+ }
1588
+ seenTypes[typ] = true
1589
+ switch typed := typ.(type) {
1590
+ case *types.Named:
1591
+ add(typed)
1592
+ collect(typed.Underlying())
1593
+ case *types.Pointer:
1594
+ collect(typed.Elem())
1595
+ case *types.Slice:
1596
+ collect(typed.Elem())
1597
+ case *types.Array:
1598
+ collect(typed.Elem())
1599
+ case *types.Map:
1600
+ collect(typed.Key())
1601
+ collect(typed.Elem())
1602
+ case *types.Chan:
1603
+ collect(typed.Elem())
1604
+ case *types.Struct:
1605
+ for field := range typed.Fields() {
1606
+ collect(field.Type())
1607
+ }
1608
+ case *types.Interface:
1609
+ typed.Complete()
1610
+ for method := range typed.Methods() {
1611
+ collect(method.Type())
1612
+ }
1613
+ case *types.Signature:
1614
+ if typed.Recv() != nil {
1615
+ collect(typed.Recv().Type())
1616
+ }
1617
+ collectTuple(collect, typed.Params())
1618
+ collectTuple(collect, typed.Results())
1619
+ }
1620
+ }
1621
+ for _, semType := range model.types {
1622
+ collect(semType.named)
1623
+ for _, field := range semType.fields {
1624
+ collect(field.typ)
1625
+ }
1626
+ }
1627
+ for _, semFn := range model.functions {
1628
+ collect(semFn.signature)
1629
+ }
1630
+ for _, semValue := range model.values {
1631
+ collect(semValue.typ)
1632
+ }
1633
+ for _, semPkg := range model.packages {
1634
+ for _, assertion := range semPkg.typeAssertions {
1635
+ collect(assertion.source)
1636
+ collect(assertion.target)
1637
+ }
1638
+ for _, fact := range semPkg.nilFacts {
1639
+ collect(fact.typ)
1640
+ }
1641
+ }
1642
+ return interfaces
1643
+ }
1644
+
1645
+ func collectTuple(collect func(types.Type), tuple *types.Tuple) {
1646
+ if tuple == nil {
1647
+ return
1648
+ }
1649
+ for v := range tuple.Variables() {
1650
+ collect(v.Type())
1651
+ }
1652
+ }
1653
+
1212
1654
  func (o *SemanticModelOwner) applyInterfaceAsyncMethods(
1213
1655
  ctx context.Context,
1214
1656
  model *SemanticModel,
1215
1657
  interfaceGraph []semanticInterfaceImplementationGraphEntry,
1216
1658
  ) []Diagnostic {
1217
- model.interfaceImplementations = model.interfaceImplementations[:0]
1659
+ if cap(model.interfaceImplementations) < len(interfaceGraph) {
1660
+ model.interfaceImplementations = make([]semanticInterfaceImplementation, 0, len(interfaceGraph))
1661
+ } else {
1662
+ model.interfaceImplementations = model.interfaceImplementations[:0]
1663
+ }
1218
1664
  for _, graphEntry := range interfaceGraph {
1219
1665
  if err := ctx.Err(); err != nil {
1220
1666
  return []Diagnostic{contextCanceledDiagnostic(err)}
1221
1667
  }
1222
1668
  implementation := semanticInterfaceImplementation{
1223
- typ: graphEntry.typ,
1224
- iface: graphEntry.iface,
1225
- pointer: graphEntry.pointer,
1226
- asyncMethods: make(map[string]bool),
1669
+ typ: graphEntry.typ,
1670
+ iface: graphEntry.iface,
1671
+ pointer: graphEntry.pointer,
1227
1672
  }
1228
- for methodName, implMethod := range graphEntry.implMethods {
1229
- implFn := model.functions[implMethod]
1673
+ for methodName, ifaceMethod := range graphEntry.ifaceMethods {
1674
+ implMethod := graphEntry.implMethods[methodName]
1675
+ implFn := semanticFunctionFor(model, implMethod)
1230
1676
  if implFn != nil && implFn.async {
1231
- implementation.asyncMethods[methodName] = true
1232
- if ifaceFn := model.functions[graphEntry.ifaceMethods[methodName]]; ifaceFn != nil {
1677
+ model.markInterfaceMethodAsync(ifaceMethod)
1678
+ if ifaceFn := semanticFunctionFor(model, ifaceMethod); ifaceFn != nil {
1233
1679
  markFunctionAsync(ifaceFn, "interface-implementation")
1234
1680
  }
1681
+ markFunctionAsync(implFn, "interface-method")
1235
1682
  }
1236
1683
  }
1237
- for methodName, async := range implementation.asyncMethods {
1238
- if !async {
1239
- continue
1684
+ model.interfaceImplementations = append(model.interfaceImplementations, implementation)
1685
+ }
1686
+ return nil
1687
+ }
1688
+
1689
+ func (o *SemanticModelOwner) applyAnonymousInterfaceAsyncMethods(
1690
+ ctx context.Context,
1691
+ model *SemanticModel,
1692
+ interfaceGraph []semanticAnonymousInterfaceImplementation,
1693
+ ) []Diagnostic {
1694
+ for _, graphEntry := range interfaceGraph {
1695
+ if err := ctx.Err(); err != nil {
1696
+ return []Diagnostic{contextCanceledDiagnostic(err)}
1697
+ }
1698
+ for methodName, ifaceMethod := range graphEntry.ifaceMethods {
1699
+ implMethod := graphEntry.implMethods[methodName]
1700
+ if model.functionAsync(implMethod) {
1701
+ model.markInterfaceMethodAsync(ifaceMethod)
1240
1702
  }
1241
- markFunctionAsync(model.functions[graphEntry.implMethods[methodName]], "interface-method")
1242
1703
  }
1243
- model.interfaceImplementations = append(model.interfaceImplementations, implementation)
1244
1704
  }
1245
1705
  return nil
1246
1706
  }
1247
1707
 
1708
+ func (m *SemanticModel) functionAsync(fn *types.Func) bool {
1709
+ semFn := semanticFunctionFor(m, fn)
1710
+ if semFn != nil && semFn.async {
1711
+ return true
1712
+ }
1713
+ return m.interfaceMethodAsync(fn)
1714
+ }
1715
+
1716
+ func (m *SemanticModel) markInterfaceMethodAsync(fn *types.Func) {
1717
+ if m == nil || fn == nil {
1718
+ return
1719
+ }
1720
+ m.asyncInterfaceMethodObjs[fn] = true
1721
+ key := m.functionFullName(fn)
1722
+ if key != "" {
1723
+ m.asyncInterfaceMethods[key] = true
1724
+ }
1725
+ }
1726
+
1727
+ func (m *SemanticModel) interfaceMethodAsync(fn *types.Func) bool {
1728
+ if m == nil || fn == nil {
1729
+ return false
1730
+ }
1731
+ if m.asyncInterfaceMethodObjs[fn] {
1732
+ return true
1733
+ }
1734
+ key := m.functionFullName(fn)
1735
+ return key != "" && m.asyncInterfaceMethods[key]
1736
+ }
1737
+
1248
1738
  func contextCanceledDiagnostic(err error) Diagnostic {
1249
1739
  return Diagnostic{
1250
1740
  Severity: DiagnosticSeverityError,
@@ -1262,6 +1752,22 @@ func (o *SemanticModelOwner) interfaceImplementationGraphEntry(
1262
1752
  return semanticInterfaceImplementationGraphEntry{}, false
1263
1753
  }
1264
1754
 
1755
+ if !namedTypeHasParams(methodSet.typ) && !namedTypeHasParams(ifaceNamed) {
1756
+ if matches, exact := implementationHasExactMethodSignatures(methodSet.methods, ifaceMethods); exact {
1757
+ if !matches {
1758
+ return semanticInterfaceImplementationGraphEntry{}, false
1759
+ }
1760
+ implementation := semanticInterfaceImplementationGraphEntry{
1761
+ typ: methodSet.typ,
1762
+ iface: ifaceNamed,
1763
+ pointer: methodSet.pointer,
1764
+ ifaceMethods: ifaceMethods,
1765
+ implMethods: methodSet.methods,
1766
+ }
1767
+ return implementation, true
1768
+ }
1769
+ }
1770
+
1265
1771
  implementsReceiver := methodSet.receiver
1266
1772
  implementsIface := types.Type(ifaceNamed.Underlying())
1267
1773
  if methodSet.typ.TypeParams() != nil && methodSet.typ.TypeParams().Len() != 0 {
@@ -1286,10 +1792,9 @@ func (o *SemanticModelOwner) interfaceImplementationGraphEntry(
1286
1792
  typ: methodSet.typ,
1287
1793
  iface: ifaceNamed,
1288
1794
  pointer: methodSet.pointer,
1289
- ifaceMethods: make(map[string]*types.Func),
1290
- implMethods: implementationMethodMap(methodSet.methods, ifaceMethods),
1795
+ ifaceMethods: ifaceMethods,
1796
+ implMethods: methodSet.methods,
1291
1797
  }
1292
- maps.Copy(implementation.ifaceMethods, ifaceMethods)
1293
1798
  return implementation, true
1294
1799
  }
1295
1800
 
@@ -1304,6 +1809,56 @@ func interfaceMethodMap(iface *types.Interface) map[string]*types.Func {
1304
1809
  return methods
1305
1810
  }
1306
1811
 
1812
+ func indexImplementationMethodSets(methodSets []semanticImplementationMethodSet) map[string][]int {
1813
+ index := make(map[string][]int)
1814
+ for methodSetIndex, methodSet := range methodSets {
1815
+ for methodName := range methodSet.methods {
1816
+ index[methodName] = append(index[methodName], methodSetIndex)
1817
+ }
1818
+ }
1819
+ return index
1820
+ }
1821
+
1822
+ func implementationMethodSetCandidates(
1823
+ index map[string][]int,
1824
+ ifaceMethods map[string]*types.Func,
1825
+ ) []int {
1826
+ var candidates []int
1827
+ for methodName := range ifaceMethods {
1828
+ methodSets := index[methodName]
1829
+ if len(methodSets) == 0 {
1830
+ return nil
1831
+ }
1832
+ if candidates == nil || len(methodSets) < len(candidates) {
1833
+ candidates = methodSets
1834
+ }
1835
+ }
1836
+ return candidates
1837
+ }
1838
+
1839
+ func (m *SemanticModel) functionFullName(fn *types.Func) string {
1840
+ if m == nil || fn == nil {
1841
+ return ""
1842
+ }
1843
+ original := fn
1844
+ if fullName, ok := m.functionFullNames[original]; ok {
1845
+ return fullName
1846
+ }
1847
+ if origin := fn.Origin(); origin != nil && origin != fn {
1848
+ if fullName, ok := m.functionFullNames[origin]; ok {
1849
+ m.functionFullNames[original] = fullName
1850
+ return fullName
1851
+ }
1852
+ fn = origin
1853
+ }
1854
+ fullName := fn.FullName()
1855
+ m.functionFullNames[fn] = fullName
1856
+ if original != fn {
1857
+ m.functionFullNames[original] = fullName
1858
+ }
1859
+ return fullName
1860
+ }
1861
+
1307
1862
  func implementationMethodSets(concretes []*types.Named) []semanticImplementationMethodSet {
1308
1863
  methodSets := make([]semanticImplementationMethodSet, 0, len(concretes)*2)
1309
1864
  for _, concrete := range concretes {
@@ -1356,15 +1911,78 @@ func implementationHasMethods(
1356
1911
  return true
1357
1912
  }
1358
1913
 
1359
- func implementationMethodMap(
1914
+ func implementationHasExactMethodSignatures(
1360
1915
  receiverMethods map[string]*types.Func,
1361
1916
  ifaceMethods map[string]*types.Func,
1362
- ) map[string]*types.Func {
1363
- methods := make(map[string]*types.Func, len(ifaceMethods))
1364
- for methodName := range ifaceMethods {
1365
- methods[methodName] = receiverMethods[methodName]
1917
+ ) (bool, bool) {
1918
+ for methodName, ifaceMethod := range ifaceMethods {
1919
+ implMethod := receiverMethods[methodName]
1920
+ if implMethod == nil {
1921
+ return false, true
1922
+ }
1923
+ if !methodPackagesCompatible(implMethod, ifaceMethod) {
1924
+ return false, true
1925
+ }
1926
+ implSignature, _ := implMethod.Type().(*types.Signature)
1927
+ ifaceSignature, _ := ifaceMethod.Type().(*types.Signature)
1928
+ if implSignature == nil || ifaceSignature == nil {
1929
+ return false, false
1930
+ }
1931
+ if !methodSignaturesIdentical(implSignature, ifaceSignature) {
1932
+ return false, true
1933
+ }
1366
1934
  }
1367
- return methods
1935
+ return true, true
1936
+ }
1937
+
1938
+ func methodPackagesCompatible(implMethod *types.Func, ifaceMethod *types.Func) bool {
1939
+ if implMethod == nil || ifaceMethod == nil {
1940
+ return false
1941
+ }
1942
+ if ifaceMethod.Exported() {
1943
+ return true
1944
+ }
1945
+ return packagePathOfObject(implMethod) == packagePathOfObject(ifaceMethod)
1946
+ }
1947
+
1948
+ func packagePathOfObject(obj types.Object) string {
1949
+ if obj == nil || obj.Pkg() == nil {
1950
+ return ""
1951
+ }
1952
+ return obj.Pkg().Path()
1953
+ }
1954
+
1955
+ func methodSignaturesIdentical(implSignature *types.Signature, ifaceSignature *types.Signature) bool {
1956
+ if implSignature == nil || ifaceSignature == nil || implSignature.Variadic() != ifaceSignature.Variadic() {
1957
+ return false
1958
+ }
1959
+ return tupleTypesIdentical(implSignature.Params(), ifaceSignature.Params()) &&
1960
+ tupleTypesIdentical(implSignature.Results(), ifaceSignature.Results())
1961
+ }
1962
+
1963
+ func tupleTypesIdentical(a *types.Tuple, b *types.Tuple) bool {
1964
+ if a == nil || b == nil {
1965
+ return a == b
1966
+ }
1967
+ if a.Len() != b.Len() {
1968
+ return false
1969
+ }
1970
+ for idx := range a.Len() {
1971
+ if !types.IdenticalIgnoreTags(a.At(idx).Type(), b.At(idx).Type()) {
1972
+ return false
1973
+ }
1974
+ }
1975
+ return true
1976
+ }
1977
+
1978
+ func namedTypeHasParams(named *types.Named) bool {
1979
+ if named == nil {
1980
+ return false
1981
+ }
1982
+ if params := named.TypeParams(); params != nil && params.Len() != 0 {
1983
+ return true
1984
+ }
1985
+ return named.TypeArgs() != nil && named.TypeArgs().Len() != 0
1368
1986
  }
1369
1987
 
1370
1988
  func typeParamTypes(params *types.TypeParamList) []types.Type {
@@ -1378,6 +1996,16 @@ func typeParamTypes(params *types.TypeParamList) []types.Type {
1378
1996
  return args
1379
1997
  }
1380
1998
 
1999
+ func namedOriginOrSelf(named *types.Named) *types.Named {
2000
+ if named == nil {
2001
+ return nil
2002
+ }
2003
+ if origin := named.Origin(); origin != nil {
2004
+ return origin
2005
+ }
2006
+ return named
2007
+ }
2008
+
1381
2009
  func sortNamedTypes(named []*types.Named) {
1382
2010
  slices.SortFunc(named, func(a, b *types.Named) int {
1383
2011
  return cmp.Compare(namedTypeKey(a), namedTypeKey(b))
@@ -1526,7 +2154,16 @@ func (o *SemanticModelOwner) recordGeneratedImports(
1526
2154
  if file == "" || typ == nil {
1527
2155
  return
1528
2156
  }
1529
- o.recordTypeImports(model, semPkg, file, currentPkg, typ, make(map[types.Type]bool))
2157
+ o.recordTypeImports(model, semPkg, file, currentPkg, typ, model.generatedImportSeen(file))
2158
+ }
2159
+
2160
+ func (m *SemanticModel) generatedImportSeen(file string) map[types.Type]bool {
2161
+ seen := m.generatedImportTypes[file]
2162
+ if seen == nil {
2163
+ seen = make(map[types.Type]bool)
2164
+ m.generatedImportTypes[file] = seen
2165
+ }
2166
+ return seen
1530
2167
  }
1531
2168
 
1532
2169
  func (o *SemanticModelOwner) recordTypeImports(