@greenpandastudios/aug-cli 0.19.0 → 0.20.1

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 (459) hide show
  1. package/README.md +9 -6
  2. package/THIRD_PARTY_NOTICES.md +4 -0
  3. package/bin/aug.mjs +12 -2
  4. package/docs/about.md +27 -0
  5. package/docs/api/crypto.md +103 -69
  6. package/docs/api/io.md +35 -33
  7. package/docs/api/json.md +3 -3
  8. package/docs/api/memory.md +23 -19
  9. package/docs/api/time.md +10 -9
  10. package/docs/api/web.md +33 -38
  11. package/docs/compatibility.md +3 -3
  12. package/docs/contributing-benchmarks.md +38 -0
  13. package/docs/dev-containers.md +95 -0
  14. package/docs/diagnostics.md +15 -5
  15. package/docs/docker.md +174 -12
  16. package/docs/editor.md +35 -0
  17. package/docs/example-projects.json +206 -24
  18. package/docs/examples/approved-design/counters.md +34 -126
  19. package/docs/examples/approved-design/dependencies/august/0.20.1/io/contracts.md +178 -0
  20. package/docs/examples/approved-design/domain/app.md +13 -77
  21. package/docs/examples/approved-design/domain/export.md +5 -19
  22. package/docs/examples/approved-design/domain/models.md +4 -23
  23. package/docs/examples/approved-design/domain/numbers.md +24 -114
  24. package/docs/examples/approved-design/index.md +16 -7
  25. package/docs/examples/approved-design/main.md +19 -96
  26. package/docs/examples/benchmark/index.md +6 -5
  27. package/docs/examples/benchmark/main.md +7 -35
  28. package/docs/examples/cli-args/index.md +6 -5
  29. package/docs/examples/cli-args/main.md +6 -31
  30. package/docs/examples/collections/index.md +6 -5
  31. package/docs/examples/collections/main.md +7 -35
  32. package/docs/examples/collections-benchmark/index.md +6 -5
  33. package/docs/examples/collections-benchmark/main.md +7 -35
  34. package/docs/examples/cpu-benchmark/index.md +6 -5
  35. package/docs/examples/cpu-benchmark/main.md +5 -24
  36. package/docs/examples/developer-workflow/calculator.md +39 -186
  37. package/docs/examples/developer-workflow/dependencies/august/0.20.1/io/contracts.md +178 -0
  38. package/docs/examples/developer-workflow/index.md +16 -7
  39. package/docs/examples/developer-workflow/logging/console.md +10 -56
  40. package/docs/examples/developer-workflow/logging/export.md +4 -14
  41. package/docs/examples/developer-workflow/logging/logger.md +7 -43
  42. package/docs/examples/developer-workflow/main.md +17 -69
  43. package/docs/examples/drop/index.md +6 -5
  44. package/docs/examples/drop/main.md +7 -27
  45. package/docs/examples/drop/resource.md +7 -30
  46. package/docs/examples/errors/errors.md +7 -27
  47. package/docs/examples/errors/index.md +6 -5
  48. package/docs/examples/errors/main.md +7 -28
  49. package/docs/examples/ffi/index.md +6 -5
  50. package/docs/examples/ffi/main.md +6 -20
  51. package/docs/examples/ffi/native.md +8 -34
  52. package/docs/examples/generic-di/dependencies/august/0.20.1/io/contracts.md +178 -0
  53. package/docs/examples/generic-di/index.md +6 -5
  54. package/docs/examples/generic-di/main.md +9 -39
  55. package/docs/examples/generic-di/types.md +23 -92
  56. package/docs/examples/generics/index.md +6 -5
  57. package/docs/examples/generics/main.md +10 -47
  58. package/docs/examples/generics/types.md +25 -100
  59. package/docs/examples/hello/app/export.md +4 -12
  60. package/docs/examples/hello/app/greeter.md +13 -91
  61. package/docs/examples/hello/dependencies/august/0.20.1/io/contracts.md +178 -0
  62. package/docs/examples/hello/index.md +17 -6
  63. package/docs/examples/hello/logging/console.md +10 -54
  64. package/docs/examples/hello/logging/export.md +4 -14
  65. package/docs/examples/hello/logging/logger.md +7 -45
  66. package/docs/examples/hello/main.md +9 -39
  67. package/docs/examples/http-benchmark/index.md +6 -5
  68. package/docs/examples/http-benchmark/main.md +6 -20
  69. package/docs/examples/http-benchmark/routes.md +9 -31
  70. package/docs/examples/index.md +46 -29
  71. package/docs/examples/interceptors/app.md +20 -139
  72. package/docs/examples/interceptors/dependencies/august/0.20.1/io/contracts.md +178 -0
  73. package/docs/examples/interceptors/index.md +6 -5
  74. package/docs/examples/interceptors/interceptors.md +24 -148
  75. package/docs/examples/interceptors/logging.md +13 -76
  76. package/docs/examples/interceptors/main.md +10 -65
  77. package/docs/examples/json-benchmark/data.md +4 -20
  78. package/docs/examples/json-benchmark/dependencies/packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +67 -0
  79. package/docs/examples/json-benchmark/index.md +7 -5
  80. package/docs/examples/json-benchmark/main-yaml.md +20 -0
  81. package/docs/examples/json-benchmark/main.md +10 -49
  82. package/docs/examples/new-syntax/console.md +10 -52
  83. package/docs/examples/new-syntax/dependencies/august/0.20.1/io/contracts.md +178 -0
  84. package/docs/examples/new-syntax/greeter.md +13 -71
  85. package/docs/examples/new-syntax/index.md +6 -5
  86. package/docs/examples/new-syntax/logger.md +7 -43
  87. package/docs/examples/new-syntax/main.md +10 -53
  88. package/docs/examples/new-syntax/math.md +6 -24
  89. package/docs/examples/oidc-login/client/contracts.md +10 -61
  90. package/docs/examples/oidc-login/client/endpoints.md +32 -154
  91. package/docs/examples/oidc-login/client/export.md +5 -23
  92. package/docs/examples/oidc-login/client/login.md +234 -344
  93. package/docs/examples/oidc-login/client/logout.md +38 -143
  94. package/docs/examples/oidc-login/client/protocol.md +183 -304
  95. package/docs/examples/oidc-login/client/session.md +41 -149
  96. package/docs/examples/oidc-login/client/views.md +13 -58
  97. package/docs/examples/oidc-login/common/export.md +6 -26
  98. package/docs/examples/oidc-login/common/headers.md +42 -72
  99. package/docs/examples/oidc-login/common/keys.md +40 -164
  100. package/docs/examples/oidc-login/common/settings.md +24 -40
  101. package/docs/examples/oidc-login/common/views.md +7 -28
  102. package/docs/examples/oidc-login/dependencies/packages/@git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.md +205 -0
  103. package/docs/examples/oidc-login/dependencies/packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +67 -0
  104. package/docs/examples/oidc-login/dependencies/packages/@git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +267 -0
  105. package/docs/examples/oidc-login/dependencies/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.md +415 -0
  106. package/docs/examples/oidc-login/dependencies/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/jose.md +271 -0
  107. package/docs/examples/oidc-login/dependencies/packages/@git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +89 -0
  108. package/docs/examples/oidc-login/index.md +8 -7
  109. package/docs/examples/oidc-login/main-yaml.md +7 -0
  110. package/docs/examples/oidc-login/main.md +26 -153
  111. package/docs/examples/oidc-login/provider/authorization.md +232 -275
  112. package/docs/examples/oidc-login/provider/contracts.md +24 -146
  113. package/docs/examples/oidc-login/provider/credentials.md +24 -57
  114. package/docs/examples/oidc-login/provider/discovery.md +48 -122
  115. package/docs/examples/oidc-login/provider/export.md +11 -37
  116. package/docs/examples/oidc-login/provider/token.md +159 -237
  117. package/docs/examples/oidc-login/provider/userinfo.md +47 -102
  118. package/docs/examples/oidc-login/provider/views.md +13 -53
  119. package/docs/examples/ownership/counter.md +17 -63
  120. package/docs/examples/ownership/index.md +6 -5
  121. package/docs/examples/ownership/main.md +7 -30
  122. package/docs/examples/ownership-transfer/dependencies/august/0.20.1/io/contracts.md +178 -0
  123. package/docs/examples/ownership-transfer/index.md +6 -5
  124. package/docs/examples/ownership-transfer/main.md +10 -52
  125. package/docs/examples/ownership-transfer/resource.md +15 -67
  126. package/docs/examples/packages-app/dependencies/packages/@example/aug-math/0.1.0/arithmetic.md +12 -50
  127. package/docs/examples/packages-app/index.md +7 -6
  128. package/docs/examples/packages-app/main.md +7 -25
  129. package/docs/examples/packages-math/aug-package-json.md +1 -1
  130. package/docs/examples/packages-math/index.md +7 -6
  131. package/docs/examples/packages-math/src/arithmetic.md +12 -50
  132. package/docs/examples/packages-math/src/export.md +4 -12
  133. package/docs/examples/startup-benchmark/index.md +6 -5
  134. package/docs/examples/startup-benchmark/main.md +5 -17
  135. package/docs/examples/visibility/counter.md +19 -67
  136. package/docs/examples/visibility/index.md +6 -5
  137. package/docs/examples/visibility/main.md +7 -31
  138. package/docs/examples/weather-api/forecasts.md +168 -0
  139. package/docs/examples/weather-api/index.md +42 -0
  140. package/docs/examples/weather-api/main-yaml.md +21 -0
  141. package/docs/examples/weather-api/main.md +65 -0
  142. package/docs/examples.json +10 -0
  143. package/docs/getting-started.md +105 -2
  144. package/docs/grammar.md +6 -4
  145. package/docs/guides/change-a-module.md +64 -0
  146. package/docs/guides/index.md +27 -0
  147. package/docs/index.md +51 -29
  148. package/docs/language-conformance.md +1 -1
  149. package/docs/language-constructs.md +22 -22
  150. package/docs/language-design-audit.md +1 -1
  151. package/docs/learn/data-and-errors.md +77 -0
  152. package/docs/learn/index.md +30 -0
  153. package/docs/learn/modules-and-dependencies.md +73 -0
  154. package/docs/learn/state-and-tests.md +71 -0
  155. package/docs/learn/values-and-functions.md +62 -0
  156. package/docs/lesson-failures.json +8 -0
  157. package/docs/maintaining-docs.md +16 -4
  158. package/docs/packages.md +72 -126
  159. package/docs/performance.md +13 -41
  160. package/docs/production-readiness.md +5 -4
  161. package/docs/public/downloads/approved-design.zip +0 -0
  162. package/docs/public/downloads/benchmark.zip +0 -0
  163. package/docs/public/downloads/cli-args.zip +0 -0
  164. package/docs/public/downloads/collections-benchmark.zip +0 -0
  165. package/docs/public/downloads/collections.zip +0 -0
  166. package/docs/public/downloads/cpu-benchmark.zip +0 -0
  167. package/docs/public/downloads/developer-workflow.zip +0 -0
  168. package/docs/public/downloads/drop.zip +0 -0
  169. package/docs/public/downloads/errors.zip +0 -0
  170. package/docs/public/downloads/ffi.zip +0 -0
  171. package/docs/public/downloads/generic-di.zip +0 -0
  172. package/docs/public/downloads/generics.zip +0 -0
  173. package/docs/public/downloads/hello.zip +0 -0
  174. package/docs/public/downloads/http-benchmark.zip +0 -0
  175. package/docs/public/downloads/interceptors.zip +0 -0
  176. package/docs/public/downloads/json-benchmark.zip +0 -0
  177. package/docs/public/downloads/new-syntax.zip +0 -0
  178. package/docs/public/downloads/oidc-login.zip +0 -0
  179. package/docs/public/downloads/ownership-transfer.zip +0 -0
  180. package/docs/public/downloads/ownership.zip +0 -0
  181. package/docs/public/downloads/packages-app.zip +0 -0
  182. package/docs/public/downloads/packages-math.zip +0 -0
  183. package/docs/public/downloads/startup-benchmark.zip +0 -0
  184. package/docs/public/downloads/visibility.zip +0 -0
  185. package/docs/public/downloads/weather-api.zip +0 -0
  186. package/docs/reference.md +23 -17
  187. package/docs/releasing.md +29 -15
  188. package/docs/research/code-to-natural-language.md +108 -0
  189. package/docs/research/ecosystem-workflow.md +41 -0
  190. package/docs/research/wiki-editorial-design.md +71 -0
  191. package/docs/roadmap.md +1 -1
  192. package/docs/specifications.md +27 -11
  193. package/docs/testing.md +19 -5
  194. package/docs/tooling.md +25 -12
  195. package/docs/weather-api.md +65 -0
  196. package/docs/web.md +50 -18
  197. package/docs/writing-docs.md +49 -0
  198. package/examples/{hello/.aug-spec/august/0.19.0 → approved-design/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
  199. package/examples/approved-design/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
  200. package/examples/approved-design/.aug-spec/manifest.json +3 -3
  201. package/examples/approved-design/counters.aug +5 -4
  202. package/examples/approved-design/counters.aug.md +25 -132
  203. package/examples/approved-design/domain/app.aug +2 -1
  204. package/examples/approved-design/domain/app.aug.md +10 -80
  205. package/examples/approved-design/domain/export.aug +1 -0
  206. package/examples/approved-design/domain/export.aug.md +4 -20
  207. package/examples/approved-design/domain/models.aug +1 -0
  208. package/examples/approved-design/domain/models.aug.md +3 -25
  209. package/examples/approved-design/domain/numbers.aug +3 -2
  210. package/examples/approved-design/domain/numbers.aug.md +19 -116
  211. package/examples/approved-design/main.aug +1 -0
  212. package/examples/approved-design/main.aug.md +12 -95
  213. package/examples/benchmark/.aug-spec/manifest.json +1 -1
  214. package/examples/benchmark/main.aug +1 -0
  215. package/examples/benchmark/main.aug.md +6 -36
  216. package/examples/cli-args/.aug-spec/manifest.json +1 -1
  217. package/examples/cli-args/main.aug +1 -0
  218. package/examples/cli-args/main.aug.md +5 -32
  219. package/examples/collections/.aug-spec/manifest.json +1 -1
  220. package/examples/collections/main.aug +1 -0
  221. package/examples/collections/main.aug.md +6 -36
  222. package/examples/{generic-di/.aug-spec/august/0.19.0 → developer-workflow/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
  223. package/examples/developer-workflow/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
  224. package/examples/developer-workflow/.aug-spec/manifest.json +3 -3
  225. package/examples/developer-workflow/calculator.aug +3 -2
  226. package/examples/developer-workflow/calculator.aug.md +28 -189
  227. package/examples/developer-workflow/logging/console.aug +2 -1
  228. package/examples/developer-workflow/logging/console.aug.md +7 -57
  229. package/examples/developer-workflow/logging/export.aug +1 -0
  230. package/examples/developer-workflow/logging/export.aug.md +3 -15
  231. package/examples/developer-workflow/logging/logger.aug +1 -0
  232. package/examples/developer-workflow/logging/logger.aug.md +6 -46
  233. package/examples/developer-workflow/main.aug +1 -0
  234. package/examples/developer-workflow/main.aug.md +10 -68
  235. package/examples/drop/.aug-spec/manifest.json +1 -1
  236. package/examples/drop/main.aug +1 -0
  237. package/examples/drop/main.aug.md +6 -28
  238. package/examples/drop/resource.aug +1 -0
  239. package/examples/drop/resource.aug.md +6 -34
  240. package/examples/errors/.aug-spec/manifest.json +1 -1
  241. package/examples/errors/errors.aug +2 -1
  242. package/examples/errors/errors.aug.md +4 -27
  243. package/examples/errors/main.aug +1 -0
  244. package/examples/errors/main.aug.md +6 -29
  245. package/examples/ffi/.aug-spec/manifest.json +1 -1
  246. package/examples/ffi/main.aug +1 -0
  247. package/examples/ffi/main.aug.md +5 -21
  248. package/examples/ffi/native.aug +2 -1
  249. package/examples/ffi/native.aug.md +5 -35
  250. package/examples/{approved-design/.aug-spec/august/0.19.0 → generic-di/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
  251. package/examples/generic-di/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
  252. package/examples/generic-di/.aug-spec/manifest.json +3 -3
  253. package/examples/generic-di/main.aug +1 -0
  254. package/examples/generic-di/main.aug.md +8 -40
  255. package/examples/generic-di/types.aug +3 -2
  256. package/examples/generic-di/types.aug.md +18 -97
  257. package/examples/generics/.aug-spec/manifest.json +1 -1
  258. package/examples/generics/main.aug +1 -0
  259. package/examples/generics/main.aug.md +9 -48
  260. package/examples/generics/types.aug +4 -3
  261. package/examples/generics/types.aug.md +18 -104
  262. package/examples/{developer-workflow/.aug-spec/august/0.19.0 → hello/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
  263. package/examples/hello/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
  264. package/examples/hello/.aug-spec/manifest.json +3 -3
  265. package/examples/hello/app/export.aug +1 -0
  266. package/examples/hello/app/export.aug.md +3 -13
  267. package/examples/hello/app/greeter.aug +2 -1
  268. package/examples/hello/app/greeter.aug.md +10 -94
  269. package/examples/hello/logging/console.aug +2 -1
  270. package/examples/hello/logging/console.aug.md +7 -55
  271. package/examples/hello/logging/export.aug +1 -0
  272. package/examples/hello/logging/export.aug.md +3 -15
  273. package/examples/hello/logging/logger.aug +1 -0
  274. package/examples/hello/logging/logger.aug.md +6 -48
  275. package/examples/hello/main.aug +1 -0
  276. package/examples/hello/main.aug.md +8 -40
  277. package/examples/interceptors/.aug-spec/august/0.20.1/io/contracts.aug +37 -0
  278. package/examples/interceptors/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
  279. package/examples/interceptors/.aug-spec/manifest.json +3 -3
  280. package/examples/interceptors/app.aug +3 -2
  281. package/examples/interceptors/app.aug.md +15 -141
  282. package/examples/interceptors/interceptors.aug +3 -2
  283. package/examples/interceptors/interceptors.aug.md +19 -152
  284. package/examples/interceptors/logging.aug +2 -1
  285. package/examples/interceptors/logging.aug.md +10 -79
  286. package/examples/interceptors/main.aug +1 -0
  287. package/examples/interceptors/main.aug.md +9 -66
  288. package/examples/new-syntax/.aug-spec/august/0.20.1/io/contracts.aug +37 -0
  289. package/examples/new-syntax/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
  290. package/examples/new-syntax/.aug-spec/manifest.json +3 -3
  291. package/examples/new-syntax/console.aug +2 -1
  292. package/examples/new-syntax/console.aug.md +7 -53
  293. package/examples/new-syntax/greeter.aug +2 -1
  294. package/examples/new-syntax/greeter.aug.md +10 -74
  295. package/examples/new-syntax/logger.aug +1 -0
  296. package/examples/new-syntax/logger.aug.md +6 -46
  297. package/examples/new-syntax/main.aug +1 -0
  298. package/examples/new-syntax/main.aug.md +9 -54
  299. package/examples/new-syntax/math.aug +2 -1
  300. package/examples/new-syntax/math.aug.md +3 -24
  301. package/examples/oidc-login/.aug-spec/manifest.json +13 -13
  302. package/examples/oidc-login/.aug-spec/packages/@git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md +71 -0
  303. package/examples/oidc-login/.aug-spec/packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md +17 -0
  304. package/examples/oidc-login/.aug-spec/packages/@git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md +125 -0
  305. package/examples/oidc-login/.aug-spec/{august/0.19.0/crypto → packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40}/contracts.aug +12 -11
  306. package/examples/oidc-login/.aug-spec/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md +244 -0
  307. package/examples/oidc-login/.aug-spec/{august/0.19.0/crypto → packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40}/jose.aug +6 -5
  308. package/examples/oidc-login/.aug-spec/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/jose.aug.md +71 -0
  309. package/examples/oidc-login/.aug-spec/packages/@git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md +30 -0
  310. package/examples/oidc-login/aug.lock.json +100 -0
  311. package/examples/oidc-login/client/contracts.aug +1 -0
  312. package/examples/oidc-login/client/contracts.aug.md +9 -66
  313. package/examples/oidc-login/client/endpoints.aug +6 -5
  314. package/examples/oidc-login/client/endpoints.aug.md +13 -145
  315. package/examples/oidc-login/client/export.aug +1 -0
  316. package/examples/oidc-login/client/export.aug.md +4 -24
  317. package/examples/oidc-login/client/login.aug +7 -6
  318. package/examples/oidc-login/client/login.aug.md +25 -303
  319. package/examples/oidc-login/client/logout.aug +5 -4
  320. package/examples/oidc-login/client/logout.aug.md +13 -135
  321. package/examples/oidc-login/client/protocol.aug +7 -6
  322. package/examples/oidc-login/client/protocol.aug.md +36 -283
  323. package/examples/oidc-login/client/session.aug +5 -4
  324. package/examples/oidc-login/client/session.aug.md +12 -139
  325. package/examples/oidc-login/client/views.aug +3 -2
  326. package/examples/oidc-login/client/views.aug.md +8 -57
  327. package/examples/oidc-login/common/export.aug +1 -0
  328. package/examples/oidc-login/common/export.aug.md +5 -27
  329. package/examples/oidc-login/common/headers.aug +4 -3
  330. package/examples/oidc-login/common/headers.aug.md +9 -67
  331. package/examples/oidc-login/common/keys.aug +6 -5
  332. package/examples/oidc-login/common/keys.aug.md +29 -165
  333. package/examples/oidc-login/common/settings.aug +2 -1
  334. package/examples/oidc-login/common/settings.aug.md +5 -39
  335. package/examples/oidc-login/common/views.aug +2 -1
  336. package/examples/oidc-login/common/views.aug.md +4 -28
  337. package/examples/oidc-login/main.aug +6 -16
  338. package/examples/oidc-login/main.aug.md +17 -146
  339. package/examples/oidc-login/main.yaml +7 -0
  340. package/examples/oidc-login/provider/authorization.aug +7 -6
  341. package/examples/oidc-login/provider/authorization.aug.md +23 -238
  342. package/examples/oidc-login/provider/contracts.aug +1 -0
  343. package/examples/oidc-login/provider/contracts.aug.md +23 -158
  344. package/examples/oidc-login/provider/credentials.aug +3 -2
  345. package/examples/oidc-login/provider/credentials.aug.md +9 -53
  346. package/examples/oidc-login/provider/discovery.aug +4 -3
  347. package/examples/oidc-login/provider/discovery.aug.md +11 -118
  348. package/examples/oidc-login/provider/export.aug +1 -0
  349. package/examples/oidc-login/provider/export.aug.md +6 -34
  350. package/examples/oidc-login/provider/token.aug +6 -5
  351. package/examples/oidc-login/provider/token.aug.md +16 -204
  352. package/examples/oidc-login/provider/userinfo.aug +4 -3
  353. package/examples/oidc-login/provider/userinfo.aug.md +10 -92
  354. package/examples/oidc-login/provider/views.aug +3 -2
  355. package/examples/oidc-login/provider/views.aug.md +8 -52
  356. package/examples/ownership/.aug-spec/manifest.json +1 -1
  357. package/examples/ownership/counter.aug +3 -2
  358. package/examples/ownership/counter.aug.md +12 -66
  359. package/examples/ownership/main.aug +1 -0
  360. package/examples/ownership/main.aug.md +6 -31
  361. package/examples/ownership-transfer/.aug-spec/august/0.20.1/io/contracts.aug +37 -0
  362. package/examples/ownership-transfer/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
  363. package/examples/ownership-transfer/.aug-spec/manifest.json +3 -3
  364. package/examples/ownership-transfer/main.aug +1 -0
  365. package/examples/ownership-transfer/main.aug.md +9 -53
  366. package/examples/ownership-transfer/resource.aug +2 -1
  367. package/examples/ownership-transfer/resource.aug.md +12 -71
  368. package/examples/packages/app/.aug-spec/manifest.json +1 -1
  369. package/examples/packages/app/.aug-spec/packages/@example/aug-math/0.1.0/arithmetic.aug +2 -1
  370. package/examples/packages/app/.aug-spec/packages/@example/aug-math/0.1.0/arithmetic.aug.md +9 -51
  371. package/examples/packages/app/main.aug +1 -0
  372. package/examples/packages/app/main.aug.md +6 -26
  373. package/examples/packages/math/.aug-spec/manifest.json +1 -1
  374. package/examples/packages/math/aug-package.json +1 -1
  375. package/examples/packages/math/src/arithmetic.aug +2 -1
  376. package/examples/packages/math/src/arithmetic.aug.md +9 -51
  377. package/examples/packages/math/src/export.aug +1 -0
  378. package/examples/packages/math/src/export.aug.md +3 -13
  379. package/examples/visibility/.aug-spec/manifest.json +1 -1
  380. package/examples/visibility/counter.aug +4 -3
  381. package/examples/visibility/counter.aug.md +12 -68
  382. package/examples/visibility/main.aug +1 -0
  383. package/examples/visibility/main.aug.md +6 -32
  384. package/examples/weather-api/.aug-spec/manifest.json +8 -0
  385. package/examples/weather-api/AGENTS.md +17 -0
  386. package/examples/weather-api/README.md +19 -0
  387. package/examples/weather-api/forecasts.aug +47 -0
  388. package/examples/weather-api/forecasts.aug.md +32 -0
  389. package/examples/weather-api/main.aug +4 -0
  390. package/examples/weather-api/main.aug.md +15 -0
  391. package/examples/weather-api/main.yaml +5 -0
  392. package/examples/weather-api/weather.http +5 -0
  393. package/package.json +3 -4
  394. package/scripts/bootstrap-native.mjs +181 -106
  395. package/scripts/native-setup.mjs +98 -0
  396. package/scripts/native-toolchain.mjs +28 -0
  397. package/src/builtins.js +1 -1
  398. package/src/checker.js +259 -72
  399. package/src/cli.js +114 -20
  400. package/src/codegen.js +1 -1
  401. package/src/config.js +1 -1
  402. package/src/contracts.js +10 -0
  403. package/src/editor.js +71 -16
  404. package/src/fixes.js +90 -2
  405. package/src/formatter.js +19 -8
  406. package/src/git-packages.js +110 -0
  407. package/src/help.js +24 -23
  408. package/src/http-contracts.js +14 -0
  409. package/src/http-policies.js +5 -5
  410. package/src/libraries.js +1 -1
  411. package/src/lsp.js +14 -5
  412. package/src/native.js +19 -13
  413. package/src/navigation.js +4 -2
  414. package/src/openapi.js +5 -4
  415. package/src/package-locking.js +45 -0
  416. package/src/package-manager.js +251 -67
  417. package/src/parser.js +13 -5
  418. package/src/policies.js +3 -3
  419. package/src/project-init.js +78 -4
  420. package/src/project.js +9 -7
  421. package/src/semantic.js +46 -2
  422. package/src/snippets.js +59 -0
  423. package/src/spec-hints.js +56 -0
  424. package/src/spec-tree.js +241 -0
  425. package/src/spec.js +626 -303
  426. package/docs/examples/approved-design/dependencies/august/0.19.0/io/contracts.md +0 -395
  427. package/docs/examples/developer-workflow/dependencies/august/0.19.0/io/contracts.md +0 -395
  428. package/docs/examples/generic-di/dependencies/august/0.19.0/io/contracts.md +0 -395
  429. package/docs/examples/hello/dependencies/august/0.19.0/io/contracts.md +0 -395
  430. package/docs/examples/interceptors/dependencies/august/0.19.0/io/contracts.md +0 -395
  431. package/docs/examples/json-benchmark/dependencies/august/0.19.0/json/contracts.md +0 -103
  432. package/docs/examples/new-syntax/dependencies/august/0.19.0/io/contracts.md +0 -395
  433. package/docs/examples/oidc-login/dependencies/august/0.19.0/crypto/contracts.md +0 -925
  434. package/docs/examples/oidc-login/dependencies/august/0.19.0/crypto/jose.md +0 -434
  435. package/docs/examples/oidc-login/dependencies/august/0.19.0/json/contracts.md +0 -103
  436. package/docs/examples/oidc-login/dependencies/august/0.19.0/memory/store.md +0 -374
  437. package/docs/examples/oidc-login/dependencies/august/0.19.0/time/contracts.md +0 -150
  438. package/docs/examples/oidc-login/dependencies/august/0.19.0/web/contracts.md +0 -532
  439. package/docs/examples/ownership-transfer/dependencies/august/0.19.0/io/contracts.md +0 -395
  440. package/examples/approved-design/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  441. package/examples/developer-workflow/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  442. package/examples/generic-di/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  443. package/examples/hello/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  444. package/examples/interceptors/.aug-spec/august/0.19.0/io/contracts.aug +0 -36
  445. package/examples/interceptors/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  446. package/examples/new-syntax/.aug-spec/august/0.19.0/io/contracts.aug +0 -36
  447. package/examples/new-syntax/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  448. package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/contracts.aug.md +0 -791
  449. package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/jose.aug.md +0 -266
  450. package/examples/oidc-login/.aug-spec/august/0.19.0/json/contracts.aug.md +0 -55
  451. package/examples/oidc-login/.aug-spec/august/0.19.0/memory/store.aug.md +0 -250
  452. package/examples/oidc-login/.aug-spec/august/0.19.0/time/contracts.aug.md +0 -96
  453. package/examples/oidc-login/.aug-spec/august/0.19.0/web/contracts.aug.md +0 -420
  454. package/examples/ownership-transfer/.aug-spec/august/0.19.0/io/contracts.aug +0 -36
  455. package/examples/ownership-transfer/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  456. /package/examples/oidc-login/.aug-spec/{august/0.19.0/memory → packages/@git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/store.aug +0 -0
  457. /package/examples/oidc-login/.aug-spec/{august/0.19.0/json → packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/contracts.aug +0 -0
  458. /package/examples/oidc-login/.aug-spec/{august/0.19.0/web → packages/@git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/contracts.aug +0 -0
  459. /package/examples/oidc-login/.aug-spec/{august/0.19.0/time → packages/@git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/contracts.aug +0 -0
package/src/checker.js CHANGED
@@ -10,14 +10,16 @@ import { builtinType as builtin, builtinTypes, builtinProperties, collectionOper
10
10
  import { orderGraph } from "./di.js";
11
11
  import { javadocBefore } from "./javadoc.js";
12
12
  import { callableDocumentation } from "./documentation.js";
13
+ import { nativeHttpContracts } from "./http-contracts.js";
13
14
  import { jsonDataType } from "./schemas.js";
14
15
  import { htmlTags, htmlVoidTags, htmlAttribute, htmlUrlAttributes } from "./html.js";
15
16
  import { generateOpenApi } from "./openapi.js";
16
- import { httpPolicyNames, checkHttpPolicy } from "./http-policies.js";
17
+ import { httpPolicyNames, httpPolicyOptions, checkHttpPolicy } from "./http-policies.js";
17
18
  export { tyName } from "./types.js";
18
19
  const builtinNames = new Set(Object.keys(builtinTypes));
19
20
  const errorTy = { id: 'error', name: '<error>', kind: 'error', args: [], nullable: false };
20
21
  const nullTy = { id: 'null', name: 'null', kind: 'null', args: [], nullable: true };
22
+ const unresolved = (type) => type.kind === 'error' || type.args.some(unresolved);
21
23
  export function checkProject(project) {
22
24
  const checker = new Checker(project);
23
25
  const checked = checker.check();
@@ -34,6 +36,11 @@ class Checker {
34
36
  bindings = [];
35
37
  interceptorPlans = new Map();
36
38
  effectContracts = new Map();
39
+ callableContracts = new Map();
40
+ constructorContracts = new Map();
41
+ initializers = new Map();
42
+ inferredChanges = new Map();
43
+ contextualResults = new Set();
37
44
  expressionOrigins = new WeakMap();
38
45
  scopes = new Map();
39
46
  markupCalls = new WeakMap();
@@ -48,11 +55,33 @@ class Checker {
48
55
  changingInference = new Set();
49
56
  constructor(project) { this.project = project; this.diagnostics = [...project.diagnostics]; }
50
57
  check() {
58
+ // Make inherited default bodies visible to forward calls during inference.
59
+ this.inferring = true;
60
+ for (const def of this.project.definitions.values())
61
+ if (def.node.kind === 'class') {
62
+ const methods = new Map();
63
+ const types = this.paramsFor(def.node.typeParams, def.node, def.file);
64
+ for (const ref of def.node.implements)
65
+ for (const [name, entries] of this.interfaceMethods(this.resolveType(ref, def.file, types), new Set()))
66
+ if (!def.node.methods.some(method => method.name === name)) {
67
+ const entry = entries.find(entry => entry.method.body);
68
+ if (entry)
69
+ methods.set(name, entry);
70
+ }
71
+ this.defaults.set(def.id, methods);
72
+ }
73
+ this.inferring = false;
74
+ this.inferImplementationEffects();
51
75
  for (const def of this.project.definitions.values())
52
76
  if (def.node.kind === 'interceptor')
53
77
  this.checkInterceptorShape(def);
54
78
  this.planInterceptors();
55
- this.inferImplementationEffects();
79
+ this.constructorFreshness.clear();
80
+ // Layers can add contracts to callers. Recompute after their mappings exist.
81
+ this.inferImplementationEffects(false);
82
+ for (const layers of this.interceptorPlans.values())
83
+ for (const layer of layers)
84
+ layer.errors = this.bodyErrors(layer.around, layer.definition.file, layer.types);
56
85
  for (const def of this.project.definitions.values()) {
57
86
  if (def.node.kind === 'class')
58
87
  this.checkClassShape(def);
@@ -67,12 +96,9 @@ class Checker {
67
96
  if (def.node.kind === 'function' && def.node.body)
68
97
  this.checkFunctionBody(def.node, def.file);
69
98
  if (def.node.kind === 'class') {
70
- if (initializationOf(def.node).length)
71
- this.checkFunctionBody({
72
- kind: 'function', name: def.name, typeParams: [], params: [],
73
- returns: syntheticType('void', def.node.span), returnOwnership: 'managed',
74
- throws: def.node.validationErrors ?? [], body: initializationOf(def.node), externC: false, span: def.node.span,
75
- }, def.file, def, true);
99
+ const initializer = this.initializers.get(def.node);
100
+ if (initializer)
101
+ this.checkFunctionBody(initializer, def.file, def, true);
76
102
  for (const method of def.node.methods)
77
103
  if (method.body)
78
104
  this.checkFunctionBody(method, def.file, def);
@@ -96,15 +122,32 @@ class Checker {
96
122
  returns: layer.outputType, returnOwnership: layer.around.returnOwnership,
97
123
  indices: layer.argumentIndices });
98
124
  }
99
- for (const [node] of this.interceptorPlans)
100
- if (node.annotations?.length) {
101
- const source = this.project.files.get(node.span.file)?.source ?? '';
102
- const doc = javadocBefore(source, node.annotations[0].span.start);
103
- const errors = this.effectiveErrors(node, node.span.file, this.paramsFor(node.typeParams, node, node.span.file));
104
- for (const tag of doc?.tags ?? [])
125
+ for (const def of this.project.definitions.values()) {
126
+ if (this.project.files.get(def.file)?.builtin)
127
+ continue;
128
+ const methods = def.node.kind === 'function' ? [def.node] : 'methods' in def.node ? def.node.methods : [];
129
+ for (const method of methods) {
130
+ const source = this.project.files.get(def.file)?.source ?? '';
131
+ const doc = javadocBefore(source, method.annotations?.[0]?.span.start ?? method.span.start);
132
+ const types = new Map([...this.paramsFor(def.node.typeParams, def.node, def.file), ...this.paramsFor(method.typeParams, method, def.file)]);
133
+ const errors = this.effectiveErrors(method, def.file, types);
134
+ for (const tag of doc?.tags ?? []) {
135
+ if (['return', 'returns'].includes(tag.name) && this.returnType(method, def.file, types).name === 'void')
136
+ this.report(method.span, `@${tag.name} requires a value-returning callable`, 'DOC');
105
137
  if (['throws', 'exception'].includes(tag.name) && !errors.some(error => tyName(error) === tag.value.split(/\s/)[0]))
106
- this.report(node.span, `@${tag.name} ${tag.value.split(/\s/)[0]} is absent from ${node.name}'s effective unless contract`, 'DOC');
138
+ this.report(method.span, `@${tag.name} ${tag.value.split(/\s/)[0]} is absent from ${method.name}'s effective unless contract`, 'DOC');
139
+ }
140
+ }
141
+ if (def.node.kind === 'class' && def.node.record && def.node.validationDeclared === false) {
142
+ const source = this.project.files.get(def.file)?.source ?? '';
143
+ const doc = javadocBefore(source, def.node.span.start);
144
+ const errors = this.effectiveErrors(def.node, def.file, this.paramsFor(def.node.typeParams, def.node, def.file));
145
+ for (const tag of doc?.tags ?? [])
146
+ if (['throws', 'exception'].includes(tag.name) &&
147
+ !errors.some(error => tyName(error) === tag.value.split(/\s/)[0]))
148
+ this.report(def.node.span, `@${tag.name} ${tag.value.split(/\s/)[0]} is absent from ${def.node.name}'s inferred validation errors`, 'DOC');
107
149
  }
150
+ }
108
151
  if (this.project.main) {
109
152
  const context = { file: this.project.main.path, locals: new Map(),
110
153
  returns: builtin('void'), returnOwnership: 'managed', allowedErrors: this.project.testMode ? [builtin('Error')] : [],
@@ -133,7 +176,7 @@ class Checker {
133
176
  this.report(def.node.span, '/__aug/actions.js is reserved for HTTP action transport', 'HTTP');
134
177
  return { project: this.project, diagnostics: this.diagnostics, bindings: this.bindings,
135
178
  expressionTypes: this.expressionTypes, defaults: this.defaults, callPlans: this.callPlans,
136
- interceptorPlans: this.interceptorPlans, effectContracts: this.effectContracts,
179
+ interceptorPlans: this.interceptorPlans, effectContracts: this.effectContracts, callableContracts: this.callableContracts, constructorContracts: this.constructorContracts,
137
180
  expressionOrigins: this.expressionOrigins, scopes: this.scopes, markupCalls: this.markupCalls, actions: this.actions, httpPolicies: this.httpPolicies };
138
181
  }
139
182
  isStatement(item) {
@@ -144,48 +187,84 @@ class Checker {
144
187
  return;
145
188
  this.diagnostics.push({ file: span.file, line: span.line, column: span.column, message, code });
146
189
  }
147
- /** Infer implementation details before comparing them with public contracts. */
148
- inferImplementationEffects() {
190
+ /** Infer body-derived contracts without changing the cached source AST. */
191
+ inferImplementationEffects(initialize = true) {
149
192
  const bodies = [];
150
193
  for (const definition of this.project.definitions.values()) {
151
194
  const node = definition.node;
195
+ if (node.kind === 'class' && initializationOf(node).length) {
196
+ if (initialize) {
197
+ const initializer = { kind: 'function', name: node.name, typeParams: [], params: [],
198
+ returns: syntheticType('void', node.span), returnOwnership: 'managed', throws: node.validationErrors ?? [],
199
+ body: initializationOf(node), externC: false, span: node.span };
200
+ const errors = (node.validationErrors ?? []).map(ref => this.resolveType(ref, definition.file, this.paramsFor(node.typeParams, node, definition.file)));
201
+ const contract = { result: builtin('void'), errors, inferredResult: false,
202
+ inferredErrors: !!node.record && node.validationDeclared === false };
203
+ this.initializers.set(node, initializer);
204
+ this.callableContracts.set(initializer, contract);
205
+ this.constructorContracts.set(node, contract);
206
+ }
207
+ bodies.push({ method: this.initializers.get(node), definition, owner: definition, initializing: true });
208
+ }
152
209
  const methods = node.kind === 'function' ? [node] : 'methods' in node ? node.methods : [];
210
+ const types = this.paramsFor(node.typeParams, node, definition.file);
153
211
  for (const method of methods) {
154
- if (!method.body || method.externC || method.uses?.length || method.name === 'drop')
155
- continue;
156
- if (node.kind !== 'class' && !isPrivateName(method.name))
157
- continue;
158
- if (node.kind === 'interface')
159
- continue;
160
- this.inferredUses.set(method, new Map());
161
- bodies.push({ method, definition, owner: node.kind === 'function' ? undefined : definition });
212
+ const eligible = !!method.body && !method.externC && method.name !== 'drop';
213
+ if (initialize) {
214
+ const params = new Map([...types, ...this.paramsFor(method.typeParams, method, definition.file)]);
215
+ this.callableContracts.set(method, {
216
+ result: eligible && method.declared?.returns === false ? errorTy : this.resolveType(method.returns, definition.file, params),
217
+ errors: method.throws.map(ref => this.resolveType(ref, definition.file, params)),
218
+ inferredResult: eligible && method.declared?.returns === false,
219
+ inferredErrors: eligible && method.declared?.errors === false,
220
+ });
221
+ if (eligible && !method.uses?.length)
222
+ this.inferredUses.set(method, new Map());
223
+ if (eligible && !method.changes?.length)
224
+ this.inferredChanges.set(method, new Set());
225
+ }
226
+ if (eligible)
227
+ bodies.push({ method, definition, owner: node.kind === 'function' ? undefined : definition });
162
228
  }
163
229
  }
164
230
  this.inferring = true;
165
231
  try {
166
- for (const { method, owner } of bodies)
167
- if (owner?.node.kind === 'class') {
232
+ for (const { method, owner, initializing } of bodies)
233
+ if (!initializing && owner?.node.kind === 'class') {
168
234
  const types = this.paramsFor(owner.node.typeParams, owner.node, owner.file);
169
235
  for (const ref of owner.node.implements) {
170
236
  const implemented = this.resolveType(ref, owner.file, types);
171
237
  for (const entry of this.interfaceMethods(implemented, new Set()).get(method.name) ?? []) {
172
238
  const contractOwner = this.project.definitions.get(entry.from);
239
+ if (initialize && this.callableContracts.get(method)?.inferredResult && !entry.method.body) {
240
+ const interfaceTypes = new Map(entry.params);
241
+ entry.method.typeParams.forEach((name, index) => {
242
+ const own = this.paramsFor(method.typeParams, method, owner.file).get(method.typeParams[index]);
243
+ if (own)
244
+ interfaceTypes.set(name, own);
245
+ });
246
+ this.callableContracts.get(method).result = this.returnType(entry.method, entry.file, interfaceTypes);
247
+ this.contextualResults.add(method);
248
+ }
173
249
  if (contractOwner?.node.kind !== 'interface' || !contractOwner.node.capability)
174
250
  continue;
175
- // Invoking a capability is itself an effect, including synchronized stores and test adapters.
251
+ // Invoking a capability is an effect even for a pure test adapter.
176
252
  const contract = this.contractFor(entry.method, entry.file, contractOwner, entry.params);
177
253
  for (const [key, effect] of contract.uses)
178
- this.inferredUses.get(method).set(key, effect);
254
+ this.inferredUses.get(method)?.set(key, effect);
179
255
  }
180
256
  }
181
257
  }
182
- // A fixed point makes forward references and recursive helper calls order independent.
183
- // Type-changing generic recursion must provide an explicit finite contract.
184
- for (let pass = 0; pass <= bodies.length; pass++) {
258
+ // Forward references and recursive calls reach the same deterministic fixed point.
259
+ for (let pass = 0; pass <= bodies.length + 1; pass++) {
260
+ this.constructorFreshness.clear();
185
261
  this.inferenceChanged = false;
186
262
  this.changingInference.clear();
187
- for (const { method, definition, owner } of bodies)
188
- this.checkFunctionBody(method, definition.file, owner);
263
+ for (const { method, definition, owner, initializing } of bodies) {
264
+ const types = this.paramsFor(owner && 'typeParams' in owner.node ? owner.node.typeParams : [], owner?.node, definition.file);
265
+ const next = owner?.node.kind === 'interceptor' && method.name === 'around' ? this.nextFor(method, definition.file, types) : undefined;
266
+ this.checkFunctionBody(method, definition.file, owner, initializing, undefined, next);
267
+ }
189
268
  if (!this.inferenceChanged)
190
269
  return;
191
270
  }
@@ -194,7 +273,39 @@ class Checker {
194
273
  this.inferring = false;
195
274
  }
196
275
  for (const method of this.changingInference)
197
- this.report(method.span, `Effect inference for ${method.name} did not reach a finite contract; declare uses on recursive generic helpers`, 'EFFECT');
276
+ this.report(method.span, `Contract inference for ${method.name} did not reach a finite contract; declare returns, uses, or unless on recursive generic helpers`, 'INFERENCE');
277
+ }
278
+ returnType(fn, file, types = new Map()) {
279
+ const contract = this.callableContracts.get(fn);
280
+ return contract ? this.substitute(contract.result, types) : this.resolveType(fn.returns, file, types);
281
+ }
282
+ bodyErrors(fn, file, types = new Map()) {
283
+ const contract = this.callableContracts.get(fn);
284
+ return contract ? contract.errors.map(type => this.substitute(type, types)) : fn.throws.map(ref => this.resolveType(ref, file, types));
285
+ }
286
+ markInference(fn) {
287
+ this.inferenceChanged = true;
288
+ this.changingInference.add(fn);
289
+ }
290
+ inferredReturn(types) {
291
+ const known = types.filter(type => type.kind !== 'error');
292
+ if (!known.length)
293
+ return types.length ? errorTy : builtin('void');
294
+ let result = known[0];
295
+ for (const type of known.slice(1)) {
296
+ if (unresolved(result) && !unresolved(type))
297
+ result = type;
298
+ else if (type.kind === 'null' && result.kind !== 'null')
299
+ result = { ...result, nullable: true, optional: true };
300
+ else if (result.kind === 'null' && type.kind !== 'null')
301
+ result = { ...type, nullable: true, optional: true };
302
+ else if (this.assignable(type, result))
303
+ continue;
304
+ else if (this.assignable(result, type))
305
+ result = type;
306
+ // Keep the first type; the final checking pass diagnoses incompatible returns.
307
+ }
308
+ return result;
198
309
  }
199
310
  checkMemberVisibility(ownerId, ownerName, name, span, context) {
200
311
  if (isPrivateName(name) && context.self?.id !== ownerId)
@@ -289,8 +400,10 @@ class Checker {
289
400
  iface.extends.forEach(ref => visit(ref, 1));
290
401
  iface.methods.forEach(method => {
291
402
  method.params.forEach(param => visit(param.type, -1));
292
- visit(method.returns, 1);
293
- method.throws.forEach(ref => visit(ref, 1));
403
+ const result = this.callableContracts.get(method)?.result;
404
+ const reference = (type) => ({ name: type.name, args: type.args.map(reference), nullable: type.nullable, optional: type.optional, span: method.span });
405
+ visit(result ? reference(result) : method.returns, 1);
406
+ (this.callableContracts.get(method)?.errors.map(reference) ?? method.throws).forEach(ref => visit(ref, 1));
294
407
  });
295
408
  }
296
409
  checkFunctionSignature(fn, file, inheritedParams) {
@@ -313,7 +426,7 @@ class Checker {
313
426
  this.report(param.span, 'A resolve parameter cannot also be own or borrow', 'DI');
314
427
  this.resolveType(param.type, file, params);
315
428
  }
316
- this.resolveType(fn.returns, file, params);
429
+ this.returnType(fn, file, params);
317
430
  if (fn.endpoint) {
318
431
  const endpoint = fn.endpoint;
319
432
  if (!/^[A-Z]+$/.test(endpoint.method))
@@ -342,7 +455,7 @@ class Checker {
342
455
  if (param.source?.kind === 'request' && type.name !== 'HttpRequest')
343
456
  this.report(param.span, 'from request provides HttpRequest', 'HTTP');
344
457
  }
345
- const result = this.resolveType(fn.returns, file, params);
458
+ const result = this.returnType(fn, file, params);
346
459
  if (endpoint.streams) {
347
460
  if (!['ServerEvent', 'Bytes', 'Html'].includes(result.name) || result.optional || result.nullable)
348
461
  this.report(fn.span, 'An endpoint streams ServerEvent<T>, Bytes, or Html', 'HTTP');
@@ -414,7 +527,7 @@ class Checker {
414
527
  this.report(method.span, 'Declare generic parameters on the interceptor, rather than around', 'INTERCEPTOR');
415
528
  if (method.annotations?.length)
416
529
  this.report(method.span, 'Apply interceptor layers to the target declaration; around cannot be annotated', 'INTERCEPTOR');
417
- if (method.returns.name !== 'void' && canFallThrough(method.body ?? []))
530
+ if (this.returnType(method, def.file, types).name !== 'void' && canFallThrough(method.body ?? []))
418
531
  this.report(method.span, 'around must return its result or throw on every execution path', 'INTERCEPTOR');
419
532
  if (canRepeatNext(method.body ?? []))
420
533
  this.report(method.span, 'next may be called at most once on each execution path; a loop or catch path can call it again', 'NEXT');
@@ -424,8 +537,11 @@ class Checker {
424
537
  this.report(node.span, `${node.name} must define around(...)`, 'INTERCEPTOR');
425
538
  }
426
539
  nextFor(method, file, types) {
540
+ const result = this.returnType(method, file, types);
427
541
  return { params: method.params, types: method.params.map(param => this.resolveType(param.type, file, types)),
428
- returns: this.resolveType(method.returns, file, types), returnOwnership: method.returnOwnership };
542
+ returns: result.kind === 'error' && method.declared?.returns === false ?
543
+ { id: 'continuation:' + file + ':' + method.span.start, name: '<target result>', kind: 'param', args: [], nullable: false } : result,
544
+ returnOwnership: method.returnOwnership };
429
545
  }
430
546
  inferInterceptorType(ref, actual, names, types, file) {
431
547
  inferType(ref, actual, names, types, message => this.report(ref.span, message, 'GENERIC'), (name, value) => {
@@ -450,6 +566,24 @@ class Checker {
450
566
  }
451
567
  return undefined;
452
568
  }
569
+ /** The native policy ABI accepts the published capability shape across source-package identities. */
570
+ nativeWebCapability(type, name) {
571
+ const canonical = nativeHttpContracts.get(name);
572
+ const shape = (value) => {
573
+ if (Array.isArray(value))
574
+ return value.map(shape);
575
+ if (!value || typeof value !== 'object')
576
+ return value;
577
+ return Object.fromEntries(Object.entries(value).filter(([key]) => !['span', 'nameSpan', 'headerEnd'].includes(key)).map(([key, child]) => [key, shape(child)]));
578
+ };
579
+ if (!canonical || !type.def || JSON.stringify(shape(type.def.node)) !== JSON.stringify(shape(canonical)))
580
+ return false;
581
+ if (name === 'RequestLogger')
582
+ return true;
583
+ const principal = this.project.scopes.get(type.def.file)?.get('Principal');
584
+ const expected = nativeHttpContracts.get('Principal');
585
+ return !!principal && !!expected && JSON.stringify(shape(principal.node)) === JSON.stringify(shape(expected));
586
+ }
453
587
  planInterceptors() {
454
588
  const plan = (node, file, ownerTypes, inputs, output, ownership) => {
455
589
  const layers = [];
@@ -465,7 +599,7 @@ class Checker {
465
599
  const policies = this.httpPolicies.get(node) ?? [];
466
600
  if (['Cors', 'Compress'].includes(annotation.name) && policies.some(policy => policy.name === annotation.name))
467
601
  this.report(annotation.span, `${annotation.name} may appear only once on an endpoint`, 'HTTP');
468
- policies.push(checkHttpPolicy(annotation, node, this.diagnostics, (param, name) => this.resolveType(param.type, file, ownerTypes).id === `august/web/contracts.aug:${name}`));
602
+ policies.push(checkHttpPolicy(annotation, node, this.diagnostics, (param, name) => this.nativeWebCapability(this.resolveType(param.type, file, ownerTypes), name)));
469
603
  this.httpPolicies.set(node, policies);
470
604
  }
471
605
  continue;
@@ -511,7 +645,16 @@ class Checker {
511
645
  types.set(name, this.resolveType(annotation.typeArgs[index], file, ownerTypes));
512
646
  });
513
647
  const inferredNames = interceptor.typeParams.filter((_, index) => !annotation.typeArgs[index]);
514
- this.inferInterceptorType(around.returns, output, inferredNames, types, definition.file);
648
+ const inferredOutput = this.callableContracts.get(around);
649
+ if (inferredOutput?.inferredResult) {
650
+ types.set('<target result>', output);
651
+ if (inferredOutput.result.name !== '<target result>') {
652
+ const reference = (type) => ({ name: type.name, args: type.args.map(reference), nullable: type.nullable, optional: type.optional, span: around.span });
653
+ this.inferInterceptorType(reference(inferredOutput.result), output, inferredNames, types, definition.file);
654
+ }
655
+ }
656
+ else
657
+ this.inferInterceptorType(around.returns, output, inferredNames, types, definition.file);
515
658
  const argumentIndices = around.params.map(param => param.injected ? undefined :
516
659
  inputs.findIndex(input => input.name === (mapping.get(param.name) ?? param.name)));
517
660
  const inputTypes = argumentIndices.map((index, i) => index !== undefined && index >= 0 ?
@@ -548,7 +691,7 @@ class Checker {
548
691
  }
549
692
  return undefined;
550
693
  });
551
- const result = this.resolveType(around.returns, definition.file, types);
694
+ const result = this.returnType(around, definition.file, types);
552
695
  if (!this.assignable(result, output))
553
696
  this.report(annotation.span, `${interceptor.name}.around returns ${tyName(result)}; ${node.name} requires ${tyName(output)}`, 'INTERCEPTOR');
554
697
  if (around.returnOwnership !== ownership)
@@ -566,7 +709,7 @@ class Checker {
566
709
  const argumentInjectionIndices = around.params.map(param => param.injected ? injectedIndex(param.type) : undefined);
567
710
  layers.push({ annotation, definition, around, argumentIndices, argumentBindings, constructorKeys,
568
711
  types, inputTypes, outputType: output, constructorInputIndices, argumentInjectionIndices,
569
- errors: around.throws.map(ref => this.resolveType(ref, definition.file, types)) });
712
+ errors: this.bodyErrors(around, definition.file, types) });
570
713
  }
571
714
  };
572
715
  for (const def of this.project.definitions.values()) {
@@ -575,13 +718,13 @@ class Checker {
575
718
  if (node.kind === 'class')
576
719
  plan(node, def.file, types, node.fields, { id: def.id, name: def.name, kind: 'class', def, args: [...types.values()], nullable: false }, 'managed');
577
720
  if (node.kind === 'function')
578
- plan(node, def.file, types, node.params, this.resolveType(node.returns, def.file, types), node.returnOwnership);
721
+ plan(node, def.file, types, node.params, this.returnType(node, def.file, types), node.returnOwnership);
579
722
  if ('methods' in node)
580
723
  for (const method of node.methods) {
581
724
  if (node.kind === 'interceptor' && method.name === 'around')
582
725
  continue;
583
726
  const methodTypes = new Map([...types, ...this.paramsFor(method.typeParams, method, def.file)]);
584
- plan(method, def.file, methodTypes, method.params, this.resolveType(method.returns, def.file, methodTypes), method.returnOwnership);
727
+ plan(method, def.file, methodTypes, method.params, this.returnType(method, def.file, methodTypes), method.returnOwnership);
585
728
  }
586
729
  }
587
730
  }
@@ -594,8 +737,8 @@ class Checker {
594
737
  }
595
738
  effectiveErrors(node, file, types) {
596
739
  return [
597
- ...(node.kind === 'function' ? node.throws : node.validationErrors ?? []).map(ref => this.resolveType(ref, file, types)),
598
- ...(this.interceptorPlans.get(node) ?? []).flatMap(layer => layer.errors.map(type => this.substitute(type, types))),
740
+ ...(node.kind === 'function' ? this.bodyErrors(node, file, types) : (this.constructorContracts.get(node)?.errors.map(type => this.substitute(type, types)) ?? (node.validationErrors ?? []).map(ref => this.resolveType(ref, file, types)))),
741
+ ...(this.interceptorPlans.get(node) ?? []).flatMap(layer => this.bodyErrors(layer.around, layer.definition.file, new Map([...layer.types].map(([name, type]) => [name, this.substitute(type, types)])))),
599
742
  ];
600
743
  }
601
744
  checkInterceptorDependencies() {
@@ -745,7 +888,7 @@ class Checker {
745
888
  param.injected === method.params[i].injected &&
746
889
  param.ownership === method.params[i].ownership &&
747
890
  equalRef(param.type, method.params[i].type)) &&
748
- equalRef(left.returns, method.returns) &&
891
+ this.sameType(this.returnType(left, leftFile, leftParams), this.returnType(method, right.file, rightParams)) &&
749
892
  left.returnOwnership === method.returnOwnership &&
750
893
  this.effectiveErrors(left, leftFile, leftParams).every(thrown => this.effectiveErrors(method, right.file, rightParams).some(allowed => this.assignable(thrown, allowed)));
751
894
  }
@@ -863,7 +1006,7 @@ class Checker {
863
1006
  else if (item.keyTypeArgs.length)
864
1007
  this.report(item.span, `Named binding ${item.key} cannot take type arguments`, 'DI');
865
1008
  const stateful = fieldsOf(target.node).some(field => field.mutable || field.ownership === 'own' || field.type.name === 'Shared') ||
866
- target.node.methods.some(method => method.changes?.some(path => path === 'self' || path.startsWith('self.')));
1009
+ target.node.methods.some(method => this.effectiveContract(method, target.file, target, new Map(target.node.typeParams.map((name, index) => [name, targetType.args[index] ?? errorTy]))).changes.some(path => path === 'self' || path.startsWith('self.')));
867
1010
  const info = { key, target, exposedType, stateful, lifetime: item.lifetime ?? (stateful ? 'fresh' : 'shared'),
868
1011
  dependencies: [], constructorKeys: [], declaration: item, requiresScope: item.lifetime === 'scoped' };
869
1012
  this.bindings.push(info);
@@ -921,9 +1064,10 @@ class Checker {
921
1064
  for (const [name, ty] of this.paramsFor(fn.typeParams, fn, file))
922
1065
  params.set(name, ty);
923
1066
  this.addBounds(params, fn, file);
924
- const context = { file, locals: new Map(), returns: this.resolveType(fn.returns, file, params),
1067
+ const context = { file, locals: new Map(), returns: this.returnType(fn, file, params),
925
1068
  returnOwnership: fn.returnOwnership,
926
- allowedErrors: fn.throws.map(type => this.resolveType(type, file, params)),
1069
+ allowedErrors: this.bodyErrors(fn, file, params),
1070
+ inferredReturns: this.inferring && this.callableContracts.get(fn)?.inferredResult && !this.contextualResults.has(fn) ? [] : undefined,
927
1071
  unsafe: false, borrowed: new Set(), initializing, types: params, next, callable: fn, owner,
928
1072
  flow: new OwnershipFlow() };
929
1073
  if (fn.endpoint?.streams) {
@@ -934,7 +1078,7 @@ class Checker {
934
1078
  context.self = { id: owner.id, name: owner.name,
935
1079
  kind: owner.node.kind === 'class' ? 'class' : owner.node.kind === 'interceptor' ? 'interceptor' : 'interface', def: owner,
936
1080
  args: [...params.values()].slice(0, owner.node.typeParams.length), nullable: false };
937
- context.locals.set('self', { type: context.self, ownership: (fn.changes ?? []).some(path => path === 'self' || path.startsWith('self.')) || initializing ? 'borrow' : 'managed', moved: false });
1081
+ context.locals.set('self', { type: context.self, ownership: this.contractFor(fn, file, owner, params).changes.some(path => path === 'self' || path.startsWith('self.')) || initializing ? 'borrow' : 'managed', moved: false });
938
1082
  if (owner.node.kind === 'class' || owner.node.kind === 'interceptor') {
939
1083
  for (const field of fieldsOf(owner.node))
940
1084
  context.locals.set(field.name, { type: { ...this.resolveType(field.type, file, params), readonly: !field.mutable }, ownership: field.ownership,
@@ -966,7 +1110,28 @@ class Checker {
966
1110
  context.effects = this.contractFor(fn, file, owner, params);
967
1111
  if ((fn.changes ?? []).some(path => path.startsWith('self')) && !owner)
968
1112
  this.report(fn.span, 'A free function has no self to change', 'EFFECT');
1113
+ for (const policy of this.httpPolicies.get(fn) ?? []) {
1114
+ const operations = Object.values(httpPolicyOptions[policy.name]).filter(spec => spec.startsWith('dependency:'));
1115
+ policy.dependencies.forEach((index, order) => {
1116
+ const param = fn.params[index];
1117
+ if (!param || !operations[order])
1118
+ return;
1119
+ const type = this.resolveType(param.type, file, params);
1120
+ const operation = operations[order].split('.')[1];
1121
+ this.requireUse(capabilityKey(type, operation), `${tyName(type)}.${operation}`, policy.annotation.span, context, { source: tyName(type), operation, span: policy.annotation.span, capability: type });
1122
+ });
1123
+ }
969
1124
  this.checkStatements(fn.body ?? [], context, fn.span);
1125
+ if (context.inferredReturns) {
1126
+ const contract = this.callableContracts.get(fn);
1127
+ const result = this.inferredReturn(context.inferredReturns);
1128
+ if (!sameType(result, contract.result)) {
1129
+ contract.result = result;
1130
+ this.markInference(fn);
1131
+ }
1132
+ }
1133
+ if (!this.inferring && unresolved(this.returnType(fn, file, params)))
1134
+ this.report(fn.span, `Cannot infer ${fn.name}'s return type; add returns T to anchor recursive or ambiguous results`, 'INFERENCE');
970
1135
  if (fn.body && context.returns.id !== 'builtin:void' &&
971
1136
  !(owner?.node.kind === 'interceptor' && fn.name === 'around') && canFallThrough(fn.body))
972
1137
  this.report(fn.span, `${fn.name} must return a value or throw on every path`, 'TYPE');
@@ -1046,16 +1211,19 @@ class Checker {
1046
1211
  report: (span, message) => this.report(span, message, 'EFFECT'),
1047
1212
  });
1048
1213
  const inferred = this.inferredUses.get(fn);
1214
+ const inferredChanges = this.inferredChanges.get(fn);
1215
+ const changes = inferredChanges ? [...inferredChanges].sort() : result.changes;
1049
1216
  if (!inferred) {
1050
- this.effectContracts.set(fn, result);
1051
- return result;
1217
+ const contract = { ...result, changes, inferredChanges: !!inferredChanges };
1218
+ this.effectContracts.set(fn, contract);
1219
+ return contract;
1052
1220
  }
1053
1221
  const uses = new Map(result.uses);
1054
1222
  for (const [key, effect] of inferred) {
1055
1223
  const capability = effect.capability && this.substitute(effect.capability, types);
1056
1224
  uses.set(capability ? capabilityKey(capability, effect.operation) : key, { ...effect, capability, source: capability ? tyName(capability) : effect.source });
1057
1225
  }
1058
- const contract = { ...result, uses, inferred: true };
1226
+ const contract = { ...result, changes, uses, inferred: true, inferredChanges: !!inferredChanges };
1059
1227
  this.effectContracts.set(fn, contract);
1060
1228
  return contract;
1061
1229
  }
@@ -1096,7 +1264,7 @@ class Checker {
1096
1264
  changes.push([fn.params[target].name, ...path].join('.'));
1097
1265
  }
1098
1266
  }
1099
- const result = { changes: [...new Set(changes)], uses, inferred: base.inferred };
1267
+ const result = { changes: [...new Set(changes)], uses, inferred: base.inferred, inferredChanges: base.inferredChanges };
1100
1268
  this.effectContracts.set(fn, result);
1101
1269
  return result;
1102
1270
  }
@@ -1126,8 +1294,16 @@ class Checker {
1126
1294
  return;
1127
1295
  const input = context.callable.params.find(param => param.name === origin);
1128
1296
  if (path.startsWith('self') || input && input.ownership !== 'own') {
1129
- if (!coversChange(context.effects?.changes ?? [], path))
1130
- this.report(span, `${context.callable.name} must declare changes ${path.startsWith('self') ? 'self' : origin}`, 'EFFECT');
1297
+ const inferred = this.inferring && this.inferredChanges.get(context.callable);
1298
+ const change = path.startsWith('self') ? 'self' : origin;
1299
+ if (inferred) {
1300
+ if (!inferred.has(change)) {
1301
+ inferred.add(change);
1302
+ this.markInference(context.callable);
1303
+ }
1304
+ }
1305
+ else if (!coversChange(context.effects?.changes ?? [], path))
1306
+ this.report(span, `${context.callable.name} must declare changes ${change}`, 'EFFECT');
1131
1307
  }
1132
1308
  }
1133
1309
  immutableData(type, seen = new Set()) {
@@ -1214,8 +1390,9 @@ class Checker {
1214
1390
  const type = this.checkExpression(stmt.value, context);
1215
1391
  if (type.id !== 'builtin:Shared')
1216
1392
  this.report(stmt.value.span, 'lock requires Shared<T>', 'CONCURRENCY');
1217
- if (context.callable && !context.effects?.uses.size && !context.effects?.changes.length)
1218
- this.report(stmt.span, 'A callable that locks shared state declares its capability operation or changes contract', 'EFFECT');
1393
+ const external = type.readonly || !!context.flow.external(this.rootName(stmt.value) ?? '');
1394
+ if (context.callable && external && !context.effects?.uses.size && !context.effects?.changes.length)
1395
+ this.report(stmt.span, 'A callable that locks external shared state declares its capability operation or changes contract', 'EFFECT');
1219
1396
  const inside = this.cloneContext(context);
1220
1397
  inside.locked = true;
1221
1398
  const origins = allocationOrigin(stmt.span);
@@ -1494,8 +1671,9 @@ class Checker {
1494
1671
  return;
1495
1672
  }
1496
1673
  if (stmt.kind === 'return') {
1497
- const type = stmt.value ? this.checkExpression(stmt.value, context, context.returns) : builtin('void');
1498
- const declaredErrors = context.callable?.throws.map(type => this.resolveType(type, context.file, context.types)) ?? [];
1674
+ const type = stmt.value ? this.checkExpression(stmt.value, context, context.returns.kind === 'error' ? undefined : context.returns) : builtin('void');
1675
+ context.inferredReturns?.push(type);
1676
+ const declaredErrors = context.callable ? this.bodyErrors(context.callable, context.file, context.types) : [];
1499
1677
  for (const error of context.flow.pendingTaskErrors())
1500
1678
  this.checkAllowedError(error, stmt.span, { ...context, allowedErrors: declaredErrors, exceptionalFlows: undefined });
1501
1679
  if (!this.assignable(type, context.returns))
@@ -1829,8 +2007,17 @@ class Checker {
1829
2007
  return;
1830
2008
  }
1831
2009
  context.exceptionalFlows?.push({ type, flow: context.flow.clone() });
1832
- if (!context.allowedErrors.some(allowed => this.assignable(type, allowed)))
1833
- this.report(span, `Unhandled ${tyName(type)}; catch it or declare unless ${tyName(type)}`, 'THROWS');
2010
+ if (!context.allowedErrors.some(allowed => this.assignable(type, allowed))) {
2011
+ const contract = context.callable && this.inferring && this.callableContracts.get(context.callable);
2012
+ if (contract && contract.inferredErrors && type.kind !== 'error') {
2013
+ if (!contract.errors.some(error => sameType(error, type))) {
2014
+ contract.errors.push(type);
2015
+ this.markInference(context.callable);
2016
+ }
2017
+ }
2018
+ else
2019
+ this.report(span, `Unhandled ${tyName(type)}; catch it or declare unless ${tyName(type)}`, 'THROWS');
2020
+ }
1834
2021
  }
1835
2022
  checkCollection(expr, context, expected) {
1836
2023
  const name = expr.collection === 'empty' ? expected?.name === 'Set' ? 'Set' : 'Map' : expr.collection;
@@ -2142,14 +2329,14 @@ class Checker {
2142
2329
  this.defaults.get(def.id)?.get(name)?.method;
2143
2330
  if (method) {
2144
2331
  this.checkMemberVisibility(def.id, def.name, name, span, context);
2145
- return this.resolveType(method.returns, def.file, new Map(def.node.typeParams.map((param, i) => [param, receiver.args[i] ?? errorTy])));
2332
+ return this.returnType(method, def.file, new Map(def.node.typeParams.map((param, i) => [param, receiver.args[i] ?? errorTy])));
2146
2333
  }
2147
2334
  }
2148
2335
  if (def?.node.kind === 'interface') {
2149
2336
  const entry = this.interfaceMethods(receiver, new Set()).get(name)?.[0];
2150
2337
  if (entry) {
2151
2338
  this.checkMemberVisibility(entry.from, def.name, name, span, context);
2152
- return this.resolveType(entry.method.returns, def.file);
2339
+ return this.returnType(entry.method, entry.file, entry.params);
2153
2340
  }
2154
2341
  }
2155
2342
  this.report(span, `${tyName(receiver)} has no member ${name}`);
@@ -2604,8 +2791,8 @@ class Checker {
2604
2791
  else if (!jsonDataType(this.project, result))
2605
2792
  this.report(expr.span, `${tyName(result)} is not JSON data; use a record or data collection`, 'JSON');
2606
2793
  if (result.def?.node.kind === 'class')
2607
- for (const error of result.def.node.validationErrors ?? [])
2608
- this.checkAllowedError(this.resolveType(error, result.def.file), expr.span, context);
2794
+ for (const error of this.effectiveErrors(result.def.node, result.def.file, new Map(result.def.node.typeParams.map((name, index) => [name, result.args[index] ?? errorTy]))))
2795
+ this.checkAllowedError(error, expr.span, context);
2609
2796
  }
2610
2797
  return this.isReference(result) ? { ...result, readonly: true, frozen: decoding || receiver.name === 'Json' } : result;
2611
2798
  }
@@ -2797,7 +2984,7 @@ class Checker {
2797
2984
  ], (span, message) => this.report(span, message, 'BORROW'));
2798
2985
  for (const thrown of this.effectiveErrors(fn, fnFile, params))
2799
2986
  this.checkAllowedError(thrown, expr.span, context);
2800
- const result = this.resolveType(fn.returns, fnFile, params);
2987
+ const result = this.returnType(fn, fnFile, params);
2801
2988
  return this.isReference(result) && fn.returnOwnership !== 'own' && !this.functionIsFresh(fn, fnFile, owner && 'fields' in owner.node ? new Set(fieldsOf(owner.node).map(field => field.name)) : new Set()) ?
2802
2989
  { ...result, readonly: true } : result;
2803
2990
  }