From a6654c6e371c2c91c0d73dbebf775e466e9be056 Mon Sep 17 00:00:00 2001 From: Luke Boswell Date: Tue, 20 Jun 2023 21:39:33 +1000 Subject: [PATCH 001/140] WIP initial scope for website update --- www/generate_website/.gitignore | 2 + www/generate_website/build.sh | 9 + .../content/contributing_page.md | 23 + www/generate_website/content/discover_page.md | 42 ++ .../content/getting_started_page.md | 34 ++ www/generate_website/content/home_page.md | 16 + .../content/learn_roc_page.md | 23 + www/generate_website/main.roc | 88 +++ www/generate_website/static/site.css | 547 ++++++++++++++++++ 9 files changed, 784 insertions(+) create mode 100644 www/generate_website/.gitignore create mode 100644 www/generate_website/build.sh create mode 100644 www/generate_website/content/contributing_page.md create mode 100644 www/generate_website/content/discover_page.md create mode 100644 www/generate_website/content/getting_started_page.md create mode 100644 www/generate_website/content/home_page.md create mode 100644 www/generate_website/content/learn_roc_page.md create mode 100644 www/generate_website/main.roc create mode 100644 www/generate_website/static/site.css diff --git a/www/generate_website/.gitignore b/www/generate_website/.gitignore new file mode 100644 index 00000000000..c63bd9f48bf --- /dev/null +++ b/www/generate_website/.gitignore @@ -0,0 +1,2 @@ +roc-website +dist/ \ No newline at end of file diff --git a/www/generate_website/build.sh b/www/generate_website/build.sh new file mode 100644 index 00000000000..3b0427122d7 --- /dev/null +++ b/www/generate_website/build.sh @@ -0,0 +1,9 @@ +rm -rf dist/ + +roc run main.roc -- content/ dist/ + +cp -r static/* dist/ + +cd dist + +simple-http-server -p 8000 \ No newline at end of file diff --git a/www/generate_website/content/contributing_page.md b/www/generate_website/content/contributing_page.md new file mode 100644 index 00000000000..667a17003ee --- /dev/null +++ b/www/generate_website/content/contributing_page.md @@ -0,0 +1,23 @@ +# Contribute to Roc + +## Sponsorship + +- [Github Sponsorship](https://github.com/sponsors/roc-lang) + +## Contributor Guidelines + +- [CONTRIBUTING](https://github.com/roc-lang/roc/blob/main/CONTRIBUTING.md) + +## Ideas & Proposals + +- [Good First Issues](https://github.com/roc-lang/roc/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) + +## Community Values & Code of Conduct + +## Package Development + +## Platform Development + +## Roc Jobs Board + +## Contact the Team diff --git a/www/generate_website/content/discover_page.md b/www/generate_website/content/discover_page.md new file mode 100644 index 00000000000..30eee00ab3c --- /dev/null +++ b/www/generate_website/content/discover_page.md @@ -0,0 +1,42 @@ +# Discover Roc + +## Meet the Community + +### Zulip Chat + +- [roc.zulipchat.com](https://roc.zulipchat.com/) + +### Github Project + +- [roc-lang/roc](https://github.com/roc-lang/roc) + +### Meetups & Events + +### Socials + +## Roc Applications + +### Tools & Scripts + +### Web (coming soon) + +### Networking & Servers (coming soon) + +### Graphical (coming soon) + +### Scientific (coming soon) + +### Embedded (coming soon) + +## Roc Platforms + +## Roc Packages + +## Talks and Publications + +- Roc at Handmade Seattle - November 12, 2021 (very low-level explanation of how Roc's compiler makes programs run fast) +- Outperforming Imperative with Pure Functional Languages - October 1, 2021 (about Roc's runtime performance and optimizer) +- A taste of Roc - September 23, 2021 (syntax, application examples) +- Roc at the Philly ETE conference - May 6, 2021 (platforms and applications) +- Roc on Zig Showtime - April 24, 2021 (making a platform) +- Roc at the Berlin FP Meetup - September 1, 2020 (overall vision for the language) \ No newline at end of file diff --git a/www/generate_website/content/getting_started_page.md b/www/generate_website/content/getting_started_page.md new file mode 100644 index 00000000000..6be3e93103e --- /dev/null +++ b/www/generate_website/content/getting_started_page.md @@ -0,0 +1,34 @@ +# Getting Started + +## Installation + +- [Linux x86-64 Getting Started Guide](https://github.com/roc-lang/roc/blob/main/getting_started/linux_x86_64.md) +- [MacOS Apple Silicon Getting Started Guide](https://github.com/roc-lang/roc/blob/main/getting_started/macos_apple_silicon.md) +- [MacOS x86-64 Getting Started Guide](https://github.com/roc-lang/roc/blob/main/getting_started/macos_x86_64.md) +- [Windows Getting Started Guide](https://github.com/roc-lang/roc/blob/main/getting_started/windows.md) +- [Other Systems Getting Started Guide](https://github.com/roc-lang/roc/blob/main/getting_started/other.md) + +## Nightly Builds + +## Roc CLI + +- Develop `roc dev` + +- Test `roc test` + +- Run `roc run` + +- Build `roc build` + +- Format `roc format` + +- Documentation `roc docs` + +## Package Management + +- URL Packages + +## Editor Support + +- Language Server +- Neo(Vim) diff --git a/www/generate_website/content/home_page.md b/www/generate_website/content/home_page.md new file mode 100644 index 00000000000..04985a4db87 --- /dev/null +++ b/www/generate_website/content/home_page.md @@ -0,0 +1,16 @@ +# Roc lang + +- Fast +- Functional +- Friendly + +## Try Roc +<-- WebREPL goes here --> + +## [Discover Roc](/discover_page.html) + +## [Learn Roc](/learn_roc.html) + +## [Contribute to Roc](contributing_page.html) + +## [Getting Started](/getting_started_page.html) diff --git a/www/generate_website/content/learn_roc_page.md b/www/generate_website/content/learn_roc_page.md new file mode 100644 index 00000000000..a0406355d63 --- /dev/null +++ b/www/generate_website/content/learn_roc_page.md @@ -0,0 +1,23 @@ +# Learn Roc + +## Guides + +### The Roc Tutorial + +- [The Roc Tutorial](https://www.roc-lang.org/tutorial) + +### Frequently Asked Questions + +- [Link](https://github.com/roc-lang/roc/blob/main/FAQ.md) + +### Roc for Elm Programmers + +- [Roc for Elm Programmers](https://github.com/roc-lang/roc/blob/main/roc-for-elm-programmers.md) + +## Documentation + +### Builtin Package + +### Basic-CLI Platform + +### Language Reference \ No newline at end of file diff --git a/www/generate_website/main.roc b/www/generate_website/main.roc new file mode 100644 index 00000000000..790c7491161 --- /dev/null +++ b/www/generate_website/main.roc @@ -0,0 +1,88 @@ +app "roc-website" + packages { pf: "../../examples/static-site-gen/platform/main.roc" } + imports [ + pf.Html.{ html, head, body, footer, script, div, main, text, nav, a, link, meta }, + pf.Html.Attributes.{ content, name, id, href, rel, lang, class, title, charset, src }, + ] + provides [transformFileContent] to pf + +pageData = + Dict.empty {} + |> Dict.insert "discover_page.html" { title: "Discover Roc", description: "Discover the Roc programming language" } + |> Dict.insert "contributing_page.html" { title: "Contribute to Roc", description: "Contribute to the Roc programming language" } + |> Dict.insert "learn_roc_page.html" { title: "Learn Roc", description: "Learn the Roc programming language" } + |> Dict.insert "home_page.html" { title: "Roc Lang", description: "The Roc programming language" } + |> Dict.insert "getting_started_page.html" { title: "Let's Roc", description: "Getting started with the Roc programming language" } + +getPage : Str -> {title : Str, description : Str} +getPage = \current -> + Dict.get pageData current + |> Result.onErr \_ -> crash "expected page to be in meta" + |> Result.withDefault { title: "", description: ""} + +getTitle : Str -> Str +getTitle = \current -> + getPage current |> .title + +getDescription : Str -> Str +getDescription = \current -> + getPage current |> .description + +transformFileContent : Str, Str -> Str +transformFileContent = \page, htmlContent -> + Html.render (view page htmlContent) + +view : Str, Str -> Html.Node +view = \page, htmlContent -> + html [lang "en"] [ + head [] [ + meta [charset "utf-8"] [], + Html.title [] [text (getTitle page)], + meta [name "description", content (getDescription page)] [], + meta [name "viewport", content "width=device-width"] [], + link [rel "stylesheet", href "/site.css"] [], + link [rel "icon", href "/favicon.svg"] [], + ], + body [] [ + viewNavbar, + main [] [ + text htmlContent, + ], + footer [] [ + text "Made by people who like to make nice things. © 2022" + ] + ], + script [src "/site.js"] [], + ] + +viewNavbar : Html.Node +viewNavbar = + div [id "top-bar"] [ + nav [] [ + a [href "/home_page.html", title "The Roc Programming Language"] [ + rocLogo + ], + div [id "top-bar-links"] [ + a [href "/discover_page.html"] [text "discover"], + a [href "/learn_roc_page.html"] [text "learn"], + a [href "/contributing_page.html"] [text "contribute"], + a [href "/getting_started_page.html"] [text "getting started"], + ], + ], + ] + +rocLogo = + (Html.element "svg") [ + (Html.attribute "viewBox") "0 -6 51 58", + (Html.attribute "fill") "#7c38f5", + (Html.attribute "xmlns") "http://www.w3.org/2000/svg", + (Html.attribute "aria-labelledby") "logo-link", + (Html.attribute "role") "img", + class "roc-logo" + ] [ + (Html.element "title") [id "logo-link"] [text "Return to Roc Home"], + (Html.element "polygon") [ + (Html.attribute "role") "presentation", + (Html.attribute "points") "0,0 23.8834,3.21052 37.2438,19.0101 45.9665,16.6324 50.5,22 45,22 44.0315,26.3689 26.4673,39.3424 27.4527,45.2132 17.655,53 23.6751,22.7086", + ] [], + ] diff --git a/www/generate_website/static/site.css b/www/generate_website/static/site.css new file mode 100644 index 00000000000..189072f35be --- /dev/null +++ b/www/generate_website/static/site.css @@ -0,0 +1,547 @@ +:root { + /* WCAG AAA Compliant colors */ + --code-bg: #f4f8f9; + --gray: #717171; + --orange: #bf5000; + --green: #0b8400; + --cyan: #067c94; + --blue: #05006d; + --violet: #7c38f5; + --violet-bg: #ece2fd; + --magenta: #a20031; + + --link-color: var(--violet); + --code-link-color: var(--violet); + --text-color: #000; + --text-hover-color: var(--violet); + --body-bg-color: #ffffff; + --border-color: #717171; + --faded-color: #4c4c4c; + --font-sans: -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, + sans-serif; + --font-mono: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, + monospace; + --top-header-height: 67px; + --sidebar-width: 280px; +} + +html { + line-height: 1.5rem; + background: var(--body-bg); + color: var(--text-color); + font-family: "Lato", sans-serif; +} + +html, +body { + margin: 0; + padding: 0; +} + +footer { + max-width: 1024px; + margin: 0 auto; + font-size: 14px; + padding: 16px; +} + +section p:last-child { + margin-bottom: 0; +} + +aside { + margin-left: 4rem; +} + +a { + text-decoration: none; + color: var(--link-color); +} + +a:hover { + text-decoration: underline; +} + +li { + margin-bottom: 0.5rem; +} + +#top-bar { + background-color: var(--top-bar-bg); + width: 100%; + height: 50px; +} + +#top-bar nav { + max-width: 1024px; + margin: 0 auto; + display: flex; + justify-content: space-between; +} + +#top-bar .home-link { + display: flex; + color: var(--top-bar-fg); + font-size: 1.8rem; + padding: 10px; +} + +#top-bar-links { + display: flex; +} + +#top-bar-links a, +#top-bar-links label { + box-sizing: border-box; + color: var(--top-bar-fg); + font-size: 1.1rem; + display: block; + height: 40px; + padding: 12px 16px; + margin: 0 2px; +} + +main { + max-width: var(--body-max-width); + margin: 36px auto; + padding: 0 12px; +} + +code, +samp { + font-family: var(--font-mono); + color: var(--code-color); + background-color: var(--code-bg); + display: inline-block; +} + +p code, +td code, +li code, +th code, +samp { + padding: 0 8px; +} + +code a, +a code { + text-decoration: none; + color: var(--code-link-color); + background: none; + padding: 0; +} + +code a:visited, +a:visited code { + color: var(--code-link-color); +} + +pre { + position: relative; + margin-bottom: 16px; + padding: 8px 16px; + box-sizing: border-box; + background-color: var(--code-bg); + overflow-x: hidden; + word-wrap: normal; + font-size: 1.2rem; + line-height: 1.76em; + white-space: pre; +} + +pre > samp { + overflow-x: auto; + display: block; +} + +.repl-prompt:before { + /* Add this using CSS so it isn't selectable, which would be annoying when trying to copy/paste! */ + color: var(--repl-prompt); + content: "» "; +} + +.repl-err { + color: var(--magenta); +} + +/* Tables */ + +table { + border-collapse: collapse; + overflow-x: auto; + border: 2px solid #f0f0f0; +} + +thead { + border: none; +} + +tbody { + border: none; +} + +tr { + border: none; + border-top: 2px solid #f0f0f0; +} + +th, +td { + border: none; + border-right: 2px solid #f0f0f0; + padding: 12px; +} + +th:last-child, +td:last-child { + border-right: none; +} + +p, +aside, +li, +footer { + font-size: 1.2rem; + line-height: 1.85rem; +} + +/* Mobile-friendly screen width */ +@media only screen and (max-device-width: 480px) and (orientation: portrait) { + p, + aside, + li, + footer, + code, + samp, + .code-snippet { + font-size: 16px; + } + + h1 code, + h2 code, + h3 code, + h4 code, + h5 code { + font-size: inherit; + } + + code { + white-space: normal; + } + + #tutorial-toc-toggle-label, + #close-tutorial-toc { + display: block; + } + + #tutorial-toc-toggle:checked + #tutorial-toc { + display: block; + } + + #tutorial-toc { + display: none; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + overflow-y: auto; + margin: 0; + padding-right: 120px; + border: 0; + } + + h1, + h2, + h3, + h4, + h5, + h6, + p, + code { + word-break: break-word !important; + } + + h1, + h2, + h3, + h4, + h5 { + line-height: 1.2em !important; + font-size: 2rem !important; + } + + #top-bar-links a, + #top-bar-links label { + padding: 12px 8px; + margin: 0; + } +} + +@font-face { + font-family: "Permanent Marker"; + font-style: normal; + font-weight: 400; + src: url("/fonts/permanent-marker-v16-latin/permanent-marker-v16-latin-regular.woff2") + format("woff2"), + url("/fonts/permanent-marker-v16-latin/permanent-marker-v16-latin-regular.woff") + format("woff"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, + U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, + U+2215, U+FEFF, U+FFFD; +} + +/* latin-ext */ +@font-face { + font-family: "Merriweather"; + font-style: normal; + font-weight: 400; + src: url("/fonts/merriweather-v30-latin-ext_latin/merriweather-v30-latin-ext_latin-regular.woff2") + format("woff2"), + url("/fonts/merriweather-v30-latin-ext_latin/merriweather-v30-latin-ext_latin-regular.woff") + format("woff"); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, + U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} + +/* latin */ +@font-face { + font-family: "Merriweather"; + font-style: normal; + font-weight: 400; + src: url("/fonts/merriweather-v30-latin/merriweather-v30-latin-regular.woff2") + format("woff2"), + url("/fonts/merriweather-v30-latin/merriweather-v30-latin-regular.woff") + format("woff"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, + U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, + U+2215, U+FEFF, U+FFFD; +} + +/* latin-ext */ +@font-face { + font-family: "Merriweather Sans"; + font-style: normal; + font-weight: 400; + src: url("/fonts/merriweather-sans-v22-latin-ext_latin/merriweather-sans-v22-latin-ext_latin-regular.woff2") + format("woff2"), + url("/fonts/merriweather-sans-v22-latin-ext_latin/merriweather-sans-v22-latin-ext_latin-regular.woff") + format("woff"); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, + U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} + +/* latin */ +@font-face { + font-family: "Merriweather Sans"; + font-style: normal; + font-weight: 400; + src: url("/fonts/merriweather-sans-v22-latin/merriweather-sans-v22-latin-regular.woff2") + format("woff2"), + url("/fonts/merriweather-sans-v22-latin/merriweather-sans-v22-latin-regular.woff") + format("woff"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, + U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, + U+2215, U+FEFF, U+FFFD; +} + +/* latin-ext */ +@font-face { + font-family: "Lato"; + font-style: normal; + font-weight: 400; + src: url("/fonts/lato-v23-latin-ext_latin/lato-v23-latin-ext_latin-regular.woff2") + format("woff2"), + url("/fonts/lato-v23-latin-ext_latin/lato-v23-latin-ext_latin-regular.woff") + format("woff"); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, + U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} + +/* latin */ +@font-face { + font-family: "Lato"; + font-style: normal; + font-weight: 400; + src: url("/fonts/lato-v23-latin/lato-v23-latin-regular.woff2") + format("woff2"), + url("/fonts/lato-v23-latin/lato-v23-latin-regular.woff") format("woff"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, + U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, + U+2215, U+FEFF, U+FFFD; +} + +/* latin-ext */ +@font-face { + font-family: "Source Code Pro"; + font-style: normal; + font-weight: 400; + src: url("/fonts/source-code-pro-v22-latin-ext_latin/source-code-pro-v22-latin-ext_latin-regular.woff2") + format("woff2"), + url("/fonts/source-code-pro-v22-latin-ext_latin/source-code-pro-v22-latin-ext_latin-regular.woff") + format("woff"); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, + U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} + +/* latin */ +@font-face { + font-family: "Source Code Pro"; + font-style: normal; + font-weight: 400; + src: url("/fonts/source-code-pro-v22-latin/source-code-pro-v22-latin-regular.woff2") + format("woff2"), + url("/fonts/source-code-pro-v22-latin/source-code-pro-v22-latin-regular.woff") + format("woff"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, + U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, + U+2215, U+FEFF, U+FFFD; +} + +@media (prefers-color-scheme: dark) { + :root { + /* WCAG AAA Compliant colors */ + /* WCAG AAA Compliant colors */ + --code-bg: #202746; + --gray: #b6b6b6; + --orange: #fd6e08; + --green: #8ecc88; + --cyan: #12c9be; + --blue: #b1afdf; + --violet: #caadfb; + --violet-bg: #332944; + --magenta: #f39bac; + + --link-color: var(--violet); + --code-link-color: var(--violet); + --text-color: #eaeaea; + --body-bg-color: #0e0e0f; + --border-color: var(--gray); + --code-color: #eeeeee; + --logo-solid: #8f8f8f; + --faded-color: #bbbbbb; + --gray: #6e6e6e; + } + + h1, + h2, + h3, + h4, + h5 { + text-shadow: none; + } + + html { + scrollbar-color: #444444 #2f2f2f; + } + + table, + tr, + th, + td { + border-color: var(--gray); + } +} + +/* Comments `#` and Documentation comments `##` */ +samp .comment, +code .comment { + color: var(--green); +} + +/* Number, String, Tag literals */ +samp .storage.type, +code .storage.type, +samp .string, +code .string, +samp .string.begin, +code .string.begin, +samp .string.end, +code .string.end, +samp .constant, +code .constant, +samp .literal, +code .literal { + color: var(--cyan); +} + +/* Keywords and punctuation */ +samp .keyword, +code .keyword, +samp .punctuation.section, +code .punctuation.section, +samp .punctuation.separator, +code .punctuation.separator, +samp .punctuation.terminator, +code .punctuation.terminator, +samp .kw, +code .kw { + color: var(--magenta); +} + +/* Operators */ +samp .op, +code .op, +samp .keyword.operator, +code .keyword.operator { + color: var(--orange); +} + +/* Delimieters */ +samp .delimeter, +code .delimeter { + color: var(--gray); +} + +/* Variables modules and field names */ +samp .function, +code .function, +samp .meta.group, +code .meta.group, +samp .meta.block, +code .meta.block, +samp .lowerident, +code .lowerident { + color: var(--blue); +} + +/* Types, Tags, and Modules */ +samp .type, +code .type, +samp .meta.path, +code .meta.path, +samp .upperident, +code .upperident { + color: var(--green); +} + +samp .dim, +code .dim { + opacity: 0.55; +} + +.button-container { + position: absolute; + top: 0; + right: 0; +} + +.copy-button { + background: var(--code-bg); + border: 1px solid var(--magenta); + color: var(--magenta); + display: inline-block; + cursor: pointer; + margin: 8px; +} + +.copy-button:hover { + border-color: var(--green); + color: var(--green); +} + +.roc-logo { + width: 40px; + height: 40px; + margin: 0 auto; +} From da4891809489ec23f86737a5c9c3b2ebeb0d0f5a Mon Sep 17 00:00:00 2001 From: Luke Boswell Date: Wed, 21 Jun 2023 21:59:41 +1000 Subject: [PATCH 002/140] add wip_new_website --- www/generate_website/.gitignore | 2 - www/generate_website/build.sh | 9 --- www/generate_website/content/home_page.md | 16 ------ .../content/learn_roc_page.md | 23 -------- www/wip_new_website/.gitignore | 3 + www/wip_new_website/build.roc | 55 +++++++++++++++++++ .../content/contributing_page.md | 2 + .../content/discover_page.md | 34 ++++-------- .../content/getting_started_page.md | 7 +-- www/wip_new_website/content/home_page.md | 33 +++++++++++ www/wip_new_website/content/learn_roc_page.md | 24 ++++++++ .../main.roc | 0 .../static/site.css | 0 13 files changed, 131 insertions(+), 77 deletions(-) delete mode 100644 www/generate_website/.gitignore delete mode 100644 www/generate_website/build.sh delete mode 100644 www/generate_website/content/home_page.md delete mode 100644 www/generate_website/content/learn_roc_page.md create mode 100644 www/wip_new_website/.gitignore create mode 100755 www/wip_new_website/build.roc rename www/{generate_website => wip_new_website}/content/contributing_page.md (84%) rename www/{generate_website => wip_new_website}/content/discover_page.md (64%) rename www/{generate_website => wip_new_website}/content/getting_started_page.md (92%) create mode 100644 www/wip_new_website/content/home_page.md create mode 100644 www/wip_new_website/content/learn_roc_page.md rename www/{generate_website => wip_new_website}/main.roc (100%) rename www/{generate_website => wip_new_website}/static/site.css (100%) diff --git a/www/generate_website/.gitignore b/www/generate_website/.gitignore deleted file mode 100644 index c63bd9f48bf..00000000000 --- a/www/generate_website/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -roc-website -dist/ \ No newline at end of file diff --git a/www/generate_website/build.sh b/www/generate_website/build.sh deleted file mode 100644 index 3b0427122d7..00000000000 --- a/www/generate_website/build.sh +++ /dev/null @@ -1,9 +0,0 @@ -rm -rf dist/ - -roc run main.roc -- content/ dist/ - -cp -r static/* dist/ - -cd dist - -simple-http-server -p 8000 \ No newline at end of file diff --git a/www/generate_website/content/home_page.md b/www/generate_website/content/home_page.md deleted file mode 100644 index 04985a4db87..00000000000 --- a/www/generate_website/content/home_page.md +++ /dev/null @@ -1,16 +0,0 @@ -# Roc lang - -- Fast -- Functional -- Friendly - -## Try Roc -<-- WebREPL goes here --> - -## [Discover Roc](/discover_page.html) - -## [Learn Roc](/learn_roc.html) - -## [Contribute to Roc](contributing_page.html) - -## [Getting Started](/getting_started_page.html) diff --git a/www/generate_website/content/learn_roc_page.md b/www/generate_website/content/learn_roc_page.md deleted file mode 100644 index a0406355d63..00000000000 --- a/www/generate_website/content/learn_roc_page.md +++ /dev/null @@ -1,23 +0,0 @@ -# Learn Roc - -## Guides - -### The Roc Tutorial - -- [The Roc Tutorial](https://www.roc-lang.org/tutorial) - -### Frequently Asked Questions - -- [Link](https://github.com/roc-lang/roc/blob/main/FAQ.md) - -### Roc for Elm Programmers - -- [Roc for Elm Programmers](https://github.com/roc-lang/roc/blob/main/roc-for-elm-programmers.md) - -## Documentation - -### Builtin Package - -### Basic-CLI Platform - -### Language Reference \ No newline at end of file diff --git a/www/wip_new_website/.gitignore b/www/wip_new_website/.gitignore new file mode 100644 index 00000000000..7fb7946aa2c --- /dev/null +++ b/www/wip_new_website/.gitignore @@ -0,0 +1,3 @@ +roc-website +dist/ +build-website \ No newline at end of file diff --git a/www/wip_new_website/build.roc b/www/wip_new_website/build.roc new file mode 100755 index 00000000000..992cea072eb --- /dev/null +++ b/www/wip_new_website/build.roc @@ -0,0 +1,55 @@ +#!/usr/bin/env roc +app "build-website" + # TODO update to basic-cli release when Command module is available + packages { pf: "https://github.com/lukewilliamboswell/roc-things/releases/download/test/VQYlmhbzLld4kAE4Y8sWt349md89iyGBg5hgoIBfvcs.tar.br" } + imports [ + pf.Task.{ Task }, + pf.Command, + ] + provides [main] to pf + +main = + + # Remove dist folder + {} <- + Command.new "rm" + |> Command.arg "-rf" + |> Command.arg "dist/" + |> Command.status + |> Task.onFail \_ -> crash "Failed to remove dist folder" + |> Task.await + + # Build site + {} <- + Command.new "roc" + |> Command.arg "run" + |> Command.arg "main.roc" + |> Command.arg "--" + |> Command.arg "content/" + |> Command.arg "dist/" + |> Command.status + |> Task.onFail \_ -> crash "Failed to build site" + |> Task.await + + # Copy static files + {} <- + Command.new "cp" + |> Command.arg "-r" + |> Command.arg "static/site.css" + |> Command.arg "dist/" + |> Command.status + |> Task.onFail \_ -> crash "Failed to copy static files" + |> Task.await + + # Start file server + {} <- + Command.new "simple-http-server" + |> Command.arg "-p" + |> Command.arg "8080" + |> Command.arg "--" + |> Command.arg "dist/" + |> Command.status + |> Task.onFail \_ -> crash "Failed to change directory" + |> Task.await + + Task.succeed {} diff --git a/www/generate_website/content/contributing_page.md b/www/wip_new_website/content/contributing_page.md similarity index 84% rename from www/generate_website/content/contributing_page.md rename to www/wip_new_website/content/contributing_page.md index 667a17003ee..4dc9fcf6a97 100644 --- a/www/generate_website/content/contributing_page.md +++ b/www/wip_new_website/content/contributing_page.md @@ -1,5 +1,7 @@ # Contribute to Roc + + ## Sponsorship - [Github Sponsorship](https://github.com/sponsors/roc-lang) diff --git a/www/generate_website/content/discover_page.md b/www/wip_new_website/content/discover_page.md similarity index 64% rename from www/generate_website/content/discover_page.md rename to www/wip_new_website/content/discover_page.md index 30eee00ab3c..abacd274a50 100644 --- a/www/generate_website/content/discover_page.md +++ b/www/wip_new_website/content/discover_page.md @@ -1,32 +1,22 @@ # Discover Roc -## Meet the Community - -### Zulip Chat - -- [roc.zulipchat.com](https://roc.zulipchat.com/) + -### Github Project - -- [roc-lang/roc](https://github.com/roc-lang/roc) - -### Meetups & Events +## Meet the Community -### Socials +- Group Chat [roc.zulipchat.com](https://roc.zulipchat.com/) +- Github Project [roc-lang/roc](https://github.com/roc-lang/roc) +- Meetups & Events +- Socials ## Roc Applications -### Tools & Scripts - -### Web (coming soon) - -### Networking & Servers (coming soon) - -### Graphical (coming soon) - -### Scientific (coming soon) - -### Embedded (coming soon) +- Tools & Scripts +- Web (coming soon) +- Networking & Servers (coming soon) +- Graphical (coming soon) +- Scientific (coming soon) +- Embedded (coming soon) ## Roc Platforms diff --git a/www/generate_website/content/getting_started_page.md b/www/wip_new_website/content/getting_started_page.md similarity index 92% rename from www/generate_website/content/getting_started_page.md rename to www/wip_new_website/content/getting_started_page.md index 6be3e93103e..9bcdc98b320 100644 --- a/www/generate_website/content/getting_started_page.md +++ b/www/wip_new_website/content/getting_started_page.md @@ -1,5 +1,7 @@ # Getting Started + + ## Installation - [Linux x86-64 Getting Started Guide](https://github.com/roc-lang/roc/blob/main/getting_started/linux_x86_64.md) @@ -13,15 +15,10 @@ ## Roc CLI - Develop `roc dev` - - Test `roc test` - - Run `roc run` - - Build `roc build` - - Format `roc format` - - Documentation `roc docs` ## Package Management diff --git a/www/wip_new_website/content/home_page.md b/www/wip_new_website/content/home_page.md new file mode 100644 index 00000000000..01f9621e1ac --- /dev/null +++ b/www/wip_new_website/content/home_page.md @@ -0,0 +1,33 @@ + + +# Roc lang + + + +- fast +- friendly +- functional + +## Try Roc + + + +## [Discover Roc](/discover_page.html) + + + +## [Learn Roc](/learn_roc_page.html) + + + +## [Contribute to Roc](contributing_page.html) + + + +## [Getting Started](/getting_started_page.html) + + \ No newline at end of file diff --git a/www/wip_new_website/content/learn_roc_page.md b/www/wip_new_website/content/learn_roc_page.md new file mode 100644 index 00000000000..4992f612220 --- /dev/null +++ b/www/wip_new_website/content/learn_roc_page.md @@ -0,0 +1,24 @@ +# Learn Roc + + + +## Tutorial + +- [Tutorial](https://www.roc-lang.org/tutorial) + +## Examples + +<-- link to examples site --> + +## Guides + +<-- links to guides --> + +- [Frequently Asked Questions](https://github.com/roc-lang/roc/blob/main/FAQ.md) +- [Roc for Elm Programmers](https://github.com/roc-lang/roc/blob/main/roc-for-elm-programmers.md) + +## Documentation + +- Builtin Package +- Basic-CLI Platform +- Language Reference \ No newline at end of file diff --git a/www/generate_website/main.roc b/www/wip_new_website/main.roc similarity index 100% rename from www/generate_website/main.roc rename to www/wip_new_website/main.roc diff --git a/www/generate_website/static/site.css b/www/wip_new_website/static/site.css similarity index 100% rename from www/generate_website/static/site.css rename to www/wip_new_website/static/site.css From 71517782616de48d375f9df6f04ed1eb3d54495c Mon Sep 17 00:00:00 2001 From: Luke Boswell Date: Thu, 22 Jun 2023 15:09:43 +1000 Subject: [PATCH 003/140] fix error message in build script --- www/wip_new_website/build.roc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/wip_new_website/build.roc b/www/wip_new_website/build.roc index 992cea072eb..31b4083f852 100755 --- a/www/wip_new_website/build.roc +++ b/www/wip_new_website/build.roc @@ -49,7 +49,7 @@ main = |> Command.arg "--" |> Command.arg "dist/" |> Command.status - |> Task.onFail \_ -> crash "Failed to change directory" + |> Task.onFail \_ -> crash "Failed to run file server; consider intalling with `cargo install simple-http-server`" |> Task.await Task.succeed {} From 78c88542079c879145d90c4d08fe5d1fa4f49e91 Mon Sep 17 00:00:00 2001 From: Luke Boswell Date: Thu, 22 Jun 2023 16:16:49 +1000 Subject: [PATCH 004/140] change binary name to reduce name conflicts --- www/wip_new_website/.gitignore | 2 +- www/wip_new_website/build.roc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/www/wip_new_website/.gitignore b/www/wip_new_website/.gitignore index 7fb7946aa2c..ff2a61edb64 100644 --- a/www/wip_new_website/.gitignore +++ b/www/wip_new_website/.gitignore @@ -1,3 +1,3 @@ roc-website dist/ -build-website \ No newline at end of file +website-builder \ No newline at end of file diff --git a/www/wip_new_website/build.roc b/www/wip_new_website/build.roc index 31b4083f852..cb7a1283e50 100755 --- a/www/wip_new_website/build.roc +++ b/www/wip_new_website/build.roc @@ -1,5 +1,5 @@ #!/usr/bin/env roc -app "build-website" +app "website-builder" # TODO update to basic-cli release when Command module is available packages { pf: "https://github.com/lukewilliamboswell/roc-things/releases/download/test/VQYlmhbzLld4kAE4Y8sWt349md89iyGBg5hgoIBfvcs.tar.br" } imports [ From caf95cc811a3101685cc915f7def6fa18ee91b74 Mon Sep 17 00:00:00 2001 From: Luke Boswell Date: Thu, 22 Jun 2023 16:17:49 +1000 Subject: [PATCH 005/140] Remove crash which was caussing issues --- www/wip_new_website/main.roc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/www/wip_new_website/main.roc b/www/wip_new_website/main.roc index 790c7491161..af6b3804b6b 100644 --- a/www/wip_new_website/main.roc +++ b/www/wip_new_website/main.roc @@ -15,9 +15,8 @@ pageData = |> Dict.insert "getting_started_page.html" { title: "Let's Roc", description: "Getting started with the Roc programming language" } getPage : Str -> {title : Str, description : Str} -getPage = \current -> +getPage = \current -> Dict.get pageData current - |> Result.onErr \_ -> crash "expected page to be in meta" |> Result.withDefault { title: "", description: ""} getTitle : Str -> Str @@ -49,7 +48,9 @@ view = \page, htmlContent -> text htmlContent, ], footer [] [ - text "Made by people who like to make nice things. © 2022" + text "This site is powered by ", + a [href "https://www.netlify.com"] [ text "Netlify"], + text ". Made by people who like to make nice things. © Roc 2023", ] ], script [src "/site.js"] [], From cfe528c38dd37d4c9330257e26ffaa3191e2e804 Mon Sep 17 00:00:00 2001 From: Luke Boswell Date: Thu, 22 Jun 2023 16:18:13 +1000 Subject: [PATCH 006/140] add the Oct 2022 website update as a blog article --- .../content/blog/roc_website_2022.md | 118 ++++++++++++++++++ www/wip_new_website/content/discover_page.md | 4 + www/wip_new_website/static/site.css | 2 +- 3 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 www/wip_new_website/content/blog/roc_website_2022.md diff --git a/www/wip_new_website/content/blog/roc_website_2022.md b/www/wip_new_website/content/blog/roc_website_2022.md new file mode 100644 index 00000000000..0c431f04ccb --- /dev/null +++ b/www/wip_new_website/content/blog/roc_website_2022.md @@ -0,0 +1,118 @@ +The Roc Programming Language +============================ + +*By: Richard Feldman, 2022/10/11* + +Roc's goal is to be a fast, friendly, functional language. It's very much a work in progress; below, you can see the current progress towards this goal. This website is intentionally unstyled as a way to emphasize the language's current level of incompleteness. The website will become more polished after the language itself becomes more polished! + +Roc compiles to machine code or to [WebAssembly](https://webassembly.org). Eventually you'll be able to use Roc to build high-quality servers, command-line applications, graphical native desktop user interfaces, among other classes of applications. Today, only command-line interfaces have support beyond the proof-of-concept stage; the other use cases will mature over time. + +Like [Lua](https://www.lua.org/), Roc's automatic memory management doesn't require a virtual machine, and it's possible to call Roc functions directly from any language that can call [C](https://en.wikipedia.org/wiki/C_(programming_language)) functions. This makes Roc additionally useful as a language for implementing plugins, and gives you a way to incrementally transition a legacy code base from another language to Roc. + +So far, the Roc compiler has progressed past the "proof of concept" stage, but there are currently lots of known bugs and unimplemented features, and the documentation for both the language and the standard library is incomplete. The overall ecosystem is in its infancy, and the compiler is neither battle-tested nor fuzz-tested yet, so we don't recommend relying on Roc for critical projects until its development is further along. + +With all that context in mind, if you'd like to try it out or to get involved with contributing, the [source code repository](https://github.com/roc-lang/roc) has [nightly builds](https://github.com/roc-lang/roc/releases) you can download, and a [tutorial](https://roc-lang.org/tutorial). + +If you'd like to learn more about Roc, you can continue reading here, or check out one of these videos: + +* [Roc at Handmade Seattle](https://media.handmade-seattle.com/roc-lang) - November 12, 2021 (very low-level explanation of how Roc's compiler makes programs run fast) +* [Outperforming Imperative with Pure Functional Languages](https://youtu.be/vzfy4EKwG_Y) - October 1, 2021 (about Roc's runtime performance and optimizer) +* [A taste of Roc](https://youtu.be/6qzWm_eoUXM) - September 23, 2021 (syntax, application examples) +* [Roc at the Philly ETE conference](https://youtu.be/cpQwtwVKAfU?t=75) - May 6, 2021 (platforms and applications) +* [Roc on Zig Showtime](https://youtu.be/FMyyYdFSOHA) - April 24, 2021 (making a platform) +* [Roc at the Berlin FP Meetup](https://youtu.be/ZnYa99QoznE?t=4790) - September 1, 2020 (overall vision for the language) + +A _Fast_ Language +----------------- + +### Goal + +We want Roc to run faster than any non-systems language (like C, C++, Rust, or Zig) that sees mainstream use in industry. The goal is that nobody should find themselves thinking "I should rewrite my Roc program in \[some mainstream garbage-collected language\] because that will make it run significantly faster." + +When benchmarking Roc code against similarly-optimized programs written in [Go](https://go.dev), [Swift](https://www.swift.org/), [Java](https://www.java.com), [C#](https://learn.microsoft.com/en-us/dotnet/csharp), or [JavaScript](https://www.ecma-international.org/publications-and-standards/standards/ecma-262), we generally aim for Roc to outperform all of those languages. Outperforming systems languages like Rust, Zig, C, D, and C++ is a non-goal, as is outperforming research languages that see little or no use in industry. (Realistically, there will always be certain specific benchmarks where some popular non-systems-level languages outperform Roc, but the goal is to usually be at the front of that pack.) + +#### Current progress + +Progress towards this performance goal is already quite far along. + +Roc already uses unboxed data structures and unboxed closures, monomorphizes polymorphic code, and uses LLVM as a compiler backend. These optimizations, especially unboxed closures and monomorphization, can be found in several systems-level languages (like C++ and Rust), but not in any mainstream garbage-collected languages. Roc closures in particular have the distinction of being as ergonomic as the closures found in garbage-collected languages (where they are typically boxed), but have the performance of systems language closures (which are typically unboxed, but have more complicated types). + +Because of these optimizations, in many cases Roc code already compiles to the same machine instructions that the equivalent code written in one of these systems languages would. Something we do regularly is to compare the LLVM instructions generated by Roc's compiler and by these systems languages' compilers, to check whether we're generating equivalent instructions. + +That said, there are also cases where Roc has strictly more runtime overhead than languages like C, C++, Zig, and Rust do. The most costly is automatic memory management, which Roc implements using automatic reference counting. Static reference count optimizations like elision and reuse (thanks to Morphic and [Perceus](https://www.microsoft.com/en-us/research/publication/perceus-garbage-free-reference-counting-with-reuse/)) improve things, but significant runtime overhead remains. + +Eliminating this overhead altogether would require sacrificing other design goals (e.g. it would require introducing memory-unsafe operations, or compile-time lifetime errors), and there isn't much overhead left to remove outside of automatic memory management. For example, smaller sources of overhead include mandatory array bounds checks, disallowing cyclic references (which rules out a certain niche of efficient graph data structures), and automatic opportunistic in-place mutation instead of direct mutation. Even if all of these sources of overhead were completely eliminated, it seems unlikely that typical Roc programs would see a particularly big performance boost. + +Overall, we expect Roc's performance in the use cases mentioned above (servers, CLIs, GUIs, etc.) to be about the same as the equivalent C++ code would be, if all that C++ code (including its dependencies) were written in a restricted subset of C++ which always did array bounds checks and used shared pointers for all heap allocations. The Roc code might even run somewhat faster, because its reference counts are non-atomic by default, and can be statically optimized away in some cases—but then again, Roc also has a bit of overhead to perform opportunistic in-place mutation instead of direct mutation. + +To be clear, we don't expect this because we've benchmarked a bunch of programs written in Roc and in this restricted C++ subset, and found that the numbers were about the same (although if you know C++ well enough and want to do such experiments, we'd happy to help and would be interested to see the results!) but rather because Roc's compiler and [clang](https://clang.llvm.org/) should both be generating essentially the same LLVM instructions when the C++ is restricted to that subset. + +Of course, _unrestricted_ C++ code can certainly run faster than unrestricted Roc code. The same is true when comparing other such minimal-overhead systems languages to Roc, including Rust, Zig, C, and D. The point of the comparison is to give you a general idea of what Roc compiles to, since it is quite different from the VMs and JITted bytecode interpreters found in today's most popular garbage-collected languages! + +The talk [Outperforming Imperative with Pure Functional Languages](https://youtu.be/vzfy4EKwG_Y) discusses some early results from Roc's optimizations, and [Roc at Handmade Seattle](https://media.handmade-seattle.com/roc-lang) gets into low-level details of how Roc's compiler generates programs similarly to how clang does. + +A _Friendly_ Language +--------------------- + +### Goals + +Roc aims to be a user-friendly language with a friendly community of users. + +A programming language can be much more than a tool for writing software, it can also be a way for people to come together through shared experiences, to teach and to learn from one another, and to make new friends. + +No community is perfect, but a community where people show kindness to each another by default can be a true joy to participate in. That all starts with friendliness, especially towards beginners, and including towards people who prefer other programming languages. After all, languages are tools people use to create software, and there's no need for us to create artificial divisions between ourselves based on the tools we use! + +On a technical level, Roc aims to ship a toolset where user-friendliness is a major priority. This includes everything from helpful error messages (aiming to meet the bar set by [Elm](https://elm-lang.org)) to quality-of-life improvements inspired by dynamic languages (always being able to run your program even if there are compile errors, automatic serialization and deserialization using schemas determined by type inference, reliable hot code loading that's always enabled and requires no configuration to set up, etc.) to accessibility features in the included editor. + +Roc also aims to ship a single binary that includes not only a compiler, but also a [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop), package manager, test runner, debugger, static analyzer, code formatter, and a full-featured editor, all of which are designed to work seamlessly together. + +### Current Progress + +Work has not yet started on the package manager, static analyzer, debugger, or hot code loading system, and although work has started on the editor, it's not yet far enough along to be usable for practical purposes. The standard library is perhaps 80 percent complete in terms of functionality, but a lot of operations do not yet have documentation. + +The REPL fully supports entering arbitrary expressions, and will evaluate them and print the results. It remembers recent expressions entered in the current session (if you press the up arrow), but it can't yet execute effects. You can try out the REPL in a browser at [roc-lang.org/repl](https://roc-lang.org/repl) - it uses a WebAssembly build of Roc's compiler, and compiles the code you write to WebAssembly on the fly, which it then executes in the browser to display the answer. + +The compiler works well enough on a basic level to build things with it, but some error messages could use significant improvement, and it has a lot of known bugs and missing features. You can currently use it on macOS (either Intel or Apple Silicon), Linux (only x86-64 machines at the moment), and Windows (only recently supported; debugging and testing features don't work on it yet, and there are likely bugs we haven't encountered yet due to lack of battle testing). Support for other operating systems has not yet been discussed. + +The compiler doesn't yet support incremental compilation or hot code loading, and build times vary based on what machine you're building for. + +For example, suppose you run \`roc check\`, which reports errors it finds (type mismatches, naming errors, and so on) but doesn't actually build an executable, on a code base that's under a thousand lines of code. On an M1 MacBook Pro, this typically takes about 10 milliseconds. + +In contrast, if you do \`roc build\` (or \`roc run\`) on that same machine, it will take closer to 500 milliseconds instead. Almost all that extra time is spent waiting for LLVM to generate (unoptimized) machine code, and then for the system linker to assemble an executable from it. + +Fortunately, we can eliminate almost all of those extra 490 millisconds of build time by using Roc's (work in progress) development backend instead of LLVM. This compiles directly from Roc's internal representation to machine code, like most compilers did before LLVM. (LLVM can optimize code into running very fast, but even when it performs no optimization at all, LLVM itself takes a lot longer to run than generating unoptimized machine code directly.) + +The LLVM backend is currently the most feature-complete, followed closely by the WebAssembly backend (which the online REPL uses exclusively, instead of LLVM). The x86 and ARM backends still have a ways to go, but improving them can be done by anyone with the patience to read some documentation; we have issues split up for them, and are happy to help new contributors get up and running! + +Builds on Linux and Windows also use Roc's surgical linker instead of the system linker, which runs so fast that linking essentially disappears from the performance profile altogether. The surgical linker currently only works on Linux and Windows, and it currently supports building executables but not (yet) dynamic libraries, which is relevant if you're using Roc to create plugins or want to call Roc functions from existing code bases in other languages. Work has started on macOS surgical linking, but it isn't usable yet. If you're interested in working on that, please get in touch on [Roc Zulip](https://roc.zulipchat.com/)! + +The test runner currently has first-class support for running standard non-effectful tests. It does not yet have first-class support for effectful tests, property-based tests, snapshot tests, or "simulation tests" (where effects are replaced by hardcoded values during the test - similar to "mocking" in other languages), although these are all planned for the future. + +The code formatter is nearly feature-complete, although occasionally it will report an error - usually due to a comment being placed somewhere it doesn't yet know how to handle. Unlike most of the rest of the compiler, the formatter is one place where the number of known bugs is so small that fuzzing would be very helpful as a way to surface bugs we don't yet know about. (If you're interested in working on setting up fuzzing for the formatter, please let us know in the [`#contributing` channel](https://roc.zulipchat.com/#narrow/stream/316715-contributing) on Zulip! Separately, we're also very interested in fuzzing the compiler, even though we already have a sizable list of known bugs there.) + +On the community side, so far the community is a friendly bunch, and we want to keep it that way as it grows! We hope to do that by encouraging a culture of kindness and helping one another out, especially by being welcoming towards beginners. + +If you'd like to join in, the best place to do that is in our Zulip chat. Feel free to drop by the [`introductions` topic](https://roc.zulipchat.com/#narrow/stream/231634-beginners/topic/introductions) and introduce yourself! + +A _Functional_ Language +----------------------- + +### Goals + +Roc aims to be a purely functional programming language. This means all Roc functions are [pure functions](https://en.wikipedia.org/wiki/Pure_function), and all effects are [managed effects](https://medium.com/@kaw2k/managed-effects-and-elm-36b7fcd246a9) instead of side effects. + +A major motivating reason for this is to facilitate tooling. For example, in the future the goal is that Roc's test runner won't bother re-running tests whose outcomes could not possibly have changed (because they were pure functions whose inputs did not change). Tests that contain only pure functions can be trivially run in parallel, and they will never [flake](https://www.smashingmagazine.com/2021/04/flaky-tests-living-nightmare/). Additionally, having the guarantee that the application contains only pure functions can also make certain debugging tools more reliable, such as time travel and retroactive tracing. + +Roc also takes a novel approach to managed effects. In most programming languages, the standard library contains both data structures and I/O primitives (e.g. for using the file system or the network), and then you might decide to use a [framework](https://en.wikipedia.org/wiki/Application_framework) on top of that standard library. + +In Roc, every application is built on a _platform_. A platform is like a framework except that it also provides I/O primitives and behind-the-scenes memory management. (Roc's standard library only contains data structures.) In practice, this means that using Roc feels similar to using any other programming language where you've chosen to use a framework, except that the documentation for your I/O primitives comes from the framework instead of the standard library. + +This might sound like a minor distinction, but it turns out there are a lot of surprising benefits to organizing things this way, which would be impossible to achieve without having platforms as a first-class language concept. [The Edges of Cutting-Edge Languages](https://youtu.be/cpQwtwVKAfU) goes into more detail about some of these benefits. + +### Current Progress + +Today, platforms as a concept already exist, and there are a few different ones implemented. You can find them in the [`examples/`](https://github.com/roc-lang/roc/tree/main/examples) directory in the source code repository. The platform for building command-line interfaces is the most fully featured; the others are mostly in the proof-of-concept stage. + +Roc's built-in tooling is not yet far enough along to take advantage of pure functions. For example, there is a built-in test runner, but it does not yet run tests in parallel or skip running tests whose outcomes could not possibly have changed. + +Roc is already a purely functional programming language, though, so all of these benefits are ready to be unlocked as the tooling implementations progress! \ No newline at end of file diff --git a/www/wip_new_website/content/discover_page.md b/www/wip_new_website/content/discover_page.md index abacd274a50..80ea796478d 100644 --- a/www/wip_new_website/content/discover_page.md +++ b/www/wip_new_website/content/discover_page.md @@ -9,6 +9,10 @@ - Meetups & Events - Socials +## Blog + +- [Website Update Oct 2022](/blog/roc_website_2022.html) + ## Roc Applications - Tools & Scripts diff --git a/www/wip_new_website/static/site.css b/www/wip_new_website/static/site.css index 189072f35be..76d4f743b15 100644 --- a/www/wip_new_website/static/site.css +++ b/www/wip_new_website/static/site.css @@ -39,10 +39,10 @@ body { } footer { + font-size: 0.9rem; max-width: 1024px; margin: 0 auto; font-size: 14px; - padding: 16px; } section p:last-child { From 6851741c8ad44bf978dbdc4bff09b35db8ed3b88 Mon Sep 17 00:00:00 2001 From: ibalbaert Date: Thu, 22 Jun 2023 11:05:48 +0200 Subject: [PATCH 007/140] Update Result.roc Changed deprecated Num.negate in Result.map docs to Num.neg Signed-off-by: ibalbaert --- crates/compiler/builtins/roc/Result.roc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/compiler/builtins/roc/Result.roc b/crates/compiler/builtins/roc/Result.roc index a9075aebbf3..7ff20351768 100644 --- a/crates/compiler/builtins/roc/Result.roc +++ b/crates/compiler/builtins/roc/Result.roc @@ -42,8 +42,8 @@ withDefault = \result, default -> ## function on it. Then returns a new `Ok` holding the transformed value. If the ## result is `Err`, this has no effect. Use [mapErr] to transform an `Err`. ## ``` -## Result.map (Ok 12) Num.negate -## Result.map (Err "yipes!") Num.negate +## Result.map (Ok 12) Num.neg +## Result.map (Err "yipes!") Num.neg ## ``` ## ## Functions like `map` are common in Roc; see for example [List.map], From 683b586f60761a507aa8aa4070b97ec6e6f51f64 Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Thu, 22 Jun 2023 11:20:30 -0500 Subject: [PATCH 008/140] Use more structs instead of tuples --- crates/compiler/load_internal/src/file.rs | 89 +++++++++++++---------- crates/compiler/solve/src/module.rs | 65 ++++++++++------- crates/compiler/solve/src/solve.rs | 77 +++++++++----------- 3 files changed, 128 insertions(+), 103 deletions(-) diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index 7c0045af3c6..2213ca4dc0c 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -56,7 +56,7 @@ use roc_region::all::{LineInfo, Loc, Region}; #[cfg(not(target_family = "wasm"))] use roc_reporting::report::to_https_problem_report_string; use roc_reporting::report::{to_file_problem_report_string, Palette, RenderTarget}; -use roc_solve::module::{extract_module_owned_implementations, Solved, SolvedModule}; +use roc_solve::module::{extract_module_owned_implementations, SolveCtx, Solved, SolvedModule}; use roc_solve_problem::TypeError; use roc_target::TargetInfo; use roc_types::subs::{CopiedImport, ExposedTypesStorageSubs, Subs, VarStore, Variable}; @@ -5061,6 +5061,14 @@ fn import_variable_for_symbol( } } +struct SolveResult { + solved: Solved, + solved_implementations: ResolvedImplementations, + exposed_vars_by_symbol: Vec<(Symbol, Variable)>, + problems: Vec, + abilities_store: AbilitiesStore, +} + #[allow(clippy::complexity)] fn run_solve_solve( exposed_for_module: ExposedForModule, @@ -5071,13 +5079,7 @@ fn run_solve_solve( var_store: VarStore, module: Module, derived_module: SharedDerivedModule, -) -> ( - Solved, - ResolvedImplementations, - Vec<(Symbol, Variable)>, - Vec, - AbilitiesStore, -) { +) -> SolveResult { let Module { exposed_symbols, aliases, @@ -5116,25 +5118,29 @@ fn run_solve_solve( solve_aliases.insert(&mut types, *name, alias.clone()); } - let (solved_subs, solved_implementations, exposed_vars_by_symbol, problems, abilities_store) = { + let (solve_output, solved_implementations, exposed_vars_by_symbol) = { let module_id = module.module_id; - let (solved_subs, solved_env, problems, abilities_store) = roc_solve::module::run_solve( - module_id, + let solve_ctx = SolveCtx { + home: module_id, types, - &constraints, - actual_constraint, + constraints: &constraints, + root_constraint: actual_constraint, + pending_derives, + exposed_by_module: &exposed_for_module.exposed_by_module, + derived_module, + }; + + let solve_output = roc_solve::module::run_solve( + solve_ctx, rigid_variables, subs, solve_aliases, abilities_store, - pending_derives, - &exposed_for_module.exposed_by_module, - derived_module, ); let solved_implementations = - extract_module_owned_implementations(module_id, &abilities_store); + extract_module_owned_implementations(module_id, &solve_output.resolved_abilities_store); let is_specialization_symbol = |sym| { solved_implementations @@ -5147,7 +5153,8 @@ fn run_solve_solve( // Expose anything that is explicitly exposed by the header, or is a specialization of an // ability. - let exposed_vars_by_symbol: Vec<_> = solved_env + let exposed_vars_by_symbol: Vec<_> = solve_output + .env .vars_by_symbol() .filter(|(k, _)| { exposed_symbols.contains(k) @@ -5156,22 +5163,23 @@ fn run_solve_solve( }) .collect(); - ( - solved_subs, - solved_implementations, - exposed_vars_by_symbol, - problems, - abilities_store, - ) + (solve_output, solved_implementations, exposed_vars_by_symbol) }; - ( - solved_subs, + let roc_solve::module::SolveOutput { + subs, + env: _, + errors, + resolved_abilities_store, + } = solve_output; + + SolveResult { + solved: subs, solved_implementations, exposed_vars_by_symbol, - problems, - abilities_store, - ) + problems: errors, + abilities_store: resolved_abilities_store, + } } fn run_solve<'a>( @@ -5201,7 +5209,7 @@ fn run_solve<'a>( let loc_dbgs = std::mem::take(&mut module.loc_dbgs); let module = module; - let (solved_subs, solved_implementations, exposed_vars_by_symbol, problems, abilities_store) = { + let solve_result = { if module_id.is_builtin() { match cached_types.lock().remove(&module_id) { None => run_solve_solve( @@ -5219,13 +5227,13 @@ fn run_solve<'a>( exposed_vars_by_symbol, abilities, solved_implementations, - }) => ( - Solved(subs), + }) => SolveResult { + solved: Solved(subs), solved_implementations, exposed_vars_by_symbol, - vec![], - abilities, - ), + problems: vec![], + abilities_store: abilities, + }, } } else { run_solve_solve( @@ -5241,7 +5249,14 @@ fn run_solve<'a>( } }; - let mut solved_subs = solved_subs; + let SolveResult { + solved: mut solved_subs, + solved_implementations, + exposed_vars_by_symbol, + problems, + abilities_store, + } = solve_result; + let exposed_types = roc_solve::module::exposed_types_storage_subs( module_id, &mut solved_subs, diff --git a/crates/compiler/solve/src/module.rs b/crates/compiler/solve/src/module.rs index 1920f46eefe..544900c43a1 100644 --- a/crates/compiler/solve/src/module.rs +++ b/crates/compiler/solve/src/module.rs @@ -1,6 +1,6 @@ use crate::solve::{self, Aliases}; use roc_can::abilities::{AbilitiesStore, ResolvedImpl}; -use roc_can::constraint::{Constraint as ConstraintSoa, Constraints}; +use roc_can::constraint::{Constraint, Constraints}; use roc_can::expr::PendingDerives; use roc_can::module::{ExposedByModule, ResolvedImplementations, RigidVariables}; use roc_collections::all::MutMap; @@ -53,20 +53,41 @@ pub struct SolvedModule { pub exposed_types: ExposedTypesStorageSubs, } -#[allow(clippy::too_many_arguments)] // TODO: put params in a context/env var +pub struct SolveCtx<'a> { + /// The module we are solving. + pub home: ModuleId, + pub constraints: &'a Constraints, + pub root_constraint: Constraint, + /// All types introduced in the module. Canonicalized, but not necessarily yet associated with + /// a variable substitution. + pub types: Types, + /// Table of types introduced in this module that claim to derive an ability implementation. + /// Due for checking and instantiation after the solver runs over the module. + pub pending_derives: PendingDerives, + /// Types exposed by other modules. + /// Available for late instantiation of imports, lambda sets, or ability types. + pub exposed_by_module: &'a ExposedByModule, + /// The unique `#Derived` module, used to generate and retrieve derived ability + /// implementations. + /// Needed during solving to resolve lambda sets from derived implementations that escape into + /// the user module. + pub derived_module: SharedDerivedModule, +} + +pub struct SolveOutput { + pub subs: Solved, + pub env: solve::Env, + pub errors: Vec, + pub resolved_abilities_store: AbilitiesStore, +} + pub fn run_solve( - home: ModuleId, - types: Types, - constraints: &Constraints, - constraint: ConstraintSoa, + ctx: SolveCtx<'_>, rigid_variables: RigidVariables, mut subs: Subs, mut aliases: Aliases, mut abilities_store: AbilitiesStore, - pending_derives: PendingDerives, - exposed_by_module: &ExposedByModule, - derived_module: SharedDerivedModule, -) -> (Solved, solve::Env, Vec, AbilitiesStore) { +) -> SolveOutput { for (var, name) in rigid_variables.named { subs.rigid_var(var, name); } @@ -84,21 +105,15 @@ pub fn run_solve( let mut problems = Vec::new(); // Run the solver to populate Subs. - let (solved_subs, solved_env) = solve::run( - home, - types, - constraints, - &mut problems, - subs, - &mut aliases, - &constraint, - pending_derives, - &mut abilities_store, - exposed_by_module, - derived_module, - ); - - (solved_subs, solved_env, problems, abilities_store) + let (solved_subs, solved_env) = + solve::run(ctx, &mut problems, subs, &mut aliases, &mut abilities_store); + + SolveOutput { + subs: solved_subs, + env: solved_env, + errors: problems, + resolved_abilities_store: abilities_store, + } } /// Copies exposed types and all ability specializations, which may be implicitly exposed. diff --git a/crates/compiler/solve/src/solve.rs b/crates/compiler/solve/src/solve.rs index ba319525376..2b5c89345a0 100644 --- a/crates/compiler/solve/src/solve.rs +++ b/crates/compiler/solve/src/solve.rs @@ -4,7 +4,7 @@ use crate::ability::{ resolve_ability_specialization, type_implementing_specialization, AbilityImplError, CheckedDerives, ObligationCache, PendingDerivesTable, Resolved, }; -use crate::module::Solved; +use crate::module::{SolveCtx, Solved}; use crate::specialize::{ compact_lambda_sets_of_vars, AwaitingSpecializations, CompactionResult, DerivedEnv, SolvePhase, }; @@ -13,17 +13,14 @@ use roc_can::abilities::{AbilitiesStore, MemberSpecializationInfo}; use roc_can::constraint::Constraint::{self, *}; use roc_can::constraint::{Constraints, Cycle, LetConstraint, OpportunisticResolve, TypeOrVar}; use roc_can::expected::{Expected, PExpected}; -use roc_can::expr::PendingDerives; -use roc_can::module::ExposedByModule; use roc_collections::all::MutMap; use roc_collections::soa::{Index, Slice}; use roc_debug_flags::dbg_do; #[cfg(debug_assertions)] use roc_debug_flags::ROC_VERIFY_RIGID_LET_GENERALIZED; -use roc_derive::SharedDerivedModule; use roc_error_macros::internal_error; use roc_module::ident::TagName; -use roc_module::symbol::{ModuleId, Symbol}; +use roc_module::symbol::Symbol; use roc_problem::can::CycleEntry; use roc_region::all::Loc; use roc_solve_problem::TypeError; @@ -524,33 +521,14 @@ struct State { mark: Mark, } -#[allow(clippy::too_many_arguments)] // TODO: put params in a context/env var pub fn run( - home: ModuleId, - types: Types, - constraints: &Constraints, + ctx: SolveCtx, problems: &mut Vec, mut subs: Subs, aliases: &mut Aliases, - constraint: &Constraint, - pending_derives: PendingDerives, abilities_store: &mut AbilitiesStore, - exposed_by_module: &ExposedByModule, - derived_module: SharedDerivedModule, ) -> (Solved, Env) { - let env = run_in_place( - home, - types, - constraints, - problems, - &mut subs, - aliases, - constraint, - pending_derives, - abilities_store, - exposed_by_module, - derived_module, - ); + let env = run_in_place(ctx, problems, &mut subs, aliases, abilities_store); (Solved(subs), env) } @@ -558,18 +536,22 @@ pub fn run( /// Modify an existing subs in-place instead #[allow(clippy::too_many_arguments)] // TODO: put params in a context/env var fn run_in_place( - _home: ModuleId, // TODO: remove me? - mut types: Types, - constraints: &Constraints, + ctx: SolveCtx, problems: &mut Vec, subs: &mut Subs, aliases: &mut Aliases, - constraint: &Constraint, - pending_derives: PendingDerives, abilities_store: &mut AbilitiesStore, - exposed_by_module: &ExposedByModule, - derived_module: SharedDerivedModule, ) -> Env { + let SolveCtx { + home: _, + constraints, + root_constraint, + mut types, + pending_derives, + exposed_by_module, + derived_module, + } = ctx; + let mut pools = Pools::default(); let state = State { @@ -602,21 +584,25 @@ fn run_in_place( exposed_types: exposed_by_module, }; + let reified_ctx = ReifiedSolveCtx { + arena: &arena, + constraints, + derived_env: &derived_env, + }; + let state = solve( - &arena, + reified_ctx, types, - constraints, state, rank, &mut pools, problems, aliases, subs, - constraint, + &root_constraint, abilities_store, &mut obligation_cache, &mut awaiting_specializations, - &derived_env, ); state.env @@ -659,11 +645,15 @@ enum Work<'a> { }, } -#[allow(clippy::too_many_arguments)] +struct ReifiedSolveCtx<'a> { + arena: &'a Bump, + constraints: &'a Constraints, + derived_env: &'a DerivedEnv<'a>, +} + fn solve( - arena: &Bump, + ctx: ReifiedSolveCtx, mut can_types: Types, - constraints: &Constraints, mut state: State, rank: Rank, pools: &mut Pools, @@ -674,8 +664,13 @@ fn solve( abilities_store: &mut AbilitiesStore, obligation_cache: &mut ObligationCache, awaiting_specializations: &mut AwaitingSpecializations, - derived_env: &DerivedEnv, ) -> State { + let ReifiedSolveCtx { + arena, + constraints, + derived_env, + } = ctx; + let initial = Work::Constraint { env: &Env::default(), rank, From d1dad56331b5eea94dfb3c2ce3cc5e612c68bf04 Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Thu, 22 Jun 2023 11:37:54 -0500 Subject: [PATCH 009/140] Rename env to scope --- crates/compiler/load_internal/src/file.rs | 4 +- crates/compiler/solve/src/module.rs | 6 +- crates/compiler/solve/src/solve.rs | 87 +++++++---------------- crates/compiler/solve/src/solve/scope.rs | 40 +++++++++++ 4 files changed, 72 insertions(+), 65 deletions(-) create mode 100644 crates/compiler/solve/src/solve/scope.rs diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index 2213ca4dc0c..49d878bf739 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -5154,7 +5154,7 @@ fn run_solve_solve( // Expose anything that is explicitly exposed by the header, or is a specialization of an // ability. let exposed_vars_by_symbol: Vec<_> = solve_output - .env + .scope .vars_by_symbol() .filter(|(k, _)| { exposed_symbols.contains(k) @@ -5168,7 +5168,7 @@ fn run_solve_solve( let roc_solve::module::SolveOutput { subs, - env: _, + scope: _, errors, resolved_abilities_store, } = solve_output; diff --git a/crates/compiler/solve/src/module.rs b/crates/compiler/solve/src/module.rs index 544900c43a1..15e6ee88abb 100644 --- a/crates/compiler/solve/src/module.rs +++ b/crates/compiler/solve/src/module.rs @@ -76,7 +76,7 @@ pub struct SolveCtx<'a> { pub struct SolveOutput { pub subs: Solved, - pub env: solve::Env, + pub scope: solve::Scope, pub errors: Vec, pub resolved_abilities_store: AbilitiesStore, } @@ -105,12 +105,12 @@ pub fn run_solve( let mut problems = Vec::new(); // Run the solver to populate Subs. - let (solved_subs, solved_env) = + let (solved_subs, solved_scope) = solve::run(ctx, &mut problems, subs, &mut aliases, &mut abilities_store); SolveOutput { subs: solved_subs, - env: solved_env, + scope: solved_scope, errors: problems, resolved_abilities_store: abilities_store, } diff --git a/crates/compiler/solve/src/solve.rs b/crates/compiler/solve/src/solve.rs index 2b5c89345a0..acc43557e7e 100644 --- a/crates/compiler/solve/src/solve.rs +++ b/crates/compiler/solve/src/solve.rs @@ -39,6 +39,9 @@ use roc_unify::unify::{ SpecializationLsetCollector, Unified::*, }; +mod scope; +pub use scope::Scope; + // Type checking system adapted from Elm by Evan Czaplicki, BSD-3-Clause Licensed // https://github.com/elm/compiler // Thank you, Evan! @@ -420,43 +423,6 @@ impl Aliases { } } -#[derive(Clone, Debug, Default)] -pub struct Env { - symbols: Vec, - variables: Vec, -} - -impl Env { - pub fn vars_by_symbol(&self) -> impl Iterator + '_ { - let it1 = self.symbols.iter().copied(); - let it2 = self.variables.iter().copied(); - - it1.zip(it2) - } - - #[inline(always)] - fn get_var_by_symbol(&self, symbol: &Symbol) -> Option { - self.symbols - .iter() - .position(|s| s == symbol) - .map(|index| self.variables[index]) - } - - #[inline(always)] - fn insert_symbol_var_if_vacant(&mut self, symbol: Symbol, var: Variable) { - match self.symbols.iter().position(|s| *s == symbol) { - None => { - // symbol is not in vars_by_symbol yet; insert it - self.symbols.push(symbol); - self.variables.push(var); - } - Some(_) => { - // do nothing - } - } - } -} - const DEFAULT_POOLS: usize = 8; #[derive(Clone, Debug)] @@ -517,7 +483,7 @@ impl Pools { #[derive(Clone)] struct State { - env: Env, + scope: Scope, mark: Mark, } @@ -527,7 +493,7 @@ pub fn run( mut subs: Subs, aliases: &mut Aliases, abilities_store: &mut AbilitiesStore, -) -> (Solved, Env) { +) -> (Solved, Scope) { let env = run_in_place(ctx, problems, &mut subs, aliases, abilities_store); (Solved(subs), env) @@ -541,7 +507,7 @@ fn run_in_place( subs: &mut Subs, aliases: &mut Aliases, abilities_store: &mut AbilitiesStore, -) -> Env { +) -> Scope { let SolveCtx { home: _, constraints, @@ -555,7 +521,7 @@ fn run_in_place( let mut pools = Pools::default(); let state = State { - env: Env::default(), + scope: Scope::default(), mark: Mark::NONE.next(), }; let rank = Rank::toplevel(); @@ -605,20 +571,20 @@ fn run_in_place( &mut awaiting_specializations, ); - state.env + state.scope } #[derive(Debug)] enum Work<'a> { Constraint { - env: &'a Env, + scope: &'a Scope, rank: Rank, constraint: &'a Constraint, }, CheckForInfiniteTypes(LocalDefVarsVec<(Symbol, Loc)>), /// The ret_con part of a let constraint that does NOT introduces rigid and/or flex variables LetConNoVariables { - env: &'a Env, + scope: &'a Scope, rank: Rank, let_con: &'a LetConstraint, @@ -633,7 +599,7 @@ enum Work<'a> { /// These introduced variables must be generalized, hence this variant /// is more complex than `LetConNoVariables`. LetConIntroducesVariables { - env: &'a Env, + scope: &'a Scope, rank: Rank, let_con: &'a LetConstraint, @@ -672,7 +638,7 @@ fn solve( } = ctx; let initial = Work::Constraint { - env: &Env::default(), + scope: &Scope::default(), rank, constraint, }; @@ -682,7 +648,7 @@ fn solve( while let Some(work_item) = stack.pop() { let (env, rank, constraint) = match work_item { Work::Constraint { - env, + scope: env, rank, constraint, } => { @@ -699,7 +665,7 @@ fn solve( continue; } Work::LetConNoVariables { - env, + scope: env, rank, let_con, pool_variables, @@ -744,7 +710,7 @@ fn solve( } stack.push(Work::Constraint { - env: arena.alloc(new_env), + scope: arena.alloc(new_env), rank, constraint: ret_constraint, }); @@ -754,7 +720,7 @@ fn solve( continue; } Work::LetConIntroducesVariables { - env, + scope: env, rank, let_con, pool_variables, @@ -764,7 +730,7 @@ fn solve( let ret_constraint = &constraints.constraints[offset + 1]; let mark = state.mark; - let saved_env = state.env; + let saved_env = state.scope; let young_mark = mark; let visit_mark = young_mark.next(); @@ -878,14 +844,14 @@ fn solve( // Note that this vars_by_symbol is the one returned by the // previous call to solve() let state_for_ret_con = State { - env: saved_env, + scope: saved_env, mark: final_mark, }; // Now solve the body, using the new vars_by_symbol which includes // the assignments' name-to-variable mappings. stack.push(Work::Constraint { - env: arena.alloc(new_env), + scope: arena.alloc(new_env), rank, constraint: ret_constraint, }); @@ -903,7 +869,7 @@ fn solve( SaveTheEnvironment => { let mut copy = state; - copy.env = env.clone(); + copy.scope = env.clone(); copy } @@ -1117,7 +1083,7 @@ fn solve( let it = constraints.constraints[slice.indices()].iter().rev(); for sub_constraint in it { stack.push(Work::Constraint { - env, + scope: env, rank, constraint: sub_constraint, }) @@ -1233,7 +1199,7 @@ fn solve( // If the return expression is guaranteed to solve, // solve the assignments themselves and move on. stack.push(Work::Constraint { - env, + scope: env, rank, constraint: defs_constraint, }); @@ -1246,13 +1212,13 @@ fn solve( // Note that the LetConSimple gets the current env and rank, // and not the env/rank from after solving the defs_constraint stack.push(Work::LetConNoVariables { - env, + scope: env, rank, let_con, pool_variables, }); stack.push(Work::Constraint { - env, + scope: env, rank, constraint: defs_constraint, }); @@ -1299,13 +1265,13 @@ fn solve( // That's because the defs constraints will be solved in next_rank if it is eligible for generalization. // The LetCon will then generalize variables that are at a higher rank than the rank of the current scope. stack.push(Work::LetConIntroducesVariables { - env, + scope: env, rank, let_con, pool_variables, }); stack.push(Work::Constraint { - env, + scope: env, rank: binding_rank, constraint: defs_constraint, }); @@ -2300,6 +2266,7 @@ impl LocalDefVarsVec<(Symbol, Loc)> { use std::cell::RefCell; use std::ops::ControlFlow; + std::thread_local! { /// Scratchpad arena so we don't need to allocate a new one all the time static SCRATCHPAD: RefCell> = RefCell::new(Some(bumpalo::Bump::with_capacity(4 * 1024))); diff --git a/crates/compiler/solve/src/solve/scope.rs b/crates/compiler/solve/src/solve/scope.rs new file mode 100644 index 00000000000..5acd041c968 --- /dev/null +++ b/crates/compiler/solve/src/solve/scope.rs @@ -0,0 +1,40 @@ +use roc_module::symbol::Symbol; +use roc_types::subs::Variable; + +/// The scope of the solver, as symbols are introduced. +#[derive(Clone, Debug, Default)] +pub struct Scope { + symbols: Vec, + variables: Vec, +} + +impl Scope { + pub fn vars_by_symbol(&self) -> impl Iterator + '_ { + let it1 = self.symbols.iter().copied(); + let it2 = self.variables.iter().copied(); + + it1.zip(it2) + } + + #[inline(always)] + pub fn get_var_by_symbol(&self, symbol: &Symbol) -> Option { + self.symbols + .iter() + .position(|s| s == symbol) + .map(|index| self.variables[index]) + } + + #[inline(always)] + pub fn insert_symbol_var_if_vacant(&mut self, symbol: Symbol, var: Variable) { + match self.symbols.iter().position(|s| *s == symbol) { + None => { + // symbol is not in vars_by_symbol yet; insert it + self.symbols.push(symbol); + self.variables.push(var); + } + Some(_) => { + // do nothing + } + } + } +} From 8314d44650b0d0b82bfff3544ae1627372a53c24 Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Thu, 22 Jun 2023 12:09:28 -0500 Subject: [PATCH 010/140] Break up solve/solve into smaller modules --- crates/compiler/late_solve/src/lib.rs | 2 +- crates/compiler/load_internal/src/file.rs | 2 +- crates/compiler/solve/src/ability.rs | 3 +- crates/compiler/solve/src/aliases.rs | 343 ++++ crates/compiler/solve/src/deep_copy.rs | 375 ++++ crates/compiler/solve/src/lib.rs | 7 + crates/compiler/solve/src/module.rs | 2 +- crates/compiler/solve/src/pools.rs | 59 + crates/compiler/solve/src/solve.rs | 2192 +-------------------- crates/compiler/solve/src/specialize.rs | 4 +- crates/compiler/solve/src/to_var.rs | 1313 ++++++++++++ 11 files changed, 2180 insertions(+), 2122 deletions(-) create mode 100644 crates/compiler/solve/src/aliases.rs create mode 100644 crates/compiler/solve/src/deep_copy.rs create mode 100644 crates/compiler/solve/src/pools.rs create mode 100644 crates/compiler/solve/src/to_var.rs diff --git a/crates/compiler/late_solve/src/lib.rs b/crates/compiler/late_solve/src/lib.rs index 15098bda7aa..7189bc7a7e5 100644 --- a/crates/compiler/late_solve/src/lib.rs +++ b/crates/compiler/late_solve/src/lib.rs @@ -12,8 +12,8 @@ use roc_error_macros::internal_error; use roc_module::symbol::ModuleId; use roc_module::symbol::Symbol; use roc_solve::ability::AbilityResolver; -use roc_solve::solve::Pools; use roc_solve::specialize::{compact_lambda_sets_of_vars, DerivedEnv, Phase}; +use roc_solve::Pools; use roc_types::subs::{get_member_lambda_sets_at_region, Content, FlatType, LambdaSet}; use roc_types::subs::{ExposedTypesStorageSubs, Subs, Variable}; use roc_types::types::Polarity; diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index 49d878bf739..20f9f19ee87 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -5113,7 +5113,7 @@ fn run_solve_solve( &import_variables, ); - let mut solve_aliases = roc_solve::solve::Aliases::with_capacity(aliases.len()); + let mut solve_aliases = roc_solve::Aliases::with_capacity(aliases.len()); for (name, (_, alias)) in aliases.iter() { solve_aliases.insert(&mut types, *name, alias.clone()); } diff --git a/crates/compiler/solve/src/ability.rs b/crates/compiler/solve/src/ability.rs index 47d0ba15a3d..2bc0650ae13 100644 --- a/crates/compiler/solve/src/ability.rs +++ b/crates/compiler/solve/src/ability.rs @@ -21,8 +21,7 @@ use roc_types::types::{AliasKind, Category, MemberImpl, PatternCategory, Polarit use roc_unify::unify::{Env, MustImplementConstraints}; use roc_unify::unify::{MustImplementAbility, Obligated}; -use crate::solve::type_to_var; -use crate::solve::{Aliases, Pools}; +use crate::{aliases::Aliases, pools::Pools, to_var::type_to_var}; #[derive(Debug, Clone)] pub enum AbilityImplError { diff --git a/crates/compiler/solve/src/aliases.rs b/crates/compiler/solve/src/aliases.rs new file mode 100644 index 00000000000..6dda75e2ebf --- /dev/null +++ b/crates/compiler/solve/src/aliases.rs @@ -0,0 +1,343 @@ +use roc_can::abilities::AbilitiesStore; +use roc_collections::{soa::Index, MutMap}; +use roc_error_macros::internal_error; +use roc_module::symbol::Symbol; +use roc_solve_problem::TypeError; +use roc_types::{ + subs::{AliasVariables, Content, FlatType, Rank, Subs, SubsSlice, TagExt, UnionTags, Variable}, + types::{Alias, AliasKind, OptAbleVar, Type, TypeTag, Types}, +}; + +use crate::ability::ObligationCache; +use crate::pools::Pools; +use crate::solve::register; +use crate::to_var::type_to_var_help; + +#[derive(Debug, Clone, Copy)] +struct DelayedAliasVariables { + start: u32, + type_variables_len: u8, + lambda_set_variables_len: u8, + recursion_variables_len: u8, + infer_ext_in_output_variables_len: u8, +} + +impl DelayedAliasVariables { + fn recursion_variables(self, variables: &mut [OptAbleVar]) -> &mut [OptAbleVar] { + let start = self.start as usize + + (self.type_variables_len + self.lambda_set_variables_len) as usize; + let length = self.recursion_variables_len as usize; + + &mut variables[start..][..length] + } + + fn lambda_set_variables(self, variables: &mut [OptAbleVar]) -> &mut [OptAbleVar] { + let start = self.start as usize + self.type_variables_len as usize; + let length = self.lambda_set_variables_len as usize; + + &mut variables[start..][..length] + } + + fn type_variables(self, variables: &mut [OptAbleVar]) -> &mut [OptAbleVar] { + let start = self.start as usize; + let length = self.type_variables_len as usize; + + &mut variables[start..][..length] + } + + fn infer_ext_in_output_variables(self, variables: &mut [OptAbleVar]) -> &mut [OptAbleVar] { + let start = self.start as usize + + (self.type_variables_len + + self.lambda_set_variables_len + + self.recursion_variables_len) as usize; + let length = self.infer_ext_in_output_variables_len as usize; + + &mut variables[start..][..length] + } +} + +#[derive(Debug, Default)] +pub struct Aliases { + aliases: Vec<(Symbol, Index, DelayedAliasVariables, AliasKind)>, + variables: Vec, +} + +impl Aliases { + pub fn with_capacity(cap: usize) -> Self { + Self { + aliases: Vec::with_capacity(cap), + variables: Vec::with_capacity(cap * 2), + } + } + + pub fn insert(&mut self, types: &mut Types, symbol: Symbol, alias: Alias) { + let alias_variables = + { + let start = self.variables.len() as _; + + self.variables.extend( + alias + .type_variables + .iter() + .map(|x| OptAbleVar::from(&x.value)), + ); + + self.variables.extend(alias.lambda_set_variables.iter().map( + |x| match x.as_inner() { + Type::Variable(v) => OptAbleVar::unbound(*v), + _ => unreachable!("lambda set type is not a variable"), + }, + )); + + let recursion_variables_len = alias.recursion_variables.len() as _; + self.variables.extend( + alias + .recursion_variables + .iter() + .copied() + .map(OptAbleVar::unbound), + ); + + self.variables.extend( + alias + .infer_ext_in_output_variables + .iter() + .map(|v| OptAbleVar::unbound(*v)), + ); + + DelayedAliasVariables { + start, + type_variables_len: alias.type_variables.len() as _, + lambda_set_variables_len: alias.lambda_set_variables.len() as _, + recursion_variables_len, + infer_ext_in_output_variables_len: alias.infer_ext_in_output_variables.len() + as _, + } + }; + + // TODO: can we construct Aliases from TypeTag directly? + let alias_typ = types.from_old_type(&alias.typ); + + self.aliases + .push((symbol, alias_typ, alias_variables, alias.kind)); + } + + fn instantiate_result_result( + subs: &mut Subs, + rank: Rank, + pools: &mut Pools, + alias_variables: AliasVariables, + ) -> Variable { + let tag_names_slice = Subs::RESULT_TAG_NAMES; + + let err_slice = SubsSlice::new(alias_variables.variables_start + 1, 1); + let ok_slice = SubsSlice::new(alias_variables.variables_start, 1); + + let variable_slices = + SubsSlice::extend_new(&mut subs.variable_slices, [err_slice, ok_slice]); + + let union_tags = UnionTags::from_slices(tag_names_slice, variable_slices); + let ext_var = TagExt::Any(Variable::EMPTY_TAG_UNION); + let flat_type = FlatType::TagUnion(union_tags, ext_var); + let content = Content::Structure(flat_type); + + register(subs, rank, pools, content) + } + + /// Build an alias of the form `Num range := range` + fn build_num_opaque( + subs: &mut Subs, + rank: Rank, + pools: &mut Pools, + symbol: Symbol, + range_var: Variable, + ) -> Variable { + let content = Content::Alias( + symbol, + AliasVariables::insert_into_subs(subs, [range_var], [], []), + range_var, + AliasKind::Opaque, + ); + + register(subs, rank, pools, content) + } + + fn instantiate_builtin_aliases_real_var( + &mut self, + subs: &mut Subs, + rank: Rank, + pools: &mut Pools, + symbol: Symbol, + alias_variables: AliasVariables, + ) -> Option<(Variable, AliasKind)> { + match symbol { + Symbol::RESULT_RESULT => { + let var = Self::instantiate_result_result(subs, rank, pools, alias_variables); + + Some((var, AliasKind::Structural)) + } + Symbol::NUM_NUM | Symbol::NUM_INTEGER | Symbol::NUM_FLOATINGPOINT => { + // Num range := range | Integer range := range | FloatingPoint range := range + let range_var = subs.variables[alias_variables.variables_start as usize]; + Some((range_var, AliasKind::Opaque)) + } + Symbol::NUM_INT => { + // Int range : Num (Integer range) + // + // build `Integer range := range` + let integer_content_var = Self::build_num_opaque( + subs, + rank, + pools, + Symbol::NUM_INTEGER, + subs.variables[alias_variables.variables_start as usize], + ); + + // build `Num (Integer range) := Integer range` + let num_content_var = + Self::build_num_opaque(subs, rank, pools, Symbol::NUM_NUM, integer_content_var); + + Some((num_content_var, AliasKind::Structural)) + } + Symbol::NUM_FRAC => { + // Frac range : Num (FloatingPoint range) + // + // build `FloatingPoint range := range` + let fpoint_content_var = Self::build_num_opaque( + subs, + rank, + pools, + Symbol::NUM_FLOATINGPOINT, + subs.variables[alias_variables.variables_start as usize], + ); + + // build `Num (FloatingPoint range) := FloatingPoint range` + let num_content_var = + Self::build_num_opaque(subs, rank, pools, Symbol::NUM_NUM, fpoint_content_var); + + Some((num_content_var, AliasKind::Structural)) + } + Symbol::NUM_SIGNED8 => Some((Variable::SIGNED8, AliasKind::Opaque)), + Symbol::NUM_SIGNED16 => Some((Variable::SIGNED16, AliasKind::Opaque)), + Symbol::NUM_SIGNED32 => Some((Variable::SIGNED32, AliasKind::Opaque)), + Symbol::NUM_SIGNED64 => Some((Variable::SIGNED64, AliasKind::Opaque)), + Symbol::NUM_SIGNED128 => Some((Variable::SIGNED128, AliasKind::Opaque)), + Symbol::NUM_UNSIGNED8 => Some((Variable::UNSIGNED8, AliasKind::Opaque)), + Symbol::NUM_UNSIGNED16 => Some((Variable::UNSIGNED16, AliasKind::Opaque)), + Symbol::NUM_UNSIGNED32 => Some((Variable::UNSIGNED32, AliasKind::Opaque)), + Symbol::NUM_UNSIGNED64 => Some((Variable::UNSIGNED64, AliasKind::Opaque)), + Symbol::NUM_UNSIGNED128 => Some((Variable::UNSIGNED128, AliasKind::Opaque)), + Symbol::NUM_BINARY32 => Some((Variable::BINARY32, AliasKind::Opaque)), + Symbol::NUM_BINARY64 => Some((Variable::BINARY64, AliasKind::Opaque)), + _ => None, + } + } + + pub fn instantiate_real_var( + &mut self, + subs: &mut Subs, + rank: Rank, + pools: &mut Pools, + problems: &mut Vec, + abilities_store: &AbilitiesStore, + obligation_cache: &mut ObligationCache, + arena: &bumpalo::Bump, + types: &mut Types, + symbol: Symbol, + alias_variables: AliasVariables, + ) -> (Variable, AliasKind) { + // hardcoded instantiations for builtin aliases + if let Some((var, kind)) = Self::instantiate_builtin_aliases_real_var( + self, + subs, + rank, + pools, + symbol, + alias_variables, + ) { + return (var, kind); + } + + let (typ, delayed_variables, kind) = + match self.aliases.iter().find(|(s, _, _, _)| *s == symbol) { + None => internal_error!( + "Alias {:?} not registered in delayed aliases! {:?}", + symbol, + &self.aliases + ), + Some(&(_, typ, delayed_variables, kind)) => (typ, delayed_variables, kind), + }; + + let mut substitutions: MutMap<_, _> = Default::default(); + + let old_type_variables = delayed_variables.type_variables(&mut self.variables); + let new_type_variables = &subs.variables[alias_variables.type_variables().indices()]; + + for (old, new) in old_type_variables.iter_mut().zip(new_type_variables) { + // if constraint gen duplicated a type these variables could be the same + // (happens very often in practice) + if old.var != *new { + substitutions.insert(old.var, *new); + } + } + + for OptAbleVar { + var: rec_var, + opt_abilities, + } in delayed_variables + .recursion_variables(&mut self.variables) + .iter_mut() + { + debug_assert!(opt_abilities.is_none()); + let new_var = subs.fresh_unnamed_flex_var(); + substitutions.insert(*rec_var, new_var); + } + + let old_lambda_set_variables = delayed_variables.lambda_set_variables(&mut self.variables); + let new_lambda_set_variables = + &subs.variables[alias_variables.lambda_set_variables().indices()]; + + for (old, new) in old_lambda_set_variables + .iter_mut() + .zip(new_lambda_set_variables) + { + debug_assert!(old.opt_abilities.is_none()); + if old.var != *new { + substitutions.insert(old.var, *new); + } + } + + let old_infer_ext_vars = + delayed_variables.infer_ext_in_output_variables(&mut self.variables); + let new_infer_ext_vars = + &subs.variables[alias_variables.infer_ext_in_output_variables().indices()]; + + for (old, new) in old_infer_ext_vars.iter_mut().zip(new_infer_ext_vars) { + debug_assert!(old.opt_abilities.is_none()); + if old.var != *new { + substitutions.insert(old.var, *new); + } + } + + let typ = if !substitutions.is_empty() { + types.clone_with_variable_substitutions(typ, &substitutions) + } else { + typ + }; + + let alias_variable = type_to_var_help( + subs, + rank, + pools, + problems, + abilities_store, + obligation_cache, + arena, + self, + types, + typ, + false, + ); + (alias_variable, kind) + } +} diff --git a/crates/compiler/solve/src/deep_copy.rs b/crates/compiler/solve/src/deep_copy.rs new file mode 100644 index 00000000000..b3c8e7cb81f --- /dev/null +++ b/crates/compiler/solve/src/deep_copy.rs @@ -0,0 +1,375 @@ +use std::ops::ControlFlow; + +use bumpalo::Bump; +use roc_error_macros::internal_error; +use roc_types::{ + subs::{ + self, AliasVariables, Content, Descriptor, FlatType, GetSubsSlice, Mark, OptVariable, Rank, + RecordFields, Subs, SubsSlice, TagExt, TupleElems, UnionLabels, Variable, + }, + types::{RecordField, Uls}, +}; + +use crate::pools::Pools; + +pub(crate) fn deep_copy_var_in( + subs: &mut Subs, + rank: Rank, + pools: &mut Pools, + var: Variable, + arena: &Bump, +) -> Variable { + let mut visited = bumpalo::collections::Vec::with_capacity_in(256, arena); + + let pool = pools.get_mut(rank); + + let var = subs.get_root_key(var); + match deep_copy_var_decision(subs, rank, var) { + ControlFlow::Break(copy) => copy, + ControlFlow::Continue(copy) => { + deep_copy_var_help(subs, rank, pool, &mut visited, var, copy); + + // we have tracked all visited variables, and can now traverse them + // in one go (without looking at the UnificationTable) and clear the copy field + for var in visited { + subs.set_copy_unchecked(var, OptVariable::NONE); + } + + copy + } + } +} + +#[inline] +fn has_trivial_copy(subs: &Subs, root_var: Variable) -> Option { + let existing_copy = subs.get_copy_unchecked(root_var); + + if let Some(copy) = existing_copy.into_variable() { + Some(copy) + } else if subs.get_rank_unchecked(root_var) != Rank::GENERALIZED { + Some(root_var) + } else { + None + } +} + +#[inline] +fn deep_copy_var_decision( + subs: &mut Subs, + max_rank: Rank, + var: Variable, +) -> ControlFlow { + let var = subs.get_root_key(var); + if let Some(copy) = has_trivial_copy(subs, var) { + ControlFlow::Break(copy) + } else { + let copy_descriptor = Descriptor { + content: Content::Structure(FlatType::EmptyTagUnion), + rank: max_rank, + mark: Mark::NONE, + copy: OptVariable::NONE, + }; + + let copy = subs.fresh(copy_descriptor); + + // Link the original variable to the new variable. This lets us + // avoid making multiple copies of the variable we are instantiating. + // + // Need to do this before recursively copying to avoid looping. + subs.set_mark_unchecked(var, Mark::NONE); + subs.set_copy_unchecked(var, copy.into()); + + ControlFlow::Continue(copy) + } +} + +fn deep_copy_var_help( + subs: &mut Subs, + max_rank: Rank, + pool: &mut Vec, + visited: &mut bumpalo::collections::Vec<'_, Variable>, + initial_source: Variable, + initial_copy: Variable, +) -> Variable { + use roc_types::subs::Content::*; + use roc_types::subs::FlatType::*; + + struct DeepCopyVarWork { + source: Variable, + copy: Variable, + } + + let initial = DeepCopyVarWork { + source: initial_source, + copy: initial_copy, + }; + let mut stack = vec![initial]; + + macro_rules! work { + ($variable:expr) => {{ + let var = subs.get_root_key($variable); + match deep_copy_var_decision(subs, max_rank, var) { + ControlFlow::Break(copy) => copy, + ControlFlow::Continue(copy) => { + stack.push(DeepCopyVarWork { source: var, copy }); + + copy + } + } + }}; + } + + macro_rules! copy_sequence { + ($length:expr, $variables:expr) => {{ + let new_variables = SubsSlice::reserve_into_subs(subs, $length as _); + for (target_index, var_index) in (new_variables.indices()).zip($variables) { + let var = subs[var_index]; + let copy_var = work!(var); + subs.variables[target_index] = copy_var; + } + + new_variables + }}; + } + + macro_rules! copy_union { + ($tags:expr) => {{ + let new_variable_slices = SubsSlice::reserve_variable_slices(subs, $tags.len()); + + let it = (new_variable_slices.indices()).zip($tags.variables()); + for (target_index, index) in it { + let slice = subs[index]; + + let new_variables = copy_sequence!(slice.len(), slice); + subs.variable_slices[target_index] = new_variables; + } + + UnionLabels::from_slices($tags.labels(), new_variable_slices) + }}; + } + + // When generalizing annotations with `Openness` extensions + // we want to promote them to `Any`, so that usages at + // specialized sites can grow unboundedly and are not bound to + // openness-polymorphism. + macro_rules! copy_tag_ext { + ($ext:expr) => { + TagExt::Any(work!($ext.var())) + }; + } + + while let Some(DeepCopyVarWork { source: var, copy }) = stack.pop() { + visited.push(var); + pool.push(copy); + + let content = *subs.get_content_unchecked(var); + + // Now we recursively copy the content of the variable. + // We have already marked the variable as copied, so we + // will not repeat this work or crawl this variable again. + match content { + Structure(flat_type) => { + let new_flat_type = match flat_type { + Apply(symbol, arguments) => { + let new_arguments = copy_sequence!(arguments.len(), arguments); + + Apply(symbol, new_arguments) + } + + Func(arguments, closure_var, ret_var) => { + let new_ret_var = work!(ret_var); + let new_closure_var = work!(closure_var); + + let new_arguments = copy_sequence!(arguments.len(), arguments); + + Func(new_arguments, new_closure_var, new_ret_var) + } + + same @ EmptyRecord | same @ EmptyTuple | same @ EmptyTagUnion => same, + + Record(fields, ext_var) => { + let record_fields = { + let new_variables = + copy_sequence!(fields.len(), fields.iter_variables()); + + // When copying a let-generalized record to a specialized region, rigid + // optionals just become optionals. + let field_types = subs.get_subs_slice(fields.record_fields()); + let has_rigid_optional_field = field_types + .iter() + .any(|f| matches!(f, RecordField::RigidOptional(..))); + + let new_field_types_start = if has_rigid_optional_field { + let field_types = field_types.to_vec(); + let slice = SubsSlice::extend_new( + &mut subs.record_fields, + field_types.into_iter().map(|f| match f { + RecordField::RigidOptional(()) + | RecordField::RigidRequired(()) => internal_error!("Rigid optional/required should be generalized to non-rigid by this point"), + + RecordField::Demanded(_) + | RecordField::Required(_) + | RecordField::Optional(_) => f, + }), + ); + slice.start + } else { + fields.field_types_start + }; + + RecordFields { + length: fields.length, + field_names_start: fields.field_names_start, + variables_start: new_variables.start, + field_types_start: new_field_types_start, + } + }; + + Record(record_fields, work!(ext_var)) + } + + Tuple(elems, ext_var) => { + let tuple_elems = { + let new_variables = copy_sequence!(elems.len(), elems.iter_variables()); + + TupleElems { + length: elems.length, + variables_start: new_variables.start, + elem_index_start: elems.elem_index_start, + } + }; + + Tuple(tuple_elems, work!(ext_var)) + } + + TagUnion(tags, ext_var) => { + let union_tags = copy_union!(tags); + + TagUnion(union_tags, copy_tag_ext!(ext_var)) + } + + FunctionOrTagUnion(tag_name, symbol, ext_var) => { + FunctionOrTagUnion(tag_name, symbol, copy_tag_ext!(ext_var)) + } + + RecursiveTagUnion(rec_var, tags, ext_var) => { + let union_tags = copy_union!(tags); + + RecursiveTagUnion(work!(rec_var), union_tags, copy_tag_ext!(ext_var)) + } + }; + + subs.set_content_unchecked(copy, Structure(new_flat_type)); + } + + FlexVar(_) | FlexAbleVar(_, _) | Error => { + subs.set_content_unchecked(copy, content); + } + + RecursionVar { + opt_name, + structure, + } => { + let content = RecursionVar { + opt_name, + structure: work!(structure), + }; + + subs.set_content_unchecked(copy, content); + } + + RigidVar(name) => { + subs.set_content_unchecked(copy, FlexVar(Some(name))); + } + + RigidAbleVar(name, ability) => { + subs.set_content_unchecked(copy, FlexAbleVar(Some(name), ability)); + } + + Alias(symbol, arguments, real_type_var, kind) => { + let new_variables = + copy_sequence!(arguments.all_variables_len, arguments.all_variables()); + + let new_arguments = AliasVariables { + variables_start: new_variables.start, + ..arguments + }; + + let new_real_type_var = work!(real_type_var); + let new_content = Alias(symbol, new_arguments, new_real_type_var, kind); + + subs.set_content_unchecked(copy, new_content); + } + + LambdaSet(subs::LambdaSet { + solved, + recursion_var, + unspecialized, + ambient_function: ambient_function_var, + }) => { + let lambda_set_var = copy; + + let new_solved = copy_union!(solved); + let new_rec_var = recursion_var.map(|v| work!(v)); + let new_unspecialized = SubsSlice::reserve_uls_slice(subs, unspecialized.len()); + + for (new_uls_index, uls_index) in + (new_unspecialized.into_iter()).zip(unspecialized.into_iter()) + { + let Uls(var, sym, region) = subs[uls_index]; + let new_var = work!(var); + + deep_copy_uls_precondition(subs, var, new_var); + + subs[new_uls_index] = Uls(new_var, sym, region); + + subs.uls_of_var.add(new_var, lambda_set_var); + } + + let new_ambient_function_var = work!(ambient_function_var); + debug_assert_ne!( + ambient_function_var, new_ambient_function_var, + "lambda set cloned but its ambient function wasn't?" + ); + + subs.set_content_unchecked( + lambda_set_var, + LambdaSet(subs::LambdaSet { + solved: new_solved, + recursion_var: new_rec_var, + unspecialized: new_unspecialized, + ambient_function: new_ambient_function_var, + }), + ); + } + + RangedNumber(range) => { + let new_content = RangedNumber(range); + + subs.set_content_unchecked(copy, new_content); + } + } + } + + initial_copy +} + +#[inline(always)] +fn deep_copy_uls_precondition(subs: &Subs, original_var: Variable, new_var: Variable) { + if cfg!(debug_assertions) { + let content = subs.get_content_without_compacting(original_var); + + debug_assert!( + matches!( + content, + Content::FlexAbleVar(..) | Content::RigidAbleVar(..) + ), + "var in unspecialized lamba set is not bound to an ability, it is {:?}", + roc_types::subs::SubsFmtContent(content, subs) + ); + debug_assert!( + original_var != new_var, + "unspecialized lamba set var was not instantiated" + ); + } +} diff --git a/crates/compiler/solve/src/lib.rs b/crates/compiler/solve/src/lib.rs index fa30f79aad4..b7e9edb737e 100644 --- a/crates/compiler/solve/src/lib.rs +++ b/crates/compiler/solve/src/lib.rs @@ -8,3 +8,10 @@ pub mod ability; pub mod module; pub mod solve; pub mod specialize; + +mod aliases; +pub use aliases::Aliases; +mod deep_copy; +mod pools; +pub use pools::Pools; +mod to_var; diff --git a/crates/compiler/solve/src/module.rs b/crates/compiler/solve/src/module.rs index 15e6ee88abb..86f70a1b28e 100644 --- a/crates/compiler/solve/src/module.rs +++ b/crates/compiler/solve/src/module.rs @@ -1,4 +1,4 @@ -use crate::solve::{self, Aliases}; +use crate::{aliases::Aliases, solve}; use roc_can::abilities::{AbilitiesStore, ResolvedImpl}; use roc_can::constraint::{Constraint, Constraints}; use roc_can::expr::PendingDerives; diff --git a/crates/compiler/solve/src/pools.rs b/crates/compiler/solve/src/pools.rs new file mode 100644 index 00000000000..e3e86c20472 --- /dev/null +++ b/crates/compiler/solve/src/pools.rs @@ -0,0 +1,59 @@ +use roc_types::subs::{Rank, Variable}; + +const DEFAULT_POOLS: usize = 8; + +#[derive(Clone, Debug)] +pub struct Pools(Vec>); + +impl Default for Pools { + fn default() -> Self { + Pools::new(DEFAULT_POOLS) + } +} + +impl Pools { + pub fn new(num_pools: usize) -> Self { + Pools(vec![Vec::new(); num_pools]) + } + + pub fn len(&self) -> usize { + self.0.len() + } + + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + pub fn get_mut(&mut self, rank: Rank) -> &mut Vec { + match self.0.get_mut(rank.into_usize()) { + Some(reference) => reference, + None => panic!("Compiler bug: could not find pool at rank {}", rank), + } + } + + pub fn get(&self, rank: Rank) -> &Vec { + match self.0.get(rank.into_usize()) { + Some(reference) => reference, + None => panic!("Compiler bug: could not find pool at rank {}", rank), + } + } + + pub fn iter(&self) -> std::slice::Iter<'_, Vec> { + self.0.iter() + } + + pub fn split_last(mut self) -> (Vec, Vec>) { + let last = self + .0 + .pop() + .unwrap_or_else(|| panic!("Attempted to split_last() on non-empty Pools")); + + (last, self.0) + } + + pub fn extend_to(&mut self, n: usize) { + for _ in self.len()..n { + self.0.push(Vec::new()); + } + } +} diff --git a/crates/compiler/solve/src/solve.rs b/crates/compiler/solve/src/solve.rs index acc43557e7e..7e21a64d486 100644 --- a/crates/compiler/solve/src/solve.rs +++ b/crates/compiler/solve/src/solve.rs @@ -4,36 +4,32 @@ use crate::ability::{ resolve_ability_specialization, type_implementing_specialization, AbilityImplError, CheckedDerives, ObligationCache, PendingDerivesTable, Resolved, }; +use crate::deep_copy::deep_copy_var_in; use crate::module::{SolveCtx, Solved}; +use crate::pools::Pools; use crate::specialize::{ compact_lambda_sets_of_vars, AwaitingSpecializations, CompactionResult, DerivedEnv, SolvePhase, }; +use crate::to_var::{either_type_index_to_var, type_to_var}; +use crate::Aliases; use bumpalo::Bump; use roc_can::abilities::{AbilitiesStore, MemberSpecializationInfo}; use roc_can::constraint::Constraint::{self, *}; -use roc_can::constraint::{Constraints, Cycle, LetConstraint, OpportunisticResolve, TypeOrVar}; +use roc_can::constraint::{Constraints, Cycle, LetConstraint, OpportunisticResolve}; use roc_can::expected::{Expected, PExpected}; -use roc_collections::all::MutMap; -use roc_collections::soa::{Index, Slice}; use roc_debug_flags::dbg_do; #[cfg(debug_assertions)] use roc_debug_flags::ROC_VERIFY_RIGID_LET_GENERALIZED; use roc_error_macros::internal_error; -use roc_module::ident::TagName; use roc_module::symbol::Symbol; use roc_problem::can::CycleEntry; use roc_region::all::Loc; use roc_solve_problem::TypeError; use roc_types::subs::{ - self, AliasVariables, Content, Descriptor, FlatType, GetSubsSlice, LambdaSet, Mark, - OptVariable, Rank, RecordFields, Subs, SubsSlice, TagExt, TupleElems, UlsOfVar, UnionLabels, - UnionLambdas, UnionTags, Variable, VariableSubsSlice, -}; -use roc_types::types::{ - gather_fields_unsorted_iter, gather_tuple_elems_unsorted_iter, AliasKind, AliasShared, - Category, ExtImplicitOpenness, OptAbleVar, Polarity, Reason, RecordField, Type, TypeExtension, - TypeTag, Types, Uls, + self, Content, Descriptor, FlatType, GetSubsSlice, Mark, OptVariable, Rank, Subs, TagExt, + UlsOfVar, Variable, }; +use roc_types::types::{Category, Polarity, Reason, RecordField, Type, TypeExtension, Types, Uls}; use roc_unify::unify::{ unify, unify_introduced_ability_specialization, Env as UEnv, Mode, Obligated, SpecializationLsetCollector, Unified::*, @@ -92,395 +88,6 @@ pub use scope::Scope; // Ranks are used to limit the number of type variables considered for generalization. Only those inside // of the let (so those used in inferring the type of `\x -> x`) are considered. -use roc_types::types::Alias; - -#[derive(Debug, Clone, Copy)] -struct DelayedAliasVariables { - start: u32, - type_variables_len: u8, - lambda_set_variables_len: u8, - recursion_variables_len: u8, - infer_ext_in_output_variables_len: u8, -} - -impl DelayedAliasVariables { - fn recursion_variables(self, variables: &mut [OptAbleVar]) -> &mut [OptAbleVar] { - let start = self.start as usize - + (self.type_variables_len + self.lambda_set_variables_len) as usize; - let length = self.recursion_variables_len as usize; - - &mut variables[start..][..length] - } - - fn lambda_set_variables(self, variables: &mut [OptAbleVar]) -> &mut [OptAbleVar] { - let start = self.start as usize + self.type_variables_len as usize; - let length = self.lambda_set_variables_len as usize; - - &mut variables[start..][..length] - } - - fn type_variables(self, variables: &mut [OptAbleVar]) -> &mut [OptAbleVar] { - let start = self.start as usize; - let length = self.type_variables_len as usize; - - &mut variables[start..][..length] - } - - fn infer_ext_in_output_variables(self, variables: &mut [OptAbleVar]) -> &mut [OptAbleVar] { - let start = self.start as usize - + (self.type_variables_len - + self.lambda_set_variables_len - + self.recursion_variables_len) as usize; - let length = self.infer_ext_in_output_variables_len as usize; - - &mut variables[start..][..length] - } -} - -#[derive(Debug, Default)] -pub struct Aliases { - aliases: Vec<(Symbol, Index, DelayedAliasVariables, AliasKind)>, - variables: Vec, -} - -impl Aliases { - pub fn with_capacity(cap: usize) -> Self { - Self { - aliases: Vec::with_capacity(cap), - variables: Vec::with_capacity(cap * 2), - } - } - - pub fn insert(&mut self, types: &mut Types, symbol: Symbol, alias: Alias) { - let alias_variables = - { - let start = self.variables.len() as _; - - self.variables.extend( - alias - .type_variables - .iter() - .map(|x| OptAbleVar::from(&x.value)), - ); - - self.variables.extend(alias.lambda_set_variables.iter().map( - |x| match x.as_inner() { - Type::Variable(v) => OptAbleVar::unbound(*v), - _ => unreachable!("lambda set type is not a variable"), - }, - )); - - let recursion_variables_len = alias.recursion_variables.len() as _; - self.variables.extend( - alias - .recursion_variables - .iter() - .copied() - .map(OptAbleVar::unbound), - ); - - self.variables.extend( - alias - .infer_ext_in_output_variables - .iter() - .map(|v| OptAbleVar::unbound(*v)), - ); - - DelayedAliasVariables { - start, - type_variables_len: alias.type_variables.len() as _, - lambda_set_variables_len: alias.lambda_set_variables.len() as _, - recursion_variables_len, - infer_ext_in_output_variables_len: alias.infer_ext_in_output_variables.len() - as _, - } - }; - - // TODO: can we construct Aliases from TypeTag directly? - let alias_typ = types.from_old_type(&alias.typ); - - self.aliases - .push((symbol, alias_typ, alias_variables, alias.kind)); - } - - fn instantiate_result_result( - subs: &mut Subs, - rank: Rank, - pools: &mut Pools, - alias_variables: AliasVariables, - ) -> Variable { - let tag_names_slice = Subs::RESULT_TAG_NAMES; - - let err_slice = SubsSlice::new(alias_variables.variables_start + 1, 1); - let ok_slice = SubsSlice::new(alias_variables.variables_start, 1); - - let variable_slices = - SubsSlice::extend_new(&mut subs.variable_slices, [err_slice, ok_slice]); - - let union_tags = UnionTags::from_slices(tag_names_slice, variable_slices); - let ext_var = TagExt::Any(Variable::EMPTY_TAG_UNION); - let flat_type = FlatType::TagUnion(union_tags, ext_var); - let content = Content::Structure(flat_type); - - register(subs, rank, pools, content) - } - - /// Build an alias of the form `Num range := range` - fn build_num_opaque( - subs: &mut Subs, - rank: Rank, - pools: &mut Pools, - symbol: Symbol, - range_var: Variable, - ) -> Variable { - let content = Content::Alias( - symbol, - AliasVariables::insert_into_subs(subs, [range_var], [], []), - range_var, - AliasKind::Opaque, - ); - - register(subs, rank, pools, content) - } - - fn instantiate_builtin_aliases_real_var( - &mut self, - subs: &mut Subs, - rank: Rank, - pools: &mut Pools, - symbol: Symbol, - alias_variables: AliasVariables, - ) -> Option<(Variable, AliasKind)> { - match symbol { - Symbol::RESULT_RESULT => { - let var = Self::instantiate_result_result(subs, rank, pools, alias_variables); - - Some((var, AliasKind::Structural)) - } - Symbol::NUM_NUM | Symbol::NUM_INTEGER | Symbol::NUM_FLOATINGPOINT => { - // Num range := range | Integer range := range | FloatingPoint range := range - let range_var = subs.variables[alias_variables.variables_start as usize]; - Some((range_var, AliasKind::Opaque)) - } - Symbol::NUM_INT => { - // Int range : Num (Integer range) - // - // build `Integer range := range` - let integer_content_var = Self::build_num_opaque( - subs, - rank, - pools, - Symbol::NUM_INTEGER, - subs.variables[alias_variables.variables_start as usize], - ); - - // build `Num (Integer range) := Integer range` - let num_content_var = - Self::build_num_opaque(subs, rank, pools, Symbol::NUM_NUM, integer_content_var); - - Some((num_content_var, AliasKind::Structural)) - } - Symbol::NUM_FRAC => { - // Frac range : Num (FloatingPoint range) - // - // build `FloatingPoint range := range` - let fpoint_content_var = Self::build_num_opaque( - subs, - rank, - pools, - Symbol::NUM_FLOATINGPOINT, - subs.variables[alias_variables.variables_start as usize], - ); - - // build `Num (FloatingPoint range) := FloatingPoint range` - let num_content_var = - Self::build_num_opaque(subs, rank, pools, Symbol::NUM_NUM, fpoint_content_var); - - Some((num_content_var, AliasKind::Structural)) - } - Symbol::NUM_SIGNED8 => Some((Variable::SIGNED8, AliasKind::Opaque)), - Symbol::NUM_SIGNED16 => Some((Variable::SIGNED16, AliasKind::Opaque)), - Symbol::NUM_SIGNED32 => Some((Variable::SIGNED32, AliasKind::Opaque)), - Symbol::NUM_SIGNED64 => Some((Variable::SIGNED64, AliasKind::Opaque)), - Symbol::NUM_SIGNED128 => Some((Variable::SIGNED128, AliasKind::Opaque)), - Symbol::NUM_UNSIGNED8 => Some((Variable::UNSIGNED8, AliasKind::Opaque)), - Symbol::NUM_UNSIGNED16 => Some((Variable::UNSIGNED16, AliasKind::Opaque)), - Symbol::NUM_UNSIGNED32 => Some((Variable::UNSIGNED32, AliasKind::Opaque)), - Symbol::NUM_UNSIGNED64 => Some((Variable::UNSIGNED64, AliasKind::Opaque)), - Symbol::NUM_UNSIGNED128 => Some((Variable::UNSIGNED128, AliasKind::Opaque)), - Symbol::NUM_BINARY32 => Some((Variable::BINARY32, AliasKind::Opaque)), - Symbol::NUM_BINARY64 => Some((Variable::BINARY64, AliasKind::Opaque)), - _ => None, - } - } - - fn instantiate_real_var( - &mut self, - subs: &mut Subs, - rank: Rank, - pools: &mut Pools, - problems: &mut Vec, - abilities_store: &AbilitiesStore, - obligation_cache: &mut ObligationCache, - arena: &bumpalo::Bump, - types: &mut Types, - symbol: Symbol, - alias_variables: AliasVariables, - ) -> (Variable, AliasKind) { - // hardcoded instantiations for builtin aliases - if let Some((var, kind)) = Self::instantiate_builtin_aliases_real_var( - self, - subs, - rank, - pools, - symbol, - alias_variables, - ) { - return (var, kind); - } - - let (typ, delayed_variables, kind) = - match self.aliases.iter().find(|(s, _, _, _)| *s == symbol) { - None => internal_error!( - "Alias {:?} not registered in delayed aliases! {:?}", - symbol, - &self.aliases - ), - Some(&(_, typ, delayed_variables, kind)) => (typ, delayed_variables, kind), - }; - - let mut substitutions: MutMap<_, _> = Default::default(); - - let old_type_variables = delayed_variables.type_variables(&mut self.variables); - let new_type_variables = &subs.variables[alias_variables.type_variables().indices()]; - - for (old, new) in old_type_variables.iter_mut().zip(new_type_variables) { - // if constraint gen duplicated a type these variables could be the same - // (happens very often in practice) - if old.var != *new { - substitutions.insert(old.var, *new); - } - } - - for OptAbleVar { - var: rec_var, - opt_abilities, - } in delayed_variables - .recursion_variables(&mut self.variables) - .iter_mut() - { - debug_assert!(opt_abilities.is_none()); - let new_var = subs.fresh_unnamed_flex_var(); - substitutions.insert(*rec_var, new_var); - } - - let old_lambda_set_variables = delayed_variables.lambda_set_variables(&mut self.variables); - let new_lambda_set_variables = - &subs.variables[alias_variables.lambda_set_variables().indices()]; - - for (old, new) in old_lambda_set_variables - .iter_mut() - .zip(new_lambda_set_variables) - { - debug_assert!(old.opt_abilities.is_none()); - if old.var != *new { - substitutions.insert(old.var, *new); - } - } - - let old_infer_ext_vars = - delayed_variables.infer_ext_in_output_variables(&mut self.variables); - let new_infer_ext_vars = - &subs.variables[alias_variables.infer_ext_in_output_variables().indices()]; - - for (old, new) in old_infer_ext_vars.iter_mut().zip(new_infer_ext_vars) { - debug_assert!(old.opt_abilities.is_none()); - if old.var != *new { - substitutions.insert(old.var, *new); - } - } - - let typ = if !substitutions.is_empty() { - types.clone_with_variable_substitutions(typ, &substitutions) - } else { - typ - }; - - let alias_variable = type_to_variable( - subs, - rank, - pools, - problems, - abilities_store, - obligation_cache, - arena, - self, - types, - typ, - false, - ); - (alias_variable, kind) - } -} - -const DEFAULT_POOLS: usize = 8; - -#[derive(Clone, Debug)] -pub struct Pools(Vec>); - -impl Default for Pools { - fn default() -> Self { - Pools::new(DEFAULT_POOLS) - } -} - -impl Pools { - pub fn new(num_pools: usize) -> Self { - Pools(vec![Vec::new(); num_pools]) - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - pub fn get_mut(&mut self, rank: Rank) -> &mut Vec { - match self.0.get_mut(rank.into_usize()) { - Some(reference) => reference, - None => panic!("Compiler bug: could not find pool at rank {}", rank), - } - } - - pub fn get(&self, rank: Rank) -> &Vec { - match self.0.get(rank.into_usize()) { - Some(reference) => reference, - None => panic!("Compiler bug: could not find pool at rank {}", rank), - } - } - - pub fn iter(&self) -> std::slice::Iter<'_, Vec> { - self.0.iter() - } - - pub fn split_last(mut self) -> (Vec, Vec>) { - let last = self - .0 - .pop() - .unwrap_or_else(|| panic!("Attempted to split_last() on non-empty Pools")); - - (last, self.0) - } - - pub fn extend_to(&mut self, n: usize) { - for _ in self.len()..n { - self.0.push(Vec::new()); - } - } -} - #[derive(Clone)] struct State { scope: Scope, @@ -2264,1374 +1871,86 @@ impl LocalDefVarsVec<(Symbol, Loc)> { } } -use std::cell::RefCell; -use std::ops::ControlFlow; - -std::thread_local! { - /// Scratchpad arena so we don't need to allocate a new one all the time - static SCRATCHPAD: RefCell> = RefCell::new(Some(bumpalo::Bump::with_capacity(4 * 1024))); -} - -fn take_scratchpad() -> bumpalo::Bump { - SCRATCHPAD.with(|f| f.take().unwrap()) -} - -fn put_scratchpad(scratchpad: bumpalo::Bump) { - SCRATCHPAD.with(|f| { - f.replace(Some(scratchpad)); - }); -} - -fn either_type_index_to_var( +fn check_for_infinite_type( subs: &mut Subs, - rank: Rank, pools: &mut Pools, problems: &mut Vec, - abilities_store: &mut AbilitiesStore, - obligation_cache: &mut ObligationCache, - types: &mut Types, - aliases: &mut Aliases, - either_type_index: TypeOrVar, -) -> Variable { - match either_type_index.split() { - Ok(type_index) => { - // Converts the celled type to a variable, emplacing the new variable for re-use. - let var = type_to_var( - subs, - rank, - problems, - abilities_store, - obligation_cache, - pools, - types, - aliases, - type_index, - ); + symbol: Symbol, + loc_var: Loc, +) { + let var = loc_var.value; - debug_assert!( - matches!(types[type_index], TypeTag::Variable(v) if v == var) - || matches!( - types[type_index], - TypeTag::EmptyRecord | TypeTag::EmptyTagUnion - ) - ); - var - } - Err(var_index) => { - // we cheat, and store the variable directly in the index - unsafe { Variable::from_index(var_index.index() as _) } + 'next_occurs_check: while let Err((_, chain)) = subs.occurs(var) { + // walk the chain till we find a tag union or lambda set, starting from the variable that + // occurred recursively, which is always at the end of the chain. + for &var in chain.iter().rev() { + match *subs.get_content_without_compacting(var) { + Content::Structure(FlatType::TagUnion(tags, ext_var)) => { + let rec_var = subs.mark_tag_union_recursive(var, tags, ext_var); + register_to_pools(subs, rec_var, pools); + + continue 'next_occurs_check; + } + Content::LambdaSet(subs::LambdaSet { + solved, + recursion_var: OptVariable::NONE, + unspecialized, + ambient_function: ambient_function_var, + }) => { + let rec_var = subs.mark_lambda_set_recursive( + var, + solved, + unspecialized, + ambient_function_var, + ); + register_to_pools(subs, rec_var, pools); + + continue 'next_occurs_check; + } + _ => { /* fall through */ } + } } + + circular_error(subs, problems, symbol, &loc_var); } } -pub(crate) fn type_to_var( +fn circular_error( subs: &mut Subs, - rank: Rank, problems: &mut Vec, - abilities_store: &mut AbilitiesStore, - obligation_cache: &mut ObligationCache, - pools: &mut Pools, - types: &mut Types, - aliases: &mut Aliases, - typ: Index, -) -> Variable { - if let TypeTag::Variable(var) = types[typ] { - var - } else { - let mut arena = take_scratchpad(); - - let var = type_to_variable( - subs, - rank, - pools, - problems, - abilities_store, - obligation_cache, - &arena, - aliases, - types, - typ, - false, - ); - - arena.reset(); - put_scratchpad(arena); + symbol: Symbol, + loc_var: &Loc, +) { + let var = loc_var.value; + let error_type = subs.var_to_error_type(var, Polarity::OF_VALUE); + let problem = TypeError::CircularType(loc_var.region, symbol, error_type); - var - } -} + subs.set_content(var, Content::Error); -enum RegisterVariable { - /// Based on the Type, we already know what variable this will be - Direct(Variable), - /// This Type needs more complicated Content. We reserve a Variable - /// for it, but put a placeholder Content in subs - Deferred, + problems.push(problem); } -impl RegisterVariable { - fn from_type( - subs: &mut Subs, - rank: Rank, - pools: &mut Pools, - arena: &'_ bumpalo::Bump, - types: &mut Types, - typ: Index, - ) -> Self { - use RegisterVariable::*; - - match types[typ] { - TypeTag::Variable(var) => Direct(var), - TypeTag::EmptyRecord => Direct(Variable::EMPTY_RECORD), - TypeTag::EmptyTagUnion => Direct(Variable::EMPTY_TAG_UNION), - TypeTag::DelayedAlias { shared } - | TypeTag::StructuralAlias { shared, .. } - | TypeTag::OpaqueAlias { shared, .. } - | TypeTag::HostExposedAlias { shared, .. } => { - let AliasShared { symbol, .. } = types[shared]; - if let Some(reserved) = Variable::get_reserved(symbol) { - let direct_var = if rank.is_generalized() { - // reserved variables are stored with rank NONE - reserved - } else { - // for any other rank, we need to copy; it takes care of adjusting the rank - deep_copy_var_in(subs, rank, pools, reserved, arena) - }; - // Safety: the `destination` will become the source-of-truth for the type index, since it - // was not already transformed before (if it was, we'd be in the Variable branch!) - let _old_typ = unsafe { types.emplace_variable(typ, direct_var) }; - return Direct(direct_var); - } +/// Generalizes variables at the `young_rank`, which did not escape a let-binding +/// into a lower scope. +/// +/// Ensures that variables introduced at the `young_rank`, but that should be +/// stuck at a lower level, are marked at that level and not generalized at the +/// present `young_rank`. See [adjust_rank]. +fn generalize( + subs: &mut Subs, + young_mark: Mark, + visit_mark: Mark, + young_rank: Rank, + pools: &mut Pools, +) { + let young_vars = std::mem::take(pools.get_mut(young_rank)); + let rank_table = pool_to_rank_table(subs, young_mark, young_rank, young_vars); - Deferred - } - _ => Deferred, - } - } - - #[inline(always)] - fn with_stack( - subs: &mut Subs, - rank: Rank, - pools: &mut Pools, - arena: &'_ bumpalo::Bump, - types: &mut Types, - typ_index: Index, - stack: &mut bumpalo::collections::Vec<'_, TypeToVar>, - ) -> Variable { - match Self::from_type(subs, rank, pools, arena, types, typ_index) { - Self::Direct(var) => var, - Self::Deferred => { - let var = subs.fresh_unnamed_flex_var(); - // Safety: the `destination` will become the source-of-truth for the type index, since it - // was not already transformed before (if it was, it wouldn't be deferred!) - let typ = unsafe { types.emplace_variable(typ_index, var) }; - stack.push(TypeToVar::Defer { - typ, - typ_index, - destination: var, - ambient_function: AmbientFunctionPolicy::NoFunction, - }); - var - } - } - } -} - -/// Instantiation of ambient functions in unspecialized lambda sets is somewhat tricky due to other -/// optimizations we have in place. This struct tells us how they should be instantiated. -#[derive(Debug)] -enum AmbientFunctionPolicy { - /// We're not in a function. This variant may never hold for unspecialized lambda sets. - NoFunction, - /// We're in a known function. - Function(Variable), -} - -impl AmbientFunctionPolicy { - fn link_to_alias_lambda_set_var(&self, subs: &mut Subs, var: Variable) { - let ambient_function = match self { - AmbientFunctionPolicy::Function(var) => *var, - _ => { - // Might be linked at a deeper point in time, ignore for now - return; - } - }; - let content = subs.get_content_without_compacting(var); - let new_content = match content { - Content::LambdaSet(LambdaSet { - solved, - recursion_var, - unspecialized, - ambient_function: _, - }) => Content::LambdaSet(LambdaSet { - solved: *solved, - recursion_var: *recursion_var, - unspecialized: *unspecialized, - ambient_function, - }), - Content::FlexVar(_) => { - // Something like - // Encoder fmt : List U8, fmt -a-> List U8 | fmt has EncoderFormatting - // THEORY: Replace these with empty lambda sets. They will unify the same as a flex - // var does, but allows us to record the ambient function properly. - Content::LambdaSet(LambdaSet { - solved: UnionLabels::default(), - recursion_var: OptVariable::NONE, - unspecialized: SubsSlice::default(), - ambient_function, - }) - } - content => internal_error!("{:?}({:?}) not a lambda set", content, var), - }; - subs.set_content_unchecked(var, new_content); - } -} - -#[derive(Debug)] -enum TypeToVar { - Defer { - typ: TypeTag, - typ_index: Index, - destination: Variable, - ambient_function: AmbientFunctionPolicy, - }, -} - -#[allow(clippy::too_many_arguments)] -fn type_to_variable( - subs: &mut Subs, - rank: Rank, - pools: &mut Pools, - problems: &mut Vec, - abilities_store: &AbilitiesStore, - obligation_cache: &mut ObligationCache, - arena: &bumpalo::Bump, - aliases: &mut Aliases, - types: &mut Types, - typ: Index, - // Helpers for instantiating ambient functions of lambda set variables from type aliases. - is_alias_lambda_set_arg: bool, -) -> Variable { - use bumpalo::collections::Vec; - - let mut stack = Vec::with_capacity_in(8, arena); - let mut bind_to_abilities = Vec::new_in(arena); - - macro_rules! helper { - ($typ:expr, $ambient_function_policy:expr) => {{ - match RegisterVariable::from_type(subs, rank, pools, arena, types, $typ) { - RegisterVariable::Direct(var) => { - // If the variable is just a type variable but we know we're in a lambda set - // context, try to link to the ambient function. - $ambient_function_policy.link_to_alias_lambda_set_var(subs, var); - - var - } - RegisterVariable::Deferred => { - let var = subs.fresh_unnamed_flex_var(); - - // Safety: the `destination` will become the source-of-truth for the type index, since it - // was not already transformed before (if it was, it wouldn't be deferred!) - let typ = unsafe { types.emplace_variable($typ, var) }; - - stack.push(TypeToVar::Defer { - typ, - typ_index: $typ, - destination: var, - ambient_function: $ambient_function_policy, - }); - - var - } - } - }}; - ($typ:expr) => {{ - helper!($typ, AmbientFunctionPolicy::NoFunction) - }}; - } - - let result = helper!(typ); - - while let Some(TypeToVar::Defer { - typ_index, - typ, - destination, - ambient_function, - }) = stack.pop() - { - use TypeTag::*; - match typ { - Variable(_) | EmptyRecord | EmptyTagUnion => { - unreachable!("This variant should never be deferred!",) - } - RangedNumber(range) => { - let content = Content::RangedNumber(range); - - register_with_known_var(subs, destination, rank, pools, content) - } - Apply { - symbol, - type_argument_regions: _, - region: _, - } => { - let arguments = types.get_type_arguments(typ_index); - let new_arguments = VariableSubsSlice::reserve_into_subs(subs, arguments.len()); - for (target_index, var_index) in - (new_arguments.indices()).zip(arguments.into_iter()) - { - let var = helper!(var_index); - subs.variables[target_index] = var; - } - - let flat_type = FlatType::Apply(symbol, new_arguments); - let content = Content::Structure(flat_type); - - register_with_known_var(subs, destination, rank, pools, content) - } - - ClosureTag { - name, - ambient_function, - } => { - let captures = types.get_type_arguments(typ_index); - let union_lambdas = create_union_lambda( - subs, rank, pools, arena, types, name, captures, &mut stack, - ); - - let content = Content::LambdaSet(subs::LambdaSet { - solved: union_lambdas, - // We may figure out the lambda set is recursive during solving, but it never - // is to begin with. - recursion_var: OptVariable::NONE, - unspecialized: SubsSlice::default(), - ambient_function, - }); - - register_with_known_var(subs, destination, rank, pools, content) - } - UnspecializedLambdaSet { unspecialized } => { - let unspecialized_slice = SubsSlice::extend_new( - &mut subs.unspecialized_lambda_sets, - std::iter::once(unspecialized), - ); - - // `ClosureTag` ambient functions are resolved during constraint generation. - // But `UnspecializedLambdaSet`s can only ever live in a type signature, and don't - // correspond to a expression, so they are never constrained. - // Instead, we resolve their ambient functions during type translation, observing - // the invariant that a lambda set can only ever appear under a function type. - let ambient_function = match ambient_function { - AmbientFunctionPolicy::NoFunction => { - debug_assert!(is_alias_lambda_set_arg); - // To be filled in during delayed type alias instantiation - roc_types::subs::Variable::NULL - } - AmbientFunctionPolicy::Function(var) => var, - }; - - let content = Content::LambdaSet(subs::LambdaSet { - unspecialized: unspecialized_slice, - solved: UnionLabels::default(), - recursion_var: OptVariable::NONE, - ambient_function, - }); - - register_with_known_var(subs, destination, rank, pools, content) - } - // This case is important for the rank of boolean variables - Function(closure_type, ret_type) => { - let arguments = types.get_type_arguments(typ_index); - let new_arguments = VariableSubsSlice::reserve_into_subs(subs, arguments.len()); - for (target_index, var_index) in - (new_arguments.indices()).zip(arguments.into_iter()) - { - let var = helper!(var_index); - subs.variables[target_index] = var; - } - - let ret_var = helper!(ret_type); - let closure_var = - helper!(closure_type, AmbientFunctionPolicy::Function(destination)); - let content = - Content::Structure(FlatType::Func(new_arguments, closure_var, ret_var)); - - register_with_known_var(subs, destination, rank, pools, content) - } - Record(fields) => { - let ext_slice = types.get_type_arguments(typ_index); - - // An empty fields is inefficient (but would be correct) - // If hit, try to turn the value into an EmptyRecord in canonicalization - debug_assert!(!fields.is_empty() || !ext_slice.is_empty()); - - let mut field_vars = Vec::with_capacity_in(fields.len(), arena); - - let (fields_names, field_kinds, field_tys) = types.record_fields_slices(fields); - - for ((field, field_kind), field_type) in (fields_names.into_iter()) - .zip(field_kinds.into_iter()) - .zip(field_tys.into_iter()) - { - let field_var = { - let t = helper!(field_type); - types[field_kind].replace(t) - }; - - field_vars.push((types[field].clone(), field_var)); - } - - debug_assert!(ext_slice.len() <= 1); - let temp_ext_var = match ext_slice.into_iter().next() { - None => roc_types::subs::Variable::EMPTY_RECORD, - Some(ext) => helper!(ext), - }; - - let (it, new_ext_var) = - gather_fields_unsorted_iter(subs, RecordFields::empty(), temp_ext_var) - .expect("Something ended up weird in this record type"); - - let it = it - .into_iter() - .map(|(field, field_type)| (field.clone(), field_type)); - - field_vars.extend(it); - insertion_sort_by(&mut field_vars, RecordFields::compare); - - let record_fields = RecordFields::insert_into_subs(subs, field_vars); - - let content = Content::Structure(FlatType::Record(record_fields, new_ext_var)); - - register_with_known_var(subs, destination, rank, pools, content) - } - - Tuple(elems) => { - let ext_slice = types.get_type_arguments(typ_index); - - // Elems should never be empty; we don't support empty tuples - debug_assert!(!elems.is_empty() || !ext_slice.is_empty()); - - let mut elem_vars = Vec::with_capacity_in(elems.len(), arena); - - let (indices, elem_tys) = types.tuple_elems_slices(elems); - - for (index, elem_type) in indices.into_iter().zip(elem_tys.into_iter()) { - let elem_var = helper!(elem_type); - elem_vars.push((types[index], elem_var)); - } - - debug_assert!(ext_slice.len() <= 1); - let temp_ext_var = match ext_slice.into_iter().next() { - None => roc_types::subs::Variable::EMPTY_TUPLE, - Some(ext) => helper!(ext), - }; - - let (it, new_ext_var) = - gather_tuple_elems_unsorted_iter(subs, TupleElems::empty(), temp_ext_var) - .expect("Something ended up weird in this tuple type"); - - elem_vars.extend(it); - let tuple_elems = TupleElems::insert_into_subs(subs, elem_vars); - - let content = Content::Structure(FlatType::Tuple(tuple_elems, new_ext_var)); - - register_with_known_var(subs, destination, rank, pools, content) - } - - TagUnion(tags, ext_openness) => { - let ext_slice = types.get_type_arguments(typ_index); - - // An empty tags is inefficient (but would be correct) - // If hit, try to turn the value into an EmptyTagUnion in canonicalization - debug_assert!(!tags.is_empty() || !ext_slice.is_empty()); - - let (union_tags, ext) = type_to_union_tags( - subs, - rank, - pools, - arena, - types, - tags, - ext_slice, - ext_openness, - &mut stack, - ); - let content = Content::Structure(FlatType::TagUnion(union_tags, ext)); - - register_with_known_var(subs, destination, rank, pools, content) - } - FunctionOrTagUnion(symbol, ext_openness) => { - let ext_slice = types.get_type_arguments(typ_index); - let tag_name = types.get_tag_name(&typ_index).clone(); - - debug_assert!(ext_slice.len() <= 1); - let temp_ext = match ext_slice.into_iter().next() { - Some(ext) => { - let var = helper!(ext); - TagExt::from_can(var, ext_openness) - } - None => TagExt::Any(roc_types::subs::Variable::EMPTY_TAG_UNION), - }; - - let (it, ext) = roc_types::types::gather_tags_unsorted_iter( - subs, - UnionTags::default(), - temp_ext, - ) - .expect("extension var could not be seen as a tag union"); - - for _ in it { - unreachable!("we assert that the ext var is empty; otherwise we'd already know it was a tag union!"); - } - - let tag_names = SubsSlice::extend_new(&mut subs.tag_names, [tag_name]); - let symbols = SubsSlice::extend_new(&mut subs.symbol_names, [symbol]); - - let content = - Content::Structure(FlatType::FunctionOrTagUnion(tag_names, symbols, ext)); - - register_with_known_var(subs, destination, rank, pools, content) - } - RecursiveTagUnion(rec_var, tags, ext_openness) => { - let ext_slice = types.get_type_arguments(typ_index); - - // An empty tags is inefficient (but would be correct) - // If hit, try to turn the value into an EmptyTagUnion in canonicalization - debug_assert!(!tags.is_empty() || !ext_slice.is_empty()); - - let (union_tags, ext) = type_to_union_tags( - subs, - rank, - pools, - arena, - types, - tags, - ext_slice, - ext_openness, - &mut stack, - ); - let content = - Content::Structure(FlatType::RecursiveTagUnion(rec_var, union_tags, ext)); - - let tag_union_var = destination; - register_with_known_var(subs, tag_union_var, rank, pools, content); - - register_with_known_var( - subs, - rec_var, - rank, - pools, - Content::RecursionVar { - opt_name: None, - structure: tag_union_var, - }, - ); - - tag_union_var - } - - DelayedAlias { shared } => { - let AliasShared { - symbol, - type_argument_abilities, - type_argument_regions, - lambda_set_variables, - infer_ext_in_output_variables, - } = types[shared]; - - let type_arguments = types.get_type_arguments(typ_index); - - let alias_variables = { - let all_vars_length = type_arguments.len() - + lambda_set_variables.len() - + infer_ext_in_output_variables.len(); - let new_variables = VariableSubsSlice::reserve_into_subs(subs, all_vars_length); - - let type_arguments_offset = 0; - let lambda_set_vars_offset = type_arguments_offset + type_arguments.len(); - let infer_ext_vars_offset = lambda_set_vars_offset + lambda_set_variables.len(); - - for (((target_index, arg_type), arg_region), abilities) in - (new_variables.indices().skip(type_arguments_offset)) - .zip(type_arguments.into_iter()) - .zip(type_argument_regions.into_iter()) - .zip(type_argument_abilities.into_iter()) - { - let copy_var = helper!(arg_type); - subs.variables[target_index] = copy_var; - if !types[abilities].is_empty() { - let arg_region = types[arg_region]; - bind_to_abilities.push((Loc::at(arg_region, copy_var), abilities)); - } - } - - let it = (new_variables.indices().skip(lambda_set_vars_offset)) - .zip(lambda_set_variables.into_iter()); - for (target_index, ls) in it { - // We MUST do this now, otherwise when linking the ambient function during - // instantiation of the real var, there will be nothing to link against. - let copy_var = type_to_variable( - subs, - rank, - pools, - problems, - abilities_store, - obligation_cache, - arena, - aliases, - types, - ls, - true, - ); - subs.variables[target_index] = copy_var; - } - - let it = (new_variables.indices().skip(infer_ext_vars_offset)) - .zip(infer_ext_in_output_variables.into_iter()); - for (target_index, ext_typ) in it { - let copy_var = helper!(ext_typ); - subs.variables[target_index] = copy_var; - } - - AliasVariables { - variables_start: new_variables.start, - type_variables_len: type_arguments.len() as _, - lambda_set_variables_len: lambda_set_variables.len() as _, - all_variables_len: all_vars_length as _, - } - }; - - let (alias_variable, kind) = aliases.instantiate_real_var( - subs, - rank, - pools, - problems, - abilities_store, - obligation_cache, - arena, - types, - symbol, - alias_variables, - ); - - let content = Content::Alias(symbol, alias_variables, alias_variable, kind); - - register_with_known_var(subs, destination, rank, pools, content) - } - - StructuralAlias { shared, actual } | OpaqueAlias { shared, actual } => { - let kind = match typ { - StructuralAlias { .. } => AliasKind::Structural, - OpaqueAlias { .. } => AliasKind::Opaque, - _ => internal_error!(), - }; - - let AliasShared { - symbol, - type_argument_abilities, - type_argument_regions, - lambda_set_variables, - infer_ext_in_output_variables, - } = types[shared]; - - debug_assert!(roc_types::subs::Variable::get_reserved(symbol).is_none()); - - let type_arguments = types.get_type_arguments(typ_index); - - let alias_variables = { - let all_vars_length = type_arguments.len() - + lambda_set_variables.len() - + infer_ext_in_output_variables.len(); - - let type_arguments_offset = 0; - let lambda_set_vars_offset = type_arguments_offset + type_arguments.len(); - let infer_ext_vars_offset = lambda_set_vars_offset + lambda_set_variables.len(); - - let new_variables = VariableSubsSlice::reserve_into_subs(subs, all_vars_length); - - for (((target_index, typ), region), abilities) in - (new_variables.indices().skip(type_arguments_offset)) - .zip(type_arguments.into_iter()) - .zip(type_argument_regions.into_iter()) - .zip(type_argument_abilities.into_iter()) - { - let copy_var = helper!(typ); - subs.variables[target_index] = copy_var; - if !types[abilities].is_empty() { - let region = types[region]; - bind_to_abilities.push((Loc::at(region, copy_var), abilities)); - } - } - - let it = (new_variables.indices().skip(lambda_set_vars_offset)) - .zip(lambda_set_variables.into_iter()); - for (target_index, ls) in it { - let copy_var = helper!(ls); - subs.variables[target_index] = copy_var; - } - - let it = (new_variables.indices().skip(infer_ext_vars_offset)) - .zip(infer_ext_in_output_variables.into_iter()); - for (target_index, ext_typ) in it { - let copy_var = helper!(ext_typ); - subs.variables[target_index] = copy_var; - } - - AliasVariables { - variables_start: new_variables.start, - type_variables_len: type_arguments.len() as _, - lambda_set_variables_len: lambda_set_variables.len() as _, - all_variables_len: all_vars_length as _, - } - }; - - let alias_variable = if let Symbol::RESULT_RESULT = symbol { - roc_result_to_var(subs, rank, pools, arena, types, actual, &mut stack) - } else { - helper!(actual) - }; - let content = Content::Alias(symbol, alias_variables, alias_variable, kind); - - register_with_known_var(subs, destination, rank, pools, content) - } - HostExposedAlias { - shared, - actual_type: alias_type, - actual_variable: actual_var, - } => { - let AliasShared { - symbol, - type_argument_abilities: _, - type_argument_regions: _, - lambda_set_variables, - infer_ext_in_output_variables: _, // TODO - } = types[shared]; - - let type_arguments = types.get_type_arguments(typ_index); - - let alias_variables = { - let length = type_arguments.len() + lambda_set_variables.len(); - let new_variables = VariableSubsSlice::reserve_into_subs(subs, length); - - for (target_index, arg_type) in - (new_variables.indices()).zip(type_arguments.into_iter()) - { - let copy_var = helper!(arg_type); - subs.variables[target_index] = copy_var; - } - let it = (new_variables.indices().skip(type_arguments.len())) - .zip(lambda_set_variables.into_iter()); - for (target_index, ls) in it { - // We MUST do this now, otherwise when linking the ambient function during - // instantiation of the real var, there will be nothing to link against. - let copy_var = type_to_variable( - subs, - rank, - pools, - problems, - abilities_store, - obligation_cache, - arena, - aliases, - types, - ls, - true, - ); - subs.variables[target_index] = copy_var; - } - - AliasVariables { - variables_start: new_variables.start, - type_variables_len: type_arguments.len() as _, - lambda_set_variables_len: lambda_set_variables.len() as _, - all_variables_len: length as _, - } - }; - - // cannot use helper! here because this variable may be involved in unification below - let alias_variable = type_to_variable( - subs, - rank, - pools, - problems, - abilities_store, - obligation_cache, - arena, - aliases, - types, - alias_type, - false, - ); - // TODO(opaques): I think host-exposed aliases should always be structural - // (when does it make sense to give a host an opaque type?) - let content = Content::Alias( - symbol, - alias_variables, - alias_variable, - AliasKind::Structural, - ); - let result = register_with_known_var(subs, destination, rank, pools, content); - - // We only want to unify the actual_var with the alias once - // if it's already redirected (and therefore, redundant) - // don't do it again - if !subs.redundant(actual_var) { - let descriptor = subs.get(result); - subs.union(result, actual_var, descriptor); - } - - result - } - Error => { - let content = Content::Error; - - register_with_known_var(subs, destination, rank, pools, content) - } - }; - } - - for (Loc { value: var, region }, abilities) in bind_to_abilities { - let abilities = &types[abilities]; - match *subs.get_content_unchecked(var) { - Content::RigidVar(a) => { - // TODO(multi-abilities): check run cache - let abilities_slice = - SubsSlice::extend_new(&mut subs.symbol_names, abilities.sorted_iter().copied()); - subs.set_content(var, Content::RigidAbleVar(a, abilities_slice)); - } - Content::RigidAbleVar(_, abs) - if (subs.get_subs_slice(abs).iter()).eq(abilities.sorted_iter()) => - { - // pass, already bound - } - _ => { - let abilities_slice = - SubsSlice::extend_new(&mut subs.symbol_names, abilities.sorted_iter().copied()); - - let flex_ability = register( - subs, - rank, - pools, - Content::FlexAbleVar(None, abilities_slice), - ); - - let category = Category::OpaqueArg; - match unify( - &mut UEnv::new(subs), - var, - flex_ability, - Mode::EQ, - Polarity::OF_VALUE, - ) { - Success { - vars: _, - must_implement_ability, - lambda_sets_to_specialize, - extra_metadata: _, - } => { - // No introduction needed - - if !must_implement_ability.is_empty() { - let new_problems = obligation_cache.check_obligations( - subs, - abilities_store, - must_implement_ability, - AbilityImplError::BadExpr(region, category, flex_ability), - ); - problems.extend(new_problems); - } - debug_assert!(lambda_sets_to_specialize - .drain() - .all(|(_, vals)| vals.is_empty())); - } - Failure(_vars, actual_type, expected_type, _bad_impls) => { - // No introduction needed - - let problem = TypeError::BadExpr( - region, - category, - actual_type, - Expected::NoExpectation(expected_type), - ); - - problems.push(problem); - } - } - } - } - } - - result -} - -#[inline(always)] -fn roc_result_to_var( - subs: &mut Subs, - rank: Rank, - pools: &mut Pools, - arena: &'_ bumpalo::Bump, - types: &mut Types, - result_type: Index, - stack: &mut bumpalo::collections::Vec<'_, TypeToVar>, -) -> Variable { - match types[result_type] { - TypeTag::TagUnion(tags, _ext_openness) => { - let ext_slice = types.get_type_arguments(result_type); - - debug_assert!(ext_slice.is_empty()); - debug_assert!(tags.len() == 2); - - let (tags_slice, payload_slices_slice) = types.union_tag_slices(tags); - - if let ([err, ok], [err_args, ok_args]) = - (&types[tags_slice], &types[payload_slices_slice]) - { - debug_assert_eq!(err, &subs.tag_names[0]); - debug_assert_eq!(ok, &subs.tag_names[1]); - - debug_assert_eq!(err_args.len(), 1); - debug_assert_eq!(ok_args.len(), 1); - - if let (Some(err_type), Some(ok_type)) = - (err_args.into_iter().next(), ok_args.into_iter().next()) - { - let err_var = RegisterVariable::with_stack( - subs, rank, pools, arena, types, err_type, stack, - ); - let ok_var = RegisterVariable::with_stack( - subs, rank, pools, arena, types, ok_type, stack, - ); - - let start = subs.variables.len() as u32; - let err_slice = SubsSlice::new(start, 1); - let ok_slice = SubsSlice::new(start + 1, 1); - - subs.variables.push(err_var); - subs.variables.push(ok_var); - - let variables = SubsSlice::new(subs.variable_slices.len() as _, 2); - subs.variable_slices.push(err_slice); - subs.variable_slices.push(ok_slice); - - let union_tags = UnionTags::from_slices(Subs::RESULT_TAG_NAMES, variables); - let ext = TagExt::Any(Variable::EMPTY_TAG_UNION); - - let content = Content::Structure(FlatType::TagUnion(union_tags, ext)); - - return register(subs, rank, pools, content); - } - } - - unreachable!("invalid arguments to Result.Result; canonicalization should catch this!") - } - _ => unreachable!("not a valid type inside a Result.Result alias"), - } -} - -fn insertion_sort_by(arr: &mut [T], mut compare: F) -where - F: FnMut(&T, &T) -> std::cmp::Ordering, -{ - for i in 1..arr.len() { - let val = &arr[i]; - let mut j = i; - let pos = arr[..i] - .binary_search_by(|x| compare(x, val)) - .unwrap_or_else(|pos| pos); - // Swap all elements until specific position. - while j > pos { - arr.swap(j - 1, j); - j -= 1; - } - } -} - -fn sorted_no_duplicate_tags(tag_slices: &[TagName]) -> bool { - match tag_slices.split_first() { - None => true, - Some((first, rest)) => { - let mut current = first; - - for next in rest { - if current >= next { - return false; - } else { - current = next; - } - } - - true - } - } -} - -fn sort_and_deduplicate(tag_vars: &mut bumpalo::collections::Vec<(TagName, T)>) { - insertion_sort_by(tag_vars, |(a, _), (b, _)| a.cmp(b)); - - // deduplicate, keeping the right-most occurrence of a tag name - let mut i = 0; - - while i < tag_vars.len() { - match (tag_vars.get(i), tag_vars.get(i + 1)) { - (Some((t1, _)), Some((t2, _))) => { - if t1 == t2 { - tag_vars.remove(i); - } else { - i += 1; - } - } - _ => break, - } - } -} - -/// Find whether the current run of tag names is in the subs.tag_names array already. If so, -/// we take a SubsSlice to the existing tag names, so we don't have to add/clone those tag names -/// and keep subs memory consumption low -fn find_tag_name_run(slice: &[TagName], subs: &mut Subs) -> Option> { - use std::cmp::Ordering; - - let tag_name = slice.get(0)?; - - let mut result = None; - - // the `SubsSlice` that inserting `slice` into subs would give - let bigger_slice = SubsSlice::new(subs.tag_names.len() as _, slice.len() as _); - - match subs.tag_name_cache.get_mut(tag_name) { - Some(occupied) => { - let subs_slice = *occupied; - - let prefix_slice = SubsSlice::new(subs_slice.start, slice.len() as _); - - if slice.len() == 1 { - return Some(prefix_slice); - } - - match slice.len().cmp(&subs_slice.len()) { - Ordering::Less => { - // we might have a prefix - let tag_names = &subs.tag_names[subs_slice.start as usize..]; - - for (from_subs, from_slice) in tag_names.iter().zip(slice.iter()) { - if from_subs != from_slice { - return None; - } - } - - result = Some(prefix_slice); - } - Ordering::Equal => { - let tag_names = &subs.tag_names[subs_slice.indices()]; - - for (from_subs, from_slice) in tag_names.iter().zip(slice.iter()) { - if from_subs != from_slice { - return None; - } - } - - result = Some(subs_slice); - } - Ordering::Greater => { - // switch to the bigger slice that is not inserted yet, but will be soon - *occupied = bigger_slice; - } - } - } - None => { - subs.tag_name_cache.push(tag_name, bigger_slice); - } - } - - result -} - -#[inline(always)] -fn register_tag_arguments( - subs: &mut Subs, - rank: Rank, - pools: &mut Pools, - arena: &'_ bumpalo::Bump, - types: &mut Types, - stack: &mut bumpalo::collections::Vec<'_, TypeToVar>, - arguments: Slice, -) -> VariableSubsSlice { - if arguments.is_empty() { - VariableSubsSlice::default() - } else { - let new_variables = VariableSubsSlice::reserve_into_subs(subs, arguments.len()); - let it = new_variables.indices().zip(arguments.into_iter()); - - for (target_index, argument) in it { - let var = - RegisterVariable::with_stack(subs, rank, pools, arena, types, argument, stack); - subs.variables[target_index] = var; - } - - new_variables - } -} - -/// Assumes that the tags are sorted and there are no duplicates! -fn insert_tags_fast_path( - subs: &mut Subs, - rank: Rank, - pools: &mut Pools, - arena: &'_ bumpalo::Bump, - types: &mut Types, - union_tags: UnionTags, - stack: &mut bumpalo::collections::Vec<'_, TypeToVar>, -) -> UnionTags { - let (tags, payload_slices) = types.union_tag_slices(union_tags); - - debug_assert_eq!(tags.len(), payload_slices.len()); - - if let [arguments_slice] = &types[payload_slices] { - let arguments_slice = *arguments_slice; - - let variable_slice = - register_tag_arguments(subs, rank, pools, arena, types, stack, arguments_slice); - - let new_variable_slices = - SubsSlice::extend_new(&mut subs.variable_slices, [variable_slice]); - - macro_rules! subs_tag_name { - ($tag_name_slice:expr) => { - return UnionTags::from_slices($tag_name_slice, new_variable_slices) - }; - } - - match types[tags][0].0.as_str() { - "Ok" => subs_tag_name!(Subs::TAG_NAME_OK.as_slice()), - "Err" => subs_tag_name!(Subs::TAG_NAME_ERR.as_slice()), - "InvalidNumStr" => subs_tag_name!(Subs::TAG_NAME_INVALID_NUM_STR.as_slice()), - "BadUtf8" => subs_tag_name!(Subs::TAG_NAME_BAD_UTF_8.as_slice()), - "OutOfBounds" => subs_tag_name!(Subs::TAG_NAME_OUT_OF_BOUNDS.as_slice()), - _other => {} - } - } - - let new_variable_slices = SubsSlice::reserve_variable_slices(subs, tags.len()); - match find_tag_name_run(&types[tags], subs) { - Some(new_tag_names) => { - let it = (new_variable_slices.indices()).zip(payload_slices.into_iter()); - - for (variable_slice_index, arguments_index) in it { - let arguments = types[arguments_index]; - subs.variable_slices[variable_slice_index] = - register_tag_arguments(subs, rank, pools, arena, types, stack, arguments); - } - - UnionTags::from_slices(new_tag_names, new_variable_slices) - } - None => { - let new_tag_names = SubsSlice::reserve_tag_names(subs, tags.len()); - - let it = (new_variable_slices.indices()) - .zip(new_tag_names.indices()) - .zip(tags.into_iter()) - .zip(payload_slices.into_iter()); - - for (((variable_slice_index, tag_name_index), tag_name), arguments_index) in it { - let arguments = types[arguments_index]; - subs.variable_slices[variable_slice_index] = - register_tag_arguments(subs, rank, pools, arena, types, stack, arguments); - - subs.tag_names[tag_name_index] = types[tag_name].clone(); - } - - UnionTags::from_slices(new_tag_names, new_variable_slices) - } - } -} - -fn insert_tags_slow_path( - subs: &mut Subs, - rank: Rank, - pools: &mut Pools, - arena: &'_ bumpalo::Bump, - types: &mut Types, - union_tags: UnionTags, - mut tag_vars: bumpalo::collections::Vec<(TagName, VariableSubsSlice)>, - stack: &mut bumpalo::collections::Vec<'_, TypeToVar>, -) -> UnionTags { - let (tags, payload_slices) = types.union_tag_slices(union_tags); - - for (tag_index, tag_argument_types_index) in (tags.into_iter()).zip(payload_slices.into_iter()) - { - let tag_argument_types = &types[tag_argument_types_index]; - - let new_slice = VariableSubsSlice::reserve_into_subs(subs, tag_argument_types.len()); - - for (i, arg) in (new_slice.indices()).zip(tag_argument_types.into_iter()) { - let var = RegisterVariable::with_stack(subs, rank, pools, arena, types, arg, stack); - subs.variables[i] = var; - } - - tag_vars.push((types[tag_index].clone(), new_slice)); - } - - sort_and_deduplicate(&mut tag_vars); - - UnionTags::insert_slices_into_subs(subs, tag_vars) -} - -fn type_to_union_tags( - subs: &mut Subs, - rank: Rank, - pools: &mut Pools, - arena: &'_ bumpalo::Bump, - types: &mut Types, - union_tags: UnionTags, - opt_ext_slice: Slice, - ext_openness: ExtImplicitOpenness, - stack: &mut bumpalo::collections::Vec<'_, TypeToVar>, -) -> (UnionTags, TagExt) { - use bumpalo::collections::Vec; - - let (tags, _) = types.union_tag_slices(union_tags); - - let sorted = tags.len() == 1 || sorted_no_duplicate_tags(&types[tags]); - - debug_assert!(opt_ext_slice.len() <= 1); - - match opt_ext_slice.into_iter().next() { - None => { - let ext = Variable::EMPTY_TAG_UNION; - - let union_tags = if sorted { - insert_tags_fast_path(subs, rank, pools, arena, types, union_tags, stack) - } else { - let tag_vars = Vec::with_capacity_in(tags.len(), arena); - insert_tags_slow_path(subs, rank, pools, arena, types, union_tags, tag_vars, stack) - }; - - (union_tags, TagExt::Any(ext)) - } - Some(ext) => { - let mut tag_vars = Vec::with_capacity_in(tags.len(), arena); - - let temp_ext = { - let temp_ext_var = - RegisterVariable::with_stack(subs, rank, pools, arena, types, ext, stack); - TagExt::from_can(temp_ext_var, ext_openness) - }; - let (it, ext) = - roc_types::types::gather_tags_unsorted_iter(subs, UnionTags::default(), temp_ext) - .expect("extension var could not be seen as tag union"); - - tag_vars.extend(it.map(|(n, v)| (n.clone(), v))); - - let union_tags = if tag_vars.is_empty() && sorted { - insert_tags_fast_path(subs, rank, pools, arena, types, union_tags, stack) - } else { - insert_tags_slow_path(subs, rank, pools, arena, types, union_tags, tag_vars, stack) - }; - - (union_tags, ext) - } - } -} - -fn create_union_lambda( - subs: &mut Subs, - rank: Rank, - pools: &mut Pools, - arena: &'_ bumpalo::Bump, - types: &mut Types, - closure: Symbol, - capture_types: Slice, - stack: &mut bumpalo::collections::Vec<'_, TypeToVar>, -) -> UnionLambdas { - let variable_slice = - register_tag_arguments(subs, rank, pools, arena, types, stack, capture_types); - let new_variable_slices = SubsSlice::extend_new(&mut subs.variable_slices, [variable_slice]); - - let lambda_name_slice = SubsSlice::extend_new(&mut subs.symbol_names, [closure]); - - UnionLambdas::from_slices(lambda_name_slice, new_variable_slices) -} - -fn check_for_infinite_type( - subs: &mut Subs, - pools: &mut Pools, - problems: &mut Vec, - symbol: Symbol, - loc_var: Loc, -) { - let var = loc_var.value; - - 'next_occurs_check: while let Err((_, chain)) = subs.occurs(var) { - // walk the chain till we find a tag union or lambda set, starting from the variable that - // occurred recursively, which is always at the end of the chain. - for &var in chain.iter().rev() { - match *subs.get_content_without_compacting(var) { - Content::Structure(FlatType::TagUnion(tags, ext_var)) => { - let rec_var = subs.mark_tag_union_recursive(var, tags, ext_var); - register_to_pools(subs, rec_var, pools); - - continue 'next_occurs_check; - } - Content::LambdaSet(subs::LambdaSet { - solved, - recursion_var: OptVariable::NONE, - unspecialized, - ambient_function: ambient_function_var, - }) => { - let rec_var = subs.mark_lambda_set_recursive( - var, - solved, - unspecialized, - ambient_function_var, - ); - register_to_pools(subs, rec_var, pools); - - continue 'next_occurs_check; - } - _ => { /* fall through */ } - } - } - - circular_error(subs, problems, symbol, &loc_var); - } -} - -fn circular_error( - subs: &mut Subs, - problems: &mut Vec, - symbol: Symbol, - loc_var: &Loc, -) { - let var = loc_var.value; - let error_type = subs.var_to_error_type(var, Polarity::OF_VALUE); - let problem = TypeError::CircularType(loc_var.region, symbol, error_type); - - subs.set_content(var, Content::Error); - - problems.push(problem); -} - -/// Generalizes variables at the `young_rank`, which did not escape a let-binding -/// into a lower scope. -/// -/// Ensures that variables introduced at the `young_rank`, but that should be -/// stuck at a lower level, are marked at that level and not generalized at the -/// present `young_rank`. See [adjust_rank]. -fn generalize( - subs: &mut Subs, - young_mark: Mark, - visit_mark: Mark, - young_rank: Rank, - pools: &mut Pools, -) { - let young_vars = std::mem::take(pools.get_mut(young_rank)); - let rank_table = pool_to_rank_table(subs, young_mark, young_rank, young_vars); - - // Get the ranks right for each entry. - // Start at low ranks so we only have to pass over the information once. - for (index, table) in rank_table.iter().enumerate() { - for &var in table.iter() { - adjust_rank(subs, young_mark, visit_mark, Rank::from(index), var); + // Get the ranks right for each entry. + // Start at low ranks so we only have to pass over the information once. + for (index, table) in rank_table.iter().enumerate() { + for &var in table.iter() { + adjust_rank(subs, young_mark, visit_mark, Rank::from(index), var); } } @@ -4064,370 +2383,13 @@ pub(crate) fn introduce(subs: &mut Subs, rank: Rank, pools: &mut Pools, vars: &[ pool.extend(vars); } -pub(crate) fn deep_copy_var_in( +#[inline(always)] +pub(crate) fn register( subs: &mut Subs, rank: Rank, pools: &mut Pools, - var: Variable, - arena: &Bump, -) -> Variable { - let mut visited = bumpalo::collections::Vec::with_capacity_in(256, arena); - - let pool = pools.get_mut(rank); - - let var = subs.get_root_key(var); - match deep_copy_var_decision(subs, rank, var) { - ControlFlow::Break(copy) => copy, - ControlFlow::Continue(copy) => { - deep_copy_var_help(subs, rank, pool, &mut visited, var, copy); - - // we have tracked all visited variables, and can now traverse them - // in one go (without looking at the UnificationTable) and clear the copy field - for var in visited { - subs.set_copy_unchecked(var, OptVariable::NONE); - } - - copy - } - } -} - -#[inline] -fn has_trivial_copy(subs: &Subs, root_var: Variable) -> Option { - let existing_copy = subs.get_copy_unchecked(root_var); - - if let Some(copy) = existing_copy.into_variable() { - Some(copy) - } else if subs.get_rank_unchecked(root_var) != Rank::GENERALIZED { - Some(root_var) - } else { - None - } -} - -#[inline] -fn deep_copy_var_decision( - subs: &mut Subs, - max_rank: Rank, - var: Variable, -) -> ControlFlow { - let var = subs.get_root_key(var); - if let Some(copy) = has_trivial_copy(subs, var) { - ControlFlow::Break(copy) - } else { - let copy_descriptor = Descriptor { - content: Content::Structure(FlatType::EmptyTagUnion), - rank: max_rank, - mark: Mark::NONE, - copy: OptVariable::NONE, - }; - - let copy = subs.fresh(copy_descriptor); - - // Link the original variable to the new variable. This lets us - // avoid making multiple copies of the variable we are instantiating. - // - // Need to do this before recursively copying to avoid looping. - subs.set_mark_unchecked(var, Mark::NONE); - subs.set_copy_unchecked(var, copy.into()); - - ControlFlow::Continue(copy) - } -} - -fn deep_copy_var_help( - subs: &mut Subs, - max_rank: Rank, - pool: &mut Vec, - visited: &mut bumpalo::collections::Vec<'_, Variable>, - initial_source: Variable, - initial_copy: Variable, + content: Content, ) -> Variable { - use roc_types::subs::Content::*; - use roc_types::subs::FlatType::*; - - struct DeepCopyVarWork { - source: Variable, - copy: Variable, - } - - let initial = DeepCopyVarWork { - source: initial_source, - copy: initial_copy, - }; - let mut stack = vec![initial]; - - macro_rules! work { - ($variable:expr) => {{ - let var = subs.get_root_key($variable); - match deep_copy_var_decision(subs, max_rank, var) { - ControlFlow::Break(copy) => copy, - ControlFlow::Continue(copy) => { - stack.push(DeepCopyVarWork { source: var, copy }); - - copy - } - } - }}; - } - - macro_rules! copy_sequence { - ($length:expr, $variables:expr) => {{ - let new_variables = SubsSlice::reserve_into_subs(subs, $length as _); - for (target_index, var_index) in (new_variables.indices()).zip($variables) { - let var = subs[var_index]; - let copy_var = work!(var); - subs.variables[target_index] = copy_var; - } - - new_variables - }}; - } - - macro_rules! copy_union { - ($tags:expr) => {{ - let new_variable_slices = SubsSlice::reserve_variable_slices(subs, $tags.len()); - - let it = (new_variable_slices.indices()).zip($tags.variables()); - for (target_index, index) in it { - let slice = subs[index]; - - let new_variables = copy_sequence!(slice.len(), slice); - subs.variable_slices[target_index] = new_variables; - } - - UnionLabels::from_slices($tags.labels(), new_variable_slices) - }}; - } - - // When generalizing annotations with `Openness` extensions - // we want to promote them to `Any`, so that usages at - // specialized sites can grow unboundedly and are not bound to - // openness-polymorphism. - macro_rules! copy_tag_ext { - ($ext:expr) => { - TagExt::Any(work!($ext.var())) - }; - } - - while let Some(DeepCopyVarWork { source: var, copy }) = stack.pop() { - visited.push(var); - pool.push(copy); - - let content = *subs.get_content_unchecked(var); - - // Now we recursively copy the content of the variable. - // We have already marked the variable as copied, so we - // will not repeat this work or crawl this variable again. - match content { - Structure(flat_type) => { - let new_flat_type = match flat_type { - Apply(symbol, arguments) => { - let new_arguments = copy_sequence!(arguments.len(), arguments); - - Apply(symbol, new_arguments) - } - - Func(arguments, closure_var, ret_var) => { - let new_ret_var = work!(ret_var); - let new_closure_var = work!(closure_var); - - let new_arguments = copy_sequence!(arguments.len(), arguments); - - Func(new_arguments, new_closure_var, new_ret_var) - } - - same @ EmptyRecord | same @ EmptyTuple | same @ EmptyTagUnion => same, - - Record(fields, ext_var) => { - let record_fields = { - let new_variables = - copy_sequence!(fields.len(), fields.iter_variables()); - - // When copying a let-generalized record to a specialized region, rigid - // optionals just become optionals. - let field_types = subs.get_subs_slice(fields.record_fields()); - let has_rigid_optional_field = field_types - .iter() - .any(|f| matches!(f, RecordField::RigidOptional(..))); - - let new_field_types_start = if has_rigid_optional_field { - let field_types = field_types.to_vec(); - let slice = SubsSlice::extend_new( - &mut subs.record_fields, - field_types.into_iter().map(|f| match f { - RecordField::RigidOptional(()) - | RecordField::RigidRequired(()) => internal_error!("Rigid optional/required should be generalized to non-rigid by this point"), - - RecordField::Demanded(_) - | RecordField::Required(_) - | RecordField::Optional(_) => f, - }), - ); - slice.start - } else { - fields.field_types_start - }; - - RecordFields { - length: fields.length, - field_names_start: fields.field_names_start, - variables_start: new_variables.start, - field_types_start: new_field_types_start, - } - }; - - Record(record_fields, work!(ext_var)) - } - - Tuple(elems, ext_var) => { - let tuple_elems = { - let new_variables = copy_sequence!(elems.len(), elems.iter_variables()); - - TupleElems { - length: elems.length, - variables_start: new_variables.start, - elem_index_start: elems.elem_index_start, - } - }; - - Tuple(tuple_elems, work!(ext_var)) - } - - TagUnion(tags, ext_var) => { - let union_tags = copy_union!(tags); - - TagUnion(union_tags, copy_tag_ext!(ext_var)) - } - - FunctionOrTagUnion(tag_name, symbol, ext_var) => { - FunctionOrTagUnion(tag_name, symbol, copy_tag_ext!(ext_var)) - } - - RecursiveTagUnion(rec_var, tags, ext_var) => { - let union_tags = copy_union!(tags); - - RecursiveTagUnion(work!(rec_var), union_tags, copy_tag_ext!(ext_var)) - } - }; - - subs.set_content_unchecked(copy, Structure(new_flat_type)); - } - - FlexVar(_) | FlexAbleVar(_, _) | Error => { - subs.set_content_unchecked(copy, content); - } - - RecursionVar { - opt_name, - structure, - } => { - let content = RecursionVar { - opt_name, - structure: work!(structure), - }; - - subs.set_content_unchecked(copy, content); - } - - RigidVar(name) => { - subs.set_content_unchecked(copy, FlexVar(Some(name))); - } - - RigidAbleVar(name, ability) => { - subs.set_content_unchecked(copy, FlexAbleVar(Some(name), ability)); - } - - Alias(symbol, arguments, real_type_var, kind) => { - let new_variables = - copy_sequence!(arguments.all_variables_len, arguments.all_variables()); - - let new_arguments = AliasVariables { - variables_start: new_variables.start, - ..arguments - }; - - let new_real_type_var = work!(real_type_var); - let new_content = Alias(symbol, new_arguments, new_real_type_var, kind); - - subs.set_content_unchecked(copy, new_content); - } - - LambdaSet(subs::LambdaSet { - solved, - recursion_var, - unspecialized, - ambient_function: ambient_function_var, - }) => { - let lambda_set_var = copy; - - let new_solved = copy_union!(solved); - let new_rec_var = recursion_var.map(|v| work!(v)); - let new_unspecialized = SubsSlice::reserve_uls_slice(subs, unspecialized.len()); - - for (new_uls_index, uls_index) in - (new_unspecialized.into_iter()).zip(unspecialized.into_iter()) - { - let Uls(var, sym, region) = subs[uls_index]; - let new_var = work!(var); - - deep_copy_uls_precondition(subs, var, new_var); - - subs[new_uls_index] = Uls(new_var, sym, region); - - subs.uls_of_var.add(new_var, lambda_set_var); - } - - let new_ambient_function_var = work!(ambient_function_var); - debug_assert_ne!( - ambient_function_var, new_ambient_function_var, - "lambda set cloned but its ambient function wasn't?" - ); - - subs.set_content_unchecked( - lambda_set_var, - LambdaSet(subs::LambdaSet { - solved: new_solved, - recursion_var: new_rec_var, - unspecialized: new_unspecialized, - ambient_function: new_ambient_function_var, - }), - ); - } - - RangedNumber(range) => { - let new_content = RangedNumber(range); - - subs.set_content_unchecked(copy, new_content); - } - } - } - - initial_copy -} - -#[inline(always)] -fn deep_copy_uls_precondition(subs: &Subs, original_var: Variable, new_var: Variable) { - if cfg!(debug_assertions) { - let content = subs.get_content_without_compacting(original_var); - - debug_assert!( - matches!( - content, - Content::FlexAbleVar(..) | Content::RigidAbleVar(..) - ), - "var in unspecialized lamba set is not bound to an ability, it is {:?}", - roc_types::subs::SubsFmtContent(content, subs) - ); - debug_assert!( - original_var != new_var, - "unspecialized lamba set var was not instantiated" - ); - } -} - -#[inline(always)] -fn register(subs: &mut Subs, rank: Rank, pools: &mut Pools, content: Content) -> Variable { let descriptor = Descriptor { content, rank, @@ -4442,7 +2404,7 @@ fn register(subs: &mut Subs, rank: Rank, pools: &mut Pools, content: Content) -> var } -fn register_with_known_var( +pub(crate) fn register_with_known_var( subs: &mut Subs, var: Variable, rank: Rank, diff --git a/crates/compiler/solve/src/specialize.rs b/crates/compiler/solve/src/specialize.rs index d6344f70fc2..57397445858 100644 --- a/crates/compiler/solve/src/specialize.rs +++ b/crates/compiler/solve/src/specialize.rs @@ -25,8 +25,8 @@ use roc_types::{ use roc_unify::unify::{unify, Env as UEnv, Mode, MustImplementConstraints}; use crate::{ - ability::builtin_module_with_unlisted_ability_impl, - solve::{deep_copy_var_in, introduce, Pools}, + ability::builtin_module_with_unlisted_ability_impl, deep_copy::deep_copy_var_in, pools::Pools, + solve::introduce, }; /// What phase in the compiler is reaching out to specialize lambda sets? diff --git a/crates/compiler/solve/src/to_var.rs b/crates/compiler/solve/src/to_var.rs new file mode 100644 index 00000000000..3f049905207 --- /dev/null +++ b/crates/compiler/solve/src/to_var.rs @@ -0,0 +1,1313 @@ +use std::cell::RefCell; + +use roc_can::{abilities::AbilitiesStore, constraint::TypeOrVar, expected::Expected}; +use roc_collections::soa::{Index, Slice}; +use roc_error_macros::internal_error; +use roc_module::{ident::TagName, symbol::Symbol}; +use roc_region::all::Loc; +use roc_solve_problem::TypeError; +use roc_types::{ + subs::{ + self, AliasVariables, Content, FlatType, GetSubsSlice, LambdaSet, OptVariable, Rank, + RecordFields, Subs, SubsSlice, TagExt, TupleElems, UnionLabels, UnionLambdas, UnionTags, + Variable, VariableSubsSlice, + }, + types::{ + gather_fields_unsorted_iter, gather_tuple_elems_unsorted_iter, AliasKind, AliasShared, + Category, ExtImplicitOpenness, Polarity, TypeTag, Types, + }, +}; +use roc_unify::unify::{unify, Env as UEnv, Mode, Unified}; + +use crate::{ + ability::{AbilityImplError, ObligationCache}, + deep_copy::deep_copy_var_in, + pools::Pools, + solve::{register, register_with_known_var}, + Aliases, +}; + +std::thread_local! { + /// Scratchpad arena so we don't need to allocate a new one all the time + static SCRATCHPAD: RefCell> = RefCell::new(Some(bumpalo::Bump::with_capacity(4 * 1024))); +} + +fn take_scratchpad() -> bumpalo::Bump { + SCRATCHPAD.with(|f| f.take().unwrap()) +} + +fn put_scratchpad(scratchpad: bumpalo::Bump) { + SCRATCHPAD.with(|f| { + f.replace(Some(scratchpad)); + }); +} + +pub(crate) fn either_type_index_to_var( + subs: &mut Subs, + rank: Rank, + pools: &mut Pools, + problems: &mut Vec, + abilities_store: &mut AbilitiesStore, + obligation_cache: &mut ObligationCache, + types: &mut Types, + aliases: &mut Aliases, + either_type_index: TypeOrVar, +) -> Variable { + match either_type_index.split() { + Ok(type_index) => { + // Converts the celled type to a variable, emplacing the new variable for re-use. + let var = type_to_var( + subs, + rank, + problems, + abilities_store, + obligation_cache, + pools, + types, + aliases, + type_index, + ); + + debug_assert!( + matches!(types[type_index], TypeTag::Variable(v) if v == var) + || matches!( + types[type_index], + TypeTag::EmptyRecord | TypeTag::EmptyTagUnion + ) + ); + var + } + Err(var_index) => { + // we cheat, and store the variable directly in the index + unsafe { Variable::from_index(var_index.index() as _) } + } + } +} + +pub(crate) fn type_to_var( + subs: &mut Subs, + rank: Rank, + problems: &mut Vec, + abilities_store: &mut AbilitiesStore, + obligation_cache: &mut ObligationCache, + pools: &mut Pools, + types: &mut Types, + aliases: &mut Aliases, + typ: Index, +) -> Variable { + if let TypeTag::Variable(var) = types[typ] { + var + } else { + let mut arena = take_scratchpad(); + + let var = type_to_var_help( + subs, + rank, + pools, + problems, + abilities_store, + obligation_cache, + &arena, + aliases, + types, + typ, + false, + ); + + arena.reset(); + put_scratchpad(arena); + + var + } +} + +enum RegisterVariable { + /// Based on the Type, we already know what variable this will be + Direct(Variable), + /// This Type needs more complicated Content. We reserve a Variable + /// for it, but put a placeholder Content in subs + Deferred, +} + +impl RegisterVariable { + fn from_type( + subs: &mut Subs, + rank: Rank, + pools: &mut Pools, + arena: &'_ bumpalo::Bump, + types: &mut Types, + typ: Index, + ) -> Self { + use RegisterVariable::*; + + match types[typ] { + TypeTag::Variable(var) => Direct(var), + TypeTag::EmptyRecord => Direct(Variable::EMPTY_RECORD), + TypeTag::EmptyTagUnion => Direct(Variable::EMPTY_TAG_UNION), + TypeTag::DelayedAlias { shared } + | TypeTag::StructuralAlias { shared, .. } + | TypeTag::OpaqueAlias { shared, .. } + | TypeTag::HostExposedAlias { shared, .. } => { + let AliasShared { symbol, .. } = types[shared]; + if let Some(reserved) = Variable::get_reserved(symbol) { + let direct_var = if rank.is_generalized() { + // reserved variables are stored with rank NONE + reserved + } else { + // for any other rank, we need to copy; it takes care of adjusting the rank + deep_copy_var_in(subs, rank, pools, reserved, arena) + }; + // Safety: the `destination` will become the source-of-truth for the type index, since it + // was not already transformed before (if it was, we'd be in the Variable branch!) + let _old_typ = unsafe { types.emplace_variable(typ, direct_var) }; + return Direct(direct_var); + } + + Deferred + } + _ => Deferred, + } + } + + #[inline(always)] + fn with_stack( + subs: &mut Subs, + rank: Rank, + pools: &mut Pools, + arena: &'_ bumpalo::Bump, + types: &mut Types, + typ_index: Index, + stack: &mut bumpalo::collections::Vec<'_, TypeToVar>, + ) -> Variable { + match Self::from_type(subs, rank, pools, arena, types, typ_index) { + Self::Direct(var) => var, + Self::Deferred => { + let var = subs.fresh_unnamed_flex_var(); + // Safety: the `destination` will become the source-of-truth for the type index, since it + // was not already transformed before (if it was, it wouldn't be deferred!) + let typ = unsafe { types.emplace_variable(typ_index, var) }; + stack.push(TypeToVar::Defer { + typ, + typ_index, + destination: var, + ambient_function: AmbientFunctionPolicy::NoFunction, + }); + var + } + } + } +} + +/// Instantiation of ambient functions in unspecialized lambda sets is somewhat tricky due to other +/// optimizations we have in place. This struct tells us how they should be instantiated. +#[derive(Debug)] +enum AmbientFunctionPolicy { + /// We're not in a function. This variant may never hold for unspecialized lambda sets. + NoFunction, + /// We're in a known function. + Function(Variable), +} + +impl AmbientFunctionPolicy { + fn link_to_alias_lambda_set_var(&self, subs: &mut Subs, var: Variable) { + let ambient_function = match self { + AmbientFunctionPolicy::Function(var) => *var, + _ => { + // Might be linked at a deeper point in time, ignore for now + return; + } + }; + let content = subs.get_content_without_compacting(var); + let new_content = match content { + Content::LambdaSet(LambdaSet { + solved, + recursion_var, + unspecialized, + ambient_function: _, + }) => Content::LambdaSet(LambdaSet { + solved: *solved, + recursion_var: *recursion_var, + unspecialized: *unspecialized, + ambient_function, + }), + Content::FlexVar(_) => { + // Something like + // Encoder fmt : List U8, fmt -a-> List U8 | fmt has EncoderFormatting + // THEORY: Replace these with empty lambda sets. They will unify the same as a flex + // var does, but allows us to record the ambient function properly. + Content::LambdaSet(LambdaSet { + solved: UnionLabels::default(), + recursion_var: OptVariable::NONE, + unspecialized: SubsSlice::default(), + ambient_function, + }) + } + content => internal_error!("{:?}({:?}) not a lambda set", content, var), + }; + subs.set_content_unchecked(var, new_content); + } +} + +#[derive(Debug)] +enum TypeToVar { + Defer { + typ: TypeTag, + typ_index: Index, + destination: Variable, + ambient_function: AmbientFunctionPolicy, + }, +} + +#[allow(clippy::too_many_arguments)] +pub(crate) fn type_to_var_help( + subs: &mut Subs, + rank: Rank, + pools: &mut Pools, + problems: &mut Vec, + abilities_store: &AbilitiesStore, + obligation_cache: &mut ObligationCache, + arena: &bumpalo::Bump, + aliases: &mut Aliases, + types: &mut Types, + typ: Index, + // Helpers for instantiating ambient functions of lambda set variables from type aliases. + is_alias_lambda_set_arg: bool, +) -> Variable { + use bumpalo::collections::Vec; + + let mut stack = Vec::with_capacity_in(8, arena); + let mut bind_to_abilities = Vec::new_in(arena); + + macro_rules! helper { + ($typ:expr, $ambient_function_policy:expr) => {{ + match RegisterVariable::from_type(subs, rank, pools, arena, types, $typ) { + RegisterVariable::Direct(var) => { + // If the variable is just a type variable but we know we're in a lambda set + // context, try to link to the ambient function. + $ambient_function_policy.link_to_alias_lambda_set_var(subs, var); + + var + } + RegisterVariable::Deferred => { + let var = subs.fresh_unnamed_flex_var(); + + // Safety: the `destination` will become the source-of-truth for the type index, since it + // was not already transformed before (if it was, it wouldn't be deferred!) + let typ = unsafe { types.emplace_variable($typ, var) }; + + stack.push(TypeToVar::Defer { + typ, + typ_index: $typ, + destination: var, + ambient_function: $ambient_function_policy, + }); + + var + } + } + }}; + ($typ:expr) => {{ + helper!($typ, AmbientFunctionPolicy::NoFunction) + }}; + } + + let result = helper!(typ); + + while let Some(TypeToVar::Defer { + typ_index, + typ, + destination, + ambient_function, + }) = stack.pop() + { + use TypeTag::*; + match typ { + Variable(_) | EmptyRecord | EmptyTagUnion => { + unreachable!("This variant should never be deferred!",) + } + RangedNumber(range) => { + let content = Content::RangedNumber(range); + + register_with_known_var(subs, destination, rank, pools, content) + } + Apply { + symbol, + type_argument_regions: _, + region: _, + } => { + let arguments = types.get_type_arguments(typ_index); + let new_arguments = VariableSubsSlice::reserve_into_subs(subs, arguments.len()); + for (target_index, var_index) in + (new_arguments.indices()).zip(arguments.into_iter()) + { + let var = helper!(var_index); + subs.variables[target_index] = var; + } + + let flat_type = FlatType::Apply(symbol, new_arguments); + let content = Content::Structure(flat_type); + + register_with_known_var(subs, destination, rank, pools, content) + } + + ClosureTag { + name, + ambient_function, + } => { + let captures = types.get_type_arguments(typ_index); + let union_lambdas = create_union_lambda( + subs, rank, pools, arena, types, name, captures, &mut stack, + ); + + let content = Content::LambdaSet(subs::LambdaSet { + solved: union_lambdas, + // We may figure out the lambda set is recursive during solving, but it never + // is to begin with. + recursion_var: OptVariable::NONE, + unspecialized: SubsSlice::default(), + ambient_function, + }); + + register_with_known_var(subs, destination, rank, pools, content) + } + UnspecializedLambdaSet { unspecialized } => { + let unspecialized_slice = SubsSlice::extend_new( + &mut subs.unspecialized_lambda_sets, + std::iter::once(unspecialized), + ); + + // `ClosureTag` ambient functions are resolved during constraint generation. + // But `UnspecializedLambdaSet`s can only ever live in a type signature, and don't + // correspond to a expression, so they are never constrained. + // Instead, we resolve their ambient functions during type translation, observing + // the invariant that a lambda set can only ever appear under a function type. + let ambient_function = match ambient_function { + AmbientFunctionPolicy::NoFunction => { + debug_assert!(is_alias_lambda_set_arg); + // To be filled in during delayed type alias instantiation + roc_types::subs::Variable::NULL + } + AmbientFunctionPolicy::Function(var) => var, + }; + + let content = Content::LambdaSet(subs::LambdaSet { + unspecialized: unspecialized_slice, + solved: UnionLabels::default(), + recursion_var: OptVariable::NONE, + ambient_function, + }); + + register_with_known_var(subs, destination, rank, pools, content) + } + // This case is important for the rank of boolean variables + Function(closure_type, ret_type) => { + let arguments = types.get_type_arguments(typ_index); + let new_arguments = VariableSubsSlice::reserve_into_subs(subs, arguments.len()); + for (target_index, var_index) in + (new_arguments.indices()).zip(arguments.into_iter()) + { + let var = helper!(var_index); + subs.variables[target_index] = var; + } + + let ret_var = helper!(ret_type); + let closure_var = + helper!(closure_type, AmbientFunctionPolicy::Function(destination)); + let content = + Content::Structure(FlatType::Func(new_arguments, closure_var, ret_var)); + + register_with_known_var(subs, destination, rank, pools, content) + } + Record(fields) => { + let ext_slice = types.get_type_arguments(typ_index); + + // An empty fields is inefficient (but would be correct) + // If hit, try to turn the value into an EmptyRecord in canonicalization + debug_assert!(!fields.is_empty() || !ext_slice.is_empty()); + + let mut field_vars = Vec::with_capacity_in(fields.len(), arena); + + let (fields_names, field_kinds, field_tys) = types.record_fields_slices(fields); + + for ((field, field_kind), field_type) in (fields_names.into_iter()) + .zip(field_kinds.into_iter()) + .zip(field_tys.into_iter()) + { + let field_var = { + let t = helper!(field_type); + types[field_kind].replace(t) + }; + + field_vars.push((types[field].clone(), field_var)); + } + + debug_assert!(ext_slice.len() <= 1); + let temp_ext_var = match ext_slice.into_iter().next() { + None => roc_types::subs::Variable::EMPTY_RECORD, + Some(ext) => helper!(ext), + }; + + let (it, new_ext_var) = + gather_fields_unsorted_iter(subs, RecordFields::empty(), temp_ext_var) + .expect("Something ended up weird in this record type"); + + let it = it + .into_iter() + .map(|(field, field_type)| (field.clone(), field_type)); + + field_vars.extend(it); + insertion_sort_by(&mut field_vars, RecordFields::compare); + + let record_fields = RecordFields::insert_into_subs(subs, field_vars); + + let content = Content::Structure(FlatType::Record(record_fields, new_ext_var)); + + register_with_known_var(subs, destination, rank, pools, content) + } + + Tuple(elems) => { + let ext_slice = types.get_type_arguments(typ_index); + + // Elems should never be empty; we don't support empty tuples + debug_assert!(!elems.is_empty() || !ext_slice.is_empty()); + + let mut elem_vars = Vec::with_capacity_in(elems.len(), arena); + + let (indices, elem_tys) = types.tuple_elems_slices(elems); + + for (index, elem_type) in indices.into_iter().zip(elem_tys.into_iter()) { + let elem_var = helper!(elem_type); + elem_vars.push((types[index], elem_var)); + } + + debug_assert!(ext_slice.len() <= 1); + let temp_ext_var = match ext_slice.into_iter().next() { + None => roc_types::subs::Variable::EMPTY_TUPLE, + Some(ext) => helper!(ext), + }; + + let (it, new_ext_var) = + gather_tuple_elems_unsorted_iter(subs, TupleElems::empty(), temp_ext_var) + .expect("Something ended up weird in this tuple type"); + + elem_vars.extend(it); + let tuple_elems = TupleElems::insert_into_subs(subs, elem_vars); + + let content = Content::Structure(FlatType::Tuple(tuple_elems, new_ext_var)); + + register_with_known_var(subs, destination, rank, pools, content) + } + + TagUnion(tags, ext_openness) => { + let ext_slice = types.get_type_arguments(typ_index); + + // An empty tags is inefficient (but would be correct) + // If hit, try to turn the value into an EmptyTagUnion in canonicalization + debug_assert!(!tags.is_empty() || !ext_slice.is_empty()); + + let (union_tags, ext) = type_to_union_tags( + subs, + rank, + pools, + arena, + types, + tags, + ext_slice, + ext_openness, + &mut stack, + ); + let content = Content::Structure(FlatType::TagUnion(union_tags, ext)); + + register_with_known_var(subs, destination, rank, pools, content) + } + FunctionOrTagUnion(symbol, ext_openness) => { + let ext_slice = types.get_type_arguments(typ_index); + let tag_name = types.get_tag_name(&typ_index).clone(); + + debug_assert!(ext_slice.len() <= 1); + let temp_ext = match ext_slice.into_iter().next() { + Some(ext) => { + let var = helper!(ext); + TagExt::from_can(var, ext_openness) + } + None => TagExt::Any(roc_types::subs::Variable::EMPTY_TAG_UNION), + }; + + let (it, ext) = roc_types::types::gather_tags_unsorted_iter( + subs, + UnionTags::default(), + temp_ext, + ) + .expect("extension var could not be seen as a tag union"); + + for _ in it { + unreachable!("we assert that the ext var is empty; otherwise we'd already know it was a tag union!"); + } + + let tag_names = SubsSlice::extend_new(&mut subs.tag_names, [tag_name]); + let symbols = SubsSlice::extend_new(&mut subs.symbol_names, [symbol]); + + let content = + Content::Structure(FlatType::FunctionOrTagUnion(tag_names, symbols, ext)); + + register_with_known_var(subs, destination, rank, pools, content) + } + RecursiveTagUnion(rec_var, tags, ext_openness) => { + let ext_slice = types.get_type_arguments(typ_index); + + // An empty tags is inefficient (but would be correct) + // If hit, try to turn the value into an EmptyTagUnion in canonicalization + debug_assert!(!tags.is_empty() || !ext_slice.is_empty()); + + let (union_tags, ext) = type_to_union_tags( + subs, + rank, + pools, + arena, + types, + tags, + ext_slice, + ext_openness, + &mut stack, + ); + let content = + Content::Structure(FlatType::RecursiveTagUnion(rec_var, union_tags, ext)); + + let tag_union_var = destination; + register_with_known_var(subs, tag_union_var, rank, pools, content); + + register_with_known_var( + subs, + rec_var, + rank, + pools, + Content::RecursionVar { + opt_name: None, + structure: tag_union_var, + }, + ); + + tag_union_var + } + + DelayedAlias { shared } => { + let AliasShared { + symbol, + type_argument_abilities, + type_argument_regions, + lambda_set_variables, + infer_ext_in_output_variables, + } = types[shared]; + + let type_arguments = types.get_type_arguments(typ_index); + + let alias_variables = { + let all_vars_length = type_arguments.len() + + lambda_set_variables.len() + + infer_ext_in_output_variables.len(); + let new_variables = VariableSubsSlice::reserve_into_subs(subs, all_vars_length); + + let type_arguments_offset = 0; + let lambda_set_vars_offset = type_arguments_offset + type_arguments.len(); + let infer_ext_vars_offset = lambda_set_vars_offset + lambda_set_variables.len(); + + for (((target_index, arg_type), arg_region), abilities) in + (new_variables.indices().skip(type_arguments_offset)) + .zip(type_arguments.into_iter()) + .zip(type_argument_regions.into_iter()) + .zip(type_argument_abilities.into_iter()) + { + let copy_var = helper!(arg_type); + subs.variables[target_index] = copy_var; + if !types[abilities].is_empty() { + let arg_region = types[arg_region]; + bind_to_abilities.push((Loc::at(arg_region, copy_var), abilities)); + } + } + + let it = (new_variables.indices().skip(lambda_set_vars_offset)) + .zip(lambda_set_variables.into_iter()); + for (target_index, ls) in it { + // We MUST do this now, otherwise when linking the ambient function during + // instantiation of the real var, there will be nothing to link against. + let copy_var = type_to_var_help( + subs, + rank, + pools, + problems, + abilities_store, + obligation_cache, + arena, + aliases, + types, + ls, + true, + ); + subs.variables[target_index] = copy_var; + } + + let it = (new_variables.indices().skip(infer_ext_vars_offset)) + .zip(infer_ext_in_output_variables.into_iter()); + for (target_index, ext_typ) in it { + let copy_var = helper!(ext_typ); + subs.variables[target_index] = copy_var; + } + + AliasVariables { + variables_start: new_variables.start, + type_variables_len: type_arguments.len() as _, + lambda_set_variables_len: lambda_set_variables.len() as _, + all_variables_len: all_vars_length as _, + } + }; + + let (alias_variable, kind) = aliases.instantiate_real_var( + subs, + rank, + pools, + problems, + abilities_store, + obligation_cache, + arena, + types, + symbol, + alias_variables, + ); + + let content = Content::Alias(symbol, alias_variables, alias_variable, kind); + + register_with_known_var(subs, destination, rank, pools, content) + } + + StructuralAlias { shared, actual } | OpaqueAlias { shared, actual } => { + let kind = match typ { + StructuralAlias { .. } => AliasKind::Structural, + OpaqueAlias { .. } => AliasKind::Opaque, + _ => internal_error!(), + }; + + let AliasShared { + symbol, + type_argument_abilities, + type_argument_regions, + lambda_set_variables, + infer_ext_in_output_variables, + } = types[shared]; + + debug_assert!(roc_types::subs::Variable::get_reserved(symbol).is_none()); + + let type_arguments = types.get_type_arguments(typ_index); + + let alias_variables = { + let all_vars_length = type_arguments.len() + + lambda_set_variables.len() + + infer_ext_in_output_variables.len(); + + let type_arguments_offset = 0; + let lambda_set_vars_offset = type_arguments_offset + type_arguments.len(); + let infer_ext_vars_offset = lambda_set_vars_offset + lambda_set_variables.len(); + + let new_variables = VariableSubsSlice::reserve_into_subs(subs, all_vars_length); + + for (((target_index, typ), region), abilities) in + (new_variables.indices().skip(type_arguments_offset)) + .zip(type_arguments.into_iter()) + .zip(type_argument_regions.into_iter()) + .zip(type_argument_abilities.into_iter()) + { + let copy_var = helper!(typ); + subs.variables[target_index] = copy_var; + if !types[abilities].is_empty() { + let region = types[region]; + bind_to_abilities.push((Loc::at(region, copy_var), abilities)); + } + } + + let it = (new_variables.indices().skip(lambda_set_vars_offset)) + .zip(lambda_set_variables.into_iter()); + for (target_index, ls) in it { + let copy_var = helper!(ls); + subs.variables[target_index] = copy_var; + } + + let it = (new_variables.indices().skip(infer_ext_vars_offset)) + .zip(infer_ext_in_output_variables.into_iter()); + for (target_index, ext_typ) in it { + let copy_var = helper!(ext_typ); + subs.variables[target_index] = copy_var; + } + + AliasVariables { + variables_start: new_variables.start, + type_variables_len: type_arguments.len() as _, + lambda_set_variables_len: lambda_set_variables.len() as _, + all_variables_len: all_vars_length as _, + } + }; + + let alias_variable = if let Symbol::RESULT_RESULT = symbol { + roc_result_to_var(subs, rank, pools, arena, types, actual, &mut stack) + } else { + helper!(actual) + }; + let content = Content::Alias(symbol, alias_variables, alias_variable, kind); + + register_with_known_var(subs, destination, rank, pools, content) + } + HostExposedAlias { + shared, + actual_type: alias_type, + actual_variable: actual_var, + } => { + let AliasShared { + symbol, + type_argument_abilities: _, + type_argument_regions: _, + lambda_set_variables, + infer_ext_in_output_variables: _, // TODO + } = types[shared]; + + let type_arguments = types.get_type_arguments(typ_index); + + let alias_variables = { + let length = type_arguments.len() + lambda_set_variables.len(); + let new_variables = VariableSubsSlice::reserve_into_subs(subs, length); + + for (target_index, arg_type) in + (new_variables.indices()).zip(type_arguments.into_iter()) + { + let copy_var = helper!(arg_type); + subs.variables[target_index] = copy_var; + } + let it = (new_variables.indices().skip(type_arguments.len())) + .zip(lambda_set_variables.into_iter()); + for (target_index, ls) in it { + // We MUST do this now, otherwise when linking the ambient function during + // instantiation of the real var, there will be nothing to link against. + let copy_var = type_to_var_help( + subs, + rank, + pools, + problems, + abilities_store, + obligation_cache, + arena, + aliases, + types, + ls, + true, + ); + subs.variables[target_index] = copy_var; + } + + AliasVariables { + variables_start: new_variables.start, + type_variables_len: type_arguments.len() as _, + lambda_set_variables_len: lambda_set_variables.len() as _, + all_variables_len: length as _, + } + }; + + // cannot use helper! here because this variable may be involved in unification below + let alias_variable = type_to_var_help( + subs, + rank, + pools, + problems, + abilities_store, + obligation_cache, + arena, + aliases, + types, + alias_type, + false, + ); + // TODO(opaques): I think host-exposed aliases should always be structural + // (when does it make sense to give a host an opaque type?) + let content = Content::Alias( + symbol, + alias_variables, + alias_variable, + AliasKind::Structural, + ); + let result = register_with_known_var(subs, destination, rank, pools, content); + + // We only want to unify the actual_var with the alias once + // if it's already redirected (and therefore, redundant) + // don't do it again + if !subs.redundant(actual_var) { + let descriptor = subs.get(result); + subs.union(result, actual_var, descriptor); + } + + result + } + Error => { + let content = Content::Error; + + register_with_known_var(subs, destination, rank, pools, content) + } + }; + } + + for (Loc { value: var, region }, abilities) in bind_to_abilities { + let abilities = &types[abilities]; + match *subs.get_content_unchecked(var) { + Content::RigidVar(a) => { + // TODO(multi-abilities): check run cache + let abilities_slice = + SubsSlice::extend_new(&mut subs.symbol_names, abilities.sorted_iter().copied()); + subs.set_content(var, Content::RigidAbleVar(a, abilities_slice)); + } + Content::RigidAbleVar(_, abs) + if (subs.get_subs_slice(abs).iter()).eq(abilities.sorted_iter()) => + { + // pass, already bound + } + _ => { + let abilities_slice = + SubsSlice::extend_new(&mut subs.symbol_names, abilities.sorted_iter().copied()); + + let flex_ability = register( + subs, + rank, + pools, + Content::FlexAbleVar(None, abilities_slice), + ); + + let category = Category::OpaqueArg; + match unify( + &mut UEnv::new(subs), + var, + flex_ability, + Mode::EQ, + Polarity::OF_VALUE, + ) { + Unified::Success { + vars: _, + must_implement_ability, + lambda_sets_to_specialize, + extra_metadata: _, + } => { + // No introduction needed + + if !must_implement_ability.is_empty() { + let new_problems = obligation_cache.check_obligations( + subs, + abilities_store, + must_implement_ability, + AbilityImplError::BadExpr(region, category, flex_ability), + ); + problems.extend(new_problems); + } + debug_assert!(lambda_sets_to_specialize + .drain() + .all(|(_, vals)| vals.is_empty())); + } + Unified::Failure(_vars, actual_type, expected_type, _bad_impls) => { + // No introduction needed + + let problem = TypeError::BadExpr( + region, + category, + actual_type, + Expected::NoExpectation(expected_type), + ); + + problems.push(problem); + } + } + } + } + } + + result +} + +#[inline(always)] +fn roc_result_to_var( + subs: &mut Subs, + rank: Rank, + pools: &mut Pools, + arena: &'_ bumpalo::Bump, + types: &mut Types, + result_type: Index, + stack: &mut bumpalo::collections::Vec<'_, TypeToVar>, +) -> Variable { + match types[result_type] { + TypeTag::TagUnion(tags, _ext_openness) => { + let ext_slice = types.get_type_arguments(result_type); + + debug_assert!(ext_slice.is_empty()); + debug_assert!(tags.len() == 2); + + let (tags_slice, payload_slices_slice) = types.union_tag_slices(tags); + + if let ([err, ok], [err_args, ok_args]) = + (&types[tags_slice], &types[payload_slices_slice]) + { + debug_assert_eq!(err, &subs.tag_names[0]); + debug_assert_eq!(ok, &subs.tag_names[1]); + + debug_assert_eq!(err_args.len(), 1); + debug_assert_eq!(ok_args.len(), 1); + + if let (Some(err_type), Some(ok_type)) = + (err_args.into_iter().next(), ok_args.into_iter().next()) + { + let err_var = RegisterVariable::with_stack( + subs, rank, pools, arena, types, err_type, stack, + ); + let ok_var = RegisterVariable::with_stack( + subs, rank, pools, arena, types, ok_type, stack, + ); + + let start = subs.variables.len() as u32; + let err_slice = SubsSlice::new(start, 1); + let ok_slice = SubsSlice::new(start + 1, 1); + + subs.variables.push(err_var); + subs.variables.push(ok_var); + + let variables = SubsSlice::new(subs.variable_slices.len() as _, 2); + subs.variable_slices.push(err_slice); + subs.variable_slices.push(ok_slice); + + let union_tags = UnionTags::from_slices(Subs::RESULT_TAG_NAMES, variables); + let ext = TagExt::Any(Variable::EMPTY_TAG_UNION); + + let content = Content::Structure(FlatType::TagUnion(union_tags, ext)); + + return register(subs, rank, pools, content); + } + } + + unreachable!("invalid arguments to Result.Result; canonicalization should catch this!") + } + _ => unreachable!("not a valid type inside a Result.Result alias"), + } +} + +fn insertion_sort_by(arr: &mut [T], mut compare: F) +where + F: FnMut(&T, &T) -> std::cmp::Ordering, +{ + for i in 1..arr.len() { + let val = &arr[i]; + let mut j = i; + let pos = arr[..i] + .binary_search_by(|x| compare(x, val)) + .unwrap_or_else(|pos| pos); + // Swap all elements until specific position. + while j > pos { + arr.swap(j - 1, j); + j -= 1; + } + } +} + +fn sorted_no_duplicate_tags(tag_slices: &[TagName]) -> bool { + match tag_slices.split_first() { + None => true, + Some((first, rest)) => { + let mut current = first; + + for next in rest { + if current >= next { + return false; + } else { + current = next; + } + } + + true + } + } +} + +fn sort_and_deduplicate(tag_vars: &mut bumpalo::collections::Vec<(TagName, T)>) { + insertion_sort_by(tag_vars, |(a, _), (b, _)| a.cmp(b)); + + // deduplicate, keeping the right-most occurrence of a tag name + let mut i = 0; + + while i < tag_vars.len() { + match (tag_vars.get(i), tag_vars.get(i + 1)) { + (Some((t1, _)), Some((t2, _))) => { + if t1 == t2 { + tag_vars.remove(i); + } else { + i += 1; + } + } + _ => break, + } + } +} + +/// Find whether the current run of tag names is in the subs.tag_names array already. If so, +/// we take a SubsSlice to the existing tag names, so we don't have to add/clone those tag names +/// and keep subs memory consumption low +fn find_tag_name_run(slice: &[TagName], subs: &mut Subs) -> Option> { + use std::cmp::Ordering; + + let tag_name = slice.get(0)?; + + let mut result = None; + + // the `SubsSlice` that inserting `slice` into subs would give + let bigger_slice = SubsSlice::new(subs.tag_names.len() as _, slice.len() as _); + + match subs.tag_name_cache.get_mut(tag_name) { + Some(occupied) => { + let subs_slice = *occupied; + + let prefix_slice = SubsSlice::new(subs_slice.start, slice.len() as _); + + if slice.len() == 1 { + return Some(prefix_slice); + } + + match slice.len().cmp(&subs_slice.len()) { + Ordering::Less => { + // we might have a prefix + let tag_names = &subs.tag_names[subs_slice.start as usize..]; + + for (from_subs, from_slice) in tag_names.iter().zip(slice.iter()) { + if from_subs != from_slice { + return None; + } + } + + result = Some(prefix_slice); + } + Ordering::Equal => { + let tag_names = &subs.tag_names[subs_slice.indices()]; + + for (from_subs, from_slice) in tag_names.iter().zip(slice.iter()) { + if from_subs != from_slice { + return None; + } + } + + result = Some(subs_slice); + } + Ordering::Greater => { + // switch to the bigger slice that is not inserted yet, but will be soon + *occupied = bigger_slice; + } + } + } + None => { + subs.tag_name_cache.push(tag_name, bigger_slice); + } + } + + result +} + +#[inline(always)] +fn register_tag_arguments( + subs: &mut Subs, + rank: Rank, + pools: &mut Pools, + arena: &'_ bumpalo::Bump, + types: &mut Types, + stack: &mut bumpalo::collections::Vec<'_, TypeToVar>, + arguments: Slice, +) -> VariableSubsSlice { + if arguments.is_empty() { + VariableSubsSlice::default() + } else { + let new_variables = VariableSubsSlice::reserve_into_subs(subs, arguments.len()); + let it = new_variables.indices().zip(arguments.into_iter()); + + for (target_index, argument) in it { + let var = + RegisterVariable::with_stack(subs, rank, pools, arena, types, argument, stack); + subs.variables[target_index] = var; + } + + new_variables + } +} + +/// Assumes that the tags are sorted and there are no duplicates! +fn insert_tags_fast_path( + subs: &mut Subs, + rank: Rank, + pools: &mut Pools, + arena: &'_ bumpalo::Bump, + types: &mut Types, + union_tags: UnionTags, + stack: &mut bumpalo::collections::Vec<'_, TypeToVar>, +) -> UnionTags { + let (tags, payload_slices) = types.union_tag_slices(union_tags); + + debug_assert_eq!(tags.len(), payload_slices.len()); + + if let [arguments_slice] = &types[payload_slices] { + let arguments_slice = *arguments_slice; + + let variable_slice = + register_tag_arguments(subs, rank, pools, arena, types, stack, arguments_slice); + + let new_variable_slices = + SubsSlice::extend_new(&mut subs.variable_slices, [variable_slice]); + + macro_rules! subs_tag_name { + ($tag_name_slice:expr) => { + return UnionTags::from_slices($tag_name_slice, new_variable_slices) + }; + } + + match types[tags][0].0.as_str() { + "Ok" => subs_tag_name!(Subs::TAG_NAME_OK.as_slice()), + "Err" => subs_tag_name!(Subs::TAG_NAME_ERR.as_slice()), + "InvalidNumStr" => subs_tag_name!(Subs::TAG_NAME_INVALID_NUM_STR.as_slice()), + "BadUtf8" => subs_tag_name!(Subs::TAG_NAME_BAD_UTF_8.as_slice()), + "OutOfBounds" => subs_tag_name!(Subs::TAG_NAME_OUT_OF_BOUNDS.as_slice()), + _other => {} + } + } + + let new_variable_slices = SubsSlice::reserve_variable_slices(subs, tags.len()); + match find_tag_name_run(&types[tags], subs) { + Some(new_tag_names) => { + let it = (new_variable_slices.indices()).zip(payload_slices.into_iter()); + + for (variable_slice_index, arguments_index) in it { + let arguments = types[arguments_index]; + subs.variable_slices[variable_slice_index] = + register_tag_arguments(subs, rank, pools, arena, types, stack, arguments); + } + + UnionTags::from_slices(new_tag_names, new_variable_slices) + } + None => { + let new_tag_names = SubsSlice::reserve_tag_names(subs, tags.len()); + + let it = (new_variable_slices.indices()) + .zip(new_tag_names.indices()) + .zip(tags.into_iter()) + .zip(payload_slices.into_iter()); + + for (((variable_slice_index, tag_name_index), tag_name), arguments_index) in it { + let arguments = types[arguments_index]; + subs.variable_slices[variable_slice_index] = + register_tag_arguments(subs, rank, pools, arena, types, stack, arguments); + + subs.tag_names[tag_name_index] = types[tag_name].clone(); + } + + UnionTags::from_slices(new_tag_names, new_variable_slices) + } + } +} + +fn insert_tags_slow_path( + subs: &mut Subs, + rank: Rank, + pools: &mut Pools, + arena: &'_ bumpalo::Bump, + types: &mut Types, + union_tags: UnionTags, + mut tag_vars: bumpalo::collections::Vec<(TagName, VariableSubsSlice)>, + stack: &mut bumpalo::collections::Vec<'_, TypeToVar>, +) -> UnionTags { + let (tags, payload_slices) = types.union_tag_slices(union_tags); + + for (tag_index, tag_argument_types_index) in (tags.into_iter()).zip(payload_slices.into_iter()) + { + let tag_argument_types = &types[tag_argument_types_index]; + + let new_slice = VariableSubsSlice::reserve_into_subs(subs, tag_argument_types.len()); + + for (i, arg) in (new_slice.indices()).zip(tag_argument_types.into_iter()) { + let var = RegisterVariable::with_stack(subs, rank, pools, arena, types, arg, stack); + subs.variables[i] = var; + } + + tag_vars.push((types[tag_index].clone(), new_slice)); + } + + sort_and_deduplicate(&mut tag_vars); + + UnionTags::insert_slices_into_subs(subs, tag_vars) +} + +fn type_to_union_tags( + subs: &mut Subs, + rank: Rank, + pools: &mut Pools, + arena: &'_ bumpalo::Bump, + types: &mut Types, + union_tags: UnionTags, + opt_ext_slice: Slice, + ext_openness: ExtImplicitOpenness, + stack: &mut bumpalo::collections::Vec<'_, TypeToVar>, +) -> (UnionTags, TagExt) { + use bumpalo::collections::Vec; + + let (tags, _) = types.union_tag_slices(union_tags); + + let sorted = tags.len() == 1 || sorted_no_duplicate_tags(&types[tags]); + + debug_assert!(opt_ext_slice.len() <= 1); + + match opt_ext_slice.into_iter().next() { + None => { + let ext = Variable::EMPTY_TAG_UNION; + + let union_tags = if sorted { + insert_tags_fast_path(subs, rank, pools, arena, types, union_tags, stack) + } else { + let tag_vars = Vec::with_capacity_in(tags.len(), arena); + insert_tags_slow_path(subs, rank, pools, arena, types, union_tags, tag_vars, stack) + }; + + (union_tags, TagExt::Any(ext)) + } + Some(ext) => { + let mut tag_vars = Vec::with_capacity_in(tags.len(), arena); + + let temp_ext = { + let temp_ext_var = + RegisterVariable::with_stack(subs, rank, pools, arena, types, ext, stack); + TagExt::from_can(temp_ext_var, ext_openness) + }; + let (it, ext) = + roc_types::types::gather_tags_unsorted_iter(subs, UnionTags::default(), temp_ext) + .expect("extension var could not be seen as tag union"); + + tag_vars.extend(it.map(|(n, v)| (n.clone(), v))); + + let union_tags = if tag_vars.is_empty() && sorted { + insert_tags_fast_path(subs, rank, pools, arena, types, union_tags, stack) + } else { + insert_tags_slow_path(subs, rank, pools, arena, types, union_tags, tag_vars, stack) + }; + + (union_tags, ext) + } + } +} + +fn create_union_lambda( + subs: &mut Subs, + rank: Rank, + pools: &mut Pools, + arena: &'_ bumpalo::Bump, + types: &mut Types, + closure: Symbol, + capture_types: Slice, + stack: &mut bumpalo::collections::Vec<'_, TypeToVar>, +) -> UnionLambdas { + let variable_slice = + register_tag_arguments(subs, rank, pools, arena, types, stack, capture_types); + let new_variable_slices = SubsSlice::extend_new(&mut subs.variable_slices, [variable_slice]); + + let lambda_name_slice = SubsSlice::extend_new(&mut subs.symbol_names, [closure]); + + UnionLambdas::from_slices(lambda_name_slice, new_variable_slices) +} From 4f7f66d695578f7aff67591ba1e8dd378b580e62 Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Thu, 22 Jun 2023 12:10:40 -0500 Subject: [PATCH 011/140] Reorder --- crates/compiler/solve/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/compiler/solve/src/lib.rs b/crates/compiler/solve/src/lib.rs index b7e9edb737e..6012d722838 100644 --- a/crates/compiler/solve/src/lib.rs +++ b/crates/compiler/solve/src/lib.rs @@ -10,8 +10,9 @@ pub mod solve; pub mod specialize; mod aliases; -pub use aliases::Aliases; mod deep_copy; mod pools; -pub use pools::Pools; mod to_var; + +pub use aliases::Aliases; +pub use pools::Pools; From b5ea2c2c99f6ca85fa9cd714317cf2de0dfe2449 Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Thu, 22 Jun 2023 12:13:02 -0500 Subject: [PATCH 012/140] s/SolveCtx/SolveConfig/g --- crates/compiler/load_internal/src/file.rs | 6 +++--- crates/compiler/solve/src/module.rs | 13 +++++++++---- crates/compiler/solve/src/solve.rs | 12 ++++++------ 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index 20f9f19ee87..532802d9d91 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -56,7 +56,7 @@ use roc_region::all::{LineInfo, Loc, Region}; #[cfg(not(target_family = "wasm"))] use roc_reporting::report::to_https_problem_report_string; use roc_reporting::report::{to_file_problem_report_string, Palette, RenderTarget}; -use roc_solve::module::{extract_module_owned_implementations, SolveCtx, Solved, SolvedModule}; +use roc_solve::module::{extract_module_owned_implementations, SolveConfig, Solved, SolvedModule}; use roc_solve_problem::TypeError; use roc_target::TargetInfo; use roc_types::subs::{CopiedImport, ExposedTypesStorageSubs, Subs, VarStore, Variable}; @@ -5121,7 +5121,7 @@ fn run_solve_solve( let (solve_output, solved_implementations, exposed_vars_by_symbol) = { let module_id = module.module_id; - let solve_ctx = SolveCtx { + let solve_config = SolveConfig { home: module_id, types, constraints: &constraints, @@ -5132,7 +5132,7 @@ fn run_solve_solve( }; let solve_output = roc_solve::module::run_solve( - solve_ctx, + solve_config, rigid_variables, subs, solve_aliases, diff --git a/crates/compiler/solve/src/module.rs b/crates/compiler/solve/src/module.rs index 86f70a1b28e..628fabd6d35 100644 --- a/crates/compiler/solve/src/module.rs +++ b/crates/compiler/solve/src/module.rs @@ -53,7 +53,7 @@ pub struct SolvedModule { pub exposed_types: ExposedTypesStorageSubs, } -pub struct SolveCtx<'a> { +pub struct SolveConfig<'a> { /// The module we are solving. pub home: ModuleId, pub constraints: &'a Constraints, @@ -82,7 +82,7 @@ pub struct SolveOutput { } pub fn run_solve( - ctx: SolveCtx<'_>, + config: SolveConfig<'_>, rigid_variables: RigidVariables, mut subs: Subs, mut aliases: Aliases, @@ -105,8 +105,13 @@ pub fn run_solve( let mut problems = Vec::new(); // Run the solver to populate Subs. - let (solved_subs, solved_scope) = - solve::run(ctx, &mut problems, subs, &mut aliases, &mut abilities_store); + let (solved_subs, solved_scope) = solve::run( + config, + &mut problems, + subs, + &mut aliases, + &mut abilities_store, + ); SolveOutput { subs: solved_subs, diff --git a/crates/compiler/solve/src/solve.rs b/crates/compiler/solve/src/solve.rs index 7e21a64d486..47f9489b681 100644 --- a/crates/compiler/solve/src/solve.rs +++ b/crates/compiler/solve/src/solve.rs @@ -5,7 +5,7 @@ use crate::ability::{ CheckedDerives, ObligationCache, PendingDerivesTable, Resolved, }; use crate::deep_copy::deep_copy_var_in; -use crate::module::{SolveCtx, Solved}; +use crate::module::{SolveConfig, Solved}; use crate::pools::Pools; use crate::specialize::{ compact_lambda_sets_of_vars, AwaitingSpecializations, CompactionResult, DerivedEnv, SolvePhase, @@ -95,13 +95,13 @@ struct State { } pub fn run( - ctx: SolveCtx, + config: SolveConfig, problems: &mut Vec, mut subs: Subs, aliases: &mut Aliases, abilities_store: &mut AbilitiesStore, ) -> (Solved, Scope) { - let env = run_in_place(ctx, problems, &mut subs, aliases, abilities_store); + let env = run_in_place(config, problems, &mut subs, aliases, abilities_store); (Solved(subs), env) } @@ -109,13 +109,13 @@ pub fn run( /// Modify an existing subs in-place instead #[allow(clippy::too_many_arguments)] // TODO: put params in a context/env var fn run_in_place( - ctx: SolveCtx, + config: SolveConfig, problems: &mut Vec, subs: &mut Subs, aliases: &mut Aliases, abilities_store: &mut AbilitiesStore, ) -> Scope { - let SolveCtx { + let SolveConfig { home: _, constraints, root_constraint, @@ -123,7 +123,7 @@ fn run_in_place( pending_derives, exposed_by_module, derived_module, - } = ctx; + } = config; let mut pools = Pools::default(); From ad20a2ee41e476236fae3f9b008608a301b68d6f Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Thu, 22 Jun 2023 14:06:55 -0500 Subject: [PATCH 013/140] Shove more into a common env --- crates/compiler/can/src/constraint.rs | 20 + crates/compiler/late_solve/src/lib.rs | 40 +- crates/compiler/solve/src/ability.rs | 16 +- crates/compiler/solve/src/aliases.rs | 64 ++- crates/compiler/solve/src/deep_copy.rs | 20 +- crates/compiler/solve/src/env.rs | 75 ++++ crates/compiler/solve/src/lib.rs | 2 + crates/compiler/solve/src/solve.rs | 559 +++++++++--------------- crates/compiler/solve/src/specialize.rs | 107 +++-- crates/compiler/solve/src/to_var.rs | 287 ++++++------ 10 files changed, 566 insertions(+), 624 deletions(-) create mode 100644 crates/compiler/solve/src/env.rs diff --git a/crates/compiler/can/src/constraint.rs b/crates/compiler/can/src/constraint.rs index e22cb2fe453..4e9fc1a4c0d 100644 --- a/crates/compiler/can/src/constraint.rs +++ b/crates/compiler/can/src/constraint.rs @@ -64,6 +64,26 @@ pub type PExpectedTypeIndex = Index>; pub type TypeOrVar = EitherIndex; impl Constraints { + pub fn empty() -> Self { + Self { + constraints: Default::default(), + type_slices: Default::default(), + variables: Default::default(), + loc_symbols: Default::default(), + let_constraints: Default::default(), + categories: Default::default(), + pattern_categories: Default::default(), + expectations: Default::default(), + pattern_expectations: Default::default(), + includes_tags: Default::default(), + strings: Default::default(), + sketched_rows: Default::default(), + eq: Default::default(), + pattern_eq: Default::default(), + cycles: Default::default(), + } + } + pub fn new() -> Self { let constraints = Vec::new(); let type_slices = Vec::with_capacity(16); diff --git a/crates/compiler/late_solve/src/lib.rs b/crates/compiler/late_solve/src/lib.rs index 7189bc7a7e5..96afef7d067 100644 --- a/crates/compiler/late_solve/src/lib.rs +++ b/crates/compiler/late_solve/src/lib.rs @@ -5,6 +5,7 @@ use std::sync::{Arc, RwLock}; use bumpalo::Bump; use roc_can::abilities::AbilitiesStore; +use roc_can::constraint::Constraints; use roc_can::module::ExposedByModule; use roc_collections::MutMap; use roc_derive::SharedDerivedModule; @@ -12,13 +13,14 @@ use roc_error_macros::internal_error; use roc_module::symbol::ModuleId; use roc_module::symbol::Symbol; use roc_solve::ability::AbilityResolver; -use roc_solve::specialize::{compact_lambda_sets_of_vars, DerivedEnv, Phase}; +use roc_solve::specialize::{compact_lambda_sets_of_vars, Phase}; use roc_solve::Pools; +use roc_solve::{DerivedEnv, Env}; use roc_types::subs::{get_member_lambda_sets_at_region, Content, FlatType, LambdaSet}; use roc_types::subs::{ExposedTypesStorageSubs, Subs, Variable}; use roc_types::types::Polarity; use roc_unify::unify::MetaCollector; -use roc_unify::unify::{Env, Mode, Unified}; +use roc_unify::unify::{Env as UEnv, Mode, Unified}; pub use roc_solve::ability::{ResolveError, Resolved}; pub use roc_types::subs::instantiate_rigids; @@ -340,6 +342,19 @@ impl MetaCollector for ChangedVariableCollector { } } +std::thread_local! { + static SCRATCHPAD_FOR_OCCURS: std::cell::RefCell> = std::cell::RefCell::new(Some(Constraints::empty())); +} + +fn with_empty_solve_constraints(f: impl FnOnce(&Constraints) -> T) -> T { + SCRATCHPAD_FOR_OCCURS.with(|cell| { + let constr = cell.take().unwrap(); + let result = f(&constr); + cell.replace(Some(constr)); + result + }) +} + /// Unifies two variables and performs lambda set compaction. /// Ranks and other ability demands are disregarded. #[allow(clippy::too_many_arguments)] @@ -359,7 +374,7 @@ pub fn unify( "derived module can only unify its subs in its own context!" ); let unified = roc_unify::unify::unify_with_collector::( - &mut Env::new(subs), + &mut UEnv::new(subs), left, right, Mode::EQ, @@ -381,14 +396,17 @@ pub fn unify( exposed_types: exposed_by_module, }; - let must_implement_constraints = compact_lambda_sets_of_vars( - subs, - &derived_env, - arena, - &mut pools, - lambda_sets_to_specialize, - &late_phase, - ); + let must_implement_constraints = with_empty_solve_constraints(|c| { + let mut env = Env { + constraints: c, + subs, + derived_env: &derived_env, + arena, + pools: &mut pools, + }; + + compact_lambda_sets_of_vars(&mut env, lambda_sets_to_specialize, &late_phase) + }); // At this point we can't do anything with must-implement constraints, since we're no // longer solving. We must assume that they were totally caught during solving. // After we land https://github.com/roc-lang/roc/issues/3207 this concern should totally diff --git a/crates/compiler/solve/src/ability.rs b/crates/compiler/solve/src/ability.rs index 2bc0650ae13..c5ab1f60333 100644 --- a/crates/compiler/solve/src/ability.rs +++ b/crates/compiler/solve/src/ability.rs @@ -18,10 +18,11 @@ use roc_types::subs::{ TupleElems, Variable, }; use roc_types::types::{AliasKind, Category, MemberImpl, PatternCategory, Polarity, Types}; -use roc_unify::unify::{Env, MustImplementConstraints}; +use roc_unify::unify::{Env as UEnv, MustImplementConstraints}; use roc_unify::unify::{MustImplementAbility, Obligated}; -use crate::{aliases::Aliases, pools::Pools, to_var::type_to_var}; +use crate::env::Env; +use crate::{aliases::Aliases, to_var::type_to_var}; #[derive(Debug, Clone)] pub enum AbilityImplError { @@ -55,7 +56,7 @@ pub struct PendingDerivesTable( impl PendingDerivesTable { pub fn new( - subs: &mut Subs, + env: &mut Env, types: &mut Types, aliases: &mut Aliases, pending_derives: PendingDerives, @@ -80,17 +81,16 @@ impl PendingDerivesTable { // Neither rank nor pools should matter here. let typ = types.from_old_type(&typ); let opaque_var = type_to_var( - subs, + env, Rank::toplevel(), problems, abilities_store, obligation_cache, - &mut Pools::default(), types, aliases, typ, ); - let real_var = match subs.get_content_without_compacting(opaque_var) { + let real_var = match env.subs.get_content_without_compacting(opaque_var) { Content::Alias(_, _, real_var, AliasKind::Opaque) => real_var, _ => internal_error!("Non-opaque in derives table"), }; @@ -1283,7 +1283,7 @@ impl DerivableVisitor for DeriveEq { // Of the floating-point types, // only Dec implements Eq. - let mut env = Env::new(subs); + let mut env = UEnv::new(subs); let unified = unify( &mut env, content_var, @@ -1418,7 +1418,7 @@ pub fn resolve_ability_specialization( instantiate_rigids(subs, signature_var); let (_vars, must_implement_ability, _lambda_sets_to_specialize, _meta) = unify( - &mut Env::new(subs), + &mut UEnv::new(subs), specialization_var, signature_var, Mode::EQ, diff --git a/crates/compiler/solve/src/aliases.rs b/crates/compiler/solve/src/aliases.rs index 6dda75e2ebf..ac8aca3b04e 100644 --- a/crates/compiler/solve/src/aliases.rs +++ b/crates/compiler/solve/src/aliases.rs @@ -8,10 +8,8 @@ use roc_types::{ types::{Alias, AliasKind, OptAbleVar, Type, TypeTag, Types}, }; -use crate::ability::ObligationCache; -use crate::pools::Pools; -use crate::solve::register; use crate::to_var::type_to_var_help; +use crate::{ability::ObligationCache, env::Env}; #[derive(Debug, Clone, Copy)] struct DelayedAliasVariables { @@ -123,9 +121,8 @@ impl Aliases { } fn instantiate_result_result( - subs: &mut Subs, + env: &mut Env, rank: Rank, - pools: &mut Pools, alias_variables: AliasVariables, ) -> Variable { let tag_names_slice = Subs::RESULT_TAG_NAMES; @@ -134,51 +131,49 @@ impl Aliases { let ok_slice = SubsSlice::new(alias_variables.variables_start, 1); let variable_slices = - SubsSlice::extend_new(&mut subs.variable_slices, [err_slice, ok_slice]); + SubsSlice::extend_new(&mut env.subs.variable_slices, [err_slice, ok_slice]); let union_tags = UnionTags::from_slices(tag_names_slice, variable_slices); let ext_var = TagExt::Any(Variable::EMPTY_TAG_UNION); let flat_type = FlatType::TagUnion(union_tags, ext_var); let content = Content::Structure(flat_type); - register(subs, rank, pools, content) + env.register(rank, content) } /// Build an alias of the form `Num range := range` fn build_num_opaque( - subs: &mut Subs, + env: &mut Env, rank: Rank, - pools: &mut Pools, symbol: Symbol, range_var: Variable, ) -> Variable { let content = Content::Alias( symbol, - AliasVariables::insert_into_subs(subs, [range_var], [], []), + AliasVariables::insert_into_subs(env.subs, [range_var], [], []), range_var, AliasKind::Opaque, ); - register(subs, rank, pools, content) + env.register(rank, content) } fn instantiate_builtin_aliases_real_var( &mut self, - subs: &mut Subs, + env: &mut Env, rank: Rank, - pools: &mut Pools, symbol: Symbol, alias_variables: AliasVariables, ) -> Option<(Variable, AliasKind)> { match symbol { Symbol::RESULT_RESULT => { - let var = Self::instantiate_result_result(subs, rank, pools, alias_variables); + let var = Self::instantiate_result_result(env, rank, alias_variables); Some((var, AliasKind::Structural)) } Symbol::NUM_NUM | Symbol::NUM_INTEGER | Symbol::NUM_FLOATINGPOINT => { // Num range := range | Integer range := range | FloatingPoint range := range - let range_var = subs.variables[alias_variables.variables_start as usize]; + let range_var = env.subs.variables[alias_variables.variables_start as usize]; Some((range_var, AliasKind::Opaque)) } Symbol::NUM_INT => { @@ -186,16 +181,15 @@ impl Aliases { // // build `Integer range := range` let integer_content_var = Self::build_num_opaque( - subs, + env, rank, - pools, Symbol::NUM_INTEGER, - subs.variables[alias_variables.variables_start as usize], + env.subs.variables[alias_variables.variables_start as usize], ); // build `Num (Integer range) := Integer range` let num_content_var = - Self::build_num_opaque(subs, rank, pools, Symbol::NUM_NUM, integer_content_var); + Self::build_num_opaque(env, rank, Symbol::NUM_NUM, integer_content_var); Some((num_content_var, AliasKind::Structural)) } @@ -204,16 +198,15 @@ impl Aliases { // // build `FloatingPoint range := range` let fpoint_content_var = Self::build_num_opaque( - subs, + env, rank, - pools, Symbol::NUM_FLOATINGPOINT, - subs.variables[alias_variables.variables_start as usize], + env.subs.variables[alias_variables.variables_start as usize], ); // build `Num (FloatingPoint range) := FloatingPoint range` let num_content_var = - Self::build_num_opaque(subs, rank, pools, Symbol::NUM_NUM, fpoint_content_var); + Self::build_num_opaque(env, rank, Symbol::NUM_NUM, fpoint_content_var); Some((num_content_var, AliasKind::Structural)) } @@ -235,9 +228,8 @@ impl Aliases { pub fn instantiate_real_var( &mut self, - subs: &mut Subs, + env: &mut Env, rank: Rank, - pools: &mut Pools, problems: &mut Vec, abilities_store: &AbilitiesStore, obligation_cache: &mut ObligationCache, @@ -247,14 +239,9 @@ impl Aliases { alias_variables: AliasVariables, ) -> (Variable, AliasKind) { // hardcoded instantiations for builtin aliases - if let Some((var, kind)) = Self::instantiate_builtin_aliases_real_var( - self, - subs, - rank, - pools, - symbol, - alias_variables, - ) { + if let Some((var, kind)) = + self.instantiate_builtin_aliases_real_var(env, rank, symbol, alias_variables) + { return (var, kind); } @@ -271,7 +258,7 @@ impl Aliases { let mut substitutions: MutMap<_, _> = Default::default(); let old_type_variables = delayed_variables.type_variables(&mut self.variables); - let new_type_variables = &subs.variables[alias_variables.type_variables().indices()]; + let new_type_variables = &env.subs.variables[alias_variables.type_variables().indices()]; for (old, new) in old_type_variables.iter_mut().zip(new_type_variables) { // if constraint gen duplicated a type these variables could be the same @@ -289,13 +276,13 @@ impl Aliases { .iter_mut() { debug_assert!(opt_abilities.is_none()); - let new_var = subs.fresh_unnamed_flex_var(); + let new_var = env.subs.fresh_unnamed_flex_var(); substitutions.insert(*rec_var, new_var); } let old_lambda_set_variables = delayed_variables.lambda_set_variables(&mut self.variables); let new_lambda_set_variables = - &subs.variables[alias_variables.lambda_set_variables().indices()]; + &env.subs.variables[alias_variables.lambda_set_variables().indices()]; for (old, new) in old_lambda_set_variables .iter_mut() @@ -310,7 +297,7 @@ impl Aliases { let old_infer_ext_vars = delayed_variables.infer_ext_in_output_variables(&mut self.variables); let new_infer_ext_vars = - &subs.variables[alias_variables.infer_ext_in_output_variables().indices()]; + &env.subs.variables[alias_variables.infer_ext_in_output_variables().indices()]; for (old, new) in old_infer_ext_vars.iter_mut().zip(new_infer_ext_vars) { debug_assert!(old.opt_abilities.is_none()); @@ -326,9 +313,8 @@ impl Aliases { }; let alias_variable = type_to_var_help( - subs, + env, rank, - pools, problems, abilities_store, obligation_cache, diff --git a/crates/compiler/solve/src/deep_copy.rs b/crates/compiler/solve/src/deep_copy.rs index b3c8e7cb81f..58633a79513 100644 --- a/crates/compiler/solve/src/deep_copy.rs +++ b/crates/compiler/solve/src/deep_copy.rs @@ -10,29 +10,23 @@ use roc_types::{ types::{RecordField, Uls}, }; -use crate::pools::Pools; +use crate::env::Env; -pub(crate) fn deep_copy_var_in( - subs: &mut Subs, - rank: Rank, - pools: &mut Pools, - var: Variable, - arena: &Bump, -) -> Variable { +pub(crate) fn deep_copy_var_in(env: &mut Env, rank: Rank, var: Variable, arena: &Bump) -> Variable { let mut visited = bumpalo::collections::Vec::with_capacity_in(256, arena); - let pool = pools.get_mut(rank); + let pool = env.pools.get_mut(rank); - let var = subs.get_root_key(var); - match deep_copy_var_decision(subs, rank, var) { + let var = env.subs.get_root_key(var); + match deep_copy_var_decision(env.subs, rank, var) { ControlFlow::Break(copy) => copy, ControlFlow::Continue(copy) => { - deep_copy_var_help(subs, rank, pool, &mut visited, var, copy); + deep_copy_var_help(env.subs, rank, pool, &mut visited, var, copy); // we have tracked all visited variables, and can now traverse them // in one go (without looking at the UnificationTable) and clear the copy field for var in visited { - subs.set_copy_unchecked(var, OptVariable::NONE); + env.subs.set_copy_unchecked(var, OptVariable::NONE); } copy diff --git a/crates/compiler/solve/src/env.rs b/crates/compiler/solve/src/env.rs new file mode 100644 index 00000000000..8698ae8670e --- /dev/null +++ b/crates/compiler/solve/src/env.rs @@ -0,0 +1,75 @@ +use bumpalo::Bump; +use roc_can::{constraint::Constraints, module::ExposedByModule}; +use roc_derive::SharedDerivedModule; +use roc_types::subs::{Content, Descriptor, Mark, OptVariable, Rank, Subs, Variable}; + +use crate::Pools; + +pub struct DerivedEnv<'a> { + pub derived_module: &'a SharedDerivedModule, + /// Exposed types needed by the derived module. + pub exposed_types: &'a ExposedByModule, +} + +pub struct Env<'a> { + pub arena: &'a Bump, + pub constraints: &'a Constraints, + pub derived_env: &'a DerivedEnv<'a>, + pub subs: &'a mut Subs, + pub pools: &'a mut Pools, +} + +impl<'a> Env<'a> { + #[inline(always)] + pub fn register(&mut self, rank: Rank, content: Content) -> Variable { + let descriptor = Descriptor { + content, + rank, + mark: Mark::NONE, + copy: OptVariable::NONE, + }; + + let var = self.subs.fresh(descriptor); + + self.pools.get_mut(rank).push(var); + + var + } + + /// Introduce some variables to Pools at the given rank. + /// Also, set each of their ranks in Subs to be the given rank. + pub fn introduce(&mut self, rank: Rank, vars: &[Variable]) { + let pool: &mut Vec = self.pools.get_mut(rank); + + for &var in vars.iter() { + self.subs.set_rank(var, rank); + } + + pool.extend(vars); + } + + #[inline(always)] + pub fn register_existing_var(&mut self, var: Variable) { + self.pools.get_mut(self.subs.get_rank(var)).push(var); + } + + pub fn register_with_known_var( + &mut self, + var: Variable, + rank: Rank, + content: Content, + ) -> Variable { + let descriptor = Descriptor { + content, + rank, + mark: Mark::NONE, + copy: OptVariable::NONE, + }; + + self.subs.set(var, descriptor); + + self.pools.get_mut(rank).push(var); + + var + } +} diff --git a/crates/compiler/solve/src/lib.rs b/crates/compiler/solve/src/lib.rs index 6012d722838..292c79d8622 100644 --- a/crates/compiler/solve/src/lib.rs +++ b/crates/compiler/solve/src/lib.rs @@ -11,8 +11,10 @@ pub mod specialize; mod aliases; mod deep_copy; +mod env; mod pools; mod to_var; pub use aliases::Aliases; +pub use env::{DerivedEnv, Env}; pub use pools::Pools; diff --git a/crates/compiler/solve/src/solve.rs b/crates/compiler/solve/src/solve.rs index 47f9489b681..fb890944efe 100644 --- a/crates/compiler/solve/src/solve.rs +++ b/crates/compiler/solve/src/solve.rs @@ -1,14 +1,13 @@ -#![allow(clippy::too_many_arguments)] - use crate::ability::{ resolve_ability_specialization, type_implementing_specialization, AbilityImplError, CheckedDerives, ObligationCache, PendingDerivesTable, Resolved, }; use crate::deep_copy::deep_copy_var_in; +use crate::env::{DerivedEnv, Env}; use crate::module::{SolveConfig, Solved}; use crate::pools::Pools; use crate::specialize::{ - compact_lambda_sets_of_vars, AwaitingSpecializations, CompactionResult, DerivedEnv, SolvePhase, + compact_lambda_sets_of_vars, AwaitingSpecializations, CompactionResult, SolvePhase, }; use crate::to_var::{either_type_index_to_var, type_to_var}; use crate::Aliases; @@ -26,8 +25,8 @@ use roc_problem::can::CycleEntry; use roc_region::all::Loc; use roc_solve_problem::TypeError; use roc_types::subs::{ - self, Content, Descriptor, FlatType, GetSubsSlice, Mark, OptVariable, Rank, Subs, TagExt, - UlsOfVar, Variable, + self, Content, FlatType, GetSubsSlice, Mark, OptVariable, Rank, Subs, TagExt, UlsOfVar, + Variable, }; use roc_types::types::{Category, Polarity, Reason, RecordField, Type, TypeExtension, Types, Uls}; use roc_unify::unify::{ @@ -137,8 +136,21 @@ fn run_in_place( let mut obligation_cache = ObligationCache::default(); let mut awaiting_specializations = AwaitingSpecializations::default(); - let pending_derives = PendingDerivesTable::new( + let derived_env = DerivedEnv { + derived_module: &derived_module, + exposed_types: exposed_by_module, + }; + + let mut env = Env { + arena: &arena, + constraints, + derived_env: &derived_env, subs, + pools: &mut pools, + }; + + let pending_derives = PendingDerivesTable::new( + &mut env, &mut types, aliases, pending_derives, @@ -149,29 +161,16 @@ fn run_in_place( let CheckedDerives { legal_derives: _, problems: derives_problems, - } = obligation_cache.check_derives(subs, abilities_store, pending_derives); + } = obligation_cache.check_derives(env.subs, abilities_store, pending_derives); problems.extend(derives_problems); - let derived_env = DerivedEnv { - derived_module: &derived_module, - exposed_types: exposed_by_module, - }; - - let reified_ctx = ReifiedSolveCtx { - arena: &arena, - constraints, - derived_env: &derived_env, - }; - let state = solve( - reified_ctx, + &mut env, types, state, rank, - &mut pools, problems, aliases, - subs, &root_constraint, abilities_store, &mut obligation_cache, @@ -218,32 +217,18 @@ enum Work<'a> { }, } -struct ReifiedSolveCtx<'a> { - arena: &'a Bump, - constraints: &'a Constraints, - derived_env: &'a DerivedEnv<'a>, -} - fn solve( - ctx: ReifiedSolveCtx, + env: &mut Env, mut can_types: Types, mut state: State, rank: Rank, - pools: &mut Pools, problems: &mut Vec, aliases: &mut Aliases, - subs: &mut Subs, constraint: &Constraint, abilities_store: &mut AbilitiesStore, obligation_cache: &mut ObligationCache, awaiting_specializations: &mut AwaitingSpecializations, ) -> State { - let ReifiedSolveCtx { - arena, - constraints, - derived_env, - } = ctx; - let initial = Work::Constraint { scope: &Scope::default(), rank, @@ -253,57 +238,52 @@ fn solve( let mut stack = vec![initial]; while let Some(work_item) = stack.pop() { - let (env, rank, constraint) = match work_item { + let (scope, rank, constraint) = match work_item { Work::Constraint { - scope: env, + scope, rank, constraint, } => { // the default case; actually solve this constraint - (env, rank, constraint) + (scope, rank, constraint) } Work::CheckForInfiniteTypes(def_vars) => { // after a LetCon, we must check if any of the variables that we introduced // loop back to themselves after solving the ret_constraint for (symbol, loc_var) in def_vars.iter() { - check_for_infinite_type(subs, pools, problems, *symbol, *loc_var); + check_for_infinite_type(env, problems, *symbol, *loc_var); } continue; } Work::LetConNoVariables { - scope: env, + scope, rank, let_con, pool_variables, } => { // NOTE be extremely careful with shadowing here let offset = let_con.defs_and_ret_constraint.index(); - let ret_constraint = &constraints.constraints[offset + 1]; + let ret_constraint = &env.constraints.constraints[offset + 1]; // Add a variable for each def to new_vars_by_env. let local_def_vars = LocalDefVarsVec::from_def_types( - constraints, + env, rank, - pools, problems, abilities_store, obligation_cache, &mut can_types, aliases, - subs, let_con.def_types, ); - pools.get_mut(rank).extend(pool_variables); + env.pools.get_mut(rank).extend(pool_variables); - let mut new_env = env.clone(); + let mut new_scope = scope.clone(); for (symbol, loc_var) in local_def_vars.iter() { check_ability_specialization( - arena, - subs, - derived_env, - pools, + env, rank, abilities_store, obligation_cache, @@ -313,11 +293,11 @@ fn solve( *loc_var, ); - new_env.insert_symbol_var_if_vacant(*symbol, loc_var.value); + new_scope.insert_symbol_var_if_vacant(*symbol, loc_var.value); } stack.push(Work::Constraint { - scope: arena.alloc(new_env), + scope: env.arena.alloc(new_scope), rank, constraint: ret_constraint, }); @@ -327,17 +307,17 @@ fn solve( continue; } Work::LetConIntroducesVariables { - scope: env, + scope, rank, let_con, pool_variables, } => { // NOTE be extremely careful with shadowing here let offset = let_con.defs_and_ret_constraint.index(); - let ret_constraint = &constraints.constraints[offset + 1]; + let ret_constraint = &env.constraints.constraints[offset + 1]; let mark = state.mark; - let saved_env = state.scope; + let saved_scope = state.scope; let young_mark = mark; let visit_mark = young_mark.next(); @@ -351,15 +331,13 @@ fn solve( // Add a variable for each def to local_def_vars. let local_def_vars = LocalDefVarsVec::from_def_types( - constraints, + env, intro_rank, - pools, problems, abilities_store, obligation_cache, &mut can_types, aliases, - subs, let_con.def_types, ); @@ -369,27 +347,28 @@ fn solve( // Otherwise, introduce all variables at the current rank; since none of them will // end up at the next rank, none will be generalized. if let_con.generalizable.0 { - pools.get_mut(rank.next()).extend(pool_variables); + env.pools.get_mut(rank.next()).extend(pool_variables); } else { - pools.get_mut(rank).extend(pool_variables); + env.pools.get_mut(rank).extend(pool_variables); } debug_assert_eq!( // Check that no variable ended up in a higher rank than the next rank.. that // would mean we generalized one level more than we need to! { - let offenders = pools + let offenders = env + .pools .get(rank.next()) .iter() .filter(|var| { - subs.get_rank(**var).into_usize() > rank.next().into_usize() + env.subs.get_rank(**var).into_usize() > rank.next().into_usize() }) .collect::>(); let result = offenders.len(); if result > 0 { - eprintln!("subs = {:?}", &subs); + eprintln!("subs = {:?}", &env.subs); eprintln!("offenders = {:?}", &offenders); eprintln!("let_con.def_types = {:?}", &let_con.def_types); } @@ -403,12 +382,12 @@ fn solve( // next rank. The variables introduced in the let-binding that are still at // that rank (intuitively, they did not "escape" into the lower level // before or after the let-binding) now get to be generalized. - generalize(subs, young_mark, visit_mark, rank.next(), pools); - debug_assert!(pools.get(rank.next()).is_empty(), "variables left over in let-binding scope, but they should all be in a lower scope or generalized now"); + generalize(env, young_mark, visit_mark, rank.next()); + debug_assert!(env.pools.get(rank.next()).is_empty(), "variables left over in let-binding scope, but they should all be in a lower scope or generalized now"); // check that things went well dbg_do!(ROC_VERIFY_RIGID_LET_GENERALIZED, { - let rigid_vars = &constraints.variables[let_con.rigid_vars.indices()]; + let rigid_vars = &env.constraints.variables[let_con.rigid_vars.indices()]; // NOTE the `subs.redundant` check does not come from elm. // It's unclear whether this is a bug with our implementation @@ -417,7 +396,8 @@ fn solve( let mut it = rigid_vars .iter() .filter(|&var| { - !subs.redundant(*var) && subs.get_rank(*var) != Rank::GENERALIZED + !env.subs.redundant(*var) + && env.subs.get_rank(*var) != Rank::GENERALIZED }) .peekable(); @@ -429,13 +409,10 @@ fn solve( } }); - let mut new_env = env.clone(); + let mut new_scope = scope.clone(); for (symbol, loc_var) in local_def_vars.iter() { check_ability_specialization( - arena, - subs, - derived_env, - pools, + env, rank, abilities_store, obligation_cache, @@ -445,20 +422,20 @@ fn solve( *loc_var, ); - new_env.insert_symbol_var_if_vacant(*symbol, loc_var.value); + new_scope.insert_symbol_var_if_vacant(*symbol, loc_var.value); } // Note that this vars_by_symbol is the one returned by the // previous call to solve() let state_for_ret_con = State { - scope: saved_env, + scope: saved_scope, mark: final_mark, }; // Now solve the body, using the new vars_by_symbol which includes // the assignments' name-to-variable mappings. stack.push(Work::Constraint { - scope: arena.alloc(new_env), + scope: env.arena.alloc(new_scope), rank, constraint: ret_constraint, }); @@ -476,17 +453,16 @@ fn solve( SaveTheEnvironment => { let mut copy = state; - copy.scope = env.clone(); + copy.scope = scope.clone(); copy } Eq(roc_can::constraint::Eq(type_index, expectation_index, category_index, region)) => { - let category = &constraints.categories[category_index.index()]; + let category = &env.constraints.categories[category_index.index()]; let actual = either_type_index_to_var( - subs, + env, rank, - pools, problems, abilities_store, obligation_cache, @@ -495,11 +471,10 @@ fn solve( *type_index, ); - let expectation = &constraints.expectations[expectation_index.index()]; + let expectation = &env.constraints.expectations[expectation_index.index()]; let expected = either_type_index_to_var( - subs, + env, rank, - pools, problems, abilities_store, obligation_cache, @@ -509,7 +484,7 @@ fn solve( ); match unify( - &mut UEnv::new(subs), + &mut UEnv::new(env.subs), actual, expected, Mode::EQ, @@ -521,11 +496,11 @@ fn solve( lambda_sets_to_specialize, extra_metadata: _, } => { - introduce(subs, rank, pools, &vars); + env.introduce(rank, &vars); if !must_implement_ability.is_empty() { let new_problems = obligation_cache.check_obligations( - subs, + env.subs, abilities_store, must_implement_ability, AbilityImplError::BadExpr(*region, category.clone(), actual), @@ -533,21 +508,18 @@ fn solve( problems.extend(new_problems); } compact_lambdas_and_check_obligations( - arena, - pools, + env, problems, - subs, abilities_store, obligation_cache, awaiting_specializations, - derived_env, lambda_sets_to_specialize, ); state } Failure(vars, actual_type, expected_type, _bad_impls) => { - introduce(subs, rank, pools, &vars); + env.introduce(rank, &vars); let problem = TypeError::BadExpr( *region, @@ -566,9 +538,8 @@ fn solve( // a special version of Eq that is used to store types in the AST. // IT DOES NOT REPORT ERRORS! let actual = either_type_index_to_var( - subs, + env, rank, - pools, &mut vec![], // don't report any extra errors abilities_store, obligation_cache, @@ -577,12 +548,12 @@ fn solve( *source_index, ); - let actual_desc = subs.get(actual); - subs.union(*target, actual, actual_desc); + let actual_desc = env.subs.get(actual); + env.subs.union(*target, actual, actual_desc); state } Lookup(symbol, expectation_index, region) => { - match env.get_var_by_symbol(symbol) { + match scope.get_var_by_symbol(symbol) { Some(var) => { // Deep copy the vars associated with this symbol before unifying them. // Otherwise, suppose we have this: @@ -605,13 +576,12 @@ fn solve( // then we copy from that module's Subs into our own. If the value // is being looked up in this module, then we use our Subs as both // the source and destination. - let actual = deep_copy_var_in(subs, rank, pools, var, arena); - let expectation = &constraints.expectations[expectation_index.index()]; + let actual = deep_copy_var_in(env, rank, var, env.arena); + let expectation = &env.constraints.expectations[expectation_index.index()]; let expected = either_type_index_to_var( - subs, + env, rank, - pools, problems, abilities_store, obligation_cache, @@ -621,7 +591,7 @@ fn solve( ); match unify( - &mut UEnv::new(subs), + &mut UEnv::new(env.subs), actual, expected, Mode::EQ, @@ -633,11 +603,11 @@ fn solve( lambda_sets_to_specialize, extra_metadata: _, } => { - introduce(subs, rank, pools, &vars); + env.introduce(rank, &vars); if !must_implement_ability.is_empty() { let new_problems = obligation_cache.check_obligations( - subs, + env.subs, abilities_store, must_implement_ability, AbilityImplError::BadExpr( @@ -649,14 +619,11 @@ fn solve( problems.extend(new_problems); } compact_lambdas_and_check_obligations( - arena, - pools, + env, problems, - subs, abilities_store, obligation_cache, awaiting_specializations, - derived_env, lambda_sets_to_specialize, ); @@ -664,7 +631,7 @@ fn solve( } Failure(vars, actual_type, expected_type, _bad_impls) => { - introduce(subs, rank, pools, &vars); + env.introduce(rank, &vars); let problem = TypeError::BadExpr( *region, @@ -687,10 +654,10 @@ fn solve( } } And(slice) => { - let it = constraints.constraints[slice.indices()].iter().rev(); + let it = env.constraints.constraints[slice.indices()].iter().rev(); for sub_constraint in it { stack.push(Work::Constraint { - scope: env, + scope, rank, constraint: sub_constraint, }) @@ -700,12 +667,11 @@ fn solve( } Pattern(type_index, expectation_index, category_index, region) | PatternPresence(type_index, expectation_index, category_index, region) => { - let category = &constraints.pattern_categories[category_index.index()]; + let category = &env.constraints.pattern_categories[category_index.index()]; let actual = either_type_index_to_var( - subs, + env, rank, - pools, problems, abilities_store, obligation_cache, @@ -714,11 +680,10 @@ fn solve( *type_index, ); - let expectation = &constraints.pattern_expectations[expectation_index.index()]; + let expectation = &env.constraints.pattern_expectations[expectation_index.index()]; let expected = either_type_index_to_var( - subs, + env, rank, - pools, problems, abilities_store, obligation_cache, @@ -733,7 +698,7 @@ fn solve( }; match unify( - &mut UEnv::new(subs), + &mut UEnv::new(env.subs), actual, expected, mode, @@ -745,11 +710,11 @@ fn solve( lambda_sets_to_specialize, extra_metadata: _, } => { - introduce(subs, rank, pools, &vars); + env.introduce(rank, &vars); if !must_implement_ability.is_empty() { let new_problems = obligation_cache.check_obligations( - subs, + env.subs, abilities_store, must_implement_ability, AbilityImplError::BadPattern(*region, category.clone(), actual), @@ -757,21 +722,18 @@ fn solve( problems.extend(new_problems); } compact_lambdas_and_check_obligations( - arena, - pools, + env, problems, - subs, abilities_store, obligation_cache, awaiting_specializations, - derived_env, lambda_sets_to_specialize, ); state } Failure(vars, actual_type, expected_type, _bad_impls) => { - introduce(subs, rank, pools, &vars); + env.introduce(rank, &vars); let problem = TypeError::BadPattern( *region, @@ -787,26 +749,26 @@ fn solve( } } Let(index, pool_slice) => { - let let_con = &constraints.let_constraints[index.index()]; + let let_con = &env.constraints.let_constraints[index.index()]; let offset = let_con.defs_and_ret_constraint.index(); - let defs_constraint = &constraints.constraints[offset]; - let ret_constraint = &constraints.constraints[offset + 1]; + let defs_constraint = &env.constraints.constraints[offset]; + let ret_constraint = &env.constraints.constraints[offset + 1]; - let flex_vars = &constraints.variables[let_con.flex_vars.indices()]; - let rigid_vars = &constraints.variables[let_con.rigid_vars.indices()]; + let flex_vars = &env.constraints.variables[let_con.flex_vars.indices()]; + let rigid_vars = &env.constraints.variables[let_con.rigid_vars.indices()]; - let pool_variables = &constraints.variables[pool_slice.indices()]; + let pool_variables = &env.constraints.variables[pool_slice.indices()]; if matches!(&ret_constraint, True) && let_con.rigid_vars.is_empty() { debug_assert!(pool_variables.is_empty()); - introduce(subs, rank, pools, flex_vars); + env.introduce(rank, flex_vars); // If the return expression is guaranteed to solve, // solve the assignments themselves and move on. stack.push(Work::Constraint { - scope: env, + scope, rank, constraint: defs_constraint, }); @@ -819,13 +781,13 @@ fn solve( // Note that the LetConSimple gets the current env and rank, // and not the env/rank from after solving the defs_constraint stack.push(Work::LetConNoVariables { - scope: env, + scope, rank, let_con, pool_variables, }); stack.push(Work::Constraint { - scope: env, + scope, rank, constraint: defs_constraint, }); @@ -842,21 +804,21 @@ fn solve( }; // determine the next pool - if binding_rank.into_usize() < pools.len() { + if binding_rank.into_usize() < env.pools.len() { // Nothing to do, we already accounted for the next rank, no need to // adjust the pools } else { // we should be off by one at this point - debug_assert_eq!(binding_rank.into_usize(), 1 + pools.len()); - pools.extend_to(binding_rank.into_usize()); + debug_assert_eq!(binding_rank.into_usize(), 1 + env.pools.len()); + env.pools.extend_to(binding_rank.into_usize()); } - let pool: &mut Vec = pools.get_mut(binding_rank); + let pool: &mut Vec = env.pools.get_mut(binding_rank); // Introduce the variables of this binding, and extend the pool at our binding // rank. for &var in rigid_vars.iter().chain(flex_vars.iter()) { - subs.set_rank(var, binding_rank); + env.subs.set_rank(var, binding_rank); } pool.reserve(rigid_vars.len() + flex_vars.len()); pool.extend(rigid_vars.iter()); @@ -872,13 +834,13 @@ fn solve( // That's because the defs constraints will be solved in next_rank if it is eligible for generalization. // The LetCon will then generalize variables that are at a higher rank than the rank of the current scope. stack.push(Work::LetConIntroducesVariables { - scope: env, + scope, rank, let_con, pool_variables, }); stack.push(Work::Constraint { - scope: env, + scope, rank: binding_rank, constraint: defs_constraint, }); @@ -888,9 +850,8 @@ fn solve( } IsOpenType(type_index) => { let actual = either_type_index_to_var( - subs, + env, rank, - pools, problems, abilities_store, obligation_cache, @@ -899,12 +860,12 @@ fn solve( *type_index, ); - open_tag_union(subs, pools, actual); + open_tag_union(env, actual); state } IncludesTag(index) => { - let includes_tag = &constraints.includes_tags[index.index()]; + let includes_tag = &env.constraints.includes_tags[index.index()]; let roc_can::constraint::IncludesTag { type_index, @@ -914,12 +875,12 @@ fn solve( region, } = includes_tag; - let pattern_category = &constraints.pattern_categories[pattern_category.index()]; + let pattern_category = + &env.constraints.pattern_categories[pattern_category.index()]; let actual = either_type_index_to_var( - subs, + env, rank, - pools, problems, abilities_store, obligation_cache, @@ -928,7 +889,7 @@ fn solve( *type_index, ); - let payload_types = constraints.variables[types.indices()] + let payload_types = env.constraints.variables[types.indices()] .iter() .map(|v| Type::Variable(*v)) .collect(); @@ -938,19 +899,18 @@ fn solve( TypeExtension::Closed, )); let includes = type_to_var( - subs, + env, rank, problems, abilities_store, obligation_cache, - pools, &mut can_types, aliases, tag_ty, ); match unify( - &mut UEnv::new(subs), + &mut UEnv::new(env.subs), actual, includes, Mode::PRESENT, @@ -962,11 +922,11 @@ fn solve( lambda_sets_to_specialize, extra_metadata: _, } => { - introduce(subs, rank, pools, &vars); + env.introduce(rank, &vars); if !must_implement_ability.is_empty() { let new_problems = obligation_cache.check_obligations( - subs, + env.subs, abilities_store, must_implement_ability, AbilityImplError::BadPattern( @@ -978,21 +938,18 @@ fn solve( problems.extend(new_problems); } compact_lambdas_and_check_obligations( - arena, - pools, + env, problems, - subs, abilities_store, obligation_cache, awaiting_specializations, - derived_env, lambda_sets_to_specialize, ); state } Failure(vars, actual_type, expected_to_include_type, _bad_impls) => { - introduce(subs, rank, pools, &vars); + env.introduce(rank, &vars); let problem = TypeError::BadPattern( *region, @@ -1021,8 +978,8 @@ fn solve( let (real_var, real_region, branches_var, category_and_expected) = match eq { Ok(eq) => { let roc_can::constraint::Eq(real_var, expected, category, real_region) = - constraints.eq[eq.index()]; - let expected = &constraints.expectations[expected.index()]; + env.constraints.eq[eq.index()]; + let expected = &env.constraints.expectations[expected.index()]; ( real_var, @@ -1037,8 +994,8 @@ fn solve( expected, category, real_region, - ) = constraints.pattern_eq[peq.index()]; - let expected = &constraints.pattern_expectations[expected.index()]; + ) = env.constraints.pattern_eq[peq.index()]; + let expected = &env.constraints.pattern_expectations[expected.index()]; ( real_var, @@ -1050,9 +1007,8 @@ fn solve( }; let real_var = either_type_index_to_var( - subs, + env, rank, - pools, problems, abilities_store, obligation_cache, @@ -1062,9 +1018,8 @@ fn solve( ); let branches_var = either_type_index_to_var( - subs, + env, rank, - pools, problems, abilities_store, obligation_cache, @@ -1080,16 +1035,16 @@ fn solve( Polarity::OF_PATTERN }; - let real_content = subs.get_content_without_compacting(real_var); - let branches_content = subs.get_content_without_compacting(branches_var); + let real_content = env.subs.get_content_without_compacting(real_var); + let branches_content = env.subs.get_content_without_compacting(branches_var); let already_have_error = matches!( (real_content, branches_content), (Content::Error, _) | (_, Content::Error) ); - let snapshot = subs.snapshot(); + let snapshot = env.subs.snapshot(); let unify_cond_and_patterns_outcome = unify( - &mut UEnv::new(subs), + &mut UEnv::new(env.subs), branches_var, real_var, Mode::EQ, @@ -1106,25 +1061,22 @@ fn solve( lambda_sets_to_specialize, extra_metadata: _, } => { - subs.commit_snapshot(snapshot); + env.subs.commit_snapshot(snapshot); - introduce(subs, rank, pools, &vars); + env.introduce(rank, &vars); problems.extend(obligation_cache.check_obligations( - subs, + env.subs, abilities_store, must_implement_ability, AbilityImplError::DoesNotImplement, )); compact_lambdas_and_check_obligations( - arena, - pools, + env, problems, - subs, abilities_store, obligation_cache, awaiting_specializations, - derived_env, lambda_sets_to_specialize, ); @@ -1134,15 +1086,15 @@ fn solve( } Failure(..) => { // Rollback and check for almost-equality. - subs.rollback_to(snapshot); + env.subs.rollback_to(snapshot); - let almost_eq_snapshot = subs.snapshot(); + let almost_eq_snapshot = env.subs.snapshot(); // TODO: turn this on for bidirectional exhaustiveness checking // open_tag_union(subs, real_var); - open_tag_union(subs, pools, branches_var); + open_tag_union(env, branches_var); let almost_eq = matches!( unify( - &mut UEnv::new(subs), + &mut UEnv::new(env.subs), real_var, branches_var, Mode::EQ, @@ -1151,7 +1103,7 @@ fn solve( Success { .. } ); - subs.rollback_to(almost_eq_snapshot); + env.subs.rollback_to(almost_eq_snapshot); if almost_eq { // Case 3: almost equal, check exhaustiveness. @@ -1160,21 +1112,22 @@ fn solve( // Case 4: incompatible types, report type error. // Re-run first failed unification to get the type diff. match unify( - &mut UEnv::new(subs), + &mut UEnv::new(env.subs), real_var, branches_var, Mode::EQ, cond_polarity, ) { Failure(vars, actual_type, expected_type, _bad_impls) => { - introduce(subs, rank, pools, &vars); + env.introduce(rank, &vars); // Figure out the problem - it might be pattern or value // related. let problem = match category_and_expected { Ok((category, expected)) => { - let real_category = - constraints.categories[category.index()].clone(); + let real_category = env.constraints.categories + [category.index()] + .clone(); TypeError::BadExpr( real_region, real_category, @@ -1184,7 +1137,7 @@ fn solve( } Err((category, expected)) => { - let real_category = constraints.pattern_categories + let real_category = env.constraints.pattern_categories [category.index()] .clone(); TypeError::BadPattern( @@ -1205,7 +1158,7 @@ fn solve( } } - let sketched_rows = constraints.sketched_rows[sketched_rows.index()].clone(); + let sketched_rows = env.constraints.sketched_rows[sketched_rows.index()].clone(); if should_check_exhaustiveness { use roc_can::exhaustive::{check, ExhaustiveSummary}; @@ -1252,23 +1205,23 @@ fn solve( // TODO: this can likely be removed after remodelling tag extension types // (#4440). if cond_source_is_likely_positive_value && has_unification_error { - close_pattern_matched_tag_unions(subs, real_var); + close_pattern_matched_tag_unions(env.subs, real_var); } if let Ok(ExhaustiveSummary { errors, exhaustive, redundancies, - }) = check(subs, real_var, sketched_rows, context) + }) = check(env.subs, real_var, sketched_rows, context) { // Store information about whether the "when" is exhaustive, and // which (if any) of its branches are redundant. Codegen may use // this for branch-fixing and redundant elimination. if !exhaustive { - exhaustive_mark.set_non_exhaustive(subs); + exhaustive_mark.set_non_exhaustive(env.subs); } for redundant_mark in redundancies { - redundant_mark.set_redundant(subs); + redundant_mark.set_redundant(env.subs); } // Store the errors. @@ -1287,7 +1240,7 @@ fn solve( specialization_id, }) => { if let Ok(Resolved::Specialization(specialization)) = resolve_ability_specialization( - subs, + env.subs, abilities_store, member, specialization_variable, @@ -1301,8 +1254,8 @@ fn solve( let Cycle { def_names, expr_regions, - } = &constraints.cycles[cycle.index()]; - let symbols = &constraints.loc_symbols[def_names.indices()]; + } = &env.constraints.cycles[cycle.index()]; + let symbols = &env.constraints.loc_symbols[def_names.indices()]; // If the type of a symbol is not a function, that's an error. // Roc is strict, so only functions can be mutually recursive. @@ -1310,8 +1263,8 @@ fn solve( use Content::*; symbols.iter().any(|(s, _)| { - let var = env.get_var_by_symbol(s).expect("Symbol not solved!"); - let (_, underlying_content) = chase_alias_content(subs, var); + let var = scope.get_var_by_symbol(s).expect("Symbol not solved!"); + let (_, underlying_content) = chase_alias_content(env.subs, var); !matches!(underlying_content, Error | Structure(FlatType::Func(..))) }) @@ -1320,7 +1273,7 @@ fn solve( if any_is_bad { // expr regions are stored in loc_symbols (that turned out to be convenient). // The symbol is just a dummy, and should not be used - let expr_regions = &constraints.loc_symbols[expr_regions.indices()]; + let expr_regions = &env.constraints.loc_symbols[expr_regions.indices()]; let cycle = symbols .iter() @@ -1334,16 +1287,15 @@ fn solve( problems.push(TypeError::CircularDef(cycle)); - cycle_mark.set_illegal(subs); + cycle_mark.set_illegal(env.subs); } state } IngestedFile(type_index, file_path, bytes) => { let actual = either_type_index_to_var( - subs, + env, rank, - pools, problems, abilities_store, obligation_cache, @@ -1352,21 +1304,21 @@ fn solve( *type_index, ); - let snapshot = subs.snapshot(); + let snapshot = env.subs.snapshot(); if let Success { vars, must_implement_ability, lambda_sets_to_specialize, extra_metadata: _, } = unify( - &mut UEnv::new(subs), + &mut UEnv::new(env.subs), actual, Variable::LIST_U8, Mode::EQ, Polarity::OF_VALUE, ) { // List U8 always valid. - introduce(subs, rank, pools, &vars); + env.introduce(rank, &vars); debug_assert!( must_implement_ability.is_empty() && lambda_sets_to_specialize.is_empty(), @@ -1375,11 +1327,11 @@ fn solve( state } else { - subs.rollback_to(snapshot); + env.subs.rollback_to(snapshot); // We explicitly match on the last unify to get the type in the case it errors. match unify( - &mut UEnv::new(subs), + &mut UEnv::new(env.subs), actual, Variable::STR, Mode::EQ, @@ -1391,7 +1343,7 @@ fn solve( lambda_sets_to_specialize, extra_metadata: _, } => { - introduce(subs, rank, pools, &vars); + env.introduce(rank, &vars); debug_assert!( must_implement_ability.is_empty() && lambda_sets_to_specialize.is_empty(), @@ -1408,7 +1360,7 @@ fn solve( state } Failure(vars, actual_type, _, _) => { - introduce(subs, rank, pools, &vars); + env.introduce(rank, &vars); let problem = TypeError::IngestedFileUnsupportedType( file_path.clone(), @@ -1437,31 +1389,24 @@ fn chase_alias_content(subs: &Subs, mut var: Variable) -> (Variable, &Content) { } } -#[allow(clippy::too_many_arguments)] fn compact_lambdas_and_check_obligations( - arena: &Bump, - pools: &mut Pools, + env: &mut Env, problems: &mut Vec, - subs: &mut Subs, abilities_store: &mut AbilitiesStore, obligation_cache: &mut ObligationCache, awaiting_specialization: &mut AwaitingSpecializations, - derived_env: &DerivedEnv, lambda_sets_to_specialize: UlsOfVar, ) { let CompactionResult { obligations, awaiting_specialization: new_awaiting, } = compact_lambda_sets_of_vars( - subs, - derived_env, - arena, - pools, + env, lambda_sets_to_specialize, &SolvePhase { abilities_store }, ); problems.extend(obligation_cache.check_obligations( - subs, + env.subs, abilities_store, obligations, AbilityImplError::DoesNotImplement, @@ -1469,39 +1414,44 @@ fn compact_lambdas_and_check_obligations( awaiting_specialization.union(new_awaiting); } -fn open_tag_union(subs: &mut Subs, pools: &mut Pools, var: Variable) { +fn open_tag_union(env: &mut Env, var: Variable) { let mut stack = vec![var]; while let Some(var) = stack.pop() { use {Content::*, FlatType::*}; - let desc = subs.get(var); + let desc = env.subs.get(var); match desc.content { Structure(TagUnion(tags, ext)) => { - if let Structure(EmptyTagUnion) = subs.get_content_without_compacting(ext.var()) { - let new_ext_var = register(subs, desc.rank, pools, Content::FlexVar(None)); + if let Structure(EmptyTagUnion) = env.subs.get_content_without_compacting(ext.var()) + { + let new_ext_var = env.register(desc.rank, Content::FlexVar(None)); let new_union = Structure(TagUnion(tags, TagExt::Any(new_ext_var))); - subs.set_content(var, new_union); + env.subs.set_content(var, new_union); } // Also open up all nested tag unions. let all_vars = tags.variables().into_iter(); - stack.extend(all_vars.flat_map(|slice| subs[slice]).map(|var| subs[var])); + stack.extend( + all_vars + .flat_map(|slice| env.subs[slice]) + .map(|var| env.subs[var]), + ); } Structure(Record(fields, _)) => { // Open up all nested tag unions. - stack.extend(subs.get_subs_slice(fields.variables())); + stack.extend(env.subs.get_subs_slice(fields.variables())); } Structure(Tuple(elems, _)) => { // Open up all nested tag unions. - stack.extend(subs.get_subs_slice(elems.variables())); + stack.extend(env.subs.get_subs_slice(elems.variables())); } Structure(Apply(Symbol::LIST_LIST, args)) => { // Open up nested tag unions. - stack.extend(subs.get_subs_slice(args)); + stack.extend(env.subs.get_subs_slice(args)); } _ => { @@ -1593,14 +1543,10 @@ fn close_pattern_matched_tag_unions(subs: &mut Subs, var: Variable) { /// If a symbol claims to specialize an ability member, check that its solved type in fact /// does specialize the ability, and record the specialization. -#[allow(clippy::too_many_arguments)] // Aggressive but necessary - there aren't many usages. #[inline(always)] fn check_ability_specialization( - arena: &Bump, - subs: &mut Subs, - derived_env: &DerivedEnv, - pools: &mut Pools, + env: &mut Env, rank: Rank, abilities_store: &mut AbilitiesStore, obligation_cache: &mut ObligationCache, @@ -1625,10 +1571,10 @@ fn check_ability_specialization( // We need to freshly instantiate the root signature so that all unifications are reflected // in the specialization type, but not the original signature type. let root_signature_var = - deep_copy_var_in(subs, Rank::toplevel(), pools, root_signature_var, arena); - let snapshot = subs.snapshot(); + deep_copy_var_in(env, Rank::toplevel(), root_signature_var, env.arena); + let snapshot = env.subs.snapshot(); let unified = unify_introduced_ability_specialization( - &mut UEnv::new(subs), + &mut UEnv::new(env.subs), root_signature_var, symbol_loc_var.value, Mode::EQ, @@ -1651,8 +1597,8 @@ fn check_ability_specialization( if opaque == impl_key.opaque { // It was! All is good. - subs.commit_snapshot(snapshot); - introduce(subs, rank, pools, &vars); + env.subs.commit_snapshot(snapshot); + env.introduce(rank, &vars); let specialization_lambda_sets = specialization_lambda_sets .into_iter() @@ -1663,14 +1609,11 @@ fn check_ability_specialization( .collect(); compact_lambdas_and_check_obligations( - arena, - pools, + env, problems, - subs, abilities_store, obligation_cache, awaiting_specializations, - derived_env, lambda_sets_to_specialize, ); @@ -1683,10 +1626,11 @@ fn check_ability_specialization( // error. // Commit so that the bad signature and its error persists in subs. - subs.commit_snapshot(snapshot); + env.subs.commit_snapshot(snapshot); - let _typ = - subs.var_to_error_type(symbol_loc_var.value, Polarity::OF_VALUE); + let _typ = env + .subs + .var_to_error_type(symbol_loc_var.value, Polarity::OF_VALUE); let problem = TypeError::WrongSpecialization { region: symbol_loc_var.region, @@ -1704,9 +1648,9 @@ fn check_ability_specialization( // This is a specialization of a structural type - never allowed. // Commit so that `var` persists in subs. - subs.commit_snapshot(snapshot); + env.subs.commit_snapshot(snapshot); - let typ = subs.var_to_error_type(var, Polarity::OF_VALUE); + let typ = env.subs.var_to_error_type(var, Polarity::OF_VALUE); let problem = TypeError::StructuralSpecialization { region: symbol_loc_var.region, @@ -1726,12 +1670,14 @@ fn check_ability_specialization( // Rollback the snapshot so we unlink the root signature with the specialization, // so we can have two separate error types. - subs.rollback_to(snapshot); + env.subs.rollback_to(snapshot); - let expected_type = - subs.var_to_error_type(root_signature_var, Polarity::OF_VALUE); - let actual_type = - subs.var_to_error_type(symbol_loc_var.value, Polarity::OF_VALUE); + let expected_type = env + .subs + .var_to_error_type(root_signature_var, Polarity::OF_VALUE); + let actual_type = env + .subs + .var_to_error_type(symbol_loc_var.value, Polarity::OF_VALUE); let reason = Reason::GeneralizedAbilityMemberSpecialization { member_name: ability_member, @@ -1753,8 +1699,8 @@ fn check_ability_specialization( } Failure(vars, expected_type, actual_type, unimplemented_abilities) => { - subs.commit_snapshot(snapshot); - introduce(subs, rank, pools, &vars); + env.subs.commit_snapshot(snapshot); + env.introduce(rank, &vars); let reason = Reason::InvalidAbilityMemberSpecialization { member_name: ability_member, @@ -1782,16 +1728,13 @@ fn check_ability_specialization( // Get the lambda sets that are ready for specialization because this ability member // specialization was resolved, and compact them. let new_lambda_sets_to_specialize = - awaiting_specializations.remove_for_specialized(subs, impl_key); + awaiting_specializations.remove_for_specialized(env.subs, impl_key); compact_lambdas_and_check_obligations( - arena, - pools, + env, problems, - subs, abilities_store, obligation_cache, awaiting_specializations, - derived_env, new_lambda_sets_to_specialize, ); debug_assert!( @@ -1835,27 +1778,24 @@ impl LocalDefVarsVec { impl LocalDefVarsVec<(Symbol, Loc)> { fn from_def_types( - constraints: &Constraints, + env: &mut Env, rank: Rank, - pools: &mut Pools, problems: &mut Vec, abilities_store: &mut AbilitiesStore, obligation_cache: &mut ObligationCache, types: &mut Types, aliases: &mut Aliases, - subs: &mut Subs, def_types_slice: roc_can::constraint::DefTypes, ) -> Self { - let type_indices_slice = &constraints.type_slices[def_types_slice.types.indices()]; - let loc_symbols_slice = &constraints.loc_symbols[def_types_slice.loc_symbols.indices()]; + let type_indices_slice = &env.constraints.type_slices[def_types_slice.types.indices()]; + let loc_symbols_slice = &env.constraints.loc_symbols[def_types_slice.loc_symbols.indices()]; let mut local_def_vars = Self::with_length(type_indices_slice.len()); for (&(symbol, region), typ_index) in (loc_symbols_slice.iter()).zip(type_indices_slice) { let var = either_type_index_to_var( - subs, + env, rank, - pools, problems, abilities_store, obligation_cache, @@ -1872,22 +1812,21 @@ impl LocalDefVarsVec<(Symbol, Loc)> { } fn check_for_infinite_type( - subs: &mut Subs, - pools: &mut Pools, + env: &mut Env, problems: &mut Vec, symbol: Symbol, loc_var: Loc, ) { let var = loc_var.value; - 'next_occurs_check: while let Err((_, chain)) = subs.occurs(var) { + 'next_occurs_check: while let Err((_, chain)) = env.subs.occurs(var) { // walk the chain till we find a tag union or lambda set, starting from the variable that // occurred recursively, which is always at the end of the chain. for &var in chain.iter().rev() { - match *subs.get_content_without_compacting(var) { + match *env.subs.get_content_without_compacting(var) { Content::Structure(FlatType::TagUnion(tags, ext_var)) => { - let rec_var = subs.mark_tag_union_recursive(var, tags, ext_var); - register_to_pools(subs, rec_var, pools); + let rec_var = env.subs.mark_tag_union_recursive(var, tags, ext_var); + env.register_existing_var(rec_var); continue 'next_occurs_check; } @@ -1897,13 +1836,13 @@ fn check_for_infinite_type( unspecialized, ambient_function: ambient_function_var, }) => { - let rec_var = subs.mark_lambda_set_recursive( + let rec_var = env.subs.mark_lambda_set_recursive( var, solved, unspecialized, ambient_function_var, ); - register_to_pools(subs, rec_var, pools); + env.register_existing_var(rec_var); continue 'next_occurs_check; } @@ -1911,7 +1850,7 @@ fn check_for_infinite_type( } } - circular_error(subs, problems, symbol, &loc_var); + circular_error(env.subs, problems, symbol, &loc_var); } } @@ -1936,13 +1875,10 @@ fn circular_error( /// Ensures that variables introduced at the `young_rank`, but that should be /// stuck at a lower level, are marked at that level and not generalized at the /// present `young_rank`. See [adjust_rank]. -fn generalize( - subs: &mut Subs, - young_mark: Mark, - visit_mark: Mark, - young_rank: Rank, - pools: &mut Pools, -) { +fn generalize(env: &mut Env, young_mark: Mark, visit_mark: Mark, young_rank: Rank) { + let subs = &mut env.subs; + let pools = &mut env.pools; + let young_vars = std::mem::take(pools.get_mut(young_rank)); let rank_table = pool_to_rank_table(subs, young_mark, young_rank, young_vars); @@ -2370,62 +2306,3 @@ fn adjust_rank_content( RangedNumber(_) => group_rank, } } - -/// Introduce some variables to Pools at the given rank. -/// Also, set each of their ranks in Subs to be the given rank. -pub(crate) fn introduce(subs: &mut Subs, rank: Rank, pools: &mut Pools, vars: &[Variable]) { - let pool: &mut Vec = pools.get_mut(rank); - - for &var in vars.iter() { - subs.set_rank(var, rank); - } - - pool.extend(vars); -} - -#[inline(always)] -pub(crate) fn register( - subs: &mut Subs, - rank: Rank, - pools: &mut Pools, - content: Content, -) -> Variable { - let descriptor = Descriptor { - content, - rank, - mark: Mark::NONE, - copy: OptVariable::NONE, - }; - - let var = subs.fresh(descriptor); - - pools.get_mut(rank).push(var); - - var -} - -pub(crate) fn register_with_known_var( - subs: &mut Subs, - var: Variable, - rank: Rank, - pools: &mut Pools, - content: Content, -) -> Variable { - let descriptor = Descriptor { - content, - rank, - mark: Mark::NONE, - copy: OptVariable::NONE, - }; - - subs.set(var, descriptor); - - pools.get_mut(rank).push(var); - - var -} - -#[inline(always)] -fn register_to_pools(subs: &Subs, var: Variable, pools: &mut Pools) { - pools.get_mut(subs.get_rank(var)).push(var); -} diff --git a/crates/compiler/solve/src/specialize.rs b/crates/compiler/solve/src/specialize.rs index 57397445858..cec27972e68 100644 --- a/crates/compiler/solve/src/specialize.rs +++ b/crates/compiler/solve/src/specialize.rs @@ -2,16 +2,11 @@ use std::collections::VecDeque; -use bumpalo::Bump; -use roc_can::{ - abilities::{AbilitiesStore, ImplKey}, - module::ExposedByModule, -}; +use roc_can::abilities::{AbilitiesStore, ImplKey}; use roc_collections::{VecMap, VecSet}; use roc_debug_flags::dbg_do; #[cfg(debug_assertions)] use roc_debug_flags::ROC_TRACE_COMPACTION; -use roc_derive::SharedDerivedModule; use roc_derive_key::{DeriveError, DeriveKey}; use roc_error_macros::{internal_error, todo_abilities}; use roc_module::symbol::{ModuleId, Symbol}; @@ -25,8 +20,9 @@ use roc_types::{ use roc_unify::unify::{unify, Env as UEnv, Mode, MustImplementConstraints}; use crate::{ - ability::builtin_module_with_unlisted_ability_impl, deep_copy::deep_copy_var_in, pools::Pools, - solve::introduce, + ability::builtin_module_with_unlisted_ability_impl, + deep_copy::deep_copy_var_in, + env::{DerivedEnv, Env}, }; /// What phase in the compiler is reaching out to specialize lambda sets? @@ -121,12 +117,6 @@ impl Phase for SolvePhase<'_> { } } -pub struct DerivedEnv<'a> { - pub derived_module: &'a SharedDerivedModule, - /// Exposed types needed by the derived module. - pub exposed_types: &'a ExposedByModule, -} - #[derive(Default)] pub struct AwaitingSpecializations { // What variables' specialized lambda sets in `uls_of_var` will be unlocked for specialization @@ -305,10 +295,7 @@ fn unique_unspecialized_lambda(subs: &Subs, c_a: Variable, uls: &[Uls]) -> Optio #[must_use] pub fn compact_lambda_sets_of_vars( - subs: &mut Subs, - derived_env: &DerivedEnv, - arena: &Bump, - pools: &mut Pools, + env: &mut Env, uls_of_var: UlsOfVar, phase: &P, ) -> CompactionResult { @@ -320,7 +307,7 @@ pub fn compact_lambda_sets_of_vars( // Suppose a type variable `a` with `uls_of_var` mapping `uls_a = {l1, ... ln}` has been instantiated to a concrete type `C_a`. while let Some((c_a, uls_a)) = uls_of_var_queue.pop_front() { - let c_a = subs.get_root_key_without_compacting(c_a); + let c_a = env.subs.get_root_key_without_compacting(c_a); // 1. Let each `l` in `uls_a` be of form `[solved_lambdas + ... + C:f:r + ...]`. // NB: There may be multiple unspecialized lambdas of form `C:f:r, C:f1:r1, ..., C:fn:rn` in `l`. // In this case, let `t1, ... tm` be the other unspecialized lambdas not of form `C:_:_`, @@ -332,13 +319,13 @@ pub fn compact_lambda_sets_of_vars( let mut uls = uls_a.into_vec(); // De-duplicate lambdas by root key. - uls.iter_mut().for_each(|v| *v = subs.get_root_key(*v)); + uls.iter_mut().for_each(|v| *v = env.subs.get_root_key(*v)); uls.sort(); uls.dedup(); uls }; - trace_compact!(1. subs, c_a, &uls_a); + trace_compact!(1. env.subs, c_a, &uls_a); // The flattening step - remove lambda sets that don't reference the concrete var, and for // flatten lambda sets that reference it more than once. @@ -350,15 +337,15 @@ pub fn compact_lambda_sets_of_vars( recursion_var, unspecialized, ambient_function, - } = subs.get_lambda_set(lambda_set); - let lambda_set_rank = subs.get_rank(lambda_set); - let unspecialized = subs.get_subs_slice(unspecialized); + } = env.subs.get_lambda_set(lambda_set); + let lambda_set_rank = env.subs.get_rank(lambda_set); + let unspecialized = env.subs.get_subs_slice(unspecialized); // TODO: is it faster to traverse once, see if we only have one concrete lambda, and // bail in that happy-path, rather than always splitting? let (concrete, mut not_concrete): (Vec<_>, Vec<_>) = unspecialized .iter() .copied() - .partition(|Uls(var, _, _)| subs.equivalent_without_compacting(*var, c_a)); + .partition(|Uls(var, _, _)| env.subs.equivalent_without_compacting(*var, c_a)); if concrete.len() == 1 { // No flattening needs to be done, just return the lambda set as-is return vec![lambda_set]; @@ -373,7 +360,7 @@ pub fn compact_lambda_sets_of_vars( // lambdas, plus all other unspecialized lambdas. // l' = [solved_lambdas + t1 + ... + tm + C:f:r] let unspecialized = SubsSlice::extend_new( - &mut subs.unspecialized_lambda_sets, + &mut env.subs.unspecialized_lambda_sets, not_concrete .drain(..) .chain(std::iter::once(concrete_lambda)), @@ -384,10 +371,10 @@ pub fn compact_lambda_sets_of_vars( // lambdas. // ln = [[] + C:fn:rn] let unspecialized = SubsSlice::extend_new( - &mut subs.unspecialized_lambda_sets, + &mut env.subs.unspecialized_lambda_sets, [concrete_lambda], ); - let var = subs.fresh(Descriptor { + let var = env.subs.fresh(Descriptor { content: Content::Error, rank: lambda_set_rank, mark: Mark::NONE, @@ -396,7 +383,7 @@ pub fn compact_lambda_sets_of_vars( (var, unspecialized) }; - subs.set_content( + env.subs.set_content( var, Content::LambdaSet(LambdaSet { solved, @@ -414,11 +401,15 @@ pub fn compact_lambda_sets_of_vars( // 2. Now, each `l` in `uls_a` has a unique unspecialized lambda of form `C:f:r`. // Sort `uls_a` primarily by `f` (arbitrary order), and secondarily by `r` in descending order. uls_a.sort_by(|v1, v2| { - let unspec_1 = subs.get_subs_slice(subs.get_lambda_set(*v1).unspecialized); - let unspec_2 = subs.get_subs_slice(subs.get_lambda_set(*v2).unspecialized); + let unspec_1 = env + .subs + .get_subs_slice(env.subs.get_lambda_set(*v1).unspecialized); + let unspec_2 = env + .subs + .get_subs_slice(env.subs.get_lambda_set(*v2).unspecialized); - let Uls(_, f1, r1) = unique_unspecialized_lambda(subs, c_a, unspec_1).unwrap(); - let Uls(_, f2, r2) = unique_unspecialized_lambda(subs, c_a, unspec_2).unwrap(); + let Uls(_, f1, r1) = unique_unspecialized_lambda(env.subs, c_a, unspec_1).unwrap(); + let Uls(_, f2, r2) = unique_unspecialized_lambda(env.subs, c_a, unspec_2).unwrap(); match f1.cmp(&f2) { std::cmp::Ordering::Equal => { @@ -429,7 +420,7 @@ pub fn compact_lambda_sets_of_vars( } }); - trace_compact!(2. subs, &uls_a); + trace_compact!(2. env.subs, &uls_a); // 3. For each `l` in `uls_a` with unique unspecialized lambda `C:f:r`: // 1. Let `t_f1` be the directly ambient function of the lambda set containing `C:f:r`. Remove `C:f:r` from `t_f1`'s lambda set. @@ -439,8 +430,7 @@ pub fn compact_lambda_sets_of_vars( // 3. Unify `t_f1 ~ t_f2`. trace_compact!(3start.); for l in uls_a { - let compaction_result = - compact_lambda_set(subs, derived_env, arena, pools, c_a, l, phase); + let compaction_result = compact_lambda_set(env, c_a, l, phase); match compaction_result { OneCompactionResult::Compacted { @@ -474,10 +464,7 @@ enum OneCompactionResult { #[must_use] #[allow(clippy::too_many_arguments)] fn compact_lambda_set( - subs: &mut Subs, - derived_env: &DerivedEnv, - arena: &Bump, - pools: &mut Pools, + env: &mut Env, resolved_concrete: Variable, this_lambda_set: Variable, phase: &P, @@ -493,23 +480,24 @@ fn compact_lambda_set( recursion_var, unspecialized, ambient_function: t_f1, - } = subs.get_lambda_set(this_lambda_set); - let target_rank = subs.get_rank(this_lambda_set); + } = env.subs.get_lambda_set(this_lambda_set); + let target_rank = env.subs.get_rank(this_lambda_set); debug_assert!(!unspecialized.is_empty()); - let unspecialized = subs.get_subs_slice(unspecialized); + let unspecialized = env.subs.get_subs_slice(unspecialized); // 1. Let `t_f1` be the directly ambient function of the lambda set containing `C:f:r`. - let Uls(c, f, r) = unique_unspecialized_lambda(subs, resolved_concrete, unspecialized).unwrap(); + let Uls(c, f, r) = + unique_unspecialized_lambda(env.subs, resolved_concrete, unspecialized).unwrap(); - debug_assert!(subs.equivalent_without_compacting(c, resolved_concrete)); + debug_assert!(env.subs.equivalent_without_compacting(c, resolved_concrete)); // Now decide: do we // - proceed with specialization // - simply drop the specialization lambda set (due to an error) // - or do we need to wait, because we don't know enough information for the specialization yet? - let specialization_decision = make_specialization_decision(subs, phase, c, f); + let specialization_decision = make_specialization_decision(env.subs, phase, c, f); let specialization_key_or_drop = match specialization_decision { SpecializeDecision::Specialize(key) => Ok(key), SpecializeDecision::Drop => Err(()), @@ -522,7 +510,10 @@ fn compact_lambda_set( // 1b. Remove `C:f:r` from `t_f1`'s lambda set. let new_unspecialized: Vec<_> = unspecialized .iter() - .filter(|Uls(v, _, _)| !subs.equivalent_without_compacting(*v, resolved_concrete)) + .filter(|Uls(v, _, _)| { + !env.subs + .equivalent_without_compacting(*v, resolved_concrete) + }) .copied() .collect(); debug_assert_eq!(new_unspecialized.len(), unspecialized.len() - 1); @@ -530,12 +521,12 @@ fn compact_lambda_set( solved, recursion_var, unspecialized: SubsSlice::extend_new( - &mut subs.unspecialized_lambda_sets, + &mut env.subs.unspecialized_lambda_sets, new_unspecialized, ), ambient_function: t_f1, }; - subs.set_content( + env.subs.set_content( this_lambda_set, Content::LambdaSet(t_f1_lambda_set_without_concrete), ); @@ -545,7 +536,7 @@ fn compact_lambda_set( Err(()) => { // Do nothing other than to remove the concrete lambda to drop from the lambda set, // which we already did in 1b above. - trace_compact!(3iter_end_skipped.subs, t_f1); + trace_compact!(3iter_end_skipped. env.subs, t_f1); return OneCompactionResult::Compacted { new_obligations: Default::default(), new_lambda_sets_to_specialize: Default::default(), @@ -554,8 +545,8 @@ fn compact_lambda_set( }; let specialization_ambient_function_var = get_specialization_lambda_set_ambient_function( - subs, - derived_env, + env.subs, + env.derived_env, phase, f, r, @@ -568,7 +559,7 @@ fn compact_lambda_set( Err(()) => { // Do nothing other than to remove the concrete lambda to drop from the lambda set, // which we already did in 1b above. - trace_compact!(3iter_end_skipped.subs, t_f1); + trace_compact!(3iter_end_skipped. env.subs, t_f1); return OneCompactionResult::Compacted { new_obligations: Default::default(), new_lambda_sets_to_specialize: Default::default(), @@ -578,21 +569,21 @@ fn compact_lambda_set( // Ensure the specialized ambient function we'll unify with is not a generalized one, but one // at the rank of the lambda set being compacted. - let t_f2 = deep_copy_var_in(subs, target_rank, pools, t_f2, arena); + let t_f2 = deep_copy_var_in(env, target_rank, t_f2, env.arena); // 3. Unify `t_f1 ~ t_f2`. - trace_compact!(3iter_start.subs, this_lambda_set, t_f1, t_f2); + trace_compact!(3iter_start. env.subs, this_lambda_set, t_f1, t_f2); let (vars, new_obligations, new_lambda_sets_to_specialize, _meta) = unify( - &mut UEnv::new(subs), + &mut UEnv::new(env.subs), t_f1, t_f2, Mode::LAMBDA_SET_SPECIALIZATION, Polarity::Pos, ) .expect_success("ambient functions don't unify"); - trace_compact!(3iter_end.subs, t_f1); + trace_compact!(3iter_end. env.subs, t_f1); - introduce(subs, target_rank, pools, &vars); + env.introduce(target_rank, &vars); OneCompactionResult::Compacted { new_obligations, diff --git a/crates/compiler/solve/src/to_var.rs b/crates/compiler/solve/src/to_var.rs index 3f049905207..7ec197cc0e3 100644 --- a/crates/compiler/solve/src/to_var.rs +++ b/crates/compiler/solve/src/to_var.rs @@ -22,8 +22,7 @@ use roc_unify::unify::{unify, Env as UEnv, Mode, Unified}; use crate::{ ability::{AbilityImplError, ObligationCache}, deep_copy::deep_copy_var_in, - pools::Pools, - solve::{register, register_with_known_var}, + env::Env, Aliases, }; @@ -43,9 +42,8 @@ fn put_scratchpad(scratchpad: bumpalo::Bump) { } pub(crate) fn either_type_index_to_var( - subs: &mut Subs, + env: &mut Env, rank: Rank, - pools: &mut Pools, problems: &mut Vec, abilities_store: &mut AbilitiesStore, obligation_cache: &mut ObligationCache, @@ -57,12 +55,11 @@ pub(crate) fn either_type_index_to_var( Ok(type_index) => { // Converts the celled type to a variable, emplacing the new variable for re-use. let var = type_to_var( - subs, + env, rank, problems, abilities_store, obligation_cache, - pools, types, aliases, type_index, @@ -85,12 +82,11 @@ pub(crate) fn either_type_index_to_var( } pub(crate) fn type_to_var( - subs: &mut Subs, + env: &mut Env, rank: Rank, problems: &mut Vec, abilities_store: &mut AbilitiesStore, obligation_cache: &mut ObligationCache, - pools: &mut Pools, types: &mut Types, aliases: &mut Aliases, typ: Index, @@ -101,9 +97,8 @@ pub(crate) fn type_to_var( let mut arena = take_scratchpad(); let var = type_to_var_help( - subs, + env, rank, - pools, problems, abilities_store, obligation_cache, @@ -131,9 +126,8 @@ enum RegisterVariable { impl RegisterVariable { fn from_type( - subs: &mut Subs, + env: &mut Env, rank: Rank, - pools: &mut Pools, arena: &'_ bumpalo::Bump, types: &mut Types, typ: Index, @@ -155,7 +149,7 @@ impl RegisterVariable { reserved } else { // for any other rank, we need to copy; it takes care of adjusting the rank - deep_copy_var_in(subs, rank, pools, reserved, arena) + deep_copy_var_in(env, rank, reserved, arena) }; // Safety: the `destination` will become the source-of-truth for the type index, since it // was not already transformed before (if it was, we'd be in the Variable branch!) @@ -171,18 +165,17 @@ impl RegisterVariable { #[inline(always)] fn with_stack( - subs: &mut Subs, + env: &mut Env, rank: Rank, - pools: &mut Pools, arena: &'_ bumpalo::Bump, types: &mut Types, typ_index: Index, stack: &mut bumpalo::collections::Vec<'_, TypeToVar>, ) -> Variable { - match Self::from_type(subs, rank, pools, arena, types, typ_index) { + match Self::from_type(env, rank, arena, types, typ_index) { Self::Direct(var) => var, Self::Deferred => { - let var = subs.fresh_unnamed_flex_var(); + let var = env.subs.fresh_unnamed_flex_var(); // Safety: the `destination` will become the source-of-truth for the type index, since it // was not already transformed before (if it was, it wouldn't be deferred!) let typ = unsafe { types.emplace_variable(typ_index, var) }; @@ -260,9 +253,8 @@ enum TypeToVar { #[allow(clippy::too_many_arguments)] pub(crate) fn type_to_var_help( - subs: &mut Subs, + env: &mut Env, rank: Rank, - pools: &mut Pools, problems: &mut Vec, abilities_store: &AbilitiesStore, obligation_cache: &mut ObligationCache, @@ -280,16 +272,16 @@ pub(crate) fn type_to_var_help( macro_rules! helper { ($typ:expr, $ambient_function_policy:expr) => {{ - match RegisterVariable::from_type(subs, rank, pools, arena, types, $typ) { + match RegisterVariable::from_type(env, rank, arena, types, $typ) { RegisterVariable::Direct(var) => { // If the variable is just a type variable but we know we're in a lambda set // context, try to link to the ambient function. - $ambient_function_policy.link_to_alias_lambda_set_var(subs, var); + $ambient_function_policy.link_to_alias_lambda_set_var(env.subs, var); var } RegisterVariable::Deferred => { - let var = subs.fresh_unnamed_flex_var(); + let var = env.subs.fresh_unnamed_flex_var(); // Safety: the `destination` will become the source-of-truth for the type index, since it // was not already transformed before (if it was, it wouldn't be deferred!) @@ -328,7 +320,7 @@ pub(crate) fn type_to_var_help( RangedNumber(range) => { let content = Content::RangedNumber(range); - register_with_known_var(subs, destination, rank, pools, content) + env.register_with_known_var(destination, rank, content) } Apply { symbol, @@ -336,18 +328,18 @@ pub(crate) fn type_to_var_help( region: _, } => { let arguments = types.get_type_arguments(typ_index); - let new_arguments = VariableSubsSlice::reserve_into_subs(subs, arguments.len()); + let new_arguments = VariableSubsSlice::reserve_into_subs(env.subs, arguments.len()); for (target_index, var_index) in (new_arguments.indices()).zip(arguments.into_iter()) { let var = helper!(var_index); - subs.variables[target_index] = var; + env.subs.variables[target_index] = var; } let flat_type = FlatType::Apply(symbol, new_arguments); let content = Content::Structure(flat_type); - register_with_known_var(subs, destination, rank, pools, content) + env.register_with_known_var(destination, rank, content) } ClosureTag { @@ -355,9 +347,8 @@ pub(crate) fn type_to_var_help( ambient_function, } => { let captures = types.get_type_arguments(typ_index); - let union_lambdas = create_union_lambda( - subs, rank, pools, arena, types, name, captures, &mut stack, - ); + let union_lambdas = + create_union_lambda(env, rank, arena, types, name, captures, &mut stack); let content = Content::LambdaSet(subs::LambdaSet { solved: union_lambdas, @@ -368,11 +359,11 @@ pub(crate) fn type_to_var_help( ambient_function, }); - register_with_known_var(subs, destination, rank, pools, content) + env.register_with_known_var(destination, rank, content) } UnspecializedLambdaSet { unspecialized } => { let unspecialized_slice = SubsSlice::extend_new( - &mut subs.unspecialized_lambda_sets, + &mut env.subs.unspecialized_lambda_sets, std::iter::once(unspecialized), ); @@ -397,17 +388,17 @@ pub(crate) fn type_to_var_help( ambient_function, }); - register_with_known_var(subs, destination, rank, pools, content) + env.register_with_known_var(destination, rank, content) } // This case is important for the rank of boolean variables Function(closure_type, ret_type) => { let arguments = types.get_type_arguments(typ_index); - let new_arguments = VariableSubsSlice::reserve_into_subs(subs, arguments.len()); + let new_arguments = VariableSubsSlice::reserve_into_subs(env.subs, arguments.len()); for (target_index, var_index) in (new_arguments.indices()).zip(arguments.into_iter()) { let var = helper!(var_index); - subs.variables[target_index] = var; + env.subs.variables[target_index] = var; } let ret_var = helper!(ret_type); @@ -416,7 +407,7 @@ pub(crate) fn type_to_var_help( let content = Content::Structure(FlatType::Func(new_arguments, closure_var, ret_var)); - register_with_known_var(subs, destination, rank, pools, content) + env.register_with_known_var(destination, rank, content) } Record(fields) => { let ext_slice = types.get_type_arguments(typ_index); @@ -448,7 +439,7 @@ pub(crate) fn type_to_var_help( }; let (it, new_ext_var) = - gather_fields_unsorted_iter(subs, RecordFields::empty(), temp_ext_var) + gather_fields_unsorted_iter(env.subs, RecordFields::empty(), temp_ext_var) .expect("Something ended up weird in this record type"); let it = it @@ -458,11 +449,11 @@ pub(crate) fn type_to_var_help( field_vars.extend(it); insertion_sort_by(&mut field_vars, RecordFields::compare); - let record_fields = RecordFields::insert_into_subs(subs, field_vars); + let record_fields = RecordFields::insert_into_subs(env.subs, field_vars); let content = Content::Structure(FlatType::Record(record_fields, new_ext_var)); - register_with_known_var(subs, destination, rank, pools, content) + env.register_with_known_var(destination, rank, content) } Tuple(elems) => { @@ -487,15 +478,15 @@ pub(crate) fn type_to_var_help( }; let (it, new_ext_var) = - gather_tuple_elems_unsorted_iter(subs, TupleElems::empty(), temp_ext_var) + gather_tuple_elems_unsorted_iter(env.subs, TupleElems::empty(), temp_ext_var) .expect("Something ended up weird in this tuple type"); elem_vars.extend(it); - let tuple_elems = TupleElems::insert_into_subs(subs, elem_vars); + let tuple_elems = TupleElems::insert_into_subs(env.subs, elem_vars); let content = Content::Structure(FlatType::Tuple(tuple_elems, new_ext_var)); - register_with_known_var(subs, destination, rank, pools, content) + env.register_with_known_var(destination, rank, content) } TagUnion(tags, ext_openness) => { @@ -506,9 +497,8 @@ pub(crate) fn type_to_var_help( debug_assert!(!tags.is_empty() || !ext_slice.is_empty()); let (union_tags, ext) = type_to_union_tags( - subs, + env, rank, - pools, arena, types, tags, @@ -518,7 +508,7 @@ pub(crate) fn type_to_var_help( ); let content = Content::Structure(FlatType::TagUnion(union_tags, ext)); - register_with_known_var(subs, destination, rank, pools, content) + env.register_with_known_var(destination, rank, content) } FunctionOrTagUnion(symbol, ext_openness) => { let ext_slice = types.get_type_arguments(typ_index); @@ -534,7 +524,7 @@ pub(crate) fn type_to_var_help( }; let (it, ext) = roc_types::types::gather_tags_unsorted_iter( - subs, + env.subs, UnionTags::default(), temp_ext, ) @@ -544,13 +534,13 @@ pub(crate) fn type_to_var_help( unreachable!("we assert that the ext var is empty; otherwise we'd already know it was a tag union!"); } - let tag_names = SubsSlice::extend_new(&mut subs.tag_names, [tag_name]); - let symbols = SubsSlice::extend_new(&mut subs.symbol_names, [symbol]); + let tag_names = SubsSlice::extend_new(&mut env.subs.tag_names, [tag_name]); + let symbols = SubsSlice::extend_new(&mut env.subs.symbol_names, [symbol]); let content = Content::Structure(FlatType::FunctionOrTagUnion(tag_names, symbols, ext)); - register_with_known_var(subs, destination, rank, pools, content) + env.register_with_known_var(destination, rank, content) } RecursiveTagUnion(rec_var, tags, ext_openness) => { let ext_slice = types.get_type_arguments(typ_index); @@ -560,9 +550,8 @@ pub(crate) fn type_to_var_help( debug_assert!(!tags.is_empty() || !ext_slice.is_empty()); let (union_tags, ext) = type_to_union_tags( - subs, + env, rank, - pools, arena, types, tags, @@ -574,13 +563,11 @@ pub(crate) fn type_to_var_help( Content::Structure(FlatType::RecursiveTagUnion(rec_var, union_tags, ext)); let tag_union_var = destination; - register_with_known_var(subs, tag_union_var, rank, pools, content); + env.register_with_known_var(tag_union_var, rank, content); - register_with_known_var( - subs, + env.register_with_known_var( rec_var, rank, - pools, Content::RecursionVar { opt_name: None, structure: tag_union_var, @@ -605,7 +592,8 @@ pub(crate) fn type_to_var_help( let all_vars_length = type_arguments.len() + lambda_set_variables.len() + infer_ext_in_output_variables.len(); - let new_variables = VariableSubsSlice::reserve_into_subs(subs, all_vars_length); + let new_variables = + VariableSubsSlice::reserve_into_subs(env.subs, all_vars_length); let type_arguments_offset = 0; let lambda_set_vars_offset = type_arguments_offset + type_arguments.len(); @@ -618,7 +606,7 @@ pub(crate) fn type_to_var_help( .zip(type_argument_abilities.into_iter()) { let copy_var = helper!(arg_type); - subs.variables[target_index] = copy_var; + env.subs.variables[target_index] = copy_var; if !types[abilities].is_empty() { let arg_region = types[arg_region]; bind_to_abilities.push((Loc::at(arg_region, copy_var), abilities)); @@ -631,9 +619,8 @@ pub(crate) fn type_to_var_help( // We MUST do this now, otherwise when linking the ambient function during // instantiation of the real var, there will be nothing to link against. let copy_var = type_to_var_help( - subs, + env, rank, - pools, problems, abilities_store, obligation_cache, @@ -643,14 +630,14 @@ pub(crate) fn type_to_var_help( ls, true, ); - subs.variables[target_index] = copy_var; + env.subs.variables[target_index] = copy_var; } let it = (new_variables.indices().skip(infer_ext_vars_offset)) .zip(infer_ext_in_output_variables.into_iter()); for (target_index, ext_typ) in it { let copy_var = helper!(ext_typ); - subs.variables[target_index] = copy_var; + env.subs.variables[target_index] = copy_var; } AliasVariables { @@ -662,9 +649,8 @@ pub(crate) fn type_to_var_help( }; let (alias_variable, kind) = aliases.instantiate_real_var( - subs, + env, rank, - pools, problems, abilities_store, obligation_cache, @@ -676,7 +662,7 @@ pub(crate) fn type_to_var_help( let content = Content::Alias(symbol, alias_variables, alias_variable, kind); - register_with_known_var(subs, destination, rank, pools, content) + env.register_with_known_var(destination, rank, content) } StructuralAlias { shared, actual } | OpaqueAlias { shared, actual } => { @@ -707,7 +693,8 @@ pub(crate) fn type_to_var_help( let lambda_set_vars_offset = type_arguments_offset + type_arguments.len(); let infer_ext_vars_offset = lambda_set_vars_offset + lambda_set_variables.len(); - let new_variables = VariableSubsSlice::reserve_into_subs(subs, all_vars_length); + let new_variables = + VariableSubsSlice::reserve_into_subs(env.subs, all_vars_length); for (((target_index, typ), region), abilities) in (new_variables.indices().skip(type_arguments_offset)) @@ -716,7 +703,7 @@ pub(crate) fn type_to_var_help( .zip(type_argument_abilities.into_iter()) { let copy_var = helper!(typ); - subs.variables[target_index] = copy_var; + env.subs.variables[target_index] = copy_var; if !types[abilities].is_empty() { let region = types[region]; bind_to_abilities.push((Loc::at(region, copy_var), abilities)); @@ -727,14 +714,14 @@ pub(crate) fn type_to_var_help( .zip(lambda_set_variables.into_iter()); for (target_index, ls) in it { let copy_var = helper!(ls); - subs.variables[target_index] = copy_var; + env.subs.variables[target_index] = copy_var; } let it = (new_variables.indices().skip(infer_ext_vars_offset)) .zip(infer_ext_in_output_variables.into_iter()); for (target_index, ext_typ) in it { let copy_var = helper!(ext_typ); - subs.variables[target_index] = copy_var; + env.subs.variables[target_index] = copy_var; } AliasVariables { @@ -746,13 +733,13 @@ pub(crate) fn type_to_var_help( }; let alias_variable = if let Symbol::RESULT_RESULT = symbol { - roc_result_to_var(subs, rank, pools, arena, types, actual, &mut stack) + roc_result_to_var(env, rank, arena, types, actual, &mut stack) } else { helper!(actual) }; let content = Content::Alias(symbol, alias_variables, alias_variable, kind); - register_with_known_var(subs, destination, rank, pools, content) + env.register_with_known_var(destination, rank, content) } HostExposedAlias { shared, @@ -771,13 +758,13 @@ pub(crate) fn type_to_var_help( let alias_variables = { let length = type_arguments.len() + lambda_set_variables.len(); - let new_variables = VariableSubsSlice::reserve_into_subs(subs, length); + let new_variables = VariableSubsSlice::reserve_into_subs(env.subs, length); for (target_index, arg_type) in (new_variables.indices()).zip(type_arguments.into_iter()) { let copy_var = helper!(arg_type); - subs.variables[target_index] = copy_var; + env.subs.variables[target_index] = copy_var; } let it = (new_variables.indices().skip(type_arguments.len())) .zip(lambda_set_variables.into_iter()); @@ -785,9 +772,8 @@ pub(crate) fn type_to_var_help( // We MUST do this now, otherwise when linking the ambient function during // instantiation of the real var, there will be nothing to link against. let copy_var = type_to_var_help( - subs, + env, rank, - pools, problems, abilities_store, obligation_cache, @@ -797,7 +783,7 @@ pub(crate) fn type_to_var_help( ls, true, ); - subs.variables[target_index] = copy_var; + env.subs.variables[target_index] = copy_var; } AliasVariables { @@ -810,9 +796,8 @@ pub(crate) fn type_to_var_help( // cannot use helper! here because this variable may be involved in unification below let alias_variable = type_to_var_help( - subs, + env, rank, - pools, problems, abilities_store, obligation_cache, @@ -830,14 +815,14 @@ pub(crate) fn type_to_var_help( alias_variable, AliasKind::Structural, ); - let result = register_with_known_var(subs, destination, rank, pools, content); + let result = env.register_with_known_var(destination, rank, content); // We only want to unify the actual_var with the alias once // if it's already redirected (and therefore, redundant) // don't do it again - if !subs.redundant(actual_var) { - let descriptor = subs.get(result); - subs.union(result, actual_var, descriptor); + if !env.subs.redundant(actual_var) { + let descriptor = env.subs.get(result); + env.subs.union(result, actual_var, descriptor); } result @@ -845,39 +830,39 @@ pub(crate) fn type_to_var_help( Error => { let content = Content::Error; - register_with_known_var(subs, destination, rank, pools, content) + env.register_with_known_var(destination, rank, content) } }; } for (Loc { value: var, region }, abilities) in bind_to_abilities { let abilities = &types[abilities]; - match *subs.get_content_unchecked(var) { + match *env.subs.get_content_unchecked(var) { Content::RigidVar(a) => { // TODO(multi-abilities): check run cache - let abilities_slice = - SubsSlice::extend_new(&mut subs.symbol_names, abilities.sorted_iter().copied()); - subs.set_content(var, Content::RigidAbleVar(a, abilities_slice)); + let abilities_slice = SubsSlice::extend_new( + &mut env.subs.symbol_names, + abilities.sorted_iter().copied(), + ); + env.subs + .set_content(var, Content::RigidAbleVar(a, abilities_slice)); } Content::RigidAbleVar(_, abs) - if (subs.get_subs_slice(abs).iter()).eq(abilities.sorted_iter()) => + if (env.subs.get_subs_slice(abs).iter()).eq(abilities.sorted_iter()) => { // pass, already bound } _ => { - let abilities_slice = - SubsSlice::extend_new(&mut subs.symbol_names, abilities.sorted_iter().copied()); - - let flex_ability = register( - subs, - rank, - pools, - Content::FlexAbleVar(None, abilities_slice), + let abilities_slice = SubsSlice::extend_new( + &mut env.subs.symbol_names, + abilities.sorted_iter().copied(), ); + let flex_ability = env.register(rank, Content::FlexAbleVar(None, abilities_slice)); + let category = Category::OpaqueArg; match unify( - &mut UEnv::new(subs), + &mut UEnv::new(env.subs), var, flex_ability, Mode::EQ, @@ -893,7 +878,7 @@ pub(crate) fn type_to_var_help( if !must_implement_ability.is_empty() { let new_problems = obligation_cache.check_obligations( - subs, + env.subs, abilities_store, must_implement_ability, AbilityImplError::BadExpr(region, category, flex_ability), @@ -926,9 +911,8 @@ pub(crate) fn type_to_var_help( #[inline(always)] fn roc_result_to_var( - subs: &mut Subs, + env: &mut Env, rank: Rank, - pools: &mut Pools, arena: &'_ bumpalo::Bump, types: &mut Types, result_type: Index, @@ -946,8 +930,8 @@ fn roc_result_to_var( if let ([err, ok], [err_args, ok_args]) = (&types[tags_slice], &types[payload_slices_slice]) { - debug_assert_eq!(err, &subs.tag_names[0]); - debug_assert_eq!(ok, &subs.tag_names[1]); + debug_assert_eq!(err, &env.subs.tag_names[0]); + debug_assert_eq!(ok, &env.subs.tag_names[1]); debug_assert_eq!(err_args.len(), 1); debug_assert_eq!(ok_args.len(), 1); @@ -955,30 +939,28 @@ fn roc_result_to_var( if let (Some(err_type), Some(ok_type)) = (err_args.into_iter().next(), ok_args.into_iter().next()) { - let err_var = RegisterVariable::with_stack( - subs, rank, pools, arena, types, err_type, stack, - ); - let ok_var = RegisterVariable::with_stack( - subs, rank, pools, arena, types, ok_type, stack, - ); - - let start = subs.variables.len() as u32; + let err_var = + RegisterVariable::with_stack(env, rank, arena, types, err_type, stack); + let ok_var = + RegisterVariable::with_stack(env, rank, arena, types, ok_type, stack); + + let start = env.subs.variables.len() as u32; let err_slice = SubsSlice::new(start, 1); let ok_slice = SubsSlice::new(start + 1, 1); - subs.variables.push(err_var); - subs.variables.push(ok_var); + env.subs.variables.push(err_var); + env.subs.variables.push(ok_var); - let variables = SubsSlice::new(subs.variable_slices.len() as _, 2); - subs.variable_slices.push(err_slice); - subs.variable_slices.push(ok_slice); + let variables = SubsSlice::new(env.subs.variable_slices.len() as _, 2); + env.subs.variable_slices.push(err_slice); + env.subs.variable_slices.push(ok_slice); let union_tags = UnionTags::from_slices(Subs::RESULT_TAG_NAMES, variables); let ext = TagExt::Any(Variable::EMPTY_TAG_UNION); let content = Content::Structure(FlatType::TagUnion(union_tags, ext)); - return register(subs, rank, pools, content); + return env.register(rank, content); } } @@ -1108,9 +1090,8 @@ fn find_tag_name_run(slice: &[TagName], subs: &mut Subs) -> Option, @@ -1119,13 +1100,12 @@ fn register_tag_arguments( if arguments.is_empty() { VariableSubsSlice::default() } else { - let new_variables = VariableSubsSlice::reserve_into_subs(subs, arguments.len()); + let new_variables = VariableSubsSlice::reserve_into_subs(env.subs, arguments.len()); let it = new_variables.indices().zip(arguments.into_iter()); for (target_index, argument) in it { - let var = - RegisterVariable::with_stack(subs, rank, pools, arena, types, argument, stack); - subs.variables[target_index] = var; + let var = RegisterVariable::with_stack(env, rank, arena, types, argument, stack); + env.subs.variables[target_index] = var; } new_variables @@ -1134,9 +1114,8 @@ fn register_tag_arguments( /// Assumes that the tags are sorted and there are no duplicates! fn insert_tags_fast_path( - subs: &mut Subs, + env: &mut Env, rank: Rank, - pools: &mut Pools, arena: &'_ bumpalo::Bump, types: &mut Types, union_tags: UnionTags, @@ -1150,10 +1129,10 @@ fn insert_tags_fast_path( let arguments_slice = *arguments_slice; let variable_slice = - register_tag_arguments(subs, rank, pools, arena, types, stack, arguments_slice); + register_tag_arguments(env, rank, arena, types, stack, arguments_slice); let new_variable_slices = - SubsSlice::extend_new(&mut subs.variable_slices, [variable_slice]); + SubsSlice::extend_new(&mut env.subs.variable_slices, [variable_slice]); macro_rules! subs_tag_name { ($tag_name_slice:expr) => { @@ -1171,21 +1150,21 @@ fn insert_tags_fast_path( } } - let new_variable_slices = SubsSlice::reserve_variable_slices(subs, tags.len()); - match find_tag_name_run(&types[tags], subs) { + let new_variable_slices = SubsSlice::reserve_variable_slices(env.subs, tags.len()); + match find_tag_name_run(&types[tags], env.subs) { Some(new_tag_names) => { let it = (new_variable_slices.indices()).zip(payload_slices.into_iter()); for (variable_slice_index, arguments_index) in it { let arguments = types[arguments_index]; - subs.variable_slices[variable_slice_index] = - register_tag_arguments(subs, rank, pools, arena, types, stack, arguments); + env.subs.variable_slices[variable_slice_index] = + register_tag_arguments(env, rank, arena, types, stack, arguments); } UnionTags::from_slices(new_tag_names, new_variable_slices) } None => { - let new_tag_names = SubsSlice::reserve_tag_names(subs, tags.len()); + let new_tag_names = SubsSlice::reserve_tag_names(env.subs, tags.len()); let it = (new_variable_slices.indices()) .zip(new_tag_names.indices()) @@ -1194,10 +1173,10 @@ fn insert_tags_fast_path( for (((variable_slice_index, tag_name_index), tag_name), arguments_index) in it { let arguments = types[arguments_index]; - subs.variable_slices[variable_slice_index] = - register_tag_arguments(subs, rank, pools, arena, types, stack, arguments); + env.subs.variable_slices[variable_slice_index] = + register_tag_arguments(env, rank, arena, types, stack, arguments); - subs.tag_names[tag_name_index] = types[tag_name].clone(); + env.subs.tag_names[tag_name_index] = types[tag_name].clone(); } UnionTags::from_slices(new_tag_names, new_variable_slices) @@ -1206,9 +1185,8 @@ fn insert_tags_fast_path( } fn insert_tags_slow_path( - subs: &mut Subs, + env: &mut Env, rank: Rank, - pools: &mut Pools, arena: &'_ bumpalo::Bump, types: &mut Types, union_tags: UnionTags, @@ -1221,11 +1199,11 @@ fn insert_tags_slow_path( { let tag_argument_types = &types[tag_argument_types_index]; - let new_slice = VariableSubsSlice::reserve_into_subs(subs, tag_argument_types.len()); + let new_slice = VariableSubsSlice::reserve_into_subs(env.subs, tag_argument_types.len()); for (i, arg) in (new_slice.indices()).zip(tag_argument_types.into_iter()) { - let var = RegisterVariable::with_stack(subs, rank, pools, arena, types, arg, stack); - subs.variables[i] = var; + let var = RegisterVariable::with_stack(env, rank, arena, types, arg, stack); + env.subs.variables[i] = var; } tag_vars.push((types[tag_index].clone(), new_slice)); @@ -1233,13 +1211,12 @@ fn insert_tags_slow_path( sort_and_deduplicate(&mut tag_vars); - UnionTags::insert_slices_into_subs(subs, tag_vars) + UnionTags::insert_slices_into_subs(env.subs, tag_vars) } fn type_to_union_tags( - subs: &mut Subs, + env: &mut Env, rank: Rank, - pools: &mut Pools, arena: &'_ bumpalo::Bump, types: &mut Types, union_tags: UnionTags, @@ -1260,10 +1237,10 @@ fn type_to_union_tags( let ext = Variable::EMPTY_TAG_UNION; let union_tags = if sorted { - insert_tags_fast_path(subs, rank, pools, arena, types, union_tags, stack) + insert_tags_fast_path(env, rank, arena, types, union_tags, stack) } else { let tag_vars = Vec::with_capacity_in(tags.len(), arena); - insert_tags_slow_path(subs, rank, pools, arena, types, union_tags, tag_vars, stack) + insert_tags_slow_path(env, rank, arena, types, union_tags, tag_vars, stack) }; (union_tags, TagExt::Any(ext)) @@ -1273,19 +1250,22 @@ fn type_to_union_tags( let temp_ext = { let temp_ext_var = - RegisterVariable::with_stack(subs, rank, pools, arena, types, ext, stack); + RegisterVariable::with_stack(env, rank, arena, types, ext, stack); TagExt::from_can(temp_ext_var, ext_openness) }; - let (it, ext) = - roc_types::types::gather_tags_unsorted_iter(subs, UnionTags::default(), temp_ext) - .expect("extension var could not be seen as tag union"); + let (it, ext) = roc_types::types::gather_tags_unsorted_iter( + env.subs, + UnionTags::default(), + temp_ext, + ) + .expect("extension var could not be seen as tag union"); tag_vars.extend(it.map(|(n, v)| (n.clone(), v))); let union_tags = if tag_vars.is_empty() && sorted { - insert_tags_fast_path(subs, rank, pools, arena, types, union_tags, stack) + insert_tags_fast_path(env, rank, arena, types, union_tags, stack) } else { - insert_tags_slow_path(subs, rank, pools, arena, types, union_tags, tag_vars, stack) + insert_tags_slow_path(env, rank, arena, types, union_tags, tag_vars, stack) }; (union_tags, ext) @@ -1294,20 +1274,19 @@ fn type_to_union_tags( } fn create_union_lambda( - subs: &mut Subs, + env: &mut Env, rank: Rank, - pools: &mut Pools, arena: &'_ bumpalo::Bump, types: &mut Types, closure: Symbol, capture_types: Slice, stack: &mut bumpalo::collections::Vec<'_, TypeToVar>, ) -> UnionLambdas { - let variable_slice = - register_tag_arguments(subs, rank, pools, arena, types, stack, capture_types); - let new_variable_slices = SubsSlice::extend_new(&mut subs.variable_slices, [variable_slice]); + let variable_slice = register_tag_arguments(env, rank, arena, types, stack, capture_types); + let new_variable_slices = + SubsSlice::extend_new(&mut env.subs.variable_slices, [variable_slice]); - let lambda_name_slice = SubsSlice::extend_new(&mut subs.symbol_names, [closure]); + let lambda_name_slice = SubsSlice::extend_new(&mut env.subs.symbol_names, [closure]); UnionLambdas::from_slices(lambda_name_slice, new_variable_slices) } From adf961ba0b97b332d0d9d8b6b7cfce9365f2cdcd Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Thu, 22 Jun 2023 14:12:05 -0500 Subject: [PATCH 014/140] Use UEnv where possible --- crates/compiler/solve/src/env.rs | 6 ++++++ crates/compiler/solve/src/solve.rs | 26 ++++++++++++------------- crates/compiler/solve/src/specialize.rs | 4 ++-- crates/compiler/solve/src/to_var.rs | 4 ++-- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/crates/compiler/solve/src/env.rs b/crates/compiler/solve/src/env.rs index 8698ae8670e..1f795046987 100644 --- a/crates/compiler/solve/src/env.rs +++ b/crates/compiler/solve/src/env.rs @@ -2,6 +2,7 @@ use bumpalo::Bump; use roc_can::{constraint::Constraints, module::ExposedByModule}; use roc_derive::SharedDerivedModule; use roc_types::subs::{Content, Descriptor, Mark, OptVariable, Rank, Subs, Variable}; +use roc_unify::unify::Env as UEnv; use crate::Pools; @@ -72,4 +73,9 @@ impl<'a> Env<'a> { var } + + /// Retrieves an environment for unification. + pub fn uenv<'r>(&'r mut self) -> UEnv<'r> { + UEnv::new(self.subs) + } } diff --git a/crates/compiler/solve/src/solve.rs b/crates/compiler/solve/src/solve.rs index fb890944efe..ea36ca5391b 100644 --- a/crates/compiler/solve/src/solve.rs +++ b/crates/compiler/solve/src/solve.rs @@ -14,7 +14,7 @@ use crate::Aliases; use bumpalo::Bump; use roc_can::abilities::{AbilitiesStore, MemberSpecializationInfo}; use roc_can::constraint::Constraint::{self, *}; -use roc_can::constraint::{Constraints, Cycle, LetConstraint, OpportunisticResolve}; +use roc_can::constraint::{Cycle, LetConstraint, OpportunisticResolve}; use roc_can::expected::{Expected, PExpected}; use roc_debug_flags::dbg_do; #[cfg(debug_assertions)] @@ -30,8 +30,8 @@ use roc_types::subs::{ }; use roc_types::types::{Category, Polarity, Reason, RecordField, Type, TypeExtension, Types, Uls}; use roc_unify::unify::{ - unify, unify_introduced_ability_specialization, Env as UEnv, Mode, Obligated, - SpecializationLsetCollector, Unified::*, + unify, unify_introduced_ability_specialization, Mode, Obligated, SpecializationLsetCollector, + Unified::*, }; mod scope; @@ -484,7 +484,7 @@ fn solve( ); match unify( - &mut UEnv::new(env.subs), + &mut env.uenv(), actual, expected, Mode::EQ, @@ -591,7 +591,7 @@ fn solve( ); match unify( - &mut UEnv::new(env.subs), + &mut env.uenv(), actual, expected, Mode::EQ, @@ -698,7 +698,7 @@ fn solve( }; match unify( - &mut UEnv::new(env.subs), + &mut env.uenv(), actual, expected, mode, @@ -910,7 +910,7 @@ fn solve( ); match unify( - &mut UEnv::new(env.subs), + &mut env.uenv(), actual, includes, Mode::PRESENT, @@ -1044,7 +1044,7 @@ fn solve( let snapshot = env.subs.snapshot(); let unify_cond_and_patterns_outcome = unify( - &mut UEnv::new(env.subs), + &mut env.uenv(), branches_var, real_var, Mode::EQ, @@ -1094,7 +1094,7 @@ fn solve( open_tag_union(env, branches_var); let almost_eq = matches!( unify( - &mut UEnv::new(env.subs), + &mut env.uenv(), real_var, branches_var, Mode::EQ, @@ -1112,7 +1112,7 @@ fn solve( // Case 4: incompatible types, report type error. // Re-run first failed unification to get the type diff. match unify( - &mut UEnv::new(env.subs), + &mut env.uenv(), real_var, branches_var, Mode::EQ, @@ -1311,7 +1311,7 @@ fn solve( lambda_sets_to_specialize, extra_metadata: _, } = unify( - &mut UEnv::new(env.subs), + &mut env.uenv(), actual, Variable::LIST_U8, Mode::EQ, @@ -1331,7 +1331,7 @@ fn solve( // We explicitly match on the last unify to get the type in the case it errors. match unify( - &mut UEnv::new(env.subs), + &mut env.uenv(), actual, Variable::STR, Mode::EQ, @@ -1574,7 +1574,7 @@ fn check_ability_specialization( deep_copy_var_in(env, Rank::toplevel(), root_signature_var, env.arena); let snapshot = env.subs.snapshot(); let unified = unify_introduced_ability_specialization( - &mut UEnv::new(env.subs), + &mut env.uenv(), root_signature_var, symbol_loc_var.value, Mode::EQ, diff --git a/crates/compiler/solve/src/specialize.rs b/crates/compiler/solve/src/specialize.rs index cec27972e68..1ea79cff59a 100644 --- a/crates/compiler/solve/src/specialize.rs +++ b/crates/compiler/solve/src/specialize.rs @@ -17,7 +17,7 @@ use roc_types::{ }, types::{AliasKind, MemberImpl, Polarity, Uls}, }; -use roc_unify::unify::{unify, Env as UEnv, Mode, MustImplementConstraints}; +use roc_unify::unify::{unify, Mode, MustImplementConstraints}; use crate::{ ability::builtin_module_with_unlisted_ability_impl, @@ -574,7 +574,7 @@ fn compact_lambda_set( // 3. Unify `t_f1 ~ t_f2`. trace_compact!(3iter_start. env.subs, this_lambda_set, t_f1, t_f2); let (vars, new_obligations, new_lambda_sets_to_specialize, _meta) = unify( - &mut UEnv::new(env.subs), + &mut env.uenv(), t_f1, t_f2, Mode::LAMBDA_SET_SPECIALIZATION, diff --git a/crates/compiler/solve/src/to_var.rs b/crates/compiler/solve/src/to_var.rs index 7ec197cc0e3..b49cddd1c1d 100644 --- a/crates/compiler/solve/src/to_var.rs +++ b/crates/compiler/solve/src/to_var.rs @@ -17,7 +17,7 @@ use roc_types::{ Category, ExtImplicitOpenness, Polarity, TypeTag, Types, }, }; -use roc_unify::unify::{unify, Env as UEnv, Mode, Unified}; +use roc_unify::unify::{unify, Mode, Unified}; use crate::{ ability::{AbilityImplError, ObligationCache}, @@ -862,7 +862,7 @@ pub(crate) fn type_to_var_help( let category = Category::OpaqueArg; match unify( - &mut UEnv::new(env.subs), + &mut env.uenv(), var, flex_ability, Mode::EQ, From e019ec6736e5a821b1c40ee5b8d7939c007b60fd Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Thu, 22 Jun 2023 14:13:42 -0500 Subject: [PATCH 015/140] Add todo --- crates/compiler/solve/src/deep_copy.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/compiler/solve/src/deep_copy.rs b/crates/compiler/solve/src/deep_copy.rs index 58633a79513..12eab6def5d 100644 --- a/crates/compiler/solve/src/deep_copy.rs +++ b/crates/compiler/solve/src/deep_copy.rs @@ -12,6 +12,7 @@ use roc_types::{ use crate::env::Env; +// TODO: eventually, we could possibly use the arena in Env instead. pub(crate) fn deep_copy_var_in(env: &mut Env, rank: Rank, var: Variable, arena: &Bump) -> Variable { let mut visited = bumpalo::collections::Vec::with_capacity_in(256, arena); From 6e5ee5562ec9acdd761d87aa29dc72d644d7576e Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Thu, 22 Jun 2023 14:22:18 -0500 Subject: [PATCH 016/140] Update tests --- crates/compiler/test_derive/src/util.rs | 24 +++++++++++++++++------- crates/reporting/tests/helpers/mod.rs | 21 ++++++++++----------- crates/reporting/tests/test_reporting.rs | 4 ++-- 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/crates/compiler/test_derive/src/util.rs b/crates/compiler/test_derive/src/util.rs index 566d433c9c0..5d050827386 100644 --- a/crates/compiler/test_derive/src/util.rs +++ b/crates/compiler/test_derive/src/util.rs @@ -3,6 +3,7 @@ use std::path::PathBuf; use bumpalo::Bump; use roc_packaging::cache::RocCacheDir; +use roc_solve::module::{SolveConfig, SolveOutput}; use ven_pretty::DocAllocator; use roc_can::{ @@ -418,18 +419,27 @@ fn check_derived_typechecks_and_golden( roc_debug_flags::ROC_PRINT_UNIFICATIONS_DERIVED, std::env::set_var(roc_debug_flags::ROC_PRINT_UNIFICATIONS, "1") ); - let (mut solved_subs, _, problems, _) = roc_solve::module::run_solve( - test_module, + + let solve_config = SolveConfig { + home: test_module, + constraints: &constraints, + root_constraint: constr, types, - &constraints, - constr, + pending_derives: Default::default(), + exposed_by_module: &exposed_for_module.exposed_by_module, + derived_module: Default::default(), + }; + + let SolveOutput { + subs: mut solved_subs, + errors: problems, + .. + } = roc_solve::module::run_solve( + solve_config, RigidVariables::default(), test_subs, Default::default(), abilities_store, - Default::default(), - &exposed_for_module.exposed_by_module, - Default::default(), ); dbg_do!( roc_debug_flags::ROC_PRINT_UNIFICATIONS_DERIVED, diff --git a/crates/reporting/tests/helpers/mod.rs b/crates/reporting/tests/helpers/mod.rs index 187102105ea..a8bea3eeacb 100644 --- a/crates/reporting/tests/helpers/mod.rs +++ b/crates/reporting/tests/helpers/mod.rs @@ -15,7 +15,8 @@ use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds}; use roc_parse::parser::{SourceError, SyntaxError}; use roc_problem::can::Problem; use roc_region::all::Loc; -use roc_solve::solve::{self, Aliases}; +use roc_solve::module::SolveConfig; +use roc_solve::{solve, Aliases}; use roc_solve_problem::TypeError; use roc_types::subs::{Content, Subs, VarStore, Variable}; use roc_types::types::Types; @@ -33,26 +34,24 @@ pub fn infer_expr( problems: &mut Vec, types: Types, constraints: &Constraints, - constraint: &Constraint, + constraint: Constraint, pending_derives: PendingDerives, aliases: &mut Aliases, abilities_store: &mut AbilitiesStore, derived_module: SharedDerivedModule, expr_var: Variable, ) -> (Content, Subs) { - let (solved, _) = solve::run( - ModuleId::ATTR, + let config = SolveConfig { types, constraints, - problems, - subs, - aliases, - constraint, + root_constraint: constraint, + home: ModuleId::ATTR, pending_derives, - abilities_store, - &Default::default(), + exposed_by_module: &Default::default(), derived_module, - ); + }; + + let (solved, _) = solve::run(config, problems, subs, aliases, abilities_store); let content = *solved.inner().get_content_without_compacting(expr_var); diff --git a/crates/reporting/tests/test_reporting.rs b/crates/reporting/tests/test_reporting.rs index 4d51d7c1907..aeed31a9fcc 100644 --- a/crates/reporting/tests/test_reporting.rs +++ b/crates/reporting/tests/test_reporting.rs @@ -258,7 +258,7 @@ mod test_reporting { subs.rigid_var(var.value, "*".into()); } - let mut solve_aliases = roc_solve::solve::Aliases::default(); + let mut solve_aliases = roc_solve::Aliases::default(); for (name, alias) in output.aliases { solve_aliases.insert(&mut types, name, alias); @@ -271,7 +271,7 @@ mod test_reporting { &mut unify_problems, types, &constraints, - &constraint, + constraint, // Use `new_report_problem_as` in order to get proper derives. // TODO: remove the non-new reporting test infra. PendingDerives::default(), From 739343a5b6f2dd114ede043f64eb843cf4853d82 Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Thu, 22 Jun 2023 14:30:16 -0500 Subject: [PATCH 017/140] Clippy --- crates/compiler/solve/src/env.rs | 2 +- crates/compiler/solve/src/lib.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/compiler/solve/src/env.rs b/crates/compiler/solve/src/env.rs index 1f795046987..d55a571a904 100644 --- a/crates/compiler/solve/src/env.rs +++ b/crates/compiler/solve/src/env.rs @@ -75,7 +75,7 @@ impl<'a> Env<'a> { } /// Retrieves an environment for unification. - pub fn uenv<'r>(&'r mut self) -> UEnv<'r> { + pub fn uenv(&mut self) -> UEnv { UEnv::new(self.subs) } } diff --git a/crates/compiler/solve/src/lib.rs b/crates/compiler/solve/src/lib.rs index 292c79d8622..d43fc7bff41 100644 --- a/crates/compiler/solve/src/lib.rs +++ b/crates/compiler/solve/src/lib.rs @@ -3,6 +3,8 @@ #![warn(clippy::dbg_macro)] // See github.com/roc-lang/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] +// TODO to be removed +#![allow(clippy::too_many_arguments)] pub mod ability; pub mod module; From ebac468d248d4840289addb4e3f4ca37417b9990 Mon Sep 17 00:00:00 2001 From: Luke Boswell Date: Sat, 24 Jun 2023 20:08:16 +1000 Subject: [PATCH 018/140] Udpate structure of WIP website --- .../content/blog/roc_website_2022.md | 118 ------------------ www/wip_new_website/content/community_page.md | 39 ++++++ .../content/contributing_page.md | 25 ---- www/wip_new_website/content/design_goals.md | 44 +++++++ www/wip_new_website/content/discover_page.md | 36 ------ www/wip_new_website/content/docs_page.md | 11 ++ www/wip_new_website/content/home_page.md | 35 ++++-- ...etting_started_page.md => install_page.md} | 27 +++- www/wip_new_website/content/learn_roc_page.md | 24 ---- www/wip_new_website/content/sponsor_page.md | 8 ++ www/wip_new_website/content/tutorial_page.md | 5 + www/wip_new_website/main.roc | 11 +- 12 files changed, 160 insertions(+), 223 deletions(-) delete mode 100644 www/wip_new_website/content/blog/roc_website_2022.md create mode 100644 www/wip_new_website/content/community_page.md delete mode 100644 www/wip_new_website/content/contributing_page.md create mode 100644 www/wip_new_website/content/design_goals.md delete mode 100644 www/wip_new_website/content/discover_page.md create mode 100644 www/wip_new_website/content/docs_page.md rename www/wip_new_website/content/{getting_started_page.md => install_page.md} (56%) delete mode 100644 www/wip_new_website/content/learn_roc_page.md create mode 100644 www/wip_new_website/content/sponsor_page.md create mode 100644 www/wip_new_website/content/tutorial_page.md diff --git a/www/wip_new_website/content/blog/roc_website_2022.md b/www/wip_new_website/content/blog/roc_website_2022.md deleted file mode 100644 index 0c431f04ccb..00000000000 --- a/www/wip_new_website/content/blog/roc_website_2022.md +++ /dev/null @@ -1,118 +0,0 @@ -The Roc Programming Language -============================ - -*By: Richard Feldman, 2022/10/11* - -Roc's goal is to be a fast, friendly, functional language. It's very much a work in progress; below, you can see the current progress towards this goal. This website is intentionally unstyled as a way to emphasize the language's current level of incompleteness. The website will become more polished after the language itself becomes more polished! - -Roc compiles to machine code or to [WebAssembly](https://webassembly.org). Eventually you'll be able to use Roc to build high-quality servers, command-line applications, graphical native desktop user interfaces, among other classes of applications. Today, only command-line interfaces have support beyond the proof-of-concept stage; the other use cases will mature over time. - -Like [Lua](https://www.lua.org/), Roc's automatic memory management doesn't require a virtual machine, and it's possible to call Roc functions directly from any language that can call [C](https://en.wikipedia.org/wiki/C_(programming_language)) functions. This makes Roc additionally useful as a language for implementing plugins, and gives you a way to incrementally transition a legacy code base from another language to Roc. - -So far, the Roc compiler has progressed past the "proof of concept" stage, but there are currently lots of known bugs and unimplemented features, and the documentation for both the language and the standard library is incomplete. The overall ecosystem is in its infancy, and the compiler is neither battle-tested nor fuzz-tested yet, so we don't recommend relying on Roc for critical projects until its development is further along. - -With all that context in mind, if you'd like to try it out or to get involved with contributing, the [source code repository](https://github.com/roc-lang/roc) has [nightly builds](https://github.com/roc-lang/roc/releases) you can download, and a [tutorial](https://roc-lang.org/tutorial). - -If you'd like to learn more about Roc, you can continue reading here, or check out one of these videos: - -* [Roc at Handmade Seattle](https://media.handmade-seattle.com/roc-lang) - November 12, 2021 (very low-level explanation of how Roc's compiler makes programs run fast) -* [Outperforming Imperative with Pure Functional Languages](https://youtu.be/vzfy4EKwG_Y) - October 1, 2021 (about Roc's runtime performance and optimizer) -* [A taste of Roc](https://youtu.be/6qzWm_eoUXM) - September 23, 2021 (syntax, application examples) -* [Roc at the Philly ETE conference](https://youtu.be/cpQwtwVKAfU?t=75) - May 6, 2021 (platforms and applications) -* [Roc on Zig Showtime](https://youtu.be/FMyyYdFSOHA) - April 24, 2021 (making a platform) -* [Roc at the Berlin FP Meetup](https://youtu.be/ZnYa99QoznE?t=4790) - September 1, 2020 (overall vision for the language) - -A _Fast_ Language ------------------ - -### Goal - -We want Roc to run faster than any non-systems language (like C, C++, Rust, or Zig) that sees mainstream use in industry. The goal is that nobody should find themselves thinking "I should rewrite my Roc program in \[some mainstream garbage-collected language\] because that will make it run significantly faster." - -When benchmarking Roc code against similarly-optimized programs written in [Go](https://go.dev), [Swift](https://www.swift.org/), [Java](https://www.java.com), [C#](https://learn.microsoft.com/en-us/dotnet/csharp), or [JavaScript](https://www.ecma-international.org/publications-and-standards/standards/ecma-262), we generally aim for Roc to outperform all of those languages. Outperforming systems languages like Rust, Zig, C, D, and C++ is a non-goal, as is outperforming research languages that see little or no use in industry. (Realistically, there will always be certain specific benchmarks where some popular non-systems-level languages outperform Roc, but the goal is to usually be at the front of that pack.) - -#### Current progress - -Progress towards this performance goal is already quite far along. - -Roc already uses unboxed data structures and unboxed closures, monomorphizes polymorphic code, and uses LLVM as a compiler backend. These optimizations, especially unboxed closures and monomorphization, can be found in several systems-level languages (like C++ and Rust), but not in any mainstream garbage-collected languages. Roc closures in particular have the distinction of being as ergonomic as the closures found in garbage-collected languages (where they are typically boxed), but have the performance of systems language closures (which are typically unboxed, but have more complicated types). - -Because of these optimizations, in many cases Roc code already compiles to the same machine instructions that the equivalent code written in one of these systems languages would. Something we do regularly is to compare the LLVM instructions generated by Roc's compiler and by these systems languages' compilers, to check whether we're generating equivalent instructions. - -That said, there are also cases where Roc has strictly more runtime overhead than languages like C, C++, Zig, and Rust do. The most costly is automatic memory management, which Roc implements using automatic reference counting. Static reference count optimizations like elision and reuse (thanks to Morphic and [Perceus](https://www.microsoft.com/en-us/research/publication/perceus-garbage-free-reference-counting-with-reuse/)) improve things, but significant runtime overhead remains. - -Eliminating this overhead altogether would require sacrificing other design goals (e.g. it would require introducing memory-unsafe operations, or compile-time lifetime errors), and there isn't much overhead left to remove outside of automatic memory management. For example, smaller sources of overhead include mandatory array bounds checks, disallowing cyclic references (which rules out a certain niche of efficient graph data structures), and automatic opportunistic in-place mutation instead of direct mutation. Even if all of these sources of overhead were completely eliminated, it seems unlikely that typical Roc programs would see a particularly big performance boost. - -Overall, we expect Roc's performance in the use cases mentioned above (servers, CLIs, GUIs, etc.) to be about the same as the equivalent C++ code would be, if all that C++ code (including its dependencies) were written in a restricted subset of C++ which always did array bounds checks and used shared pointers for all heap allocations. The Roc code might even run somewhat faster, because its reference counts are non-atomic by default, and can be statically optimized away in some cases—but then again, Roc also has a bit of overhead to perform opportunistic in-place mutation instead of direct mutation. - -To be clear, we don't expect this because we've benchmarked a bunch of programs written in Roc and in this restricted C++ subset, and found that the numbers were about the same (although if you know C++ well enough and want to do such experiments, we'd happy to help and would be interested to see the results!) but rather because Roc's compiler and [clang](https://clang.llvm.org/) should both be generating essentially the same LLVM instructions when the C++ is restricted to that subset. - -Of course, _unrestricted_ C++ code can certainly run faster than unrestricted Roc code. The same is true when comparing other such minimal-overhead systems languages to Roc, including Rust, Zig, C, and D. The point of the comparison is to give you a general idea of what Roc compiles to, since it is quite different from the VMs and JITted bytecode interpreters found in today's most popular garbage-collected languages! - -The talk [Outperforming Imperative with Pure Functional Languages](https://youtu.be/vzfy4EKwG_Y) discusses some early results from Roc's optimizations, and [Roc at Handmade Seattle](https://media.handmade-seattle.com/roc-lang) gets into low-level details of how Roc's compiler generates programs similarly to how clang does. - -A _Friendly_ Language ---------------------- - -### Goals - -Roc aims to be a user-friendly language with a friendly community of users. - -A programming language can be much more than a tool for writing software, it can also be a way for people to come together through shared experiences, to teach and to learn from one another, and to make new friends. - -No community is perfect, but a community where people show kindness to each another by default can be a true joy to participate in. That all starts with friendliness, especially towards beginners, and including towards people who prefer other programming languages. After all, languages are tools people use to create software, and there's no need for us to create artificial divisions between ourselves based on the tools we use! - -On a technical level, Roc aims to ship a toolset where user-friendliness is a major priority. This includes everything from helpful error messages (aiming to meet the bar set by [Elm](https://elm-lang.org)) to quality-of-life improvements inspired by dynamic languages (always being able to run your program even if there are compile errors, automatic serialization and deserialization using schemas determined by type inference, reliable hot code loading that's always enabled and requires no configuration to set up, etc.) to accessibility features in the included editor. - -Roc also aims to ship a single binary that includes not only a compiler, but also a [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop), package manager, test runner, debugger, static analyzer, code formatter, and a full-featured editor, all of which are designed to work seamlessly together. - -### Current Progress - -Work has not yet started on the package manager, static analyzer, debugger, or hot code loading system, and although work has started on the editor, it's not yet far enough along to be usable for practical purposes. The standard library is perhaps 80 percent complete in terms of functionality, but a lot of operations do not yet have documentation. - -The REPL fully supports entering arbitrary expressions, and will evaluate them and print the results. It remembers recent expressions entered in the current session (if you press the up arrow), but it can't yet execute effects. You can try out the REPL in a browser at [roc-lang.org/repl](https://roc-lang.org/repl) - it uses a WebAssembly build of Roc's compiler, and compiles the code you write to WebAssembly on the fly, which it then executes in the browser to display the answer. - -The compiler works well enough on a basic level to build things with it, but some error messages could use significant improvement, and it has a lot of known bugs and missing features. You can currently use it on macOS (either Intel or Apple Silicon), Linux (only x86-64 machines at the moment), and Windows (only recently supported; debugging and testing features don't work on it yet, and there are likely bugs we haven't encountered yet due to lack of battle testing). Support for other operating systems has not yet been discussed. - -The compiler doesn't yet support incremental compilation or hot code loading, and build times vary based on what machine you're building for. - -For example, suppose you run \`roc check\`, which reports errors it finds (type mismatches, naming errors, and so on) but doesn't actually build an executable, on a code base that's under a thousand lines of code. On an M1 MacBook Pro, this typically takes about 10 milliseconds. - -In contrast, if you do \`roc build\` (or \`roc run\`) on that same machine, it will take closer to 500 milliseconds instead. Almost all that extra time is spent waiting for LLVM to generate (unoptimized) machine code, and then for the system linker to assemble an executable from it. - -Fortunately, we can eliminate almost all of those extra 490 millisconds of build time by using Roc's (work in progress) development backend instead of LLVM. This compiles directly from Roc's internal representation to machine code, like most compilers did before LLVM. (LLVM can optimize code into running very fast, but even when it performs no optimization at all, LLVM itself takes a lot longer to run than generating unoptimized machine code directly.) - -The LLVM backend is currently the most feature-complete, followed closely by the WebAssembly backend (which the online REPL uses exclusively, instead of LLVM). The x86 and ARM backends still have a ways to go, but improving them can be done by anyone with the patience to read some documentation; we have issues split up for them, and are happy to help new contributors get up and running! - -Builds on Linux and Windows also use Roc's surgical linker instead of the system linker, which runs so fast that linking essentially disappears from the performance profile altogether. The surgical linker currently only works on Linux and Windows, and it currently supports building executables but not (yet) dynamic libraries, which is relevant if you're using Roc to create plugins or want to call Roc functions from existing code bases in other languages. Work has started on macOS surgical linking, but it isn't usable yet. If you're interested in working on that, please get in touch on [Roc Zulip](https://roc.zulipchat.com/)! - -The test runner currently has first-class support for running standard non-effectful tests. It does not yet have first-class support for effectful tests, property-based tests, snapshot tests, or "simulation tests" (where effects are replaced by hardcoded values during the test - similar to "mocking" in other languages), although these are all planned for the future. - -The code formatter is nearly feature-complete, although occasionally it will report an error - usually due to a comment being placed somewhere it doesn't yet know how to handle. Unlike most of the rest of the compiler, the formatter is one place where the number of known bugs is so small that fuzzing would be very helpful as a way to surface bugs we don't yet know about. (If you're interested in working on setting up fuzzing for the formatter, please let us know in the [`#contributing` channel](https://roc.zulipchat.com/#narrow/stream/316715-contributing) on Zulip! Separately, we're also very interested in fuzzing the compiler, even though we already have a sizable list of known bugs there.) - -On the community side, so far the community is a friendly bunch, and we want to keep it that way as it grows! We hope to do that by encouraging a culture of kindness and helping one another out, especially by being welcoming towards beginners. - -If you'd like to join in, the best place to do that is in our Zulip chat. Feel free to drop by the [`introductions` topic](https://roc.zulipchat.com/#narrow/stream/231634-beginners/topic/introductions) and introduce yourself! - -A _Functional_ Language ------------------------ - -### Goals - -Roc aims to be a purely functional programming language. This means all Roc functions are [pure functions](https://en.wikipedia.org/wiki/Pure_function), and all effects are [managed effects](https://medium.com/@kaw2k/managed-effects-and-elm-36b7fcd246a9) instead of side effects. - -A major motivating reason for this is to facilitate tooling. For example, in the future the goal is that Roc's test runner won't bother re-running tests whose outcomes could not possibly have changed (because they were pure functions whose inputs did not change). Tests that contain only pure functions can be trivially run in parallel, and they will never [flake](https://www.smashingmagazine.com/2021/04/flaky-tests-living-nightmare/). Additionally, having the guarantee that the application contains only pure functions can also make certain debugging tools more reliable, such as time travel and retroactive tracing. - -Roc also takes a novel approach to managed effects. In most programming languages, the standard library contains both data structures and I/O primitives (e.g. for using the file system or the network), and then you might decide to use a [framework](https://en.wikipedia.org/wiki/Application_framework) on top of that standard library. - -In Roc, every application is built on a _platform_. A platform is like a framework except that it also provides I/O primitives and behind-the-scenes memory management. (Roc's standard library only contains data structures.) In practice, this means that using Roc feels similar to using any other programming language where you've chosen to use a framework, except that the documentation for your I/O primitives comes from the framework instead of the standard library. - -This might sound like a minor distinction, but it turns out there are a lot of surprising benefits to organizing things this way, which would be impossible to achieve without having platforms as a first-class language concept. [The Edges of Cutting-Edge Languages](https://youtu.be/cpQwtwVKAfU) goes into more detail about some of these benefits. - -### Current Progress - -Today, platforms as a concept already exist, and there are a few different ones implemented. You can find them in the [`examples/`](https://github.com/roc-lang/roc/tree/main/examples) directory in the source code repository. The platform for building command-line interfaces is the most fully featured; the others are mostly in the proof-of-concept stage. - -Roc's built-in tooling is not yet far enough along to take advantage of pure functions. For example, there is a built-in test runner, but it does not yet run tests in parallel or skip running tests whose outcomes could not possibly have changed. - -Roc is already a purely functional programming language, though, so all of these benefits are ready to be unlocked as the tooling implementations progress! \ No newline at end of file diff --git a/www/wip_new_website/content/community_page.md b/www/wip_new_website/content/community_page.md new file mode 100644 index 00000000000..e78151d6fce --- /dev/null +++ b/www/wip_new_website/content/community_page.md @@ -0,0 +1,39 @@ +# Contribute to Roc + +## Community Values + + + +## Meet the Community + +- Group Chat [roc.zulipchat.com](https://roc.zulipchat.com/) +- Github Project [roc-lang/roc](https://github.com/roc-lang/roc) +- Meetups & Events + +## Ideas & Proposals + +- [Good First Issues](https://github.com/roc-lang/roc/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) + + + +Roc doesn't have a formal process for managing design proposals. The guiding principal for now is that as a community we should all be friendly, supportive, and openly discuss and sharing ideas. + +There are three loose stages that a design proposal can go through in Roc: Idea, Proposal, and Implementation. + +In the Idea stage, people are encouraged to describe their idea and explore the problem, potential solutions, and trade-offs. It is helpful to share the idea in the group chat using the #ideas channel. + +If there is a general consensus that an idea is promising and worth developing, people are encouraged to develop a design Proposal. Some ideas are simple and should progress straight to implementation. However, for more complex Proposals a it write the design into an article or blog post and share it online. This documentation helps in clarifying the proposal and making it more accessible to the community. + +Implementation using PR... + +## Code of Conduct + + diff --git a/www/wip_new_website/content/contributing_page.md b/www/wip_new_website/content/contributing_page.md deleted file mode 100644 index 4dc9fcf6a97..00000000000 --- a/www/wip_new_website/content/contributing_page.md +++ /dev/null @@ -1,25 +0,0 @@ -# Contribute to Roc - - - -## Sponsorship - -- [Github Sponsorship](https://github.com/sponsors/roc-lang) - -## Contributor Guidelines - -- [CONTRIBUTING](https://github.com/roc-lang/roc/blob/main/CONTRIBUTING.md) - -## Ideas & Proposals - -- [Good First Issues](https://github.com/roc-lang/roc/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) - -## Community Values & Code of Conduct - -## Package Development - -## Platform Development - -## Roc Jobs Board - -## Contact the Team diff --git a/www/wip_new_website/content/design_goals.md b/www/wip_new_website/content/design_goals.md new file mode 100644 index 00000000000..2148b5e12fc --- /dev/null +++ b/www/wip_new_website/content/design_goals.md @@ -0,0 +1,44 @@ + +# Design Goals + + + +# Fast + + + +# Friendly + + + +# Functional + + \ No newline at end of file diff --git a/www/wip_new_website/content/discover_page.md b/www/wip_new_website/content/discover_page.md deleted file mode 100644 index 80ea796478d..00000000000 --- a/www/wip_new_website/content/discover_page.md +++ /dev/null @@ -1,36 +0,0 @@ -# Discover Roc - - - -## Meet the Community - -- Group Chat [roc.zulipchat.com](https://roc.zulipchat.com/) -- Github Project [roc-lang/roc](https://github.com/roc-lang/roc) -- Meetups & Events -- Socials - -## Blog - -- [Website Update Oct 2022](/blog/roc_website_2022.html) - -## Roc Applications - -- Tools & Scripts -- Web (coming soon) -- Networking & Servers (coming soon) -- Graphical (coming soon) -- Scientific (coming soon) -- Embedded (coming soon) - -## Roc Platforms - -## Roc Packages - -## Talks and Publications - -- Roc at Handmade Seattle - November 12, 2021 (very low-level explanation of how Roc's compiler makes programs run fast) -- Outperforming Imperative with Pure Functional Languages - October 1, 2021 (about Roc's runtime performance and optimizer) -- A taste of Roc - September 23, 2021 (syntax, application examples) -- Roc at the Philly ETE conference - May 6, 2021 (platforms and applications) -- Roc on Zig Showtime - April 24, 2021 (making a platform) -- Roc at the Berlin FP Meetup - September 1, 2020 (overall vision for the language) \ No newline at end of file diff --git a/www/wip_new_website/content/docs_page.md b/www/wip_new_website/content/docs_page.md new file mode 100644 index 00000000000..764b1b5de7c --- /dev/null +++ b/www/wip_new_website/content/docs_page.md @@ -0,0 +1,11 @@ +# Documentation + +- Builtin Package +- Basic-CLI Platform + + + +## Guides + +- [Frequently Asked Questions](https://github.com/roc-lang/roc/blob/main/FAQ.md) +- [Roc for Elm Programmers](https://github.com/roc-lang/roc/blob/main/roc-for-elm-programmers.md) \ No newline at end of file diff --git a/www/wip_new_website/content/home_page.md b/www/wip_new_website/content/home_page.md index 01f9621e1ac..b45b1fbf443 100644 --- a/www/wip_new_website/content/home_page.md +++ b/www/wip_new_website/content/home_page.md @@ -4,30 +4,43 @@ The purpose of the Home page is to function as the first point of contact for al This page contains minimal content, so that visitors are able to quickly scan the page. It should not be cluttered or overwhelming. It should reflect Roc's goals (fast, friendly, functional) and values (welcoming community). --> -# Roc lang - - +# Roc lang{#page-title} - fast - friendly - functional + + ## Try Roc -## [Discover Roc](/discover_page.html) +## Use cases (Roc applications) - + -## [Learn Roc](/learn_roc_page.html) +- Tools & Scripts +- Web (coming soon) +- Networking & Servers (coming soon) +- Graphical (coming soon) +- Scientific (coming soon) +- Embedded (coming soon) - +## Roc Platforms/Applications (vs libraries) -## [Contribute to Roc](contributing_page.html) + - +## Talks and Publications -## [Getting Started](/getting_started_page.html) + - \ No newline at end of file +- Roc at Handmade Seattle - November 12, 2021 (very low-level explanation of how Roc's compiler makes programs run fast) +- Outperforming Imperative with Pure Functional Languages - October 1, 2021 (about Roc's runtime performance and optimizer) +- A taste of Roc - September 23, 2021 (syntax, application examples) +- Roc at the Philly ETE conference - May 6, 2021 (platforms and applications) +- Roc on Zig Showtime - April 24, 2021 (making a platform) +- Roc at the Berlin FP Meetup - September 1, 2020 (overall vision for the language) \ No newline at end of file diff --git a/www/wip_new_website/content/getting_started_page.md b/www/wip_new_website/content/install_page.md similarity index 56% rename from www/wip_new_website/content/getting_started_page.md rename to www/wip_new_website/content/install_page.md index 9bcdc98b320..b4f08562df4 100644 --- a/www/wip_new_website/content/getting_started_page.md +++ b/www/wip_new_website/content/install_page.md @@ -1,6 +1,4 @@ -# Getting Started - - +# Installing Roc ## Installation @@ -12,9 +10,13 @@ ## Nightly Builds + + ## Roc CLI -- Develop `roc dev` + +- Script `roc myApp.roc` +- Develop `roc dev` - Test `roc test` - Run `roc run` - Build `roc build` @@ -23,9 +25,24 @@ ## Package Management -- URL Packages + ## Editor Support + + - Language Server - Neo(Vim) diff --git a/www/wip_new_website/content/learn_roc_page.md b/www/wip_new_website/content/learn_roc_page.md deleted file mode 100644 index 4992f612220..00000000000 --- a/www/wip_new_website/content/learn_roc_page.md +++ /dev/null @@ -1,24 +0,0 @@ -# Learn Roc - - - -## Tutorial - -- [Tutorial](https://www.roc-lang.org/tutorial) - -## Examples - -<-- link to examples site --> - -## Guides - -<-- links to guides --> - -- [Frequently Asked Questions](https://github.com/roc-lang/roc/blob/main/FAQ.md) -- [Roc for Elm Programmers](https://github.com/roc-lang/roc/blob/main/roc-for-elm-programmers.md) - -## Documentation - -- Builtin Package -- Basic-CLI Platform -- Language Reference \ No newline at end of file diff --git a/www/wip_new_website/content/sponsor_page.md b/www/wip_new_website/content/sponsor_page.md new file mode 100644 index 00000000000..71a00cf1050 --- /dev/null +++ b/www/wip_new_website/content/sponsor_page.md @@ -0,0 +1,8 @@ +# Sponsor + +- [Github Sponsorship](https://github.com/sponsors/roc-lang) + + \ No newline at end of file diff --git a/www/wip_new_website/content/tutorial_page.md b/www/wip_new_website/content/tutorial_page.md new file mode 100644 index 00000000000..2d8346554d9 --- /dev/null +++ b/www/wip_new_website/content/tutorial_page.md @@ -0,0 +1,5 @@ +# Tutorial + +This is a placeholder page for the Roc tutorial. + +TODO move the tutorial here from `../generate_tutorial/src/input/tutorial.roc` \ No newline at end of file diff --git a/www/wip_new_website/main.roc b/www/wip_new_website/main.roc index af6b3804b6b..1b2d4bf9d99 100644 --- a/www/wip_new_website/main.roc +++ b/www/wip_new_website/main.roc @@ -48,6 +48,7 @@ view = \page, htmlContent -> text htmlContent, ], footer [] [ + # text "This site is powered by ", a [href "https://www.netlify.com"] [ text "Netlify"], text ". Made by people who like to make nice things. © Roc 2023", @@ -64,10 +65,12 @@ viewNavbar = rocLogo ], div [id "top-bar-links"] [ - a [href "/discover_page.html"] [text "discover"], - a [href "/learn_roc_page.html"] [text "learn"], - a [href "/contributing_page.html"] [text "contribute"], - a [href "/getting_started_page.html"] [text "getting started"], + a [href "/tutorial_page.html"] [text "tutorial"], + a [href "/install_page.html"] [text "install"], + a [href "#todo-link-to-examples-site"] [text "examples"], + a [href "/community_page.html"] [text "community"], + a [href "/sponsor_page.html"] [text "sponsor"], + a [href "/docs_page.html"] [text "docs"], ], ], ] From 97c4ca8b8d2b2b4b5e9ff92819f4cc1fb6a4cf2c Mon Sep 17 00:00:00 2001 From: Luke Boswell Date: Sat, 24 Jun 2023 20:15:52 +1000 Subject: [PATCH 019/140] update page title and descriptions --- .../content/{design_goals.md => design_goals_page.md} | 0 www/wip_new_website/main.roc | 10 ++++++---- 2 files changed, 6 insertions(+), 4 deletions(-) rename www/wip_new_website/content/{design_goals.md => design_goals_page.md} (100%) diff --git a/www/wip_new_website/content/design_goals.md b/www/wip_new_website/content/design_goals_page.md similarity index 100% rename from www/wip_new_website/content/design_goals.md rename to www/wip_new_website/content/design_goals_page.md diff --git a/www/wip_new_website/main.roc b/www/wip_new_website/main.roc index 1b2d4bf9d99..d43c61856f7 100644 --- a/www/wip_new_website/main.roc +++ b/www/wip_new_website/main.roc @@ -8,11 +8,13 @@ app "roc-website" pageData = Dict.empty {} - |> Dict.insert "discover_page.html" { title: "Discover Roc", description: "Discover the Roc programming language" } - |> Dict.insert "contributing_page.html" { title: "Contribute to Roc", description: "Contribute to the Roc programming language" } - |> Dict.insert "learn_roc_page.html" { title: "Learn Roc", description: "Learn the Roc programming language" } + |> Dict.insert "community_page.html" { title: "Community", description: "The Roc community" } + |> Dict.insert "design_goals_page.html" { title: "Design Goals", description: "Roc's design goals" } + |> Dict.insert "docs_page.html" { title: "Documentation", description: "Learn the Roc programming language" } |> Dict.insert "home_page.html" { title: "Roc Lang", description: "The Roc programming language" } - |> Dict.insert "getting_started_page.html" { title: "Let's Roc", description: "Getting started with the Roc programming language" } + |> Dict.insert "install_page.html" { title: "Install", description: "Getting started with the Roc programming language" } + |> Dict.insert "sponsor_page.html" { title: "Sponsor", description: "Sponsor Roc" } + |> Dict.insert "tutorial_page.html" { title: "Tutorial", description: "The Roc tutorial" } getPage : Str -> {title : Str, description : Str} getPage = \current -> From 17512873e8949641e12b02a38f58b16225366ebe Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 18 Jun 2023 15:44:40 +0200 Subject: [PATCH 020/140] add LayoutRepr::Ptr --- crates/compiler/alias_analysis/src/lib.rs | 3 ++- crates/compiler/gen_dev/src/generic64/mod.rs | 1 + crates/compiler/gen_dev/src/generic64/storage.rs | 2 +- crates/compiler/gen_llvm/src/llvm/align.rs | 2 +- crates/compiler/gen_llvm/src/llvm/compare.rs | 4 ++-- crates/compiler/gen_llvm/src/llvm/convert.rs | 7 +++++++ crates/compiler/gen_llvm/src/llvm/expect.rs | 4 ++++ crates/compiler/gen_llvm/src/llvm/refcounting.rs | 6 ++++++ crates/compiler/gen_wasm/src/layout.rs | 1 + crates/compiler/gen_wasm/src/low_level.rs | 3 ++- crates/compiler/mono/src/code_gen_help/equality.rs | 1 + crates/compiler/mono/src/code_gen_help/mod.rs | 6 ++++++ crates/compiler/mono/src/code_gen_help/refcount.rs | 3 +++ crates/compiler/mono/src/ir.rs | 3 +++ crates/compiler/mono/src/layout.rs | 9 +++++++-- crates/compiler/mono/src/layout/intern.rs | 8 ++++++++ crates/glue/src/types.rs | 1 + crates/repl_eval/src/eval.rs | 6 ++++++ 18 files changed, 62 insertions(+), 8 deletions(-) diff --git a/crates/compiler/alias_analysis/src/lib.rs b/crates/compiler/alias_analysis/src/lib.rs index 855b54f86e0..723c78333b9 100644 --- a/crates/compiler/alias_analysis/src/lib.rs +++ b/crates/compiler/alias_analysis/src/lib.rs @@ -1589,13 +1589,14 @@ fn layout_spec_help<'a>( } } - Boxed(inner_layout) => { + Ptr(inner_layout) | Boxed(inner_layout) => { let inner_type = layout_spec_help(env, builder, interner, interner.get_repr(inner_layout))?; let cell_type = builder.add_heap_cell_type(); builder.add_tuple_type(&[cell_type, inner_type]) } + // TODO(recursive-layouts): update once we have recursive pointer loops RecursivePointer(union_layout) => match interner.get_repr(union_layout) { LayoutRepr::Union(union_layout) => { diff --git a/crates/compiler/gen_dev/src/generic64/mod.rs b/crates/compiler/gen_dev/src/generic64/mod.rs index 30a7078ee59..db2508b990e 100644 --- a/crates/compiler/gen_dev/src/generic64/mod.rs +++ b/crates/compiler/gen_dev/src/generic64/mod.rs @@ -4385,6 +4385,7 @@ macro_rules! single_register_layouts { macro_rules! pointer_layouts { () => { LayoutRepr::Boxed(_) + | LayoutRepr::Ptr(_) | LayoutRepr::RecursivePointer(_) | LayoutRepr::Union( UnionLayout::Recursive(_) diff --git a/crates/compiler/gen_dev/src/generic64/storage.rs b/crates/compiler/gen_dev/src/generic64/storage.rs index a1581c7c037..318f9dc0f65 100644 --- a/crates/compiler/gen_dev/src/generic64/storage.rs +++ b/crates/compiler/gen_dev/src/generic64/storage.rs @@ -826,7 +826,7 @@ impl< self.copy_to_stack_offset(buf, size, from_offset, to_offset) } - LayoutRepr::RecursivePointer(_) | LayoutRepr::Boxed(_) | LayoutRepr::Union(_) => { + pointer_layouts!() => { // like a 64-bit integer debug_assert_eq!(to_offset % 8, 0); let reg = self.load_to_general_reg(buf, sym); diff --git a/crates/compiler/gen_llvm/src/llvm/align.rs b/crates/compiler/gen_llvm/src/llvm/align.rs index d26b83ad5e0..8209feb06c1 100644 --- a/crates/compiler/gen_llvm/src/llvm/align.rs +++ b/crates/compiler/gen_llvm/src/llvm/align.rs @@ -120,7 +120,7 @@ impl<'a> LlvmAlignment<'a> for LayoutRepr<'a> { .llvm_alignment_bytes(interner), Builtin(builtin) => builtin.llvm_alignment_bytes(interner), RecursivePointer(_) => interner.target_info().ptr_width() as u32, - Boxed(_) => interner.target_info().ptr_width() as u32, + Ptr(_) | Boxed(_) => interner.target_info().ptr_width() as u32, } } } diff --git a/crates/compiler/gen_llvm/src/llvm/compare.rs b/crates/compiler/gen_llvm/src/llvm/compare.rs index 3f0cb0b4764..804e8db8120 100644 --- a/crates/compiler/gen_llvm/src/llvm/compare.rs +++ b/crates/compiler/gen_llvm/src/llvm/compare.rs @@ -185,7 +185,7 @@ fn build_eq<'a, 'ctx>( rhs_val, ), - LayoutRepr::Boxed(inner_layout) => build_box_eq( + LayoutRepr::Ptr(inner_layout) | LayoutRepr::Boxed(inner_layout) => build_box_eq( env, layout_interner, layout_ids, @@ -385,7 +385,7 @@ fn build_neq<'a, 'ctx>( result.into() } - LayoutRepr::Boxed(inner_layout) => { + LayoutRepr::Ptr(inner_layout) | LayoutRepr::Boxed(inner_layout) => { let is_equal = build_box_eq( env, layout_interner, diff --git a/crates/compiler/gen_llvm/src/llvm/convert.rs b/crates/compiler/gen_llvm/src/llvm/convert.rs index 4cec102a7c1..f0326ee1e89 100644 --- a/crates/compiler/gen_llvm/src/llvm/convert.rs +++ b/crates/compiler/gen_llvm/src/llvm/convert.rs @@ -40,6 +40,13 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>( inner_type.ptr_type(AddressSpace::default()).into() } Union(union_layout) => basic_type_from_union_layout(env, layout_interner, &union_layout), + + Ptr(_) => env + .context + .i64_type() + .ptr_type(AddressSpace::default()) + .as_basic_type_enum(), + RecursivePointer(_) => env .context .i64_type() diff --git a/crates/compiler/gen_llvm/src/llvm/expect.rs b/crates/compiler/gen_llvm/src/llvm/expect.rs index 92057f21a19..3bf0fa3960e 100644 --- a/crates/compiler/gen_llvm/src/llvm/expect.rs +++ b/crates/compiler/gen_llvm/src/llvm/expect.rs @@ -390,6 +390,10 @@ fn build_clone<'a, 'ctx>( ) } + LayoutRepr::Ptr(_) => { + unreachable!("for internal use only") + } + LayoutRepr::RecursivePointer(rec_layout) => { let layout = rec_layout; diff --git a/crates/compiler/gen_llvm/src/llvm/refcounting.rs b/crates/compiler/gen_llvm/src/llvm/refcounting.rs index 5235bcf872b..06f9e73bf1e 100644 --- a/crates/compiler/gen_llvm/src/llvm/refcounting.rs +++ b/crates/compiler/gen_llvm/src/llvm/refcounting.rs @@ -537,6 +537,12 @@ fn modify_refcount_layout_build_function<'a, 'ctx>( Some(function) } + Ptr(_inner) => { + debug_assert_eq!(true, false); + + None + } + Union(variant) => { use UnionLayout::*; diff --git a/crates/compiler/gen_wasm/src/layout.rs b/crates/compiler/gen_wasm/src/layout.rs index 93e3b202b61..853d951e0d6 100644 --- a/crates/compiler/gen_wasm/src/layout.rs +++ b/crates/compiler/gen_wasm/src/layout.rs @@ -98,6 +98,7 @@ impl WasmLayout { | NullableUnwrapped { .. }, ) | LayoutRepr::Boxed(_) + | LayoutRepr::Ptr(_) | LayoutRepr::RecursivePointer(_) => Self::Primitive(PTR_TYPE, PTR_SIZE), } } diff --git a/crates/compiler/gen_wasm/src/low_level.rs b/crates/compiler/gen_wasm/src/low_level.rs index d7dd1f3a322..3883a24a4e4 100644 --- a/crates/compiler/gen_wasm/src/low_level.rs +++ b/crates/compiler/gen_wasm/src/low_level.rs @@ -2030,7 +2030,8 @@ impl<'a> LowLevelCall<'a> { | LayoutRepr::Struct { .. } | LayoutRepr::Union(_) | LayoutRepr::LambdaSet(_) - | LayoutRepr::Boxed(_) => { + | LayoutRepr::Boxed(_) + | LayoutRepr::Ptr(_) => { // Don't want Zig calling convention here, we're calling internal Roc functions backend .storage diff --git a/crates/compiler/mono/src/code_gen_help/equality.rs b/crates/compiler/mono/src/code_gen_help/equality.rs index d0e3b813af1..6c212d4c3d1 100644 --- a/crates/compiler/mono/src/code_gen_help/equality.rs +++ b/crates/compiler/mono/src/code_gen_help/equality.rs @@ -38,6 +38,7 @@ pub fn eq_generic<'a>( Struct(field_layouts) => eq_struct(root, ident_ids, ctx, layout_interner, field_layouts), Union(union_layout) => eq_tag_union(root, ident_ids, ctx, layout_interner, union_layout), Boxed(inner_layout) => eq_boxed(root, ident_ids, ctx, layout_interner, inner_layout), + Ptr(inner_layout) => eq_boxed(root, ident_ids, ctx, layout_interner, inner_layout), LambdaSet(_) => unreachable!("`==` is not defined on functions"), RecursivePointer(_) => { unreachable!( diff --git a/crates/compiler/mono/src/code_gen_help/mod.rs b/crates/compiler/mono/src/code_gen_help/mod.rs index 9f51d264942..868ba8a0882 100644 --- a/crates/compiler/mono/src/code_gen_help/mod.rs +++ b/crates/compiler/mono/src/code_gen_help/mod.rs @@ -577,6 +577,11 @@ impl<'a> CodeGenHelp<'a> { LayoutRepr::Boxed(inner) } + LayoutRepr::Ptr(inner) => { + let inner = self.replace_rec_ptr(ctx, layout_interner, inner); + LayoutRepr::Ptr(inner) + } + LayoutRepr::LambdaSet(lambda_set) => { return self.replace_rec_ptr(ctx, layout_interner, lambda_set.representation) } @@ -844,5 +849,6 @@ fn layout_needs_helper_proc<'a>( LayoutRepr::LambdaSet(_) => true, LayoutRepr::RecursivePointer(_) => false, LayoutRepr::Boxed(_) => true, + LayoutRepr::Ptr(_) => false, } } diff --git a/crates/compiler/mono/src/code_gen_help/refcount.rs b/crates/compiler/mono/src/code_gen_help/refcount.rs index 8ebaba87140..4174698e097 100644 --- a/crates/compiler/mono/src/code_gen_help/refcount.rs +++ b/crates/compiler/mono/src/code_gen_help/refcount.rs @@ -239,6 +239,9 @@ pub fn refcount_generic<'a>( inner_layout, structure, ), + LayoutRepr::Ptr(_) => { + unreachable!("We should never call a refcounting helper on a Ptr layout directly") + } } } diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index bd9a0975b79..51f06a6d560 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -9866,6 +9866,9 @@ where LayoutRepr::Boxed(boxed) => { stack.push(layout_interner.get(boxed)); } + LayoutRepr::Ptr(inner) => { + stack.push(layout_interner.get(inner)); + } LayoutRepr::Union(union_layout) => match union_layout { UnionLayout::NonRecursive(tags) => { for in_layout in tags.iter().flat_map(|e| e.iter()) { diff --git a/crates/compiler/mono/src/layout.rs b/crates/compiler/mono/src/layout.rs index 91cf9d02ba8..4da1d0c0c2a 100644 --- a/crates/compiler/mono/src/layout.rs +++ b/crates/compiler/mono/src/layout.rs @@ -675,6 +675,7 @@ pub enum LayoutRepr<'a> { Builtin(Builtin<'a>), Struct(&'a [InLayout<'a>]), Boxed(InLayout<'a>), + Ptr(InLayout<'a>), Union(UnionLayout<'a>), LambdaSet(LambdaSet<'a>), RecursivePointer(InLayout<'a>), @@ -2555,7 +2556,7 @@ impl<'a> LayoutRepr<'a> { LambdaSet(lambda_set) => interner .get_repr(lambda_set.runtime_representation()) .safe_to_memcpy(interner), - Boxed(_) | RecursivePointer(_) => { + Boxed(_) | Ptr(_) | RecursivePointer(_) => { // We cannot memcpy pointers, because then we would have the same pointer in multiple places! false } @@ -2646,6 +2647,7 @@ impl<'a> LayoutRepr<'a> { .stack_size_without_alignment(interner), RecursivePointer(_) => interner.target_info().ptr_width() as u32, Boxed(_) => interner.target_info().ptr_width() as u32, + Ptr(_) => interner.target_info().ptr_width() as u32, } } @@ -2699,6 +2701,7 @@ impl<'a> LayoutRepr<'a> { Builtin(builtin) => builtin.alignment_bytes(interner.target_info()), RecursivePointer(_) => interner.target_info().ptr_width() as u32, Boxed(_) => interner.target_info().ptr_width() as u32, + Ptr(_) => interner.target_info().ptr_width() as u32, } } @@ -2723,6 +2726,7 @@ impl<'a> LayoutRepr<'a> { ptr_width, interner.get_repr(*inner).alignment_bytes(interner), ), + Ptr(inner) => interner.get_repr(*inner).alignment_bytes(interner), } } @@ -2776,6 +2780,7 @@ impl<'a> LayoutRepr<'a> { .contains_refcounted(interner), RecursivePointer(_) => true, Boxed(_) => true, + Ptr(inner) => interner.get_repr(*inner).contains_refcounted(interner), } } @@ -2831,7 +2836,7 @@ impl<'a> LayoutRepr<'a> { } }, LambdaSet(_) => return true, - Boxed(_) => { + Boxed(_) | Ptr(_) => { // If there's any layer of indirection (behind a pointer), then it doesn't vary! } RecursivePointer(_) => { diff --git a/crates/compiler/mono/src/layout/intern.rs b/crates/compiler/mono/src/layout/intern.rs index eb182b0b86a..175893fc504 100644 --- a/crates/compiler/mono/src/layout/intern.rs +++ b/crates/compiler/mono/src/layout/intern.rs @@ -350,6 +350,10 @@ pub trait LayoutInterner<'a>: Sized { .text("Boxed(") .append(self.to_doc(inner, alloc, seen_rec, parens)) .append(")"), + Ptr(inner) => alloc + .text("Ptr(") + .append(self.to_doc(inner, alloc, seen_rec, parens)) + .append(")"), } } @@ -1108,6 +1112,7 @@ mod reify { LayoutRepr::Struct(reify_layout_slice(arena, interner, slot, field_layouts)) } LayoutRepr::Boxed(lay) => LayoutRepr::Boxed(reify_layout(arena, interner, slot, lay)), + LayoutRepr::Ptr(lay) => LayoutRepr::Ptr(reify_layout(arena, interner, slot, lay)), LayoutRepr::Union(un) => LayoutRepr::Union(reify_union(arena, interner, slot, un)), LayoutRepr::LambdaSet(ls) => { LayoutRepr::LambdaSet(reify_lambda_set(arena, interner, slot, ls)) @@ -1312,6 +1317,7 @@ mod equiv { equiv_fields!(fl1, fl2) } (Boxed(b1), Boxed(b2)) => stack.push((b1, b2)), + (Ptr(b1), Ptr(b2)) => stack.push((b1, b2)), (Union(u1), Union(u2)) => { use UnionLayout::*; match (u1, u2) { @@ -1432,6 +1438,7 @@ pub mod dbg_deep { .field("fields", &DbgFields(self.0, field_layouts)) .finish(), LayoutRepr::Boxed(b) => f.debug_tuple("Boxed").field(&Dbg(self.0, *b)).finish(), + LayoutRepr::Ptr(b) => f.debug_tuple("Ptr").field(&Dbg(self.0, *b)).finish(), LayoutRepr::Union(un) => f .debug_tuple("Union") .field(&DbgUnion(self.0, *un)) @@ -1605,6 +1612,7 @@ pub mod dbg_stable { .field("fields", &DbgFields(self.0, field_layouts)) .finish(), LayoutRepr::Boxed(b) => f.debug_tuple("Boxed").field(&Dbg(self.0, *b)).finish(), + LayoutRepr::Ptr(b) => f.debug_tuple("Ptr").field(&Dbg(self.0, *b)).finish(), LayoutRepr::Union(un) => f .debug_tuple("Union") .field(&DbgUnion(self.0, *un)) diff --git a/crates/glue/src/types.rs b/crates/glue/src/types.rs index 7b66d5ed7dd..d5b6b79fd84 100644 --- a/crates/glue/src/types.rs +++ b/crates/glue/src/types.rs @@ -2085,6 +2085,7 @@ fn tag_union_type_from_layout<'a>( }, } } + LayoutRepr::Ptr(_) => unreachable!("Ptr values are never publicly exposed"), LayoutRepr::Boxed(elem_layout) => { let (tag_name, payload_fields) = single_tag_payload_fields(env, union_tags, subs, layout, &[elem_layout], types); diff --git a/crates/repl_eval/src/eval.rs b/crates/repl_eval/src/eval.rs index 9b053198cd2..1afadb66466 100644 --- a/crates/repl_eval/src/eval.rs +++ b/crates/repl_eval/src/eval.rs @@ -534,6 +534,9 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>( LayoutRepr::RecursivePointer(_) => { unreachable!("RecursivePointers can only be inside structures") } + LayoutRepr::Ptr(_) => { + unreachable!("Ptr will never be visible to users") + } LayoutRepr::LambdaSet(_) => OPAQUE_FUNCTION, LayoutRepr::Boxed(_) => { let size = env.layout_cache.interner.stack_size(layout); @@ -918,6 +921,9 @@ fn addr_to_ast<'a, M: ReplAppMemory>( (_, LayoutRepr::Boxed(_)) => { unreachable!("Box layouts can only be behind a `Box.Box` application") } + (_, LayoutRepr::Ptr(_)) => { + unreachable!("Ptr layouts are never available in user code") + } }; apply_newtypes(env, newtype_containers.into_bump_slice(), expr) } From 76dcb75ff6f8866d8ddad85a38e981a24f561ddb Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 18 Jun 2023 15:51:12 +0200 Subject: [PATCH 021/140] add Ptr lowlevels --- crates/compiler/gen_dev/src/object_builder.rs | 2 +- crates/compiler/gen_llvm/src/llvm/lowlevel.rs | 4 ++-- crates/compiler/gen_wasm/src/low_level.rs | 4 +++- crates/compiler/module/src/low_level.rs | 4 +++- crates/compiler/mono/src/code_gen_help/mod.rs | 2 +- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/crates/compiler/gen_dev/src/object_builder.rs b/crates/compiler/gen_dev/src/object_builder.rs index a7eba25d9ff..a5f44c61da3 100644 --- a/crates/compiler/gen_dev/src/object_builder.rs +++ b/crates/compiler/gen_dev/src/object_builder.rs @@ -485,7 +485,7 @@ fn build_exposed_generic_proc<'a, B: Backend<'a>>(backend: &mut B, proc: &Proc<' let box_write = Call { call_type: roc_mono::ir::CallType::LowLevel { - op: roc_module::low_level::LowLevel::PtrWrite, + op: roc_module::low_level::LowLevel::PtrStore, update_mode: UpdateModeId::BACKEND_DUMMY, }, arguments: arena.alloc([arg_generic, s1]), diff --git a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs index ba2a60b81f4..4bfb429ce9a 100644 --- a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs +++ b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs @@ -1304,8 +1304,8 @@ pub(crate) fn run_low_level<'a, 'ctx>( .into() } - PtrWrite | RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr - | RefCountDecDataPtr => { + PtrStore | PtrLoad | PtrToZeroed | RefCountIncRcPtr | RefCountDecRcPtr + | RefCountIncDataPtr | RefCountDecDataPtr => { unreachable!("Not used in LLVM backend: {:?}", op); } diff --git a/crates/compiler/gen_wasm/src/low_level.rs b/crates/compiler/gen_wasm/src/low_level.rs index 3883a24a4e4..81ac357af11 100644 --- a/crates/compiler/gen_wasm/src/low_level.rs +++ b/crates/compiler/gen_wasm/src/low_level.rs @@ -1960,7 +1960,9 @@ impl<'a> LowLevelCall<'a> { backend.storage.load_symbols(code_builder, self.arguments); } - PtrWrite => todo!("{:?}", self.lowlevel), + PtrStore => todo!("{:?}", self.lowlevel), + PtrLoad => todo!("{:?}", self.lowlevel), + PtrToZeroed => todo!("{:?}", self.lowlevel), Hash => todo!("{:?}", self.lowlevel), diff --git a/crates/compiler/module/src/low_level.rs b/crates/compiler/module/src/low_level.rs index 32e8e162dc9..32fb65ed6d5 100644 --- a/crates/compiler/module/src/low_level.rs +++ b/crates/compiler/module/src/low_level.rs @@ -118,7 +118,9 @@ pub enum LowLevel { Not, Hash, PtrCast, - PtrWrite, + PtrStore, + PtrLoad, + PtrToZeroed, RefCountIncRcPtr, RefCountDecRcPtr, RefCountIncDataPtr, diff --git a/crates/compiler/mono/src/code_gen_help/mod.rs b/crates/compiler/mono/src/code_gen_help/mod.rs index 868ba8a0882..a79293294fa 100644 --- a/crates/compiler/mono/src/code_gen_help/mod.rs +++ b/crates/compiler/mono/src/code_gen_help/mod.rs @@ -726,7 +726,7 @@ impl<'a> CallerProc<'a> { let ptr_write = Expr::Call(Call { call_type: CallType::LowLevel { - op: LowLevel::PtrWrite, + op: LowLevel::PtrStore, update_mode: UpdateModeId::BACKEND_DUMMY, }, arguments: arena.alloc([Symbol::ARG_3, call_result]), From 4a9514d2c4cb3cd2135cb5cfedfaf91990d68842 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sat, 17 Jun 2023 20:46:59 +0200 Subject: [PATCH 022/140] rough implementation --- crates/compiler/load_internal/src/file.rs | 3 +- crates/compiler/mono/src/borrow.rs | 6 +- crates/compiler/mono/src/inc_dec.rs | 12 +- crates/compiler/mono/src/ir.rs | 39 ++- crates/compiler/mono/src/layout.rs | 12 + crates/compiler/mono/src/tail_recursion.rs | 387 ++++++++++++++++++++- crates/compiler/test_mono/src/tests.rs | 20 ++ 7 files changed, 456 insertions(+), 23 deletions(-) diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index 7c0045af3c6..5cef4dd2cef 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -5817,7 +5817,8 @@ fn make_specializations<'a>( ); let external_specializations_requested = procs.externals_we_need.clone(); - let (procedures, restored_procs_base) = procs.get_specialized_procs_without_rc(&mut mono_env); + let (procedures, restored_procs_base) = + procs.get_specialized_procs_without_rc(&mut layout_cache, &mut mono_env); // Turn `Bytes.Decode.IdentId(238)` into `Bytes.Decode.238`, we rely on this in mono tests mono_env.home.register_debug_idents(mono_env.ident_ids); diff --git a/crates/compiler/mono/src/borrow.rs b/crates/compiler/mono/src/borrow.rs index b5e4dddfaab..6978ccae3e4 100644 --- a/crates/compiler/mono/src/borrow.rs +++ b/crates/compiler/mono/src/borrow.rs @@ -1035,8 +1035,10 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[Ownership] { unreachable!("These lowlevel operations are turned into mono Expr's") } - PtrCast | PtrWrite | RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr - | RefCountDecDataPtr | RefCountIsUnique => { + PtrWrite => arena.alloc_slice_copy(&[irrelevant, irrelevant]), + + PtrCast | RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr | RefCountDecDataPtr + | RefCountIsUnique => { unreachable!("Only inserted *after* borrow checking: {:?}", op); } } diff --git a/crates/compiler/mono/src/inc_dec.rs b/crates/compiler/mono/src/inc_dec.rs index fa6978fa1ee..e03f9a8ea78 100644 --- a/crates/compiler/mono/src/inc_dec.rs +++ b/crates/compiler/mono/src/inc_dec.rs @@ -10,6 +10,7 @@ use std::{collections::HashMap, hash::BuildHasherDefault}; use bumpalo::collections::{CollectIn, Vec}; use bumpalo::Bump; use roc_collections::{all::WyHash, MutMap, MutSet}; +use roc_error_macros::internal_error; use roc_module::low_level::LowLevel; use roc_module::{low_level::LowLevelWrapperType, symbol::Symbol}; @@ -543,15 +544,16 @@ fn insert_refcount_operations_stmt<'v, 'a>( .iter() .filter(|(_, o)| o.is_owned()) { - let error = "All symbols defined in the current environment should be in the environment of the branches."; let consumed = branch_envs .iter() .any(|branch_env: &&RefcountEnvironment<'v>| { - matches!( - branch_env.get_symbol_ownership(symbol).expect(error), - Ownership::Borrowed - ) + match branch_env.get_symbol_ownership(symbol) { + None => internal_error!( + "symbol {symbol:?} in the current env should be in the branch's env" + ), + Some(ownership) => matches!(ownership, Ownership::Borrowed), + } }); if consumed { // If the symbol is currently owned, and not in a some branches, it must be consumed in all branches diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index 51f06a6d560..c8553bdaa3c 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -404,7 +404,10 @@ impl<'a> Proc<'a> { String::from_utf8(w).unwrap() } - fn make_tail_recursive(&mut self, env: &mut Env<'a, '_>) { + fn make_tail_recursive(&mut self, interner: &mut I, env: &mut Env<'a, '_>) + where + I: LayoutInterner<'a>, + { let mut args = Vec::with_capacity_in(self.args.len(), env.arena); let mut proc_args = Vec::with_capacity_in(self.args.len(), env.arena); @@ -416,18 +419,22 @@ impl<'a> Proc<'a> { use self::SelfRecursive::*; if let SelfRecursive(id) = self.is_self_recursive { - let transformed = crate::tail_recursion::make_tail_recursive( - env.arena, - id, - self.name, - self.body.clone(), - args.into_bump_slice(), - self.ret_layout, - ); + if crate::tail_recursion::is_trmc_candidate(interner, self) { + *self = crate::tail_recursion::TrmcEnv::init(env, interner, self); + } else { + let transformed = crate::tail_recursion::make_tail_recursive( + env.arena, + id, + self.name, + self.body.clone(), + args.into_bump_slice(), + self.ret_layout, + ); - if let Some(with_tco) = transformed { - self.body = with_tco; - self.args = proc_args.into_bump_slice(); + if let Some(with_tco) = transformed { + self.body = with_tco; + self.args = proc_args.into_bump_slice(); + } } } } @@ -1018,13 +1025,14 @@ impl<'a> Procs<'a> { pub fn get_specialized_procs_without_rc( self, + layout_cache: &mut LayoutCache<'a>, env: &mut Env<'a, '_>, ) -> (MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>, ProcsBase<'a>) { let mut specialized_procs = MutMap::with_capacity_and_hasher(self.specialized.len(), default_hasher()); for (symbol, layout, mut proc) in self.specialized.into_iter_assert_done() { - proc.make_tail_recursive(env); + proc.make_tail_recursive(&mut layout_cache.interner, env); let key = (symbol, layout); specialized_procs.insert(key, proc); @@ -1396,6 +1404,11 @@ impl<'a, 'i> Env<'a, 'i> { Symbol::new(self.home, ident_id) } + pub fn named_unique_symbol(&mut self, name: &str) -> Symbol { + let ident_id = self.ident_ids.add_str(name); + Symbol::new(self.home, ident_id) + } + pub fn next_update_mode_id(&mut self) -> UpdateModeId { self.update_mode_ids.next_id() } diff --git a/crates/compiler/mono/src/layout.rs b/crates/compiler/mono/src/layout.rs index 4da1d0c0c2a..5658e884315 100644 --- a/crates/compiler/mono/src/layout.rs +++ b/crates/compiler/mono/src/layout.rs @@ -1107,6 +1107,18 @@ impl<'a> UnionLayout<'a> { | UnionLayout::NullableUnwrapped { .. } => interner.target_info().ptr_width() as u32, } } + + pub fn is_recursive(&self) -> bool { + use UnionLayout::*; + + match self { + NonRecursive(_) => false, + Recursive(_) + | NonNullableUnwrapped(_) + | NullableWrapped { .. } + | NullableUnwrapped { .. } => true, + } + } } pub enum Discriminant { diff --git a/crates/compiler/mono/src/tail_recursion.rs b/crates/compiler/mono/src/tail_recursion.rs index 383363d3a2b..77db2491196 100644 --- a/crates/compiler/mono/src/tail_recursion.rs +++ b/crates/compiler/mono/src/tail_recursion.rs @@ -1,8 +1,8 @@ #![allow(clippy::manual_map)] use crate::borrow::Ownership; -use crate::ir::{CallType, Expr, JoinPointId, Param, Stmt}; -use crate::layout::{InLayout, LambdaName}; +use crate::ir::{Call, CallType, Env, Expr, JoinPointId, Param, Proc, SelfRecursive, Stmt}; +use crate::layout::{InLayout, LambdaName, LayoutInterner, LayoutRepr, TagIdIntType, UnionLayout}; use bumpalo::collections::Vec; use bumpalo::Bump; use roc_module::symbol::Symbol; @@ -29,6 +29,7 @@ use roc_module::symbol::Symbol; /// /// This will effectively compile into a loop in llvm, and /// won't grow the call stack for each iteration + pub fn make_tail_recursive<'a>( arena: &'a Bump, id: JoinPointId, @@ -323,3 +324,385 @@ fn insert_jumps<'a>( Crash(..) => None, } } + +pub(crate) fn is_trmc_candidate<'a, I>(interner: &I, proc: &Proc<'a>) -> bool +where + I: LayoutInterner<'a>, +{ + // it must be a self-recursive function + if !matches!( + proc.is_self_recursive, + crate::ir::SelfRecursive::SelfRecursive(_) + ) { + return false; + } + + // and return a recursive tag union + match interner.get_repr(proc.ret_layout) { + LayoutRepr::Union(union_layout) => union_layout.is_recursive(), + _ => false, + } +} + +#[derive(Clone)] +pub(crate) struct TrmcEnv<'a> { + function_name: LambdaName<'a>, + hole_symbol: Symbol, + null_symbol: Symbol, + initial_box_symbol: Symbol, + joinpoint_id: JoinPointId, + return_layout: InLayout<'a>, + box_return_layout: InLayout<'a>, + + // the call we are performing TRMC on + recursive_call: Option<(Symbol, Call<'a>)>, +} + +struct ConstructorInfo<'a> { + tag_layout: UnionLayout<'a>, + tag_id: TagIdIntType, + arguments: &'a [Symbol], +} + +impl<'a> TrmcEnv<'a> { + fn is_recursive_expr(&mut self, expr: &Expr<'a>) -> Option> { + if let Expr::Call(call) = expr { + self.is_recursive_call(call).then_some(call.clone()) + } else { + None + } + } + + fn is_terminal_constructor(&mut self, stmt: &Stmt<'a>) -> Option> { + match stmt { + Stmt::Let(s1, expr, _layout, Stmt::Ret(s2)) if s1 == s2 => { + self.get_contructor_info(expr) + } + + _ => None, + } + } + + fn get_contructor_info(&mut self, expr: &Expr<'a>) -> Option> { + if let Expr::Tag { + tag_layout, + tag_id, + arguments, + } = expr + { + let info = ConstructorInfo { + tag_layout: *tag_layout, + tag_id: *tag_id, + arguments, + }; + + Some(info) + } else { + None + } + } + + fn is_recursive_call(&mut self, call: &Call<'a>) -> bool { + match call.call_type { + CallType::ByName { + name, + ret_layout, + arg_layouts, + specialization_id, + } => { + // TODO are there other restrictions? + name == self.function_name + } + CallType::Foreign { .. } | CallType::LowLevel { .. } | CallType::HigherOrder(_) => { + false + } + } + } + + fn ptr_write( + env: &mut Env<'a, '_>, + interner: &mut impl LayoutInterner<'a>, + return_layout: InLayout<'a>, + ptr: Symbol, + value: Symbol, + next: &'a Stmt<'a>, + ) -> Stmt<'a> { + let box_write = Call { + call_type: crate::ir::CallType::LowLevel { + op: roc_module::low_level::LowLevel::PtrWrite, + update_mode: env.next_update_mode_id(), + }, + arguments: env.arena.alloc([ptr, value]), + }; + + Stmt::Let( + env.named_unique_symbol("_ptr_write_unit"), + Expr::Call(box_write), + interner.insert_direct_no_semantic(LayoutRepr::Boxed(return_layout)), + next, + ) + } + + pub fn init( + env: &mut Env<'a, '_>, + interner: &mut impl LayoutInterner<'a>, + proc: &Proc<'a>, + ) -> Proc<'a> { + let arena = env.arena; + let return_layout = proc.ret_layout; + + let mut joinpoint_parameters = Vec::with_capacity_in(proc.args.len() + 1, env.arena); + let mut new_proc_arguments = Vec::with_capacity_in(proc.args.len(), env.arena); + let mut jump_arguments = Vec::with_capacity_in(proc.args.len() + 1, env.arena); + + for (i, (layout, old_symbol)) in proc.args.iter().enumerate() { + let symbol = env.named_unique_symbol(&format!("arg_{i}")); + new_proc_arguments.push((*layout, symbol)); + jump_arguments.push(symbol); + + let param = Param { + symbol: *old_symbol, + ownership: Ownership::Owned, + layout: *layout, + }; + joinpoint_parameters.push(param); + } + + // the root of the recursive structure that we'll be building + let initial_box_symbol = env.named_unique_symbol("initial"); + jump_arguments.push(initial_box_symbol); + + let null_symbol = env.named_unique_symbol("null"); + let let_null = |next| Stmt::Let(null_symbol, Expr::NullPointer, return_layout, next); + + let box_return_layout = + interner.insert_direct_no_semantic(LayoutRepr::Boxed(return_layout)); + let box_null = Expr::ExprBox { + symbol: null_symbol, + }; + let let_box = |next| Stmt::Let(initial_box_symbol, box_null, box_return_layout, next); + + let joinpoint_id = JoinPointId(env.named_unique_symbol("trmc")); + let hole_symbol = env.named_unique_symbol("hole"); + + let jump_stmt = Stmt::Jump(joinpoint_id, jump_arguments.into_bump_slice()); + + let mut this = Self { + function_name: proc.name, + hole_symbol, + null_symbol, + initial_box_symbol, + joinpoint_id, + return_layout, + box_return_layout, + recursive_call: None, + }; + + let param = Param { + symbol: hole_symbol, + ownership: Ownership::Owned, + layout: box_return_layout, + }; + joinpoint_parameters.push(param); + + let joinpoint = Stmt::Join { + id: joinpoint_id, + parameters: joinpoint_parameters.into_bump_slice(), + body: arena.alloc(this.walk_stmt(env, interner, &proc.body)), + remainder: arena.alloc(jump_stmt), + }; + + let body = let_null(arena.alloc( + // + let_box(arena.alloc( + // + joinpoint, + )), + )); + + #[cfg(debug_assertions)] + env.home.register_debug_idents(env.ident_ids); + + Proc { + name: proc.name, + args: new_proc_arguments.into_bump_slice(), + body, + closure_data_layout: proc.closure_data_layout, + ret_layout: proc.ret_layout, + is_self_recursive: SelfRecursive::NotSelfRecursive, + host_exposed_layouts: proc.host_exposed_layouts.clone(), + } + } + + fn walk_stmt( + &mut self, + env: &mut Env<'a, '_>, + interner: &mut impl LayoutInterner<'a>, + stmt: &Stmt<'a>, + ) -> Stmt<'a> { + let arena = env.arena; + + match stmt { + Stmt::Let(symbol, expr, layout, next) => { + if self.recursive_call.is_none() { + if let Some(call) = self.is_recursive_expr(expr) { + self.recursive_call = Some((*symbol, call)); + return self.walk_stmt(env, interner, next); + } + } + + if let Some(cons_info) = self.is_terminal_constructor(stmt) { + match &self.recursive_call { + None => { + // this control flow path did not encounter a recursive call. Just + // write the end result into the hole and we're done. + + let define_tag = |next| Stmt::Let(*symbol, expr.clone(), *layout, next); + + let output = define_tag(arena.alloc( + // + self.non_trmc_return(env, interner, *symbol), + )); + + return output; + } + Some((call_symbol, call)) => { + // we did encounter a recursive call, and can perform TRMC in this + // branch. + + // TODO remove unwrap. also what if the symbol occurs more than once? + let recursive_field_index = cons_info + .arguments + .iter() + .position(|s| *s == *call_symbol) + .unwrap(); + + let mut arguments = + Vec::from_iter_in(cons_info.arguments.iter().copied(), env.arena); + arguments[recursive_field_index] = self.null_symbol; + + let tag_expr = Expr::Tag { + tag_layout: cons_info.tag_layout, + tag_id: cons_info.tag_id, + arguments: arguments.into_bump_slice(), + }; + + let let_tag = |next| Stmt::Let(*symbol, tag_expr, *layout, next); + + let get_reference_expr = Expr::ExprBox { + symbol: self.null_symbol, + }; + + let new_hole_symbol = env.named_unique_symbol("newHole"); + let let_new_hole = |next| { + Stmt::Let( + new_hole_symbol, + get_reference_expr, + self.box_return_layout, + next, + ) + }; + + let mut jump_arguments = + Vec::from_iter_in(call.arguments.iter().copied(), env.arena); + jump_arguments.push(new_hole_symbol); + + let jump = + Stmt::Jump(self.joinpoint_id, jump_arguments.into_bump_slice()); + + let output = let_tag(arena.alloc( + // + let_new_hole(arena.alloc( + // + Self::ptr_write( + env, + interner, + *layout, + self.hole_symbol, + *symbol, + arena.alloc(jump), + ), + )), + )); + + return output; + } + } + } + + let next = self.walk_stmt(env, interner, next); + Stmt::Let(*symbol, expr.clone(), *layout, arena.alloc(next)) + } + Stmt::Switch { + cond_symbol, + cond_layout, + branches, + default_branch, + ret_layout, + } => { + let mut new_branches = Vec::with_capacity_in(branches.len(), arena); + + let opt_recursive_call = self.recursive_call.clone(); + + for (id, info, stmt) in branches.iter() { + self.recursive_call = opt_recursive_call.clone(); + let new_stmt = self.walk_stmt(env, interner, stmt); + + new_branches.push((*id, info.clone(), new_stmt)); + } + + self.recursive_call = opt_recursive_call; + let new_default_branch = + &*arena.alloc(self.walk_stmt(env, interner, default_branch.1)); + + Stmt::Switch { + cond_symbol: *cond_symbol, + cond_layout: *cond_layout, + branches: &*arena.alloc(new_branches.into_bump_slice()), + default_branch: (default_branch.0.clone(), new_default_branch), + ret_layout: *ret_layout, + } + } + Stmt::Ret(symbol) => { + // write the symbol we're supposed to return into the hole + // then read initial_symbol and return its contents + self.non_trmc_return(env, interner, *symbol) + } + Stmt::Refcounting(_, _) => todo!(), + Stmt::Expect { .. } => todo!(), + Stmt::ExpectFx { .. } => todo!(), + Stmt::Dbg { .. } => todo!(), + Stmt::Join { .. } => todo!(), + Stmt::Jump(_, _) => todo!(), + Stmt::Crash(_, _) => todo!(), + } + } + + fn non_trmc_return( + &mut self, + env: &mut Env<'a, '_>, + interner: &mut impl LayoutInterner<'a>, + value_symbol: Symbol, + ) -> Stmt<'a> { + let arena = env.arena; + let layout = self.return_layout; + + let unbox_expr = Expr::ExprUnbox { + symbol: self.initial_box_symbol, + }; + let final_symbol = env.named_unique_symbol("final"); + let unbox = |next| Stmt::Let(final_symbol, unbox_expr, layout, next); + + Self::ptr_write( + env, + interner, + layout, + self.hole_symbol, + value_symbol, + arena.alloc( + // + unbox(arena.alloc(Stmt::Ret(final_symbol))), + ), + ) + } +} diff --git a/crates/compiler/test_mono/src/tests.rs b/crates/compiler/test_mono/src/tests.rs index 1ea7bb17461..bbe0b5c213e 100644 --- a/crates/compiler/test_mono/src/tests.rs +++ b/crates/compiler/test_mono/src/tests.rs @@ -3146,3 +3146,23 @@ fn dbg_str_followed_by_number() { "# ) } + +#[mono_test] +fn linked_list_map() { + indoc!( + r#" + app "test" provides [main] to "./platform" + + LinkedList a : [Nil, Cons a (LinkedList a)] + + map : (a -> b), LinkedList a -> LinkedList b + map = \f, list -> + when list is + Nil -> Nil + Cons x xs -> Cons (f x) (map f xs) + + main : LinkedList I64 + main = map (\x -> x + 1i64) (Cons 42 Nil) + "# + ) +} From 0247237fe835e83a0f444b421bcf2b4f65f90c1e Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 18 Jun 2023 14:21:48 +0200 Subject: [PATCH 023/140] WIP --- crates/compiler/alias_analysis/src/lib.rs | 32 ++ crates/compiler/can/src/builtins.rs | 4 +- crates/compiler/debug_flags/src/lib.rs | 4 + crates/compiler/gen_dev/src/lib.rs | 17 +- crates/compiler/gen_llvm/src/llvm/build.rs | 178 +++++++-- crates/compiler/gen_llvm/src/llvm/lowlevel.rs | 24 +- crates/compiler/gen_wasm/src/backend.rs | 7 + crates/compiler/load_internal/src/file.rs | 12 +- crates/compiler/module/src/low_level.rs | 4 +- crates/compiler/mono/src/borrow.rs | 12 +- crates/compiler/mono/src/debug/checker.rs | 9 + .../compiler/mono/src/drop_specialization.rs | 24 +- crates/compiler/mono/src/inc_dec.rs | 15 +- crates/compiler/mono/src/ir.rs | 71 ++-- crates/compiler/mono/src/tail_recursion.rs | 348 ++++++++++++++---- examples/platform-switching/rocLovesZig.roc | 27 +- 16 files changed, 625 insertions(+), 163 deletions(-) diff --git a/crates/compiler/alias_analysis/src/lib.rs b/crates/compiler/alias_analysis/src/lib.rs index 723c78333b9..27a3be99478 100644 --- a/crates/compiler/alias_analysis/src/lib.rs +++ b/crates/compiler/alias_analysis/src/lib.rs @@ -1422,6 +1422,38 @@ fn expr_spec<'a>( builder.add_get_tuple_field(block, variant_id, index) } }, + UnionFieldPtrAtIndex { + index, + tag_id, + structure, + union_layout, + } => { + let index = (*index) as u32; + let tag_value_id = env.symbols[structure]; + + let type_name_bytes = recursive_tag_union_name_bytes(union_layout).as_bytes(); + let type_name = TypeName(&type_name_bytes); + + // unwrap the named wrapper + let union_id = builder.add_unwrap_named(block, MOD_APP, type_name, tag_value_id)?; + + // now we have a tuple (cell, union { ... }); decompose + let heap_cell = builder.add_get_tuple_field(block, union_id, TAG_CELL_INDEX)?; + let union_data = builder.add_get_tuple_field(block, union_id, TAG_DATA_INDEX)?; + + // we're reading from this value, so touch the heap cell + builder.add_touch(block, heap_cell)?; + + // next, unwrap the union at the tag id that we've got + let variant_id = builder.add_unwrap_union(block, union_data, *tag_id as u32)?; + + let value = builder.add_get_tuple_field(block, variant_id, index)?; + + // construct the box. Here the heap_cell of the tag is re-used, I'm hoping that that + // conveys to morphic that we're borrowing into the existing tag?! + builder.add_make_tuple(block, &[heap_cell, value]) + } + StructAtIndex { index, structure, .. } => { diff --git a/crates/compiler/can/src/builtins.rs b/crates/compiler/can/src/builtins.rs index 9f05e61ddfe..d59e23d5238 100644 --- a/crates/compiler/can/src/builtins.rs +++ b/crates/compiler/can/src/builtins.rs @@ -85,7 +85,9 @@ macro_rules! map_symbol_to_lowlevel_and_arity { // these are used internally and not tied to a symbol LowLevel::Hash => unimplemented!(), LowLevel::PtrCast => unimplemented!(), - LowLevel::PtrWrite => unimplemented!(), + LowLevel::PtrStore => unimplemented!(), + LowLevel::PtrLoad => unimplemented!(), + LowLevel::PtrToZeroed => unimplemented!(), LowLevel::RefCountIncRcPtr => unimplemented!(), LowLevel::RefCountDecRcPtr=> unimplemented!(), LowLevel::RefCountIncDataPtr => unimplemented!(), diff --git a/crates/compiler/debug_flags/src/lib.rs b/crates/compiler/debug_flags/src/lib.rs index 3852100c710..ede77bd317a 100644 --- a/crates/compiler/debug_flags/src/lib.rs +++ b/crates/compiler/debug_flags/src/lib.rs @@ -135,6 +135,10 @@ flags! { /// instructions. ROC_PRINT_IR_AFTER_REFCOUNT + /// Writes a pretty-printed mono IR to stderr after the tail recursion (modulo cons) + /// has been applied. + ROC_PRINT_IR_AFTER_TRMC + /// Writes a pretty-printed mono IR to stderr after performing dropspecialization. /// Which inlines drop functions to remove pairs of alloc/dealloc instructions of its children. ROC_PRINT_IR_AFTER_DROP_SPECIALIZATION diff --git a/crates/compiler/gen_dev/src/lib.rs b/crates/compiler/gen_dev/src/lib.rs index 648ab8247c3..fd63a1d95f4 100644 --- a/crates/compiler/gen_dev/src/lib.rs +++ b/crates/compiler/gen_dev/src/lib.rs @@ -163,6 +163,9 @@ impl<'a> LastSeenMap<'a> { Expr::UnionAtIndex { structure, .. } => { self.set_last_seen(*structure, stmt); } + Expr::UnionFieldPtrAtIndex { structure, .. } => { + self.set_last_seen(*structure, stmt); + } Expr::Array { elems, .. } => { for elem in *elems { if let ListLiteralElement::Symbol(sym) = elem { @@ -794,6 +797,14 @@ trait Backend<'a> { } => { self.load_union_at_index(sym, structure, *tag_id, *index, union_layout); } + Expr::UnionFieldPtrAtIndex { + structure, + tag_id, + union_layout, + index, + } => { + todo!(); + } Expr::GetTagId { structure, union_layout, @@ -1581,7 +1592,7 @@ trait Backend<'a> { self.build_ptr_cast(sym, &args[0]) } - LowLevel::PtrWrite => { + LowLevel::PtrStore => { let element_layout = match self.interner().get_repr(*ret_layout) { LayoutRepr::Boxed(boxed) => boxed, _ => unreachable!("cannot write to {:?}", self.interner().dbg(*ret_layout)), @@ -1589,6 +1600,10 @@ trait Backend<'a> { self.build_ptr_write(*sym, args[0], args[1], element_layout); } + LowLevel::PtrLoad => { + // + todo!() + } LowLevel::RefCountDecRcPtr => self.build_fn_call( sym, bitcode::UTILS_DECREF_RC_PTR.to_string(), diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index c400bcce26a..b7f91ddff01 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -23,7 +23,7 @@ use inkwell::passes::{PassManager, PassManagerBuilder}; use inkwell::types::{ AnyType, BasicMetadataTypeEnum, BasicType, BasicTypeEnum, FunctionType, IntType, StructType, }; -use inkwell::values::BasicValueEnum::{self}; +use inkwell::values::BasicValueEnum; use inkwell::values::{ BasicMetadataValueEnum, CallSiteValue, FunctionValue, InstructionValue, IntValue, PointerValue, StructValue, @@ -1379,12 +1379,13 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( layout_interner.get_repr(layout), ); - lookup_at_index_ptr2( + lookup_at_index_ptr( env, layout_interner, field_layouts, *index as usize, ptr, + None, target_loaded_type, ) } @@ -1404,7 +1405,7 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( field_layouts, *index as usize, argument.into_pointer_value(), - struct_type.into_struct_type(), + Some(struct_type.into_struct_type()), target_loaded_type, ) } @@ -1430,12 +1431,13 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( layout_interner.get_repr(layout), ); - lookup_at_index_ptr2( + lookup_at_index_ptr( env, layout_interner, field_layouts, *index as usize, ptr, + None, target_loaded_type, ) } @@ -1463,13 +1465,117 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( // the tag id is not stored *index as usize, argument.into_pointer_value(), - struct_type.into_struct_type(), + Some(struct_type.into_struct_type()), target_loaded_type, ) } } } + UnionFieldPtrAtIndex { + tag_id, + structure, + index, + union_layout, + } => { + // cast the argument bytes into the desired shape for this tag + let (argument, structure_layout) = scope.load_symbol_and_layout(structure); + let ret_repr = layout_interner.get_repr(layout); + + let pointer_value = match union_layout { + UnionLayout::NonRecursive(_) => unreachable!(), + UnionLayout::Recursive(tag_layouts) => { + debug_assert!(argument.is_pointer_value()); + + let field_layouts = tag_layouts[*tag_id as usize]; + + let ptr = tag_pointer_clear_tag_id(env, argument.into_pointer_value()); + let target_loaded_type = basic_type_from_layout(env, layout_interner, ret_repr); + + union_field_at_index( + env, + layout_interner, + field_layouts, + None, + *index as usize, + ptr, + target_loaded_type, + ) + } + UnionLayout::NonNullableUnwrapped(field_layouts) => { + let struct_layout = LayoutRepr::struct_(field_layouts); + + let struct_type = basic_type_from_layout(env, layout_interner, struct_layout); + let target_loaded_type = basic_type_from_layout(env, layout_interner, ret_repr); + + union_field_at_index( + env, + layout_interner, + field_layouts, + Some(struct_type.into_struct_type()), + *index as usize, + argument.into_pointer_value(), + target_loaded_type, + ) + } + UnionLayout::NullableWrapped { + nullable_id, + other_tags, + } => { + debug_assert!(argument.is_pointer_value()); + debug_assert_ne!(*tag_id, *nullable_id); + + let tag_index = if *tag_id < *nullable_id { + *tag_id + } else { + tag_id - 1 + }; + + let field_layouts = other_tags[tag_index as usize]; + + let ptr = tag_pointer_clear_tag_id(env, argument.into_pointer_value()); + let target_loaded_type = basic_type_from_layout(env, layout_interner, ret_repr); + + union_field_at_index( + env, + layout_interner, + field_layouts, + None, + *index as usize, + ptr, + target_loaded_type, + ) + .into() + } + UnionLayout::NullableUnwrapped { + nullable_id, + other_fields, + } => { + debug_assert!(argument.is_pointer_value()); + debug_assert_ne!(*tag_id != 0, *nullable_id); + + let field_layouts = other_fields; + let struct_layout = LayoutRepr::struct_(field_layouts); + + let struct_type = basic_type_from_layout(env, layout_interner, struct_layout); + let target_loaded_type = basic_type_from_layout(env, layout_interner, ret_repr); + + union_field_at_index( + env, + layout_interner, + field_layouts, + Some(struct_type.into_struct_type()), + // the tag id is not stored + *index as usize, + argument.into_pointer_value(), + target_loaded_type, + ) + } + }; + + pointer_value.into() + } + GetTagId { structure, union_layout, @@ -2025,21 +2131,20 @@ fn lookup_at_index_ptr<'a, 'ctx>( field_layouts: &[InLayout<'a>], index: usize, value: PointerValue<'ctx>, - struct_type: StructType<'ctx>, + struct_type: Option>, target_loaded_type: BasicTypeEnum<'ctx>, ) -> BasicValueEnum<'ctx> { let builder = env.builder; - let ptr = env.builder.build_pointer_cast( + let elem_ptr = union_field_at_index_help( + env, + layout_interner, + field_layouts, + struct_type, + index, value, - struct_type.ptr_type(AddressSpace::default()), - "cast_lookup_at_index_ptr", ); - let elem_ptr = builder - .new_build_struct_gep(struct_type, ptr, index as u32, "at_index_struct_gep") - .unwrap(); - let field_layout = field_layouts[index]; let result = load_roc_value( env, @@ -2054,19 +2159,23 @@ fn lookup_at_index_ptr<'a, 'ctx>( cast_if_necessary_for_opaque_recursive_pointers(env.builder, result, target_loaded_type) } -fn lookup_at_index_ptr2<'a, 'ctx>( +fn union_field_at_index_help<'a, 'ctx>( env: &Env<'a, 'ctx, '_>, layout_interner: &STLayoutInterner<'a>, field_layouts: &'a [InLayout<'a>], + opt_struct_type: Option>, index: usize, value: PointerValue<'ctx>, - target_loaded_type: BasicTypeEnum<'ctx>, -) -> BasicValueEnum<'ctx> { +) -> PointerValue<'ctx> { let builder = env.builder; - let struct_layout = LayoutRepr::struct_(field_layouts); - let struct_type = - basic_type_from_layout(env, layout_interner, struct_layout).into_struct_type(); + let struct_type = match opt_struct_type { + Some(st) => st, + None => { + let struct_layout = LayoutRepr::struct_(field_layouts); + basic_type_from_layout(env, layout_interner, struct_layout).into_struct_type() + } + }; let data_ptr = env.builder.build_pointer_cast( value, @@ -2074,27 +2183,40 @@ fn lookup_at_index_ptr2<'a, 'ctx>( "cast_lookup_at_index_ptr", ); - let elem_ptr = builder + builder .new_build_struct_gep( struct_type, data_ptr, index as u32, "at_index_struct_gep_data", ) - .unwrap(); + .unwrap() +} - let field_layout = field_layouts[index]; - let result = load_roc_value( +fn union_field_at_index<'a, 'ctx>( + env: &Env<'a, 'ctx, '_>, + layout_interner: &STLayoutInterner<'a>, + field_layouts: &'a [InLayout<'a>], + opt_struct_type: Option>, + index: usize, + value: PointerValue<'ctx>, + target_loaded_type: BasicTypeEnum<'ctx>, +) -> PointerValue<'ctx> { + let result = union_field_at_index_help( env, layout_interner, - layout_interner.get_repr(field_layout), - elem_ptr, - "load_at_index_ptr", + field_layouts, + opt_struct_type, + index, + value, ); // A recursive pointer in the loaded structure is stored as a `i64*`, but the loaded layout // might want a more precise structure. As such, cast it to the refined type if needed. - cast_if_necessary_for_opaque_recursive_pointers(env.builder, result, target_loaded_type) + let from_value: BasicValueEnum = result.into(); + let to_type: BasicTypeEnum = target_loaded_type; + cast_if_necessary_for_opaque_recursive_pointers(env.builder, from_value, to_type) + .into_pointer_value() } pub fn reserve_with_refcount<'a, 'ctx>( @@ -3071,7 +3193,7 @@ pub fn cast_if_necessary_for_opaque_recursive_pointers<'ctx>( to_type: BasicTypeEnum<'ctx>, ) -> BasicValueEnum<'ctx> { if from_value.get_type() != to_type - // Only perform the cast if the target types are transumatble. + // Only perform the cast if the target types are transmutable. && equivalent_type_constructors(&from_value.get_type(), &to_type) { complex_bitcast( diff --git a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs index 4bfb429ce9a..cdc3af28cb9 100644 --- a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs +++ b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs @@ -1304,8 +1304,28 @@ pub(crate) fn run_low_level<'a, 'ctx>( .into() } - PtrStore | PtrLoad | PtrToZeroed | RefCountIncRcPtr | RefCountDecRcPtr - | RefCountIncDataPtr | RefCountDecDataPtr => { + PtrStore => { + arguments!(ptr, value); + + env.builder.build_store(ptr.into_pointer_value(), value); + + // ptr + env.context.struct_type(&[], false).const_zero().into() + } + + PtrLoad => { + arguments!(ptr); + + let ret_repr = layout_interner.get_repr(layout); + let element_type = basic_type_from_layout(env, layout_interner, ret_repr); + + env.builder + .new_build_load(element_type, ptr.into_pointer_value(), "ptr_load") + } + + PtrToZeroed => todo!(), + + RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr | RefCountDecDataPtr => { unreachable!("Not used in LLVM backend: {:?}", op); } diff --git a/crates/compiler/gen_wasm/src/backend.rs b/crates/compiler/gen_wasm/src/backend.rs index 0476c9d19a4..dde79f02bd6 100644 --- a/crates/compiler/gen_wasm/src/backend.rs +++ b/crates/compiler/gen_wasm/src/backend.rs @@ -1079,6 +1079,13 @@ impl<'a, 'r> WasmBackend<'a, 'r> { index, } => self.expr_union_at_index(*structure, *tag_id, union_layout, *index, sym), + Expr::UnionFieldPtrAtIndex { + structure, + tag_id, + union_layout, + index, + } => todo!(), + Expr::ExprBox { symbol: arg_sym } => self.expr_box(sym, *arg_sym, layout, storage), Expr::ExprUnbox { symbol: arg_sym } => self.expr_unbox(sym, *arg_sym), diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index 5cef4dd2cef..86d9805786b 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -16,7 +16,7 @@ use roc_can::module::{ }; use roc_collections::{default_hasher, BumpMap, MutMap, MutSet, VecMap, VecSet}; use roc_constrain::module::constrain_module; -use roc_debug_flags::dbg_do; +use roc_debug_flags::{dbg_do, ROC_PRINT_IR_AFTER_TRMC}; #[cfg(debug_assertions)] use roc_debug_flags::{ ROC_CHECK_MONO_IR, ROC_PRINT_IR_AFTER_DROP_SPECIALIZATION, ROC_PRINT_IR_AFTER_REFCOUNT, @@ -3104,6 +3104,16 @@ fn update<'a>( let ident_ids = state.constrained_ident_ids.get_mut(&module_id).unwrap(); + roc_mono::tail_recursion::apply_trmc( + arena, + &mut layout_interner, + module_id, + ident_ids, + &mut state.procedures, + ); + + debug_print_ir!(state, &layout_interner, ROC_PRINT_IR_AFTER_TRMC); + inc_dec::insert_inc_dec_operations( arena, &layout_interner, diff --git a/crates/compiler/module/src/low_level.rs b/crates/compiler/module/src/low_level.rs index 32fb65ed6d5..76f02bc51ce 100644 --- a/crates/compiler/module/src/low_level.rs +++ b/crates/compiler/module/src/low_level.rs @@ -230,7 +230,9 @@ macro_rules! map_symbol_to_lowlevel { // these are used internally and not tied to a symbol LowLevel::Hash => unimplemented!(), LowLevel::PtrCast => unimplemented!(), - LowLevel::PtrWrite => unimplemented!(), + LowLevel::PtrStore => unimplemented!(), + LowLevel::PtrLoad => unimplemented!(), + LowLevel::PtrToZeroed => unimplemented!(), LowLevel::RefCountIncRcPtr => unimplemented!(), LowLevel::RefCountDecRcPtr=> unimplemented!(), LowLevel::RefCountIncDataPtr => unimplemented!(), diff --git a/crates/compiler/mono/src/borrow.rs b/crates/compiler/mono/src/borrow.rs index 6978ccae3e4..b71ce34ae94 100644 --- a/crates/compiler/mono/src/borrow.rs +++ b/crates/compiler/mono/src/borrow.rs @@ -741,6 +741,14 @@ impl<'a> BorrowInfState<'a> { self.if_is_owned_then_own(z, *x); } + UnionFieldPtrAtIndex { structure: x, .. } => { + // if the structure (record/tag/array) is owned, the extracted value is + self.if_is_owned_then_own(*x, z); + + // if the extracted value is owned, the structure must be too + self.if_is_owned_then_own(z, *x); + } + GetTagId { structure: x, .. } => { // if the structure (record/tag/array) is owned, the extracted value is self.if_is_owned_then_own(*x, z); @@ -1035,7 +1043,9 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[Ownership] { unreachable!("These lowlevel operations are turned into mono Expr's") } - PtrWrite => arena.alloc_slice_copy(&[irrelevant, irrelevant]), + PtrStore => arena.alloc_slice_copy(&[owned, borrowed]), + PtrLoad => arena.alloc_slice_copy(&[owned]), + PtrToZeroed => arena.alloc_slice_copy(&[owned]), PtrCast | RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr | RefCountDecDataPtr | RefCountIsUnique => { diff --git a/crates/compiler/mono/src/debug/checker.rs b/crates/compiler/mono/src/debug/checker.rs index 93621212628..d6f872ffc17 100644 --- a/crates/compiler/mono/src/debug/checker.rs +++ b/crates/compiler/mono/src/debug/checker.rs @@ -429,6 +429,15 @@ impl<'a, 'r> Ctx<'a, 'r> { } => self.with_sym_layout(structure, |ctx, _def_line, layout| { ctx.check_union_at_index(structure, layout, union_layout, tag_id, index) }), + &Expr::UnionFieldPtrAtIndex { + structure, + tag_id, + union_layout, + index, + } => self.with_sym_layout(structure, |ctx, _def_line, layout| { + // TODO: I suspect this will fail because the output layout has an extra Box layer? + ctx.check_union_at_index(structure, layout, union_layout, tag_id, index) + }), Expr::Array { elem_layout, elems } => { for elem in elems.iter() { match elem { diff --git a/crates/compiler/mono/src/drop_specialization.rs b/crates/compiler/mono/src/drop_specialization.rs index 82a4978bd50..a8aa12247f9 100644 --- a/crates/compiler/mono/src/drop_specialization.rs +++ b/crates/compiler/mono/src/drop_specialization.rs @@ -211,7 +211,20 @@ fn specialize_drops_stmt<'a, 'i>( // TODO perhaps we need the union_layout later as well? if so, create a new function/map to store it. environment.add_union_child(*structure, *binding, *tag_id, *index); // Generated code might know the tag of the union without switching on it. - // So if we unionAtIndex, we must know the tag and we can use it to specialize the drop. + // So if we UnionAtIndex, we must know the tag and we can use it to specialize the drop. + environment.symbol_tag.insert(*structure, *tag_id); + alloc_let_with_continuation!(environment) + } + Expr::UnionFieldPtrAtIndex { + structure, + tag_id, + union_layout: _, + index, + } => { + // TODO perhaps we need the union_layout later as well? if so, create a new function/map to store it. + environment.add_union_child(*structure, *binding, *tag_id, *index); + // Generated code might know the tag of the union without switching on it. + // So if we UnionFieldPtrAtIndex, we must know the tag and we can use it to specialize the drop. environment.symbol_tag.insert(*structure, *tag_id); alloc_let_with_continuation!(environment) } @@ -1666,8 +1679,13 @@ fn low_level_no_rc(lowlevel: &LowLevel) -> RC { unreachable!("These lowlevel operations are turned into mono Expr's") } - PtrCast | PtrWrite | RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr - | RefCountDecDataPtr | RefCountIsUnique => { + // only inserted for internal purposes. RC should not touch it + PtrStore => RC::NoRc, + PtrLoad => RC::NoRc, + PtrToZeroed => RC::NoRc, + + PtrCast | RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr | RefCountDecDataPtr + | RefCountIsUnique => { unreachable!("Only inserted *after* borrow checking: {:?}", lowlevel); } } diff --git a/crates/compiler/mono/src/inc_dec.rs b/crates/compiler/mono/src/inc_dec.rs index e03f9a8ea78..e02b53e1f2e 100644 --- a/crates/compiler/mono/src/inc_dec.rs +++ b/crates/compiler/mono/src/inc_dec.rs @@ -345,17 +345,16 @@ impl<'v> RefcountEnvironment<'v> { // A groupby or something similar would be nice here. let mut symbol_usage = MutMap::default(); for symbol in symbols { - match { - self.symbols_rc_types - .get(&symbol) - .expect("Expected symbol to be in the map") - } { + match self.symbols_rc_types.get(&symbol) { // If the symbol is reference counted, we need to increment the usage count. - VarRcType::ReferenceCounted => { + Some(VarRcType::ReferenceCounted) => { *symbol_usage.entry(symbol).or_default() += 1; } // If the symbol is not reference counted, we don't need to do anything. - VarRcType::NotReferenceCounted => continue, + Some(VarRcType::NotReferenceCounted) => continue, + None => { + internal_error!("symbol {symbol:?} does not have an rc type") + } } } symbol_usage @@ -891,6 +890,7 @@ fn insert_refcount_operations_binding<'a>( Expr::GetTagId { structure, .. } | Expr::StructAtIndex { structure, .. } | Expr::UnionAtIndex { structure, .. } + | Expr::UnionFieldPtrAtIndex { structure, .. } | Expr::ExprUnbox { symbol: structure } => { // All structures are alive at this point and don't have to be copied in order to take an index out/get tag id/copy values to the stack. // But we do want to make sure to decrement this item if it is the last reference. @@ -904,6 +904,7 @@ fn insert_refcount_operations_binding<'a>( match expr { Expr::StructAtIndex { .. } | Expr::UnionAtIndex { .. } + | Expr::UnionFieldPtrAtIndex { .. } | Expr::ExprUnbox { .. } => insert_inc_stmt(arena, *binding, 1, new_stmt), // No usage of an element of a reference counted symbol. No need to increment. Expr::GetTagId { .. } => new_stmt, diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index c8553bdaa3c..39a25f6815d 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -403,41 +403,6 @@ impl<'a> Proc<'a> { w.push(b'\n'); String::from_utf8(w).unwrap() } - - fn make_tail_recursive(&mut self, interner: &mut I, env: &mut Env<'a, '_>) - where - I: LayoutInterner<'a>, - { - let mut args = Vec::with_capacity_in(self.args.len(), env.arena); - let mut proc_args = Vec::with_capacity_in(self.args.len(), env.arena); - - for (layout, symbol) in self.args { - let new = env.unique_symbol(); - args.push((*layout, *symbol, new)); - proc_args.push((*layout, new)); - } - - use self::SelfRecursive::*; - if let SelfRecursive(id) = self.is_self_recursive { - if crate::tail_recursion::is_trmc_candidate(interner, self) { - *self = crate::tail_recursion::TrmcEnv::init(env, interner, self); - } else { - let transformed = crate::tail_recursion::make_tail_recursive( - env.arena, - id, - self.name, - self.body.clone(), - args.into_bump_slice(), - self.ret_layout, - ); - - if let Some(with_tco) = transformed { - self.body = with_tco; - self.args = proc_args.into_bump_slice(); - } - } - } - } } /// A host-exposed function must be specialized; it's a seed for subsequent specializations @@ -1032,7 +997,7 @@ impl<'a> Procs<'a> { MutMap::with_capacity_and_hasher(self.specialized.len(), default_hasher()); for (symbol, layout, mut proc) in self.specialized.into_iter_assert_done() { - proc.make_tail_recursive(&mut layout_cache.interner, env); + // proc.make_tail_recursive(&mut layout_cache.interner, env); let key = (symbol, layout); specialized_procs.insert(key, proc); @@ -1888,6 +1853,12 @@ pub enum Expr<'a> { union_layout: UnionLayout<'a>, index: u64, }, + UnionFieldPtrAtIndex { + structure: Symbol, + tag_id: TagIdIntType, + union_layout: UnionLayout<'a>, + index: u64, + }, Array { elem_layout: InLayout<'a>, @@ -2105,6 +2076,19 @@ impl<'a> Expr<'a> { .. } => text!(alloc, "UnionAtIndex (Id {}) (Index {}) ", tag_id, index) .append(symbol_to_doc(alloc, *structure, pretty)), + + UnionFieldPtrAtIndex { + tag_id, + structure, + index, + .. + } => text!( + alloc, + "UnionFieldPtrAtIndex (Id {}) (Index {}) ", + tag_id, + index + ) + .append(symbol_to_doc(alloc, *structure, pretty)), } } @@ -7678,6 +7662,21 @@ fn substitute_in_expr<'a>( }), None => None, }, + + UnionFieldPtrAtIndex { + structure, + tag_id, + index, + union_layout, + } => match substitute(subs, *structure) { + Some(structure) => Some(UnionFieldPtrAtIndex { + structure, + tag_id: *tag_id, + index: *index, + union_layout: *union_layout, + }), + None => None, + }, } } diff --git a/crates/compiler/mono/src/tail_recursion.rs b/crates/compiler/mono/src/tail_recursion.rs index 77db2491196..5213181b6f0 100644 --- a/crates/compiler/mono/src/tail_recursion.rs +++ b/crates/compiler/mono/src/tail_recursion.rs @@ -1,11 +1,88 @@ #![allow(clippy::manual_map)] use crate::borrow::Ownership; -use crate::ir::{Call, CallType, Env, Expr, JoinPointId, Param, Proc, SelfRecursive, Stmt}; -use crate::layout::{InLayout, LambdaName, LayoutInterner, LayoutRepr, TagIdIntType, UnionLayout}; +use crate::ir::{ + Call, CallType, Expr, JoinPointId, Param, Proc, ProcLayout, SelfRecursive, Stmt, UpdateModeId, +}; +use crate::layout::{ + InLayout, LambdaName, Layout, LayoutInterner, LayoutRepr, STLayoutInterner, TagIdIntType, + UnionLayout, +}; use bumpalo::collections::Vec; use bumpalo::Bump; -use roc_module::symbol::Symbol; +use roc_collections::MutMap; +use roc_module::low_level::LowLevel; +use roc_module::symbol::{IdentIds, ModuleId, Symbol}; + +pub struct Env<'a, 'i> { + arena: &'a Bump, + home: ModuleId, + interner: &'i mut STLayoutInterner<'a>, + ident_ids: &'i mut IdentIds, +} + +impl<'a, 'i> Env<'a, 'i> { + pub fn unique_symbol(&mut self) -> Symbol { + let ident_id = self.ident_ids.gen_unique(); + + Symbol::new(self.home, ident_id) + } + + pub fn named_unique_symbol(&mut self, name: &str) -> Symbol { + let ident_id = self.ident_ids.add_str(name); + Symbol::new(self.home, ident_id) + } +} + +pub fn apply_trmc<'a, 'i>( + arena: &'a Bump, + interner: &'i mut STLayoutInterner<'a>, + home: ModuleId, + ident_ids: &'i mut IdentIds, + procs: &mut MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>, +) { + let mut env = Env { + arena, + interner, + home, + ident_ids, + }; + + let env = &mut env; + + for (_, proc) in procs { + use self::SelfRecursive::*; + if let SelfRecursive(id) = proc.is_self_recursive { + if crate::tail_recursion::is_trmc_candidate(env.interner, proc) { + let new_proc = crate::tail_recursion::TrmcEnv::init(env, proc); + *proc = new_proc; + } else { + let mut args = Vec::with_capacity_in(proc.args.len(), arena); + let mut proc_args = Vec::with_capacity_in(proc.args.len(), arena); + + for (layout, symbol) in proc.args { + let new = env.unique_symbol(); + args.push((*layout, *symbol, new)); + proc_args.push((*layout, new)); + } + + let transformed = crate::tail_recursion::make_tail_recursive( + arena, + id, + proc.name, + proc.body.clone(), + args.into_bump_slice(), + proc.ret_layout, + ); + + if let Some(with_tco) = transformed { + proc.body = with_tco; + proc.args = proc_args.into_bump_slice(); + } + } + } + } +} /// Make tail calls into loops (using join points) /// @@ -325,7 +402,7 @@ fn insert_jumps<'a>( } } -pub(crate) fn is_trmc_candidate<'a, I>(interner: &I, proc: &Proc<'a>) -> bool +pub(crate) fn is_trmc_candidate<'a, I>(interner: &'_ I, proc: &'_ Proc<'a>) -> bool where I: LayoutInterner<'a>, { @@ -338,10 +415,68 @@ where } // and return a recursive tag union - match interner.get_repr(proc.ret_layout) { - LayoutRepr::Union(union_layout) => union_layout.is_recursive(), - _ => false, + if !matches!(interner.get_repr(proc.ret_layout), LayoutRepr::Union(union_layout) if union_layout.is_recursive()) + { + return false; } + + has_cons_in_tail_position(&proc.body, proc.name) +} + +fn has_cons_in_tail_position(initial_stmt: &Stmt<'_>, function_name: LambdaName) -> bool { + // we are looking for code of the form + // + // let x = Tag a b c + // ret x + + let mut stack = vec![(None, initial_stmt)]; + + while let Some((recursive_call, stmt)) = stack.pop() { + match stmt { + Stmt::Let(symbol, expr, _, next) => { + if let Some(cons_info) = TrmcEnv::is_terminal_constructor(stmt) { + // must use the result of a recursive call directly as an argument + if let Some(recursive_call) = recursive_call { + if cons_info.arguments.contains(&recursive_call) { + return true; + } + } + } + + let recursive_call = recursive_call + .or_else(|| TrmcEnv::is_recursive_expr(expr, function_name).map(|_| *symbol)); + + stack.push((recursive_call, next)); + } + Stmt::Switch { + branches, + default_branch, + .. + } => { + for (_, _, stmt) in branches.iter() { + stack.push((recursive_call, stmt)); + } + stack.push((recursive_call, default_branch.1)); + } + Stmt::Refcounting(_, next) => { + stack.push((recursive_call, next)); + } + Stmt::Expect { remainder, .. } + | Stmt::ExpectFx { remainder, .. } + | Stmt::Dbg { remainder, .. } => { + stack.push((recursive_call, remainder)); + } + Stmt::Join { + body, remainder, .. + } => { + stack.push((recursive_call, body)); + stack.push((recursive_call, remainder)); + } + Stmt::Ret(_) | Stmt::Jump(_, _) | Stmt::Crash(_, _) => { /* terminal */ } + } + } + + false } #[derive(Clone)] @@ -358,6 +493,7 @@ pub(crate) struct TrmcEnv<'a> { recursive_call: Option<(Symbol, Call<'a>)>, } +#[derive(Debug)] struct ConstructorInfo<'a> { tag_layout: UnionLayout<'a>, tag_id: TagIdIntType, @@ -365,25 +501,18 @@ struct ConstructorInfo<'a> { } impl<'a> TrmcEnv<'a> { - fn is_recursive_expr(&mut self, expr: &Expr<'a>) -> Option> { - if let Expr::Call(call) = expr { - self.is_recursive_call(call).then_some(call.clone()) - } else { - None - } - } - - fn is_terminal_constructor(&mut self, stmt: &Stmt<'a>) -> Option> { + #[inline(always)] + fn is_terminal_constructor(stmt: &Stmt<'a>) -> Option> { match stmt { Stmt::Let(s1, expr, _layout, Stmt::Ret(s2)) if s1 == s2 => { - self.get_contructor_info(expr) + Self::get_contructor_info(expr) } _ => None, } } - fn get_contructor_info(&mut self, expr: &Expr<'a>) -> Option> { + fn get_contructor_info(expr: &Expr<'a>) -> Option> { if let Expr::Tag { tag_layout, tag_id, @@ -402,16 +531,19 @@ impl<'a> TrmcEnv<'a> { } } - fn is_recursive_call(&mut self, call: &Call<'a>) -> bool { + fn is_recursive_expr(expr: &Expr<'a>, lambda_name: LambdaName<'_>) -> Option> { + if let Expr::Call(call) = expr { + Self::is_recursive_call(call, lambda_name).then_some(call.clone()) + } else { + None + } + } + + fn is_recursive_call(call: &Call<'a>, lambda_name: LambdaName<'_>) -> bool { match call.call_type { - CallType::ByName { - name, - ret_layout, - arg_layouts, - specialization_id, - } => { + CallType::ByName { name, .. } => { // TODO are there other restrictions? - name == self.function_name + name == lambda_name } CallType::Foreign { .. } | CallType::LowLevel { .. } | CallType::HigherOrder(_) => { false @@ -421,16 +553,16 @@ impl<'a> TrmcEnv<'a> { fn ptr_write( env: &mut Env<'a, '_>, - interner: &mut impl LayoutInterner<'a>, - return_layout: InLayout<'a>, + _return_layout: InLayout<'a>, ptr: Symbol, value: Symbol, next: &'a Stmt<'a>, ) -> Stmt<'a> { let box_write = Call { call_type: crate::ir::CallType::LowLevel { - op: roc_module::low_level::LowLevel::PtrWrite, - update_mode: env.next_update_mode_id(), + op: LowLevel::PtrStore, + // update_mode: env.next_update_mode_id(), + update_mode: UpdateModeId::BACKEND_DUMMY, }, arguments: env.arena.alloc([ptr, value]), }; @@ -438,16 +570,13 @@ impl<'a> TrmcEnv<'a> { Stmt::Let( env.named_unique_symbol("_ptr_write_unit"), Expr::Call(box_write), - interner.insert_direct_no_semantic(LayoutRepr::Boxed(return_layout)), + // interner.insert_direct_no_semantic(LayoutRepr::Boxed(return_layout)), + Layout::UNIT, next, ) } - pub fn init( - env: &mut Env<'a, '_>, - interner: &mut impl LayoutInterner<'a>, - proc: &Proc<'a>, - ) -> Proc<'a> { + pub fn init<'i>(env: &mut Env<'a, 'i>, proc: &Proc<'a>) -> Proc<'a> { let arena = env.arena; let return_layout = proc.ret_layout; @@ -475,8 +604,9 @@ impl<'a> TrmcEnv<'a> { let null_symbol = env.named_unique_symbol("null"); let let_null = |next| Stmt::Let(null_symbol, Expr::NullPointer, return_layout, next); - let box_return_layout = - interner.insert_direct_no_semantic(LayoutRepr::Boxed(return_layout)); + let box_return_layout = env + .interner + .insert_direct_no_semantic(LayoutRepr::Boxed(return_layout)); let box_null = Expr::ExprBox { symbol: null_symbol, }; @@ -508,7 +638,7 @@ impl<'a> TrmcEnv<'a> { let joinpoint = Stmt::Join { id: joinpoint_id, parameters: joinpoint_parameters.into_bump_slice(), - body: arena.alloc(this.walk_stmt(env, interner, &proc.body)), + body: arena.alloc(this.walk_stmt(env, &proc.body)), remainder: arena.alloc(jump_stmt), }; @@ -534,24 +664,19 @@ impl<'a> TrmcEnv<'a> { } } - fn walk_stmt( - &mut self, - env: &mut Env<'a, '_>, - interner: &mut impl LayoutInterner<'a>, - stmt: &Stmt<'a>, - ) -> Stmt<'a> { + fn walk_stmt(&mut self, env: &mut Env<'a, '_>, stmt: &Stmt<'a>) -> Stmt<'a> { let arena = env.arena; match stmt { Stmt::Let(symbol, expr, layout, next) => { if self.recursive_call.is_none() { - if let Some(call) = self.is_recursive_expr(expr) { + if let Some(call) = Self::is_recursive_expr(expr, self.function_name) { self.recursive_call = Some((*symbol, call)); - return self.walk_stmt(env, interner, next); + return self.walk_stmt(env, next); } } - if let Some(cons_info) = self.is_terminal_constructor(stmt) { + if let Some(cons_info) = Self::is_terminal_constructor(stmt) { match &self.recursive_call { None => { // this control flow path did not encounter a recursive call. Just @@ -561,7 +686,7 @@ impl<'a> TrmcEnv<'a> { let output = define_tag(arena.alloc( // - self.non_trmc_return(env, interner, *symbol), + self.non_trmc_return(env, *symbol), )); return output; @@ -571,11 +696,21 @@ impl<'a> TrmcEnv<'a> { // branch. // TODO remove unwrap. also what if the symbol occurs more than once? - let recursive_field_index = cons_info - .arguments - .iter() - .position(|s| *s == *call_symbol) - .unwrap(); + let opt_recursive_field_index = + cons_info.arguments.iter().position(|s| *s == *call_symbol); + + let recursive_field_index = match opt_recursive_field_index { + None => { + let next = self.walk_stmt(env, next); + return Stmt::Let( + *symbol, + expr.clone(), + *layout, + arena.alloc(next), + ); + } + Some(v) => v, + }; let mut arguments = Vec::from_iter_in(cons_info.arguments.iter().copied(), env.arena); @@ -589,8 +724,11 @@ impl<'a> TrmcEnv<'a> { let let_tag = |next| Stmt::Let(*symbol, tag_expr, *layout, next); - let get_reference_expr = Expr::ExprBox { - symbol: self.null_symbol, + let get_reference_expr = Expr::UnionFieldPtrAtIndex { + structure: *symbol, + tag_id: cons_info.tag_id, + union_layout: cons_info.tag_layout, + index: recursive_field_index as _, }; let new_hole_symbol = env.named_unique_symbol("newHole"); @@ -616,7 +754,6 @@ impl<'a> TrmcEnv<'a> { // Self::ptr_write( env, - interner, *layout, self.hole_symbol, *symbol, @@ -630,7 +767,7 @@ impl<'a> TrmcEnv<'a> { } } - let next = self.walk_stmt(env, interner, next); + let next = self.walk_stmt(env, next); Stmt::Let(*symbol, expr.clone(), *layout, arena.alloc(next)) } Stmt::Switch { @@ -646,14 +783,13 @@ impl<'a> TrmcEnv<'a> { for (id, info, stmt) in branches.iter() { self.recursive_call = opt_recursive_call.clone(); - let new_stmt = self.walk_stmt(env, interner, stmt); + let new_stmt = self.walk_stmt(env, stmt); new_branches.push((*id, info.clone(), new_stmt)); } self.recursive_call = opt_recursive_call; - let new_default_branch = - &*arena.alloc(self.walk_stmt(env, interner, default_branch.1)); + let new_default_branch = &*arena.alloc(self.walk_stmt(env, default_branch.1)); Stmt::Switch { cond_symbol: *cond_symbol, @@ -666,42 +802,92 @@ impl<'a> TrmcEnv<'a> { Stmt::Ret(symbol) => { // write the symbol we're supposed to return into the hole // then read initial_symbol and return its contents - self.non_trmc_return(env, interner, *symbol) + self.non_trmc_return(env, *symbol) + } + Stmt::Refcounting(op, next) => { + let new_next = self.walk_stmt(env, next); + Stmt::Refcounting(*op, arena.alloc(new_next)) + } + Stmt::Expect { + condition, + region, + lookups, + variables, + remainder, + } => Stmt::Expect { + condition: *condition, + region: *region, + lookups, + variables, + remainder: arena.alloc(self.walk_stmt(env, remainder)), + }, + Stmt::ExpectFx { + condition, + region, + lookups, + variables, + remainder, + } => Stmt::Expect { + condition: *condition, + region: *region, + lookups, + variables, + remainder: arena.alloc(self.walk_stmt(env, remainder)), + }, + Stmt::Dbg { + symbol, + variable, + remainder, + } => Stmt::Dbg { + symbol: *symbol, + variable: *variable, + remainder: arena.alloc(self.walk_stmt(env, remainder)), + }, + Stmt::Join { + id, + parameters, + body, + remainder, + } => { + let new_body = self.walk_stmt(env, body); + let new_remainder = self.walk_stmt(env, remainder); + + Stmt::Join { + id: *id, + parameters, + body: arena.alloc(new_body), + remainder: arena.alloc(new_remainder), + } } - Stmt::Refcounting(_, _) => todo!(), - Stmt::Expect { .. } => todo!(), - Stmt::ExpectFx { .. } => todo!(), - Stmt::Dbg { .. } => todo!(), - Stmt::Join { .. } => todo!(), - Stmt::Jump(_, _) => todo!(), - Stmt::Crash(_, _) => todo!(), + Stmt::Jump(id, arguments) => Stmt::Jump(*id, arguments), + Stmt::Crash(symbol, crash_tag) => Stmt::Crash(*symbol, *crash_tag), } } - fn non_trmc_return( - &mut self, - env: &mut Env<'a, '_>, - interner: &mut impl LayoutInterner<'a>, - value_symbol: Symbol, - ) -> Stmt<'a> { + fn non_trmc_return(&mut self, env: &mut Env<'a, '_>, value_symbol: Symbol) -> Stmt<'a> { let arena = env.arena; let layout = self.return_layout; - let unbox_expr = Expr::ExprUnbox { - symbol: self.initial_box_symbol, - }; let final_symbol = env.named_unique_symbol("final"); - let unbox = |next| Stmt::Let(final_symbol, unbox_expr, layout, next); + + let call = Call { + call_type: CallType::LowLevel { + op: LowLevel::PtrLoad, + update_mode: UpdateModeId::BACKEND_DUMMY, + }, + arguments: &*arena.alloc([self.initial_box_symbol]), + }; + + let ptr_load = |next| Stmt::Let(final_symbol, Expr::Call(call), layout, next); Self::ptr_write( env, - interner, layout, self.hole_symbol, value_symbol, arena.alloc( // - unbox(arena.alloc(Stmt::Ret(final_symbol))), + ptr_load(arena.alloc(Stmt::Ret(final_symbol))), ), ) } diff --git a/examples/platform-switching/rocLovesZig.roc b/examples/platform-switching/rocLovesZig.roc index fe838c5396c..39bab4d9861 100644 --- a/examples/platform-switching/rocLovesZig.roc +++ b/examples/platform-switching/rocLovesZig.roc @@ -3,4 +3,29 @@ app "rocLovesZig" imports [] provides [main] to pf -main = "Roc <3 Zig!\n" +LinkedList a : [Nil, Cons a (LinkedList a)] + +map : LinkedList a, (a -> b) -> LinkedList b +map = \list, f -> + when list is + Nil -> Nil + Cons x xs -> Cons (f x) (map xs f) + +unfold : a, Nat -> LinkedList a +unfold = \value, n -> + when n is + 0 -> Nil + _ -> Cons value (unfold value (n - 1)) + +length : LinkedList a -> I64 +length = \list -> + when list is + Nil -> 0 + Cons _ rest -> 1 + length rest + +main : Str +main = + unfold 42 5 + |> map (\x -> x + 1i64) + |> length + |> Num.toStr From 9c85fb90d3bcff182108a3de073fd74a35da00ea Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 18 Jun 2023 17:00:31 +0200 Subject: [PATCH 024/140] fix bugs --- crates/compiler/can/src/builtins.rs | 2 +- crates/compiler/gen_llvm/src/llvm/convert.rs | 9 +- crates/compiler/gen_llvm/src/llvm/lowlevel.rs | 14 +- crates/compiler/gen_wasm/src/low_level.rs | 2 +- crates/compiler/module/src/low_level.rs | 4 +- crates/compiler/mono/src/borrow.rs | 4 +- .../compiler/mono/src/drop_specialization.rs | 2 +- crates/compiler/mono/src/layout.rs | 6 +- crates/compiler/mono/src/tail_recursion.rs | 91 +- ...e_in_polymorphic_expression_issue_4717.txt | 4 +- .../test_mono/generated/binary_tree_fbip.txt | 26 +- ...ose_correct_recursion_var_under_record.txt | 20 +- ...lambda_set_productive_nullable_wrapped.txt | 28 +- crates/compiler/test_mono/generated/dict.txt | 44 +- .../encode_derived_nested_record_string.txt | 1884 ++++++++--------- ...encode_derived_record_one_field_string.txt | 320 +-- ...ncode_derived_record_two_field_strings.txt | 320 +-- .../generated/encode_derived_string.txt | 182 +- .../encode_derived_tag_one_field_string.txt | 248 +-- ...encode_derived_tag_two_payloads_string.txt | 254 +-- .../test_mono/generated/factorial.txt | 4 +- ...e_return_joinpoints_in_bool_lambda_set.txt | 4 +- ...e_return_joinpoints_in_enum_lambda_set.txt | 4 +- ..._return_joinpoints_in_union_lambda_set.txt | 4 +- .../test_mono/generated/issue_3669.txt | 8 +- .../test_mono/generated/issue_4749.txt | 218 +- .../test_mono/generated/issue_4770.txt | 28 +- ..._4772_weakened_monomorphic_destructure.txt | 86 +- ...ure_with_multiple_recursive_structures.txt | 4 +- .../test_mono/generated/quicksort_help.txt | 4 +- .../test_mono/generated/rb_tree_fbip.txt | 793 +++---- .../recursive_call_capturing_function.txt | 4 +- ...function_and_union_with_inference_hole.txt | 4 +- ...d_non_recursive_lambda_sets_issue_5026.txt | 10 +- ..._set_resolved_only_upon_specialization.txt | 18 +- .../generated/recursively_build_effect.txt | 18 +- .../generated/specialize_after_match.txt | 24 +- .../generated/tail_call_elimination.txt | 4 +- ...not_duplicate_identical_concrete_types.txt | 56 +- ...all_concrete_types_without_unification.txt | 4 +- ...types_without_unification_of_unifiable.txt | 212 +- .../weakening_avoids_overspecialization.txt | 4 +- crates/compiler/test_mono/src/tests.rs | 23 + .../platform-switching/zig-platform/host.zig | 2 +- 44 files changed, 2542 insertions(+), 2462 deletions(-) diff --git a/crates/compiler/can/src/builtins.rs b/crates/compiler/can/src/builtins.rs index d59e23d5238..cf8ca72ee94 100644 --- a/crates/compiler/can/src/builtins.rs +++ b/crates/compiler/can/src/builtins.rs @@ -87,7 +87,7 @@ macro_rules! map_symbol_to_lowlevel_and_arity { LowLevel::PtrCast => unimplemented!(), LowLevel::PtrStore => unimplemented!(), LowLevel::PtrLoad => unimplemented!(), - LowLevel::PtrToZeroed => unimplemented!(), + LowLevel::PtrToStackValue => unimplemented!(), LowLevel::RefCountIncRcPtr => unimplemented!(), LowLevel::RefCountDecRcPtr=> unimplemented!(), LowLevel::RefCountIncDataPtr => unimplemented!(), diff --git a/crates/compiler/gen_llvm/src/llvm/convert.rs b/crates/compiler/gen_llvm/src/llvm/convert.rs index f0326ee1e89..65b9a1a1c95 100644 --- a/crates/compiler/gen_llvm/src/llvm/convert.rs +++ b/crates/compiler/gen_llvm/src/llvm/convert.rs @@ -30,7 +30,8 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>( layout_interner, layout_interner.get_repr(lambda_set.runtime_representation()), ), - Boxed(inner_layout) => { + + Ptr(inner_layout) | Boxed(inner_layout) => { let inner_type = basic_type_from_layout( env, layout_interner, @@ -41,12 +42,6 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>( } Union(union_layout) => basic_type_from_union_layout(env, layout_interner, &union_layout), - Ptr(_) => env - .context - .i64_type() - .ptr_type(AddressSpace::default()) - .as_basic_type_enum(), - RecursivePointer(_) => env .context .i64_type() diff --git a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs index cdc3af28cb9..7d6145e8391 100644 --- a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs +++ b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs @@ -28,8 +28,8 @@ use crate::llvm::{ }, build::{ cast_basic_basic, complex_bitcast_check_size, create_entry_block_alloca, - function_value_by_func_spec, load_roc_value, roc_function_call, tag_pointer_clear_tag_id, - BuilderExt, RocReturn, + entry_block_alloca_zerofill, function_value_by_func_spec, load_roc_value, + roc_function_call, tag_pointer_clear_tag_id, BuilderExt, RocReturn, }, build_list::{ list_append_unsafe, list_concat, list_drop_at, list_get_unsafe, list_len, list_map, @@ -1323,7 +1323,15 @@ pub(crate) fn run_low_level<'a, 'ctx>( .new_build_load(element_type, ptr.into_pointer_value(), "ptr_load") } - PtrToZeroed => todo!(), + PtrToStackValue => { + arguments!(initial_value); + + let ptr = entry_block_alloca_zerofill(env, initial_value.get_type(), "stack_value"); + + env.builder.build_store(ptr, initial_value); + + ptr.into() + } RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr | RefCountDecDataPtr => { unreachable!("Not used in LLVM backend: {:?}", op); diff --git a/crates/compiler/gen_wasm/src/low_level.rs b/crates/compiler/gen_wasm/src/low_level.rs index 81ac357af11..2096b30bc04 100644 --- a/crates/compiler/gen_wasm/src/low_level.rs +++ b/crates/compiler/gen_wasm/src/low_level.rs @@ -1962,7 +1962,7 @@ impl<'a> LowLevelCall<'a> { PtrStore => todo!("{:?}", self.lowlevel), PtrLoad => todo!("{:?}", self.lowlevel), - PtrToZeroed => todo!("{:?}", self.lowlevel), + PtrToStackValue => todo!("{:?}", self.lowlevel), Hash => todo!("{:?}", self.lowlevel), diff --git a/crates/compiler/module/src/low_level.rs b/crates/compiler/module/src/low_level.rs index 76f02bc51ce..a8b68cd4f34 100644 --- a/crates/compiler/module/src/low_level.rs +++ b/crates/compiler/module/src/low_level.rs @@ -120,7 +120,7 @@ pub enum LowLevel { PtrCast, PtrStore, PtrLoad, - PtrToZeroed, + PtrToStackValue, RefCountIncRcPtr, RefCountDecRcPtr, RefCountIncDataPtr, @@ -232,7 +232,7 @@ macro_rules! map_symbol_to_lowlevel { LowLevel::PtrCast => unimplemented!(), LowLevel::PtrStore => unimplemented!(), LowLevel::PtrLoad => unimplemented!(), - LowLevel::PtrToZeroed => unimplemented!(), + LowLevel::PtrToStackValue => unimplemented!(), LowLevel::RefCountIncRcPtr => unimplemented!(), LowLevel::RefCountDecRcPtr=> unimplemented!(), LowLevel::RefCountIncDataPtr => unimplemented!(), diff --git a/crates/compiler/mono/src/borrow.rs b/crates/compiler/mono/src/borrow.rs index b71ce34ae94..cb2b9aeb5bf 100644 --- a/crates/compiler/mono/src/borrow.rs +++ b/crates/compiler/mono/src/borrow.rs @@ -1043,9 +1043,9 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[Ownership] { unreachable!("These lowlevel operations are turned into mono Expr's") } - PtrStore => arena.alloc_slice_copy(&[owned, borrowed]), + PtrStore => arena.alloc_slice_copy(&[owned, owned]), PtrLoad => arena.alloc_slice_copy(&[owned]), - PtrToZeroed => arena.alloc_slice_copy(&[owned]), + PtrToStackValue => arena.alloc_slice_copy(&[owned]), PtrCast | RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr | RefCountDecDataPtr | RefCountIsUnique => { diff --git a/crates/compiler/mono/src/drop_specialization.rs b/crates/compiler/mono/src/drop_specialization.rs index a8aa12247f9..a695c89ac65 100644 --- a/crates/compiler/mono/src/drop_specialization.rs +++ b/crates/compiler/mono/src/drop_specialization.rs @@ -1682,7 +1682,7 @@ fn low_level_no_rc(lowlevel: &LowLevel) -> RC { // only inserted for internal purposes. RC should not touch it PtrStore => RC::NoRc, PtrLoad => RC::NoRc, - PtrToZeroed => RC::NoRc, + PtrToStackValue => RC::NoRc, PtrCast | RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr | RefCountDecDataPtr | RefCountIsUnique => { diff --git a/crates/compiler/mono/src/layout.rs b/crates/compiler/mono/src/layout.rs index 5658e884315..f2ddd9c3a8c 100644 --- a/crates/compiler/mono/src/layout.rs +++ b/crates/compiler/mono/src/layout.rs @@ -2792,7 +2792,11 @@ impl<'a> LayoutRepr<'a> { .contains_refcounted(interner), RecursivePointer(_) => true, Boxed(_) => true, - Ptr(inner) => interner.get_repr(*inner).contains_refcounted(interner), + Ptr(_) => { + // we never consider pointers for refcounting. Ptr is not user-facing. The compiler + // author must make sure that invariants are upheld + false + } } } diff --git a/crates/compiler/mono/src/tail_recursion.rs b/crates/compiler/mono/src/tail_recursion.rs index 5213181b6f0..09a48d17497 100644 --- a/crates/compiler/mono/src/tail_recursion.rs +++ b/crates/compiler/mono/src/tail_recursion.rs @@ -22,13 +22,13 @@ pub struct Env<'a, 'i> { } impl<'a, 'i> Env<'a, 'i> { - pub fn unique_symbol(&mut self) -> Symbol { + fn unique_symbol(&mut self) -> Symbol { let ident_id = self.ident_ids.gen_unique(); Symbol::new(self.home, ident_id) } - pub fn named_unique_symbol(&mut self, name: &str) -> Symbol { + fn named_unique_symbol(&mut self, name: &str) -> Symbol { let ident_id = self.ident_ids.add_str(name); Symbol::new(self.home, ident_id) } @@ -107,7 +107,7 @@ pub fn apply_trmc<'a, 'i>( /// This will effectively compile into a loop in llvm, and /// won't grow the call stack for each iteration -pub fn make_tail_recursive<'a>( +fn make_tail_recursive<'a>( arena: &'a Bump, id: JoinPointId, needle: LambdaName, @@ -483,11 +483,10 @@ fn has_cons_in_tail_position(initial_stmt: &Stmt<'_>, function_name: LambdaName) pub(crate) struct TrmcEnv<'a> { function_name: LambdaName<'a>, hole_symbol: Symbol, - null_symbol: Symbol, - initial_box_symbol: Symbol, + initial_ptr_symbol: Symbol, joinpoint_id: JoinPointId, return_layout: InLayout<'a>, - box_return_layout: InLayout<'a>, + ptr_return_layout: InLayout<'a>, // the call we are performing TRMC on recursive_call: Option<(Symbol, Call<'a>)>, @@ -553,12 +552,11 @@ impl<'a> TrmcEnv<'a> { fn ptr_write( env: &mut Env<'a, '_>, - _return_layout: InLayout<'a>, ptr: Symbol, value: Symbol, next: &'a Stmt<'a>, ) -> Stmt<'a> { - let box_write = Call { + let ptr_write = Call { call_type: crate::ir::CallType::LowLevel { op: LowLevel::PtrStore, // update_mode: env.next_update_mode_id(), @@ -569,8 +567,7 @@ impl<'a> TrmcEnv<'a> { Stmt::Let( env.named_unique_symbol("_ptr_write_unit"), - Expr::Call(box_write), - // interner.insert_direct_no_semantic(LayoutRepr::Boxed(return_layout)), + Expr::Call(ptr_write), Layout::UNIT, next, ) @@ -598,19 +595,26 @@ impl<'a> TrmcEnv<'a> { } // the root of the recursive structure that we'll be building - let initial_box_symbol = env.named_unique_symbol("initial"); - jump_arguments.push(initial_box_symbol); + let initial_ptr_symbol = env.named_unique_symbol("initial"); + jump_arguments.push(initial_ptr_symbol); let null_symbol = env.named_unique_symbol("null"); let let_null = |next| Stmt::Let(null_symbol, Expr::NullPointer, return_layout, next); - let box_return_layout = env + let ptr_return_layout = env .interner - .insert_direct_no_semantic(LayoutRepr::Boxed(return_layout)); - let box_null = Expr::ExprBox { - symbol: null_symbol, + .insert_direct_no_semantic(LayoutRepr::Ptr(return_layout)); + + let call = Call { + call_type: CallType::LowLevel { + op: LowLevel::PtrToStackValue, + update_mode: UpdateModeId::BACKEND_DUMMY, + }, + arguments: arena.alloc([null_symbol]), }; - let let_box = |next| Stmt::Let(initial_box_symbol, box_null, box_return_layout, next); + + let ptr_null = Expr::Call(call); + let let_ptr = |next| Stmt::Let(initial_ptr_symbol, ptr_null, ptr_return_layout, next); let joinpoint_id = JoinPointId(env.named_unique_symbol("trmc")); let hole_symbol = env.named_unique_symbol("hole"); @@ -620,18 +624,17 @@ impl<'a> TrmcEnv<'a> { let mut this = Self { function_name: proc.name, hole_symbol, - null_symbol, - initial_box_symbol, + initial_ptr_symbol, joinpoint_id, return_layout, - box_return_layout, + ptr_return_layout, recursive_call: None, }; let param = Param { symbol: hole_symbol, ownership: Ownership::Owned, - layout: box_return_layout, + layout: ptr_return_layout, }; joinpoint_parameters.push(param); @@ -644,7 +647,7 @@ impl<'a> TrmcEnv<'a> { let body = let_null(arena.alloc( // - let_box(arena.alloc( + let_ptr(arena.alloc( // joinpoint, )), @@ -671,8 +674,10 @@ impl<'a> TrmcEnv<'a> { Stmt::Let(symbol, expr, layout, next) => { if self.recursive_call.is_none() { if let Some(call) = Self::is_recursive_expr(expr, self.function_name) { - self.recursive_call = Some((*symbol, call)); - return self.walk_stmt(env, next); + if has_cons_in_tail_position(next, self.function_name) { + self.recursive_call = Some((*symbol, call)); + return self.walk_stmt(env, next); + } } } @@ -695,7 +700,6 @@ impl<'a> TrmcEnv<'a> { // we did encounter a recursive call, and can perform TRMC in this // branch. - // TODO remove unwrap. also what if the symbol occurs more than once? let opt_recursive_field_index = cons_info.arguments.iter().position(|s| *s == *call_symbol); @@ -712,9 +716,19 @@ impl<'a> TrmcEnv<'a> { Some(v) => v, }; + let tag_arg_null_symbol = env.named_unique_symbol("tag_arg_null"); + let let_tag_arg_null = |next| { + Stmt::Let( + tag_arg_null_symbol, + Expr::NullPointer, + self.return_layout, + next, + ) + }; + let mut arguments = Vec::from_iter_in(cons_info.arguments.iter().copied(), env.arena); - arguments[recursive_field_index] = self.null_symbol; + arguments[recursive_field_index] = tag_arg_null_symbol; let tag_expr = Expr::Tag { tag_layout: cons_info.tag_layout, @@ -736,7 +750,7 @@ impl<'a> TrmcEnv<'a> { Stmt::Let( new_hole_symbol, get_reference_expr, - self.box_return_layout, + self.ptr_return_layout, next, ) }; @@ -748,17 +762,19 @@ impl<'a> TrmcEnv<'a> { let jump = Stmt::Jump(self.joinpoint_id, jump_arguments.into_bump_slice()); - let output = let_tag(arena.alloc( + let output = let_tag_arg_null(arena.alloc( // - let_new_hole(arena.alloc( + let_tag(arena.alloc( // - Self::ptr_write( - env, - *layout, - self.hole_symbol, - *symbol, - arena.alloc(jump), - ), + let_new_hole(arena.alloc( + // + Self::ptr_write( + env, + self.hole_symbol, + *symbol, + arena.alloc(jump), + ), + )), )), )); @@ -875,14 +891,13 @@ impl<'a> TrmcEnv<'a> { op: LowLevel::PtrLoad, update_mode: UpdateModeId::BACKEND_DUMMY, }, - arguments: &*arena.alloc([self.initial_box_symbol]), + arguments: &*arena.alloc([self.initial_ptr_symbol]), }; let ptr_load = |next| Stmt::Let(final_symbol, Expr::Call(call), layout, next); Self::ptr_write( env, - layout, self.hole_symbol, value_symbol, arena.alloc( diff --git a/crates/compiler/test_mono/generated/anonymous_closure_in_polymorphic_expression_issue_4717.txt b/crates/compiler/test_mono/generated/anonymous_closure_in_polymorphic_expression_issue_4717.txt index 42f3862731e..f3eca0d0aa6 100644 --- a/crates/compiler/test_mono/generated/anonymous_closure_in_polymorphic_expression_issue_4717.txt +++ b/crates/compiler/test_mono/generated/anonymous_closure_in_polymorphic_expression_issue_4717.txt @@ -53,7 +53,7 @@ procedure List.72 (#Attr.2, #Attr.3, #Attr.4): let List.527 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; ret List.527; -procedure List.80 (List.571, List.572, List.573, List.574, List.575): +procedure List.80 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): joinpoint List.545 List.439 List.440 List.441 List.442 List.443: let List.547 : Int1 = CallByName Num.22 List.442 List.443; if List.547 then @@ -77,7 +77,7 @@ procedure List.80 (List.571, List.572, List.573, List.574, List.575): let List.546 : [C U64, C U64] = TagId(1) List.440; ret List.546; in - jump List.545 List.571 List.572 List.573 List.574 List.575; + jump List.545 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; procedure List.93 (List.436, List.437, List.438): let List.543 : U64 = 0i64; diff --git a/crates/compiler/test_mono/generated/binary_tree_fbip.txt b/crates/compiler/test_mono/generated/binary_tree_fbip.txt index 84f7f6907c3..77de42cdbd8 100644 --- a/crates/compiler/test_mono/generated/binary_tree_fbip.txt +++ b/crates/compiler/test_mono/generated/binary_tree_fbip.txt @@ -8,7 +8,7 @@ procedure Test.4 (Test.27): let Test.38 : I64 = CallByName Test.5 Test.27 Test.39 Test.40; ret Test.38; -procedure Test.5 (Test.67, Test.68, Test.69): +procedure Test.5 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): joinpoint Test.41 Test.29 Test.30 Test.31: let Test.51 : U8 = 0i64; let Test.52 : U8 = GetTagId Test.29; @@ -16,23 +16,23 @@ procedure Test.5 (Test.67, Test.68, Test.69): if Test.53 then let Test.32 : [, C *self *self] = UnionAtIndex (Id 0) (Index 0) Test.29; let Test.33 : [, C *self *self] = UnionAtIndex (Id 0) (Index 1) Test.29; - joinpoint #Derived_gen.0 #Derived_gen.4: - let #Derived_gen.5 : [C [, C *self *self] *self, ] = lowlevel PtrCast #Derived_gen.4; - let Test.43 : [C [, C *self *self] *self, ] = Reuse #Derived_gen.5 UpdateModeId { id: 1 } TagId(1) Test.33 Test.30; + joinpoint #Derived_gen.3 #Derived_gen.7: + let #Derived_gen.8 : [C [, C *self *self] *self, ] = lowlevel PtrCast #Derived_gen.7; + let Test.43 : [C [, C *self *self] *self, ] = Reuse #Derived_gen.8 UpdateModeId { id: 1 } TagId(1) Test.33 Test.30; let Test.45 : I64 = 1i64; let Test.44 : I64 = CallByName Num.19 Test.31 Test.45; jump Test.41 Test.32 Test.43 Test.44; in - let #Derived_gen.1 : Int1 = lowlevel RefCountIsUnique Test.29; - if #Derived_gen.1 then - let #Derived_gen.6 : [, C *self *self] = ResetRef { symbol: Test.29, id: UpdateModeId { id: 2 } }; - jump #Derived_gen.0 #Derived_gen.6; + let #Derived_gen.4 : Int1 = lowlevel RefCountIsUnique Test.29; + if #Derived_gen.4 then + let #Derived_gen.9 : [, C *self *self] = ResetRef { symbol: Test.29, id: UpdateModeId { id: 2 } }; + jump #Derived_gen.3 #Derived_gen.9; else inc Test.32; inc Test.33; decref Test.29; - let #Derived_gen.7 : [, C *self *self] = NullPointer; - jump #Derived_gen.0 #Derived_gen.7; + let #Derived_gen.10 : [, C *self *self] = NullPointer; + jump #Derived_gen.3 #Derived_gen.10; else let Test.48 : U8 = 1i64; let Test.49 : U8 = GetTagId Test.30; @@ -40,8 +40,8 @@ procedure Test.5 (Test.67, Test.68, Test.69): if Test.50 then let Test.35 : [, C *self *self] = UnionAtIndex (Id 1) (Index 0) Test.30; let Test.36 : [C [, C *self *self] *self, ] = UnionAtIndex (Id 1) (Index 1) Test.30; - let #Derived_gen.2 : Int1 = lowlevel RefCountIsUnique Test.30; - if #Derived_gen.2 then + let #Derived_gen.5 : Int1 = lowlevel RefCountIsUnique Test.30; + if #Derived_gen.5 then decref Test.30; jump Test.41 Test.35 Test.36 Test.31; else @@ -52,7 +52,7 @@ procedure Test.5 (Test.67, Test.68, Test.69): else ret Test.31; in - jump Test.41 Test.67 Test.68 Test.69; + jump Test.41 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2; procedure Test.0 (): let Test.64 : [, C *self *self] = TagId(1) ; diff --git a/crates/compiler/test_mono/generated/choose_correct_recursion_var_under_record.txt b/crates/compiler/test_mono/generated/choose_correct_recursion_var_under_record.txt index 7a3b68e8d6e..653d6dc3b9e 100644 --- a/crates/compiler/test_mono/generated/choose_correct_recursion_var_under_record.txt +++ b/crates/compiler/test_mono/generated/choose_correct_recursion_var_under_record.txt @@ -78,7 +78,7 @@ procedure Test.2 (Test.6): let Test.31 : Int1 = lowlevel Eq Test.29 Test.30; if Test.31 then let Test.7 : [C List *self, C *self] = UnionAtIndex (Id 1) (Index 0) Test.6; - joinpoint #Derived_gen.0: + joinpoint #Derived_gen.1: let Test.8 : Str = CallByName Test.2 Test.7; let Test.18 : Int1 = CallByName Bool.1; if Test.18 then @@ -88,17 +88,17 @@ procedure Test.2 (Test.6): let Test.17 : Str = "foo"; ret Test.17; in - let #Derived_gen.1 : Int1 = lowlevel RefCountIsUnique Test.6; - if #Derived_gen.1 then + let #Derived_gen.2 : Int1 = lowlevel RefCountIsUnique Test.6; + if #Derived_gen.2 then decref Test.6; - jump #Derived_gen.0; + jump #Derived_gen.1; else inc Test.7; decref Test.6; - jump #Derived_gen.0; + jump #Derived_gen.1; else let Test.9 : List [C List [C List *self, C *self], C [C List *self, C *self]] = UnionAtIndex (Id 0) (Index 0) Test.6; - joinpoint #Derived_gen.2: + joinpoint #Derived_gen.3: let Test.24 : {} = Struct {}; let Test.23 : List Str = CallByName List.5 Test.9 Test.24; let Test.21 : [C {}, C Str] = CallByName List.9 Test.23; @@ -106,14 +106,14 @@ procedure Test.2 (Test.6): let Test.20 : Str = CallByName Result.5 Test.21 Test.22; ret Test.20; in - let #Derived_gen.3 : Int1 = lowlevel RefCountIsUnique Test.6; - if #Derived_gen.3 then + let #Derived_gen.4 : Int1 = lowlevel RefCountIsUnique Test.6; + if #Derived_gen.4 then decref Test.6; - jump #Derived_gen.2; + jump #Derived_gen.3; else inc Test.9; decref Test.6; - jump #Derived_gen.2; + jump #Derived_gen.3; procedure Test.0 (): let Test.32 : List [C List [C List *self, C *self], C [C List *self, C *self]] = Array []; diff --git a/crates/compiler/test_mono/generated/compose_recursive_lambda_set_productive_nullable_wrapped.txt b/crates/compiler/test_mono/generated/compose_recursive_lambda_set_productive_nullable_wrapped.txt index 39dc4fc550a..ca95a51d0b1 100644 --- a/crates/compiler/test_mono/generated/compose_recursive_lambda_set_productive_nullable_wrapped.txt +++ b/crates/compiler/test_mono/generated/compose_recursive_lambda_set_productive_nullable_wrapped.txt @@ -18,7 +18,7 @@ procedure List.66 (#Attr.2, #Attr.3): let List.537 : Int1 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.537; -procedure List.80 (List.544, List.545, List.546, List.547, List.548): +procedure List.80 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): joinpoint List.527 List.439 List.440 List.441 List.442 List.443: let List.529 : Int1 = CallByName Num.22 List.442 List.443; if List.529 then @@ -31,7 +31,7 @@ procedure List.80 (List.544, List.545, List.546, List.547, List.548): dec List.439; ret List.440; in - jump List.527 List.544 List.545 List.546 List.547 List.548; + jump List.527 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; procedure List.93 (List.436, List.437, List.438): let List.525 : U64 = 0i64; @@ -54,11 +54,11 @@ procedure Str.3 (#Attr.2, #Attr.3): procedure Test.1 (Test.5): ret Test.5; -procedure Test.11 (Test.53, Test.54): +procedure Test.11 (#Derived_gen.7, #Derived_gen.8): joinpoint Test.27 Test.12 #Attr.12: let Test.8 : Int1 = UnionAtIndex (Id 2) (Index 1) #Attr.12; let Test.7 : [, C *self Int1, C *self Int1] = UnionAtIndex (Id 2) (Index 0) #Attr.12; - joinpoint #Derived_gen.2: + joinpoint #Derived_gen.14: joinpoint Test.31 Test.29: let Test.30 : U8 = GetTagId Test.7; switch Test.30: @@ -85,16 +85,16 @@ procedure Test.11 (Test.53, Test.54): jump Test.31 Test.32; in - let #Derived_gen.3 : Int1 = lowlevel RefCountIsUnique #Attr.12; - if #Derived_gen.3 then + let #Derived_gen.15 : Int1 = lowlevel RefCountIsUnique #Attr.12; + if #Derived_gen.15 then decref #Attr.12; - jump #Derived_gen.2; + jump #Derived_gen.14; else inc Test.7; decref #Attr.12; - jump #Derived_gen.2; + jump #Derived_gen.14; in - jump Test.27 Test.53 Test.54; + jump Test.27 #Derived_gen.7 #Derived_gen.8; procedure Test.2 (Test.13): ret Test.13; @@ -125,7 +125,7 @@ procedure Test.6 (Test.7, Test.8, Test.5): procedure Test.9 (Test.10, #Attr.12): let Test.8 : Int1 = UnionAtIndex (Id 1) (Index 1) #Attr.12; let Test.7 : [, C *self Int1, C *self Int1] = UnionAtIndex (Id 1) (Index 0) #Attr.12; - joinpoint #Derived_gen.0: + joinpoint #Derived_gen.12: let Test.37 : U8 = GetTagId Test.7; joinpoint Test.38 Test.36: switch Test.8: @@ -153,14 +153,14 @@ procedure Test.9 (Test.10, #Attr.12): jump Test.38 Test.39; in - let #Derived_gen.1 : Int1 = lowlevel RefCountIsUnique #Attr.12; - if #Derived_gen.1 then + let #Derived_gen.13 : Int1 = lowlevel RefCountIsUnique #Attr.12; + if #Derived_gen.13 then decref #Attr.12; - jump #Derived_gen.0; + jump #Derived_gen.12; else inc Test.7; decref #Attr.12; - jump #Derived_gen.0; + jump #Derived_gen.12; procedure Test.0 (): let Test.41 : Int1 = false; diff --git a/crates/compiler/test_mono/generated/dict.txt b/crates/compiler/test_mono/generated/dict.txt index 74e203e84a9..faed8e7fc74 100644 --- a/crates/compiler/test_mono/generated/dict.txt +++ b/crates/compiler/test_mono/generated/dict.txt @@ -16,12 +16,12 @@ procedure Dict.36 (): procedure Dict.4 (Dict.543): let Dict.97 : U64 = StructAtIndex 3 Dict.543; - let #Derived_gen.2 : List {[], []} = StructAtIndex 0 Dict.543; - dec #Derived_gen.2; - let #Derived_gen.1 : List U64 = StructAtIndex 1 Dict.543; - dec #Derived_gen.1; - let #Derived_gen.0 : List I8 = StructAtIndex 2 Dict.543; - dec #Derived_gen.0; + let #Derived_gen.8 : List {[], []} = StructAtIndex 0 Dict.543; + dec #Derived_gen.8; + let #Derived_gen.7 : List U64 = StructAtIndex 1 Dict.543; + dec #Derived_gen.7; + let #Derived_gen.6 : List I8 = StructAtIndex 2 Dict.543; + dec #Derived_gen.6; ret Dict.97; procedure List.11 (List.121, List.122): @@ -50,21 +50,7 @@ procedure List.71 (#Attr.2, #Attr.3): let List.541 : List U64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; ret List.541; -procedure List.83 (List.545, List.546, List.547): - joinpoint List.523 List.123 List.124 List.125: - let List.531 : U64 = 0i64; - let List.525 : Int1 = CallByName Num.24 List.124 List.531; - if List.525 then - let List.530 : U64 = 1i64; - let List.527 : U64 = CallByName Num.20 List.124 List.530; - let List.528 : List I8 = CallByName List.71 List.125 List.123; - jump List.523 List.123 List.527 List.528; - else - ret List.125; - in - jump List.523 List.545 List.546 List.547; - -procedure List.83 (List.553, List.554, List.555): +procedure List.83 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): joinpoint List.535 List.123 List.124 List.125: let List.543 : U64 = 0i64; let List.537 : Int1 = CallByName Num.24 List.124 List.543; @@ -76,7 +62,21 @@ procedure List.83 (List.553, List.554, List.555): else ret List.125; in - jump List.535 List.553 List.554 List.555; + jump List.535 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2; + +procedure List.83 (#Derived_gen.3, #Derived_gen.4, #Derived_gen.5): + joinpoint List.523 List.123 List.124 List.125: + let List.531 : U64 = 0i64; + let List.525 : Int1 = CallByName Num.24 List.124 List.531; + if List.525 then + let List.530 : U64 = 1i64; + let List.527 : U64 = CallByName Num.20 List.124 List.530; + let List.528 : List I8 = CallByName List.71 List.125 List.123; + jump List.523 List.123 List.527 List.528; + else + ret List.125; + in + jump List.523 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5; procedure Num.20 (#Attr.2, #Attr.3): let Num.293 : U64 = lowlevel NumSub #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/encode_derived_nested_record_string.txt b/crates/compiler/test_mono/generated/encode_derived_nested_record_string.txt index 9f28113a0c3..9aa6441298a 100644 --- a/crates/compiler/test_mono/generated/encode_derived_nested_record_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_nested_record_string.txt @@ -12,17 +12,17 @@ procedure #Derived.2 (#Derived.3, #Derived.4, #Derived.1): ret #Derived_gen.3; procedure #Derived.5 (#Derived.6): - let #Derived_gen.14 : Str = CallByName Encode.23 #Derived.6; - ret #Derived_gen.14; + let #Derived_gen.10 : Str = CallByName Encode.23 #Derived.6; + ret #Derived_gen.10; procedure #Derived.7 (#Derived.8, #Derived.9, #Derived.6): - let #Derived_gen.21 : Str = "b"; - let #Derived_gen.22 : Str = CallByName TotallyNotJson.25 #Derived.6; - let #Derived_gen.20 : {Str, Str} = Struct {#Derived_gen.21, #Derived_gen.22}; - let #Derived_gen.19 : List {Str, Str} = Array [#Derived_gen.20]; - let #Derived_gen.18 : List {Str, Str} = CallByName TotallyNotJson.29 #Derived_gen.19; - let #Derived_gen.17 : List U8 = CallByName Encode.24 #Derived.8 #Derived_gen.18 #Derived.9; - ret #Derived_gen.17; + let #Derived_gen.17 : Str = "b"; + let #Derived_gen.18 : Str = CallByName TotallyNotJson.25 #Derived.6; + let #Derived_gen.16 : {Str, Str} = Struct {#Derived_gen.17, #Derived_gen.18}; + let #Derived_gen.15 : List {Str, Str} = Array [#Derived_gen.16]; + let #Derived_gen.14 : List {Str, Str} = CallByName TotallyNotJson.29 #Derived_gen.15; + let #Derived_gen.13 : List U8 = CallByName Encode.24 #Derived.8 #Derived_gen.14 #Derived.9; + ret #Derived_gen.13; procedure Bool.1 (): let Bool.76 : Int1 = false; @@ -56,20 +56,20 @@ procedure Encode.24 (Encode.99, Encode.107, Encode.101): ret Encode.111; procedure Encode.24 (Encode.99, Encode.107, Encode.101): - let Encode.118 : List U8 = CallByName TotallyNotJson.234 Encode.99 Encode.101 Encode.107; - ret Encode.118; + let Encode.113 : List U8 = CallByName TotallyNotJson.234 Encode.99 Encode.101 Encode.107; + ret Encode.113; procedure Encode.24 (Encode.99, Encode.107, Encode.101): - let Encode.120 : List U8 = CallByName #Derived.7 Encode.99 Encode.101 Encode.107; - ret Encode.120; + let Encode.115 : List U8 = CallByName #Derived.7 Encode.99 Encode.101 Encode.107; + ret Encode.115; procedure Encode.24 (Encode.99, Encode.107, Encode.101): - let Encode.130 : List U8 = CallByName TotallyNotJson.234 Encode.99 Encode.101 Encode.107; - ret Encode.130; + let Encode.117 : List U8 = CallByName TotallyNotJson.234 Encode.99 Encode.101 Encode.107; + ret Encode.117; procedure Encode.24 (Encode.99, Encode.107, Encode.101): - let Encode.133 : List U8 = CallByName TotallyNotJson.182 Encode.99 Encode.101 Encode.107; - ret Encode.133; + let Encode.120 : List U8 = CallByName TotallyNotJson.182 Encode.99 Encode.101 Encode.107; + ret Encode.120; procedure Encode.26 (Encode.105, Encode.106): let Encode.109 : List U8 = Array []; @@ -78,303 +78,303 @@ procedure Encode.26 (Encode.105, Encode.106): ret Encode.108; procedure List.13 (#Attr.2, #Attr.3): - let List.730 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; - ret List.730; + let List.689 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; + ret List.689; procedure List.145 (List.146, List.147, List.144): - let List.570 : {List U8, U64} = CallByName TotallyNotJson.237 List.146 List.147 List.144; - ret List.570; + let List.569 : {List U8, U64} = CallByName TotallyNotJson.237 List.146 List.147 List.144; + ret List.569; procedure List.145 (List.146, List.147, List.144): - let List.678 : {List U8, U64} = CallByName TotallyNotJson.237 List.146 List.147 List.144; - ret List.678; + let List.637 : {List U8, U64} = CallByName TotallyNotJson.237 List.146 List.147 List.144; + ret List.637; procedure List.145 (List.146, List.147, List.144): - let List.698 : List U8 = CallByName TotallyNotJson.215 List.146 List.147; - ret List.698; + let List.657 : List U8 = CallByName TotallyNotJson.215 List.146 List.147; + ret List.657; procedure List.18 (List.142, List.143, List.144): - let List.551 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; - ret List.551; + let List.550 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; + ret List.550; procedure List.18 (List.142, List.143, List.144): - let List.659 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; - ret List.659; + let List.618 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; + ret List.618; procedure List.18 (List.142, List.143, List.144): - let List.679 : List U8 = CallByName List.93 List.142 List.143 List.144; - ret List.679; + let List.638 : List U8 = CallByName List.93 List.142 List.143 List.144; + ret List.638; procedure List.26 (List.159, List.160, List.161): - let List.747 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.93 List.159 List.160 List.161; - let List.750 : U8 = 1i64; - let List.751 : U8 = GetTagId List.747; - let List.752 : Int1 = lowlevel Eq List.750 List.751; - if List.752 then - let List.162 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.747; + let List.706 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.93 List.159 List.160 List.161; + let List.709 : U8 = 1i64; + let List.710 : U8 = GetTagId List.706; + let List.711 : Int1 = lowlevel Eq List.709 List.710; + if List.711 then + let List.162 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.706; ret List.162; else - let List.163 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.747; + let List.163 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.706; ret List.163; procedure List.31 (#Attr.2, #Attr.3): - let List.712 : List Str = lowlevel ListDropAt #Attr.2 #Attr.3; - ret List.712; + let List.671 : List Str = lowlevel ListDropAt #Attr.2 #Attr.3; + ret List.671; procedure List.38 (List.298): - let List.720 : U64 = 0i64; - let List.719 : List Str = CallByName List.31 List.298 List.720; - ret List.719; + let List.679 : U64 = 0i64; + let List.678 : List Str = CallByName List.31 List.298 List.679; + ret List.678; procedure List.4 (List.113, List.114): - let List.655 : U64 = 1i64; - let List.654 : List Str = CallByName List.70 List.113 List.655; - let List.653 : List Str = CallByName List.71 List.654 List.114; - ret List.653; + let List.614 : U64 = 1i64; + let List.613 : List Str = CallByName List.70 List.113 List.614; + let List.612 : List Str = CallByName List.71 List.613 List.114; + ret List.612; procedure List.4 (List.113, List.114): - let List.658 : U64 = 1i64; - let List.657 : List U8 = CallByName List.70 List.113 List.658; - let List.656 : List U8 = CallByName List.71 List.657 List.114; - ret List.656; + let List.617 : U64 = 1i64; + let List.616 : List U8 = CallByName List.70 List.113 List.617; + let List.615 : List U8 = CallByName List.71 List.616 List.114; + ret List.615; procedure List.49 (List.376, List.377): - let List.739 : U64 = StructAtIndex 0 List.377; - let List.740 : U64 = 0i64; - let List.737 : Int1 = CallByName Bool.11 List.739 List.740; - if List.737 then + let List.698 : U64 = StructAtIndex 0 List.377; + let List.699 : U64 = 0i64; + let List.696 : Int1 = CallByName Bool.11 List.698 List.699; + if List.696 then dec List.376; - let List.738 : List U8 = Array []; - ret List.738; + let List.697 : List U8 = Array []; + ret List.697; else - let List.734 : U64 = StructAtIndex 1 List.377; - let List.735 : U64 = StructAtIndex 0 List.377; - let List.733 : List U8 = CallByName List.72 List.376 List.734 List.735; - ret List.733; + let List.693 : U64 = StructAtIndex 1 List.377; + let List.694 : U64 = StructAtIndex 0 List.377; + let List.692 : List U8 = CallByName List.72 List.376 List.693 List.694; + ret List.692; procedure List.52 (List.391, List.392): let List.393 : U64 = CallByName List.6 List.391; - joinpoint List.745 List.394: - let List.743 : U64 = 0i64; - let List.742 : {U64, U64} = Struct {List.394, List.743}; + joinpoint List.704 List.394: + let List.702 : U64 = 0i64; + let List.701 : {U64, U64} = Struct {List.394, List.702}; inc List.391; - let List.395 : List U8 = CallByName List.49 List.391 List.742; - let List.741 : U64 = CallByName Num.20 List.393 List.394; - let List.732 : {U64, U64} = Struct {List.741, List.394}; - let List.396 : List U8 = CallByName List.49 List.391 List.732; - let List.731 : {List U8, List U8} = Struct {List.395, List.396}; - ret List.731; + let List.395 : List U8 = CallByName List.49 List.391 List.701; + let List.700 : U64 = CallByName Num.20 List.393 List.394; + let List.691 : {U64, U64} = Struct {List.700, List.394}; + let List.396 : List U8 = CallByName List.49 List.391 List.691; + let List.690 : {List U8, List U8} = Struct {List.395, List.396}; + ret List.690; in - let List.746 : Int1 = CallByName Num.24 List.393 List.392; - if List.746 then - jump List.745 List.392; + let List.705 : Int1 = CallByName Num.24 List.393 List.392; + if List.705 then + jump List.704 List.392; else - jump List.745 List.393; + jump List.704 List.393; procedure List.6 (#Attr.2): - let List.589 : U64 = lowlevel ListLen #Attr.2; - ret List.589; + let List.588 : U64 = lowlevel ListLen #Attr.2; + ret List.588; procedure List.6 (#Attr.2): - let List.726 : U64 = lowlevel ListLen #Attr.2; - ret List.726; + let List.685 : U64 = lowlevel ListLen #Attr.2; + ret List.685; procedure List.6 (#Attr.2): - let List.727 : U64 = lowlevel ListLen #Attr.2; - ret List.727; + let List.686 : U64 = lowlevel ListLen #Attr.2; + ret List.686; procedure List.6 (#Attr.2): - let List.729 : U64 = lowlevel ListLen #Attr.2; - ret List.729; + let List.688 : U64 = lowlevel ListLen #Attr.2; + ret List.688; procedure List.66 (#Attr.2, #Attr.3): - let List.567 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.567; + let List.566 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.566; procedure List.66 (#Attr.2, #Attr.3): - let List.675 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.675; + let List.634 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.634; procedure List.66 (#Attr.2, #Attr.3): - let List.695 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.695; + let List.654 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.654; procedure List.68 (#Attr.2): - let List.722 : List Str = lowlevel ListWithCapacity #Attr.2; - ret List.722; + let List.681 : List Str = lowlevel ListWithCapacity #Attr.2; + ret List.681; procedure List.68 (#Attr.2): - let List.724 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.724; + let List.683 : List U8 = lowlevel ListWithCapacity #Attr.2; + ret List.683; procedure List.70 (#Attr.2, #Attr.3): - let List.635 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.635; + let List.594 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.594; procedure List.70 (#Attr.2, #Attr.3): - let List.652 : List Str = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.652; + let List.611 : List Str = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.611; procedure List.71 (#Attr.2, #Attr.3): - let List.633 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.633; + let List.592 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.592; procedure List.71 (#Attr.2, #Attr.3): - let List.650 : List Str = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.650; + let List.609 : List Str = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.609; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.736 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.736; + let List.695 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.695; procedure List.8 (#Attr.2, #Attr.3): - let List.701 : List Str = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.701; + let List.660 : List Str = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.660; procedure List.8 (#Attr.2, #Attr.3): - let List.709 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.709; - -procedure List.80 (List.606, List.607, List.608, List.609, List.610): - joinpoint List.557 List.439 List.440 List.441 List.442 List.443: - let List.559 : Int1 = CallByName Num.22 List.442 List.443; - if List.559 then - let List.566 : {Str, Str} = CallByName List.66 List.439 List.442; - inc List.566; - let List.560 : {List U8, U64} = CallByName List.145 List.440 List.566 List.441; - let List.563 : U64 = 1i64; - let List.562 : U64 = CallByName Num.19 List.442 List.563; - jump List.557 List.439 List.560 List.441 List.562 List.443; + let List.668 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.668; + +procedure List.80 (#Derived_gen.23, #Derived_gen.24, #Derived_gen.25, #Derived_gen.26, #Derived_gen.27): + joinpoint List.715 List.439 List.440 List.441 List.442 List.443: + let List.717 : Int1 = CallByName Num.22 List.442 List.443; + if List.717 then + let List.726 : U8 = CallByName List.66 List.439 List.442; + let List.718 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.440 List.726; + let List.723 : U8 = 1i64; + let List.724 : U8 = GetTagId List.718; + let List.725 : Int1 = lowlevel Eq List.723 List.724; + if List.725 then + let List.444 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.718; + let List.721 : U64 = 1i64; + let List.720 : U64 = CallByName Num.19 List.442 List.721; + jump List.715 List.439 List.444 List.441 List.720 List.443; + else + dec List.439; + let List.445 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.718; + let List.722 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.445; + ret List.722; else dec List.439; - ret List.440; + let List.716 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; + ret List.716; in - jump List.557 List.606 List.607 List.608 List.609 List.610; - -procedure List.80 (List.783, List.784, List.785, List.786, List.787): - joinpoint List.665 List.439 List.440 List.441 List.442 List.443: - let List.667 : Int1 = CallByName Num.22 List.442 List.443; - if List.667 then - let List.674 : {Str, Str} = CallByName List.66 List.439 List.442; - inc List.674; - let List.668 : {List U8, U64} = CallByName List.145 List.440 List.674 List.441; - let List.671 : U64 = 1i64; - let List.670 : U64 = CallByName Num.19 List.442 List.671; - jump List.665 List.439 List.668 List.441 List.670 List.443; + jump List.715 #Derived_gen.23 #Derived_gen.24 #Derived_gen.25 #Derived_gen.26 #Derived_gen.27; + +procedure List.80 (#Derived_gen.31, #Derived_gen.32, #Derived_gen.33, #Derived_gen.34, #Derived_gen.35): + joinpoint List.644 List.439 List.440 List.441 List.442 List.443: + let List.646 : Int1 = CallByName Num.22 List.442 List.443; + if List.646 then + let List.653 : U8 = CallByName List.66 List.439 List.442; + let List.647 : List U8 = CallByName List.145 List.440 List.653 List.441; + let List.650 : U64 = 1i64; + let List.649 : U64 = CallByName Num.19 List.442 List.650; + jump List.644 List.439 List.647 List.441 List.649 List.443; else dec List.439; ret List.440; in - jump List.665 List.783 List.784 List.785 List.786 List.787; - -procedure List.80 (List.800, List.801, List.802, List.803, List.804): - joinpoint List.685 List.439 List.440 List.441 List.442 List.443: - let List.687 : Int1 = CallByName Num.22 List.442 List.443; - if List.687 then - let List.694 : U8 = CallByName List.66 List.439 List.442; - let List.688 : List U8 = CallByName List.145 List.440 List.694 List.441; - let List.691 : U64 = 1i64; - let List.690 : U64 = CallByName Num.19 List.442 List.691; - jump List.685 List.439 List.688 List.441 List.690 List.443; + jump List.644 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33 #Derived_gen.34 #Derived_gen.35; + +procedure List.80 (#Derived_gen.36, #Derived_gen.37, #Derived_gen.38, #Derived_gen.39, #Derived_gen.40): + joinpoint List.624 List.439 List.440 List.441 List.442 List.443: + let List.626 : Int1 = CallByName Num.22 List.442 List.443; + if List.626 then + let List.633 : {Str, Str} = CallByName List.66 List.439 List.442; + inc List.633; + let List.627 : {List U8, U64} = CallByName List.145 List.440 List.633 List.441; + let List.630 : U64 = 1i64; + let List.629 : U64 = CallByName Num.19 List.442 List.630; + jump List.624 List.439 List.627 List.441 List.629 List.443; else dec List.439; ret List.440; in - jump List.685 List.800 List.801 List.802 List.803 List.804; - -procedure List.80 (List.836, List.837, List.838, List.839, List.840): - joinpoint List.756 List.439 List.440 List.441 List.442 List.443: - let List.758 : Int1 = CallByName Num.22 List.442 List.443; - if List.758 then - let List.767 : U8 = CallByName List.66 List.439 List.442; - let List.759 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.440 List.767; - let List.764 : U8 = 1i64; - let List.765 : U8 = GetTagId List.759; - let List.766 : Int1 = lowlevel Eq List.764 List.765; - if List.766 then - let List.444 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.759; - let List.762 : U64 = 1i64; - let List.761 : U64 = CallByName Num.19 List.442 List.762; - jump List.756 List.439 List.444 List.441 List.761 List.443; - else - dec List.439; - let List.445 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.759; - let List.763 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.445; - ret List.763; + jump List.624 #Derived_gen.36 #Derived_gen.37 #Derived_gen.38 #Derived_gen.39 #Derived_gen.40; + +procedure List.80 (#Derived_gen.42, #Derived_gen.43, #Derived_gen.44, #Derived_gen.45, #Derived_gen.46): + joinpoint List.556 List.439 List.440 List.441 List.442 List.443: + let List.558 : Int1 = CallByName Num.22 List.442 List.443; + if List.558 then + let List.565 : {Str, Str} = CallByName List.66 List.439 List.442; + inc List.565; + let List.559 : {List U8, U64} = CallByName List.145 List.440 List.565 List.441; + let List.562 : U64 = 1i64; + let List.561 : U64 = CallByName Num.19 List.442 List.562; + jump List.556 List.439 List.559 List.441 List.561 List.443; else dec List.439; - let List.757 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; - ret List.757; + ret List.440; in - jump List.756 List.836 List.837 List.838 List.839 List.840; + jump List.556 #Derived_gen.42 #Derived_gen.43 #Derived_gen.44 #Derived_gen.45 #Derived_gen.46; procedure List.93 (List.436, List.437, List.438): - let List.555 : U64 = 0i64; - let List.556 : U64 = CallByName List.6 List.436; - let List.554 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.555 List.556; - ret List.554; + let List.554 : U64 = 0i64; + let List.555 : U64 = CallByName List.6 List.436; + let List.553 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.554 List.555; + ret List.553; procedure List.93 (List.436, List.437, List.438): - let List.663 : U64 = 0i64; - let List.664 : U64 = CallByName List.6 List.436; - let List.662 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.663 List.664; - ret List.662; + let List.622 : U64 = 0i64; + let List.623 : U64 = CallByName List.6 List.436; + let List.621 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.622 List.623; + ret List.621; procedure List.93 (List.436, List.437, List.438): - let List.683 : U64 = 0i64; - let List.684 : U64 = CallByName List.6 List.436; - let List.682 : List U8 = CallByName List.80 List.436 List.437 List.438 List.683 List.684; - ret List.682; + let List.642 : U64 = 0i64; + let List.643 : U64 = CallByName List.6 List.436; + let List.641 : List U8 = CallByName List.80 List.436 List.437 List.438 List.642 List.643; + ret List.641; procedure List.93 (List.436, List.437, List.438): - let List.754 : U64 = 0i64; - let List.755 : U64 = CallByName List.6 List.436; - let List.753 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.436 List.437 List.438 List.754 List.755; - ret List.753; + let List.713 : U64 = 0i64; + let List.714 : U64 = CallByName List.6 List.436; + let List.712 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.436 List.437 List.438 List.713 List.714; + ret List.712; procedure Num.127 (#Attr.2): - let Num.316 : U8 = lowlevel NumIntCast #Attr.2; - ret Num.316; + let Num.307 : U8 = lowlevel NumIntCast #Attr.2; + ret Num.307; procedure Num.19 (#Attr.2, #Attr.3): - let Num.325 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.325; + let Num.316 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.316; procedure Num.20 (#Attr.2, #Attr.3): - let Num.329 : U64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.329; + let Num.320 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.320; procedure Num.21 (#Attr.2, #Attr.3): - let Num.322 : U64 = lowlevel NumMul #Attr.2 #Attr.3; - ret Num.322; + let Num.313 : U64 = lowlevel NumMul #Attr.2 #Attr.3; + ret Num.313; procedure Num.22 (#Attr.2, #Attr.3): - let Num.328 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.328; + let Num.319 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.319; procedure Num.24 (#Attr.2, #Attr.3): - let Num.330 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; - ret Num.330; + let Num.321 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; + ret Num.321; procedure Num.94 (#Attr.2, #Attr.3): - let Num.321 : U64 = lowlevel NumDivCeilUnchecked #Attr.2 #Attr.3; - ret Num.321; + let Num.312 : U64 = lowlevel NumDivCeilUnchecked #Attr.2 #Attr.3; + ret Num.312; procedure Str.12 (#Attr.2): - let Str.324 : List U8 = lowlevel StrToUtf8 #Attr.2; - ret Str.324; + let Str.316 : List U8 = lowlevel StrToUtf8 #Attr.2; + ret Str.316; procedure Str.4 (#Attr.2, #Attr.3): - let Str.327 : Str = lowlevel StrJoinWith #Attr.2 #Attr.3; - ret Str.327; + let Str.319 : Str = lowlevel StrJoinWith #Attr.2 #Attr.3; + ret Str.319; procedure Str.48 (#Attr.2, #Attr.3, #Attr.4): let Str.307 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8Range #Attr.2 #Attr.3 #Attr.4; ret Str.307; procedure Str.55 (#Attr.2): - let Str.330 : List Str = lowlevel StrGraphemes #Attr.2; - ret Str.330; + let Str.322 : List Str = lowlevel StrGraphemes #Attr.2; + ret Str.322; procedure Str.9 (Str.79): let Str.305 : U64 = 0i64; @@ -388,709 +388,709 @@ procedure Str.9 (Str.79): else let Str.300 : U8 = StructAtIndex 3 Str.80; let Str.301 : U64 = StructAtIndex 0 Str.80; - let #Derived_gen.29 : Str = StructAtIndex 1 Str.80; - dec #Derived_gen.29; + let #Derived_gen.58 : Str = StructAtIndex 1 Str.80; + dec #Derived_gen.58; let Str.299 : {U64, U8} = Struct {Str.301, Str.300}; let Str.298 : [C {U64, U8}, C Str] = TagId(0) Str.299; ret Str.298; procedure TotallyNotJson.100 (TotallyNotJson.850): - let TotallyNotJson.1853 : Str = "a"; - let TotallyNotJson.1854 : Int1 = lowlevel Eq TotallyNotJson.1853 TotallyNotJson.850; - dec TotallyNotJson.1853; - if TotallyNotJson.1854 then + let TotallyNotJson.1830 : Str = "a"; + let TotallyNotJson.1831 : Int1 = lowlevel Eq TotallyNotJson.1830 TotallyNotJson.850; + dec TotallyNotJson.1830; + if TotallyNotJson.1831 then dec TotallyNotJson.850; - let TotallyNotJson.1776 : Str = "A"; - ret TotallyNotJson.1776; + let TotallyNotJson.1753 : Str = "A"; + ret TotallyNotJson.1753; else - let TotallyNotJson.1851 : Str = "b"; - let TotallyNotJson.1852 : Int1 = lowlevel Eq TotallyNotJson.1851 TotallyNotJson.850; - dec TotallyNotJson.1851; - if TotallyNotJson.1852 then + let TotallyNotJson.1828 : Str = "b"; + let TotallyNotJson.1829 : Int1 = lowlevel Eq TotallyNotJson.1828 TotallyNotJson.850; + dec TotallyNotJson.1828; + if TotallyNotJson.1829 then dec TotallyNotJson.850; - let TotallyNotJson.1777 : Str = "B"; - ret TotallyNotJson.1777; + let TotallyNotJson.1754 : Str = "B"; + ret TotallyNotJson.1754; else - let TotallyNotJson.1849 : Str = "c"; - let TotallyNotJson.1850 : Int1 = lowlevel Eq TotallyNotJson.1849 TotallyNotJson.850; - dec TotallyNotJson.1849; - if TotallyNotJson.1850 then + let TotallyNotJson.1826 : Str = "c"; + let TotallyNotJson.1827 : Int1 = lowlevel Eq TotallyNotJson.1826 TotallyNotJson.850; + dec TotallyNotJson.1826; + if TotallyNotJson.1827 then dec TotallyNotJson.850; - let TotallyNotJson.1778 : Str = "C"; - ret TotallyNotJson.1778; + let TotallyNotJson.1755 : Str = "C"; + ret TotallyNotJson.1755; else - let TotallyNotJson.1847 : Str = "d"; - let TotallyNotJson.1848 : Int1 = lowlevel Eq TotallyNotJson.1847 TotallyNotJson.850; - dec TotallyNotJson.1847; - if TotallyNotJson.1848 then + let TotallyNotJson.1824 : Str = "d"; + let TotallyNotJson.1825 : Int1 = lowlevel Eq TotallyNotJson.1824 TotallyNotJson.850; + dec TotallyNotJson.1824; + if TotallyNotJson.1825 then dec TotallyNotJson.850; - let TotallyNotJson.1779 : Str = "D"; - ret TotallyNotJson.1779; + let TotallyNotJson.1756 : Str = "D"; + ret TotallyNotJson.1756; else - let TotallyNotJson.1845 : Str = "e"; - let TotallyNotJson.1846 : Int1 = lowlevel Eq TotallyNotJson.1845 TotallyNotJson.850; - dec TotallyNotJson.1845; - if TotallyNotJson.1846 then + let TotallyNotJson.1822 : Str = "e"; + let TotallyNotJson.1823 : Int1 = lowlevel Eq TotallyNotJson.1822 TotallyNotJson.850; + dec TotallyNotJson.1822; + if TotallyNotJson.1823 then dec TotallyNotJson.850; - let TotallyNotJson.1780 : Str = "E"; - ret TotallyNotJson.1780; + let TotallyNotJson.1757 : Str = "E"; + ret TotallyNotJson.1757; else - let TotallyNotJson.1843 : Str = "f"; - let TotallyNotJson.1844 : Int1 = lowlevel Eq TotallyNotJson.1843 TotallyNotJson.850; - dec TotallyNotJson.1843; - if TotallyNotJson.1844 then + let TotallyNotJson.1820 : Str = "f"; + let TotallyNotJson.1821 : Int1 = lowlevel Eq TotallyNotJson.1820 TotallyNotJson.850; + dec TotallyNotJson.1820; + if TotallyNotJson.1821 then dec TotallyNotJson.850; - let TotallyNotJson.1781 : Str = "F"; - ret TotallyNotJson.1781; + let TotallyNotJson.1758 : Str = "F"; + ret TotallyNotJson.1758; else - let TotallyNotJson.1841 : Str = "g"; - let TotallyNotJson.1842 : Int1 = lowlevel Eq TotallyNotJson.1841 TotallyNotJson.850; - dec TotallyNotJson.1841; - if TotallyNotJson.1842 then + let TotallyNotJson.1818 : Str = "g"; + let TotallyNotJson.1819 : Int1 = lowlevel Eq TotallyNotJson.1818 TotallyNotJson.850; + dec TotallyNotJson.1818; + if TotallyNotJson.1819 then dec TotallyNotJson.850; - let TotallyNotJson.1782 : Str = "G"; - ret TotallyNotJson.1782; + let TotallyNotJson.1759 : Str = "G"; + ret TotallyNotJson.1759; else - let TotallyNotJson.1839 : Str = "h"; - let TotallyNotJson.1840 : Int1 = lowlevel Eq TotallyNotJson.1839 TotallyNotJson.850; - dec TotallyNotJson.1839; - if TotallyNotJson.1840 then + let TotallyNotJson.1816 : Str = "h"; + let TotallyNotJson.1817 : Int1 = lowlevel Eq TotallyNotJson.1816 TotallyNotJson.850; + dec TotallyNotJson.1816; + if TotallyNotJson.1817 then dec TotallyNotJson.850; - let TotallyNotJson.1783 : Str = "H"; - ret TotallyNotJson.1783; + let TotallyNotJson.1760 : Str = "H"; + ret TotallyNotJson.1760; else - let TotallyNotJson.1837 : Str = "i"; - let TotallyNotJson.1838 : Int1 = lowlevel Eq TotallyNotJson.1837 TotallyNotJson.850; - dec TotallyNotJson.1837; - if TotallyNotJson.1838 then + let TotallyNotJson.1814 : Str = "i"; + let TotallyNotJson.1815 : Int1 = lowlevel Eq TotallyNotJson.1814 TotallyNotJson.850; + dec TotallyNotJson.1814; + if TotallyNotJson.1815 then dec TotallyNotJson.850; - let TotallyNotJson.1784 : Str = "I"; - ret TotallyNotJson.1784; + let TotallyNotJson.1761 : Str = "I"; + ret TotallyNotJson.1761; else - let TotallyNotJson.1835 : Str = "j"; - let TotallyNotJson.1836 : Int1 = lowlevel Eq TotallyNotJson.1835 TotallyNotJson.850; - dec TotallyNotJson.1835; - if TotallyNotJson.1836 then + let TotallyNotJson.1812 : Str = "j"; + let TotallyNotJson.1813 : Int1 = lowlevel Eq TotallyNotJson.1812 TotallyNotJson.850; + dec TotallyNotJson.1812; + if TotallyNotJson.1813 then dec TotallyNotJson.850; - let TotallyNotJson.1785 : Str = "J"; - ret TotallyNotJson.1785; + let TotallyNotJson.1762 : Str = "J"; + ret TotallyNotJson.1762; else - let TotallyNotJson.1833 : Str = "k"; - let TotallyNotJson.1834 : Int1 = lowlevel Eq TotallyNotJson.1833 TotallyNotJson.850; - dec TotallyNotJson.1833; - if TotallyNotJson.1834 then + let TotallyNotJson.1810 : Str = "k"; + let TotallyNotJson.1811 : Int1 = lowlevel Eq TotallyNotJson.1810 TotallyNotJson.850; + dec TotallyNotJson.1810; + if TotallyNotJson.1811 then dec TotallyNotJson.850; - let TotallyNotJson.1786 : Str = "K"; - ret TotallyNotJson.1786; + let TotallyNotJson.1763 : Str = "K"; + ret TotallyNotJson.1763; else - let TotallyNotJson.1831 : Str = "l"; - let TotallyNotJson.1832 : Int1 = lowlevel Eq TotallyNotJson.1831 TotallyNotJson.850; - dec TotallyNotJson.1831; - if TotallyNotJson.1832 then + let TotallyNotJson.1808 : Str = "l"; + let TotallyNotJson.1809 : Int1 = lowlevel Eq TotallyNotJson.1808 TotallyNotJson.850; + dec TotallyNotJson.1808; + if TotallyNotJson.1809 then dec TotallyNotJson.850; - let TotallyNotJson.1787 : Str = "L"; - ret TotallyNotJson.1787; + let TotallyNotJson.1764 : Str = "L"; + ret TotallyNotJson.1764; else - let TotallyNotJson.1829 : Str = "m"; - let TotallyNotJson.1830 : Int1 = lowlevel Eq TotallyNotJson.1829 TotallyNotJson.850; - dec TotallyNotJson.1829; - if TotallyNotJson.1830 then + let TotallyNotJson.1806 : Str = "m"; + let TotallyNotJson.1807 : Int1 = lowlevel Eq TotallyNotJson.1806 TotallyNotJson.850; + dec TotallyNotJson.1806; + if TotallyNotJson.1807 then dec TotallyNotJson.850; - let TotallyNotJson.1788 : Str = "M"; - ret TotallyNotJson.1788; + let TotallyNotJson.1765 : Str = "M"; + ret TotallyNotJson.1765; else - let TotallyNotJson.1827 : Str = "n"; - let TotallyNotJson.1828 : Int1 = lowlevel Eq TotallyNotJson.1827 TotallyNotJson.850; - dec TotallyNotJson.1827; - if TotallyNotJson.1828 then + let TotallyNotJson.1804 : Str = "n"; + let TotallyNotJson.1805 : Int1 = lowlevel Eq TotallyNotJson.1804 TotallyNotJson.850; + dec TotallyNotJson.1804; + if TotallyNotJson.1805 then dec TotallyNotJson.850; - let TotallyNotJson.1789 : Str = "N"; - ret TotallyNotJson.1789; + let TotallyNotJson.1766 : Str = "N"; + ret TotallyNotJson.1766; else - let TotallyNotJson.1825 : Str = "o"; - let TotallyNotJson.1826 : Int1 = lowlevel Eq TotallyNotJson.1825 TotallyNotJson.850; - dec TotallyNotJson.1825; - if TotallyNotJson.1826 then + let TotallyNotJson.1802 : Str = "o"; + let TotallyNotJson.1803 : Int1 = lowlevel Eq TotallyNotJson.1802 TotallyNotJson.850; + dec TotallyNotJson.1802; + if TotallyNotJson.1803 then dec TotallyNotJson.850; - let TotallyNotJson.1790 : Str = "O"; - ret TotallyNotJson.1790; + let TotallyNotJson.1767 : Str = "O"; + ret TotallyNotJson.1767; else - let TotallyNotJson.1823 : Str = "p"; - let TotallyNotJson.1824 : Int1 = lowlevel Eq TotallyNotJson.1823 TotallyNotJson.850; - dec TotallyNotJson.1823; - if TotallyNotJson.1824 then + let TotallyNotJson.1800 : Str = "p"; + let TotallyNotJson.1801 : Int1 = lowlevel Eq TotallyNotJson.1800 TotallyNotJson.850; + dec TotallyNotJson.1800; + if TotallyNotJson.1801 then dec TotallyNotJson.850; - let TotallyNotJson.1791 : Str = "P"; - ret TotallyNotJson.1791; + let TotallyNotJson.1768 : Str = "P"; + ret TotallyNotJson.1768; else - let TotallyNotJson.1821 : Str = "q"; - let TotallyNotJson.1822 : Int1 = lowlevel Eq TotallyNotJson.1821 TotallyNotJson.850; - dec TotallyNotJson.1821; - if TotallyNotJson.1822 then + let TotallyNotJson.1798 : Str = "q"; + let TotallyNotJson.1799 : Int1 = lowlevel Eq TotallyNotJson.1798 TotallyNotJson.850; + dec TotallyNotJson.1798; + if TotallyNotJson.1799 then dec TotallyNotJson.850; - let TotallyNotJson.1792 : Str = "Q"; - ret TotallyNotJson.1792; + let TotallyNotJson.1769 : Str = "Q"; + ret TotallyNotJson.1769; else - let TotallyNotJson.1819 : Str = "r"; - let TotallyNotJson.1820 : Int1 = lowlevel Eq TotallyNotJson.1819 TotallyNotJson.850; - dec TotallyNotJson.1819; - if TotallyNotJson.1820 then + let TotallyNotJson.1796 : Str = "r"; + let TotallyNotJson.1797 : Int1 = lowlevel Eq TotallyNotJson.1796 TotallyNotJson.850; + dec TotallyNotJson.1796; + if TotallyNotJson.1797 then dec TotallyNotJson.850; - let TotallyNotJson.1793 : Str = "R"; - ret TotallyNotJson.1793; + let TotallyNotJson.1770 : Str = "R"; + ret TotallyNotJson.1770; else - let TotallyNotJson.1817 : Str = "s"; - let TotallyNotJson.1818 : Int1 = lowlevel Eq TotallyNotJson.1817 TotallyNotJson.850; - dec TotallyNotJson.1817; - if TotallyNotJson.1818 then + let TotallyNotJson.1794 : Str = "s"; + let TotallyNotJson.1795 : Int1 = lowlevel Eq TotallyNotJson.1794 TotallyNotJson.850; + dec TotallyNotJson.1794; + if TotallyNotJson.1795 then dec TotallyNotJson.850; - let TotallyNotJson.1794 : Str = "S"; - ret TotallyNotJson.1794; + let TotallyNotJson.1771 : Str = "S"; + ret TotallyNotJson.1771; else - let TotallyNotJson.1815 : Str = "t"; - let TotallyNotJson.1816 : Int1 = lowlevel Eq TotallyNotJson.1815 TotallyNotJson.850; - dec TotallyNotJson.1815; - if TotallyNotJson.1816 then + let TotallyNotJson.1792 : Str = "t"; + let TotallyNotJson.1793 : Int1 = lowlevel Eq TotallyNotJson.1792 TotallyNotJson.850; + dec TotallyNotJson.1792; + if TotallyNotJson.1793 then dec TotallyNotJson.850; - let TotallyNotJson.1795 : Str = "T"; - ret TotallyNotJson.1795; + let TotallyNotJson.1772 : Str = "T"; + ret TotallyNotJson.1772; else - let TotallyNotJson.1813 : Str = "u"; - let TotallyNotJson.1814 : Int1 = lowlevel Eq TotallyNotJson.1813 TotallyNotJson.850; - dec TotallyNotJson.1813; - if TotallyNotJson.1814 then + let TotallyNotJson.1790 : Str = "u"; + let TotallyNotJson.1791 : Int1 = lowlevel Eq TotallyNotJson.1790 TotallyNotJson.850; + dec TotallyNotJson.1790; + if TotallyNotJson.1791 then dec TotallyNotJson.850; - let TotallyNotJson.1796 : Str = "U"; - ret TotallyNotJson.1796; + let TotallyNotJson.1773 : Str = "U"; + ret TotallyNotJson.1773; else - let TotallyNotJson.1811 : Str = "v"; - let TotallyNotJson.1812 : Int1 = lowlevel Eq TotallyNotJson.1811 TotallyNotJson.850; - dec TotallyNotJson.1811; - if TotallyNotJson.1812 then + let TotallyNotJson.1788 : Str = "v"; + let TotallyNotJson.1789 : Int1 = lowlevel Eq TotallyNotJson.1788 TotallyNotJson.850; + dec TotallyNotJson.1788; + if TotallyNotJson.1789 then dec TotallyNotJson.850; - let TotallyNotJson.1797 : Str = "V"; - ret TotallyNotJson.1797; + let TotallyNotJson.1774 : Str = "V"; + ret TotallyNotJson.1774; else - let TotallyNotJson.1809 : Str = "w"; - let TotallyNotJson.1810 : Int1 = lowlevel Eq TotallyNotJson.1809 TotallyNotJson.850; - dec TotallyNotJson.1809; - if TotallyNotJson.1810 then + let TotallyNotJson.1786 : Str = "w"; + let TotallyNotJson.1787 : Int1 = lowlevel Eq TotallyNotJson.1786 TotallyNotJson.850; + dec TotallyNotJson.1786; + if TotallyNotJson.1787 then dec TotallyNotJson.850; - let TotallyNotJson.1798 : Str = "W"; - ret TotallyNotJson.1798; + let TotallyNotJson.1775 : Str = "W"; + ret TotallyNotJson.1775; else - let TotallyNotJson.1807 : Str = "x"; - let TotallyNotJson.1808 : Int1 = lowlevel Eq TotallyNotJson.1807 TotallyNotJson.850; - dec TotallyNotJson.1807; - if TotallyNotJson.1808 then + let TotallyNotJson.1784 : Str = "x"; + let TotallyNotJson.1785 : Int1 = lowlevel Eq TotallyNotJson.1784 TotallyNotJson.850; + dec TotallyNotJson.1784; + if TotallyNotJson.1785 then dec TotallyNotJson.850; - let TotallyNotJson.1799 : Str = "X"; - ret TotallyNotJson.1799; + let TotallyNotJson.1776 : Str = "X"; + ret TotallyNotJson.1776; else - let TotallyNotJson.1805 : Str = "y"; - let TotallyNotJson.1806 : Int1 = lowlevel Eq TotallyNotJson.1805 TotallyNotJson.850; - dec TotallyNotJson.1805; - if TotallyNotJson.1806 then + let TotallyNotJson.1782 : Str = "y"; + let TotallyNotJson.1783 : Int1 = lowlevel Eq TotallyNotJson.1782 TotallyNotJson.850; + dec TotallyNotJson.1782; + if TotallyNotJson.1783 then dec TotallyNotJson.850; - let TotallyNotJson.1800 : Str = "Y"; - ret TotallyNotJson.1800; + let TotallyNotJson.1777 : Str = "Y"; + ret TotallyNotJson.1777; else - let TotallyNotJson.1803 : Str = "z"; - let TotallyNotJson.1804 : Int1 = lowlevel Eq TotallyNotJson.1803 TotallyNotJson.850; - dec TotallyNotJson.1803; - if TotallyNotJson.1804 then + let TotallyNotJson.1780 : Str = "z"; + let TotallyNotJson.1781 : Int1 = lowlevel Eq TotallyNotJson.1780 TotallyNotJson.850; + dec TotallyNotJson.1780; + if TotallyNotJson.1781 then dec TotallyNotJson.850; - let TotallyNotJson.1801 : Str = "Z"; - ret TotallyNotJson.1801; + let TotallyNotJson.1778 : Str = "Z"; + ret TotallyNotJson.1778; else ret TotallyNotJson.850; procedure TotallyNotJson.101 (TotallyNotJson.851): - let TotallyNotJson.1677 : Str = "A"; - let TotallyNotJson.1678 : Int1 = lowlevel Eq TotallyNotJson.1677 TotallyNotJson.851; - dec TotallyNotJson.1677; - if TotallyNotJson.1678 then + let TotallyNotJson.1654 : Str = "A"; + let TotallyNotJson.1655 : Int1 = lowlevel Eq TotallyNotJson.1654 TotallyNotJson.851; + dec TotallyNotJson.1654; + if TotallyNotJson.1655 then dec TotallyNotJson.851; - let TotallyNotJson.1600 : Str = "a"; - ret TotallyNotJson.1600; + let TotallyNotJson.1577 : Str = "a"; + ret TotallyNotJson.1577; else - let TotallyNotJson.1675 : Str = "B"; - let TotallyNotJson.1676 : Int1 = lowlevel Eq TotallyNotJson.1675 TotallyNotJson.851; - dec TotallyNotJson.1675; - if TotallyNotJson.1676 then + let TotallyNotJson.1652 : Str = "B"; + let TotallyNotJson.1653 : Int1 = lowlevel Eq TotallyNotJson.1652 TotallyNotJson.851; + dec TotallyNotJson.1652; + if TotallyNotJson.1653 then dec TotallyNotJson.851; - let TotallyNotJson.1601 : Str = "b"; - ret TotallyNotJson.1601; + let TotallyNotJson.1578 : Str = "b"; + ret TotallyNotJson.1578; else - let TotallyNotJson.1673 : Str = "C"; - let TotallyNotJson.1674 : Int1 = lowlevel Eq TotallyNotJson.1673 TotallyNotJson.851; - dec TotallyNotJson.1673; - if TotallyNotJson.1674 then + let TotallyNotJson.1650 : Str = "C"; + let TotallyNotJson.1651 : Int1 = lowlevel Eq TotallyNotJson.1650 TotallyNotJson.851; + dec TotallyNotJson.1650; + if TotallyNotJson.1651 then dec TotallyNotJson.851; - let TotallyNotJson.1602 : Str = "c"; - ret TotallyNotJson.1602; + let TotallyNotJson.1579 : Str = "c"; + ret TotallyNotJson.1579; else - let TotallyNotJson.1671 : Str = "D"; - let TotallyNotJson.1672 : Int1 = lowlevel Eq TotallyNotJson.1671 TotallyNotJson.851; - dec TotallyNotJson.1671; - if TotallyNotJson.1672 then + let TotallyNotJson.1648 : Str = "D"; + let TotallyNotJson.1649 : Int1 = lowlevel Eq TotallyNotJson.1648 TotallyNotJson.851; + dec TotallyNotJson.1648; + if TotallyNotJson.1649 then dec TotallyNotJson.851; - let TotallyNotJson.1603 : Str = "d"; - ret TotallyNotJson.1603; + let TotallyNotJson.1580 : Str = "d"; + ret TotallyNotJson.1580; else - let TotallyNotJson.1669 : Str = "E"; - let TotallyNotJson.1670 : Int1 = lowlevel Eq TotallyNotJson.1669 TotallyNotJson.851; - dec TotallyNotJson.1669; - if TotallyNotJson.1670 then + let TotallyNotJson.1646 : Str = "E"; + let TotallyNotJson.1647 : Int1 = lowlevel Eq TotallyNotJson.1646 TotallyNotJson.851; + dec TotallyNotJson.1646; + if TotallyNotJson.1647 then dec TotallyNotJson.851; - let TotallyNotJson.1604 : Str = "e"; - ret TotallyNotJson.1604; + let TotallyNotJson.1581 : Str = "e"; + ret TotallyNotJson.1581; else - let TotallyNotJson.1667 : Str = "F"; - let TotallyNotJson.1668 : Int1 = lowlevel Eq TotallyNotJson.1667 TotallyNotJson.851; - dec TotallyNotJson.1667; - if TotallyNotJson.1668 then + let TotallyNotJson.1644 : Str = "F"; + let TotallyNotJson.1645 : Int1 = lowlevel Eq TotallyNotJson.1644 TotallyNotJson.851; + dec TotallyNotJson.1644; + if TotallyNotJson.1645 then dec TotallyNotJson.851; - let TotallyNotJson.1605 : Str = "f"; - ret TotallyNotJson.1605; + let TotallyNotJson.1582 : Str = "f"; + ret TotallyNotJson.1582; else - let TotallyNotJson.1665 : Str = "G"; - let TotallyNotJson.1666 : Int1 = lowlevel Eq TotallyNotJson.1665 TotallyNotJson.851; - dec TotallyNotJson.1665; - if TotallyNotJson.1666 then + let TotallyNotJson.1642 : Str = "G"; + let TotallyNotJson.1643 : Int1 = lowlevel Eq TotallyNotJson.1642 TotallyNotJson.851; + dec TotallyNotJson.1642; + if TotallyNotJson.1643 then dec TotallyNotJson.851; - let TotallyNotJson.1606 : Str = "g"; - ret TotallyNotJson.1606; + let TotallyNotJson.1583 : Str = "g"; + ret TotallyNotJson.1583; else - let TotallyNotJson.1663 : Str = "H"; - let TotallyNotJson.1664 : Int1 = lowlevel Eq TotallyNotJson.1663 TotallyNotJson.851; - dec TotallyNotJson.1663; - if TotallyNotJson.1664 then + let TotallyNotJson.1640 : Str = "H"; + let TotallyNotJson.1641 : Int1 = lowlevel Eq TotallyNotJson.1640 TotallyNotJson.851; + dec TotallyNotJson.1640; + if TotallyNotJson.1641 then dec TotallyNotJson.851; - let TotallyNotJson.1607 : Str = "h"; - ret TotallyNotJson.1607; + let TotallyNotJson.1584 : Str = "h"; + ret TotallyNotJson.1584; else - let TotallyNotJson.1661 : Str = "I"; - let TotallyNotJson.1662 : Int1 = lowlevel Eq TotallyNotJson.1661 TotallyNotJson.851; - dec TotallyNotJson.1661; - if TotallyNotJson.1662 then + let TotallyNotJson.1638 : Str = "I"; + let TotallyNotJson.1639 : Int1 = lowlevel Eq TotallyNotJson.1638 TotallyNotJson.851; + dec TotallyNotJson.1638; + if TotallyNotJson.1639 then dec TotallyNotJson.851; - let TotallyNotJson.1608 : Str = "i"; - ret TotallyNotJson.1608; + let TotallyNotJson.1585 : Str = "i"; + ret TotallyNotJson.1585; else - let TotallyNotJson.1659 : Str = "J"; - let TotallyNotJson.1660 : Int1 = lowlevel Eq TotallyNotJson.1659 TotallyNotJson.851; - dec TotallyNotJson.1659; - if TotallyNotJson.1660 then + let TotallyNotJson.1636 : Str = "J"; + let TotallyNotJson.1637 : Int1 = lowlevel Eq TotallyNotJson.1636 TotallyNotJson.851; + dec TotallyNotJson.1636; + if TotallyNotJson.1637 then dec TotallyNotJson.851; - let TotallyNotJson.1609 : Str = "j"; - ret TotallyNotJson.1609; + let TotallyNotJson.1586 : Str = "j"; + ret TotallyNotJson.1586; else - let TotallyNotJson.1657 : Str = "K"; - let TotallyNotJson.1658 : Int1 = lowlevel Eq TotallyNotJson.1657 TotallyNotJson.851; - dec TotallyNotJson.1657; - if TotallyNotJson.1658 then + let TotallyNotJson.1634 : Str = "K"; + let TotallyNotJson.1635 : Int1 = lowlevel Eq TotallyNotJson.1634 TotallyNotJson.851; + dec TotallyNotJson.1634; + if TotallyNotJson.1635 then dec TotallyNotJson.851; - let TotallyNotJson.1610 : Str = "k"; - ret TotallyNotJson.1610; + let TotallyNotJson.1587 : Str = "k"; + ret TotallyNotJson.1587; else - let TotallyNotJson.1655 : Str = "L"; - let TotallyNotJson.1656 : Int1 = lowlevel Eq TotallyNotJson.1655 TotallyNotJson.851; - dec TotallyNotJson.1655; - if TotallyNotJson.1656 then + let TotallyNotJson.1632 : Str = "L"; + let TotallyNotJson.1633 : Int1 = lowlevel Eq TotallyNotJson.1632 TotallyNotJson.851; + dec TotallyNotJson.1632; + if TotallyNotJson.1633 then dec TotallyNotJson.851; - let TotallyNotJson.1611 : Str = "l"; - ret TotallyNotJson.1611; + let TotallyNotJson.1588 : Str = "l"; + ret TotallyNotJson.1588; else - let TotallyNotJson.1653 : Str = "M"; - let TotallyNotJson.1654 : Int1 = lowlevel Eq TotallyNotJson.1653 TotallyNotJson.851; - dec TotallyNotJson.1653; - if TotallyNotJson.1654 then + let TotallyNotJson.1630 : Str = "M"; + let TotallyNotJson.1631 : Int1 = lowlevel Eq TotallyNotJson.1630 TotallyNotJson.851; + dec TotallyNotJson.1630; + if TotallyNotJson.1631 then dec TotallyNotJson.851; - let TotallyNotJson.1612 : Str = "m"; - ret TotallyNotJson.1612; + let TotallyNotJson.1589 : Str = "m"; + ret TotallyNotJson.1589; else - let TotallyNotJson.1651 : Str = "N"; - let TotallyNotJson.1652 : Int1 = lowlevel Eq TotallyNotJson.1651 TotallyNotJson.851; - dec TotallyNotJson.1651; - if TotallyNotJson.1652 then + let TotallyNotJson.1628 : Str = "N"; + let TotallyNotJson.1629 : Int1 = lowlevel Eq TotallyNotJson.1628 TotallyNotJson.851; + dec TotallyNotJson.1628; + if TotallyNotJson.1629 then dec TotallyNotJson.851; - let TotallyNotJson.1613 : Str = "n"; - ret TotallyNotJson.1613; + let TotallyNotJson.1590 : Str = "n"; + ret TotallyNotJson.1590; else - let TotallyNotJson.1649 : Str = "O"; - let TotallyNotJson.1650 : Int1 = lowlevel Eq TotallyNotJson.1649 TotallyNotJson.851; - dec TotallyNotJson.1649; - if TotallyNotJson.1650 then + let TotallyNotJson.1626 : Str = "O"; + let TotallyNotJson.1627 : Int1 = lowlevel Eq TotallyNotJson.1626 TotallyNotJson.851; + dec TotallyNotJson.1626; + if TotallyNotJson.1627 then dec TotallyNotJson.851; - let TotallyNotJson.1614 : Str = "o"; - ret TotallyNotJson.1614; + let TotallyNotJson.1591 : Str = "o"; + ret TotallyNotJson.1591; else - let TotallyNotJson.1647 : Str = "P"; - let TotallyNotJson.1648 : Int1 = lowlevel Eq TotallyNotJson.1647 TotallyNotJson.851; - dec TotallyNotJson.1647; - if TotallyNotJson.1648 then + let TotallyNotJson.1624 : Str = "P"; + let TotallyNotJson.1625 : Int1 = lowlevel Eq TotallyNotJson.1624 TotallyNotJson.851; + dec TotallyNotJson.1624; + if TotallyNotJson.1625 then dec TotallyNotJson.851; - let TotallyNotJson.1615 : Str = "p"; - ret TotallyNotJson.1615; + let TotallyNotJson.1592 : Str = "p"; + ret TotallyNotJson.1592; else - let TotallyNotJson.1645 : Str = "Q"; - let TotallyNotJson.1646 : Int1 = lowlevel Eq TotallyNotJson.1645 TotallyNotJson.851; - dec TotallyNotJson.1645; - if TotallyNotJson.1646 then + let TotallyNotJson.1622 : Str = "Q"; + let TotallyNotJson.1623 : Int1 = lowlevel Eq TotallyNotJson.1622 TotallyNotJson.851; + dec TotallyNotJson.1622; + if TotallyNotJson.1623 then dec TotallyNotJson.851; - let TotallyNotJson.1616 : Str = "q"; - ret TotallyNotJson.1616; + let TotallyNotJson.1593 : Str = "q"; + ret TotallyNotJson.1593; else - let TotallyNotJson.1643 : Str = "R"; - let TotallyNotJson.1644 : Int1 = lowlevel Eq TotallyNotJson.1643 TotallyNotJson.851; - dec TotallyNotJson.1643; - if TotallyNotJson.1644 then + let TotallyNotJson.1620 : Str = "R"; + let TotallyNotJson.1621 : Int1 = lowlevel Eq TotallyNotJson.1620 TotallyNotJson.851; + dec TotallyNotJson.1620; + if TotallyNotJson.1621 then dec TotallyNotJson.851; - let TotallyNotJson.1617 : Str = "r"; - ret TotallyNotJson.1617; + let TotallyNotJson.1594 : Str = "r"; + ret TotallyNotJson.1594; else - let TotallyNotJson.1641 : Str = "S"; - let TotallyNotJson.1642 : Int1 = lowlevel Eq TotallyNotJson.1641 TotallyNotJson.851; - dec TotallyNotJson.1641; - if TotallyNotJson.1642 then + let TotallyNotJson.1618 : Str = "S"; + let TotallyNotJson.1619 : Int1 = lowlevel Eq TotallyNotJson.1618 TotallyNotJson.851; + dec TotallyNotJson.1618; + if TotallyNotJson.1619 then dec TotallyNotJson.851; - let TotallyNotJson.1618 : Str = "s"; - ret TotallyNotJson.1618; + let TotallyNotJson.1595 : Str = "s"; + ret TotallyNotJson.1595; else - let TotallyNotJson.1639 : Str = "T"; - let TotallyNotJson.1640 : Int1 = lowlevel Eq TotallyNotJson.1639 TotallyNotJson.851; - dec TotallyNotJson.1639; - if TotallyNotJson.1640 then + let TotallyNotJson.1616 : Str = "T"; + let TotallyNotJson.1617 : Int1 = lowlevel Eq TotallyNotJson.1616 TotallyNotJson.851; + dec TotallyNotJson.1616; + if TotallyNotJson.1617 then dec TotallyNotJson.851; - let TotallyNotJson.1619 : Str = "t"; - ret TotallyNotJson.1619; + let TotallyNotJson.1596 : Str = "t"; + ret TotallyNotJson.1596; else - let TotallyNotJson.1637 : Str = "U"; - let TotallyNotJson.1638 : Int1 = lowlevel Eq TotallyNotJson.1637 TotallyNotJson.851; - dec TotallyNotJson.1637; - if TotallyNotJson.1638 then + let TotallyNotJson.1614 : Str = "U"; + let TotallyNotJson.1615 : Int1 = lowlevel Eq TotallyNotJson.1614 TotallyNotJson.851; + dec TotallyNotJson.1614; + if TotallyNotJson.1615 then dec TotallyNotJson.851; - let TotallyNotJson.1620 : Str = "u"; - ret TotallyNotJson.1620; + let TotallyNotJson.1597 : Str = "u"; + ret TotallyNotJson.1597; else - let TotallyNotJson.1635 : Str = "V"; - let TotallyNotJson.1636 : Int1 = lowlevel Eq TotallyNotJson.1635 TotallyNotJson.851; - dec TotallyNotJson.1635; - if TotallyNotJson.1636 then + let TotallyNotJson.1612 : Str = "V"; + let TotallyNotJson.1613 : Int1 = lowlevel Eq TotallyNotJson.1612 TotallyNotJson.851; + dec TotallyNotJson.1612; + if TotallyNotJson.1613 then dec TotallyNotJson.851; - let TotallyNotJson.1621 : Str = "v"; - ret TotallyNotJson.1621; + let TotallyNotJson.1598 : Str = "v"; + ret TotallyNotJson.1598; else - let TotallyNotJson.1633 : Str = "W"; - let TotallyNotJson.1634 : Int1 = lowlevel Eq TotallyNotJson.1633 TotallyNotJson.851; - dec TotallyNotJson.1633; - if TotallyNotJson.1634 then + let TotallyNotJson.1610 : Str = "W"; + let TotallyNotJson.1611 : Int1 = lowlevel Eq TotallyNotJson.1610 TotallyNotJson.851; + dec TotallyNotJson.1610; + if TotallyNotJson.1611 then dec TotallyNotJson.851; - let TotallyNotJson.1622 : Str = "w"; - ret TotallyNotJson.1622; + let TotallyNotJson.1599 : Str = "w"; + ret TotallyNotJson.1599; else - let TotallyNotJson.1631 : Str = "X"; - let TotallyNotJson.1632 : Int1 = lowlevel Eq TotallyNotJson.1631 TotallyNotJson.851; - dec TotallyNotJson.1631; - if TotallyNotJson.1632 then + let TotallyNotJson.1608 : Str = "X"; + let TotallyNotJson.1609 : Int1 = lowlevel Eq TotallyNotJson.1608 TotallyNotJson.851; + dec TotallyNotJson.1608; + if TotallyNotJson.1609 then dec TotallyNotJson.851; - let TotallyNotJson.1623 : Str = "x"; - ret TotallyNotJson.1623; + let TotallyNotJson.1600 : Str = "x"; + ret TotallyNotJson.1600; else - let TotallyNotJson.1629 : Str = "Y"; - let TotallyNotJson.1630 : Int1 = lowlevel Eq TotallyNotJson.1629 TotallyNotJson.851; - dec TotallyNotJson.1629; - if TotallyNotJson.1630 then + let TotallyNotJson.1606 : Str = "Y"; + let TotallyNotJson.1607 : Int1 = lowlevel Eq TotallyNotJson.1606 TotallyNotJson.851; + dec TotallyNotJson.1606; + if TotallyNotJson.1607 then dec TotallyNotJson.851; - let TotallyNotJson.1624 : Str = "y"; - ret TotallyNotJson.1624; + let TotallyNotJson.1601 : Str = "y"; + ret TotallyNotJson.1601; else - let TotallyNotJson.1627 : Str = "Z"; - let TotallyNotJson.1628 : Int1 = lowlevel Eq TotallyNotJson.1627 TotallyNotJson.851; - dec TotallyNotJson.1627; - if TotallyNotJson.1628 then + let TotallyNotJson.1604 : Str = "Z"; + let TotallyNotJson.1605 : Int1 = lowlevel Eq TotallyNotJson.1604 TotallyNotJson.851; + dec TotallyNotJson.1604; + if TotallyNotJson.1605 then dec TotallyNotJson.851; - let TotallyNotJson.1625 : Str = "z"; - ret TotallyNotJson.1625; + let TotallyNotJson.1602 : Str = "z"; + ret TotallyNotJson.1602; else ret TotallyNotJson.851; procedure TotallyNotJson.102 (TotallyNotJson.852): - let TotallyNotJson.1764 : Str = "A"; - let TotallyNotJson.1765 : Int1 = lowlevel Eq TotallyNotJson.1764 TotallyNotJson.852; - dec TotallyNotJson.1764; - if TotallyNotJson.1765 then + let TotallyNotJson.1741 : Str = "A"; + let TotallyNotJson.1742 : Int1 = lowlevel Eq TotallyNotJson.1741 TotallyNotJson.852; + dec TotallyNotJson.1741; + if TotallyNotJson.1742 then dec TotallyNotJson.852; - let TotallyNotJson.1687 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1687; + let TotallyNotJson.1664 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1664; else - let TotallyNotJson.1762 : Str = "B"; - let TotallyNotJson.1763 : Int1 = lowlevel Eq TotallyNotJson.1762 TotallyNotJson.852; - dec TotallyNotJson.1762; - if TotallyNotJson.1763 then + let TotallyNotJson.1739 : Str = "B"; + let TotallyNotJson.1740 : Int1 = lowlevel Eq TotallyNotJson.1739 TotallyNotJson.852; + dec TotallyNotJson.1739; + if TotallyNotJson.1740 then dec TotallyNotJson.852; - let TotallyNotJson.1688 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1688; + let TotallyNotJson.1665 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1665; else - let TotallyNotJson.1760 : Str = "C"; - let TotallyNotJson.1761 : Int1 = lowlevel Eq TotallyNotJson.1760 TotallyNotJson.852; - dec TotallyNotJson.1760; - if TotallyNotJson.1761 then + let TotallyNotJson.1737 : Str = "C"; + let TotallyNotJson.1738 : Int1 = lowlevel Eq TotallyNotJson.1737 TotallyNotJson.852; + dec TotallyNotJson.1737; + if TotallyNotJson.1738 then dec TotallyNotJson.852; - let TotallyNotJson.1689 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1689; + let TotallyNotJson.1666 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1666; else - let TotallyNotJson.1758 : Str = "D"; - let TotallyNotJson.1759 : Int1 = lowlevel Eq TotallyNotJson.1758 TotallyNotJson.852; - dec TotallyNotJson.1758; - if TotallyNotJson.1759 then + let TotallyNotJson.1735 : Str = "D"; + let TotallyNotJson.1736 : Int1 = lowlevel Eq TotallyNotJson.1735 TotallyNotJson.852; + dec TotallyNotJson.1735; + if TotallyNotJson.1736 then dec TotallyNotJson.852; - let TotallyNotJson.1690 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1690; + let TotallyNotJson.1667 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1667; else - let TotallyNotJson.1756 : Str = "E"; - let TotallyNotJson.1757 : Int1 = lowlevel Eq TotallyNotJson.1756 TotallyNotJson.852; - dec TotallyNotJson.1756; - if TotallyNotJson.1757 then + let TotallyNotJson.1733 : Str = "E"; + let TotallyNotJson.1734 : Int1 = lowlevel Eq TotallyNotJson.1733 TotallyNotJson.852; + dec TotallyNotJson.1733; + if TotallyNotJson.1734 then dec TotallyNotJson.852; - let TotallyNotJson.1691 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1691; + let TotallyNotJson.1668 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1668; else - let TotallyNotJson.1754 : Str = "F"; - let TotallyNotJson.1755 : Int1 = lowlevel Eq TotallyNotJson.1754 TotallyNotJson.852; - dec TotallyNotJson.1754; - if TotallyNotJson.1755 then + let TotallyNotJson.1731 : Str = "F"; + let TotallyNotJson.1732 : Int1 = lowlevel Eq TotallyNotJson.1731 TotallyNotJson.852; + dec TotallyNotJson.1731; + if TotallyNotJson.1732 then dec TotallyNotJson.852; - let TotallyNotJson.1692 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1692; + let TotallyNotJson.1669 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1669; else - let TotallyNotJson.1752 : Str = "G"; - let TotallyNotJson.1753 : Int1 = lowlevel Eq TotallyNotJson.1752 TotallyNotJson.852; - dec TotallyNotJson.1752; - if TotallyNotJson.1753 then + let TotallyNotJson.1729 : Str = "G"; + let TotallyNotJson.1730 : Int1 = lowlevel Eq TotallyNotJson.1729 TotallyNotJson.852; + dec TotallyNotJson.1729; + if TotallyNotJson.1730 then dec TotallyNotJson.852; - let TotallyNotJson.1693 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1693; + let TotallyNotJson.1670 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1670; else - let TotallyNotJson.1750 : Str = "H"; - let TotallyNotJson.1751 : Int1 = lowlevel Eq TotallyNotJson.1750 TotallyNotJson.852; - dec TotallyNotJson.1750; - if TotallyNotJson.1751 then + let TotallyNotJson.1727 : Str = "H"; + let TotallyNotJson.1728 : Int1 = lowlevel Eq TotallyNotJson.1727 TotallyNotJson.852; + dec TotallyNotJson.1727; + if TotallyNotJson.1728 then dec TotallyNotJson.852; - let TotallyNotJson.1694 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1694; + let TotallyNotJson.1671 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1671; else - let TotallyNotJson.1748 : Str = "I"; - let TotallyNotJson.1749 : Int1 = lowlevel Eq TotallyNotJson.1748 TotallyNotJson.852; - dec TotallyNotJson.1748; - if TotallyNotJson.1749 then + let TotallyNotJson.1725 : Str = "I"; + let TotallyNotJson.1726 : Int1 = lowlevel Eq TotallyNotJson.1725 TotallyNotJson.852; + dec TotallyNotJson.1725; + if TotallyNotJson.1726 then dec TotallyNotJson.852; - let TotallyNotJson.1695 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1695; + let TotallyNotJson.1672 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1672; else - let TotallyNotJson.1746 : Str = "J"; - let TotallyNotJson.1747 : Int1 = lowlevel Eq TotallyNotJson.1746 TotallyNotJson.852; - dec TotallyNotJson.1746; - if TotallyNotJson.1747 then + let TotallyNotJson.1723 : Str = "J"; + let TotallyNotJson.1724 : Int1 = lowlevel Eq TotallyNotJson.1723 TotallyNotJson.852; + dec TotallyNotJson.1723; + if TotallyNotJson.1724 then dec TotallyNotJson.852; - let TotallyNotJson.1696 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1696; + let TotallyNotJson.1673 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1673; else - let TotallyNotJson.1744 : Str = "K"; - let TotallyNotJson.1745 : Int1 = lowlevel Eq TotallyNotJson.1744 TotallyNotJson.852; - dec TotallyNotJson.1744; - if TotallyNotJson.1745 then + let TotallyNotJson.1721 : Str = "K"; + let TotallyNotJson.1722 : Int1 = lowlevel Eq TotallyNotJson.1721 TotallyNotJson.852; + dec TotallyNotJson.1721; + if TotallyNotJson.1722 then dec TotallyNotJson.852; - let TotallyNotJson.1697 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1697; + let TotallyNotJson.1674 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1674; else - let TotallyNotJson.1742 : Str = "L"; - let TotallyNotJson.1743 : Int1 = lowlevel Eq TotallyNotJson.1742 TotallyNotJson.852; - dec TotallyNotJson.1742; - if TotallyNotJson.1743 then + let TotallyNotJson.1719 : Str = "L"; + let TotallyNotJson.1720 : Int1 = lowlevel Eq TotallyNotJson.1719 TotallyNotJson.852; + dec TotallyNotJson.1719; + if TotallyNotJson.1720 then dec TotallyNotJson.852; - let TotallyNotJson.1698 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1698; + let TotallyNotJson.1675 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1675; else - let TotallyNotJson.1740 : Str = "M"; - let TotallyNotJson.1741 : Int1 = lowlevel Eq TotallyNotJson.1740 TotallyNotJson.852; - dec TotallyNotJson.1740; - if TotallyNotJson.1741 then + let TotallyNotJson.1717 : Str = "M"; + let TotallyNotJson.1718 : Int1 = lowlevel Eq TotallyNotJson.1717 TotallyNotJson.852; + dec TotallyNotJson.1717; + if TotallyNotJson.1718 then dec TotallyNotJson.852; - let TotallyNotJson.1699 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1699; + let TotallyNotJson.1676 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1676; else - let TotallyNotJson.1738 : Str = "N"; - let TotallyNotJson.1739 : Int1 = lowlevel Eq TotallyNotJson.1738 TotallyNotJson.852; - dec TotallyNotJson.1738; - if TotallyNotJson.1739 then + let TotallyNotJson.1715 : Str = "N"; + let TotallyNotJson.1716 : Int1 = lowlevel Eq TotallyNotJson.1715 TotallyNotJson.852; + dec TotallyNotJson.1715; + if TotallyNotJson.1716 then dec TotallyNotJson.852; - let TotallyNotJson.1700 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1700; + let TotallyNotJson.1677 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1677; else - let TotallyNotJson.1736 : Str = "O"; - let TotallyNotJson.1737 : Int1 = lowlevel Eq TotallyNotJson.1736 TotallyNotJson.852; - dec TotallyNotJson.1736; - if TotallyNotJson.1737 then + let TotallyNotJson.1713 : Str = "O"; + let TotallyNotJson.1714 : Int1 = lowlevel Eq TotallyNotJson.1713 TotallyNotJson.852; + dec TotallyNotJson.1713; + if TotallyNotJson.1714 then dec TotallyNotJson.852; - let TotallyNotJson.1701 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1701; + let TotallyNotJson.1678 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1678; else - let TotallyNotJson.1734 : Str = "P"; - let TotallyNotJson.1735 : Int1 = lowlevel Eq TotallyNotJson.1734 TotallyNotJson.852; - dec TotallyNotJson.1734; - if TotallyNotJson.1735 then + let TotallyNotJson.1711 : Str = "P"; + let TotallyNotJson.1712 : Int1 = lowlevel Eq TotallyNotJson.1711 TotallyNotJson.852; + dec TotallyNotJson.1711; + if TotallyNotJson.1712 then dec TotallyNotJson.852; - let TotallyNotJson.1702 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1702; + let TotallyNotJson.1679 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1679; else - let TotallyNotJson.1732 : Str = "Q"; - let TotallyNotJson.1733 : Int1 = lowlevel Eq TotallyNotJson.1732 TotallyNotJson.852; - dec TotallyNotJson.1732; - if TotallyNotJson.1733 then + let TotallyNotJson.1709 : Str = "Q"; + let TotallyNotJson.1710 : Int1 = lowlevel Eq TotallyNotJson.1709 TotallyNotJson.852; + dec TotallyNotJson.1709; + if TotallyNotJson.1710 then dec TotallyNotJson.852; - let TotallyNotJson.1703 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1703; + let TotallyNotJson.1680 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1680; else - let TotallyNotJson.1730 : Str = "R"; - let TotallyNotJson.1731 : Int1 = lowlevel Eq TotallyNotJson.1730 TotallyNotJson.852; - dec TotallyNotJson.1730; - if TotallyNotJson.1731 then + let TotallyNotJson.1707 : Str = "R"; + let TotallyNotJson.1708 : Int1 = lowlevel Eq TotallyNotJson.1707 TotallyNotJson.852; + dec TotallyNotJson.1707; + if TotallyNotJson.1708 then dec TotallyNotJson.852; - let TotallyNotJson.1704 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1704; + let TotallyNotJson.1681 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1681; else - let TotallyNotJson.1728 : Str = "S"; - let TotallyNotJson.1729 : Int1 = lowlevel Eq TotallyNotJson.1728 TotallyNotJson.852; - dec TotallyNotJson.1728; - if TotallyNotJson.1729 then + let TotallyNotJson.1705 : Str = "S"; + let TotallyNotJson.1706 : Int1 = lowlevel Eq TotallyNotJson.1705 TotallyNotJson.852; + dec TotallyNotJson.1705; + if TotallyNotJson.1706 then dec TotallyNotJson.852; - let TotallyNotJson.1705 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1705; + let TotallyNotJson.1682 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1682; else - let TotallyNotJson.1726 : Str = "T"; - let TotallyNotJson.1727 : Int1 = lowlevel Eq TotallyNotJson.1726 TotallyNotJson.852; - dec TotallyNotJson.1726; - if TotallyNotJson.1727 then + let TotallyNotJson.1703 : Str = "T"; + let TotallyNotJson.1704 : Int1 = lowlevel Eq TotallyNotJson.1703 TotallyNotJson.852; + dec TotallyNotJson.1703; + if TotallyNotJson.1704 then dec TotallyNotJson.852; - let TotallyNotJson.1706 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1706; + let TotallyNotJson.1683 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1683; else - let TotallyNotJson.1724 : Str = "U"; - let TotallyNotJson.1725 : Int1 = lowlevel Eq TotallyNotJson.1724 TotallyNotJson.852; - dec TotallyNotJson.1724; - if TotallyNotJson.1725 then + let TotallyNotJson.1701 : Str = "U"; + let TotallyNotJson.1702 : Int1 = lowlevel Eq TotallyNotJson.1701 TotallyNotJson.852; + dec TotallyNotJson.1701; + if TotallyNotJson.1702 then dec TotallyNotJson.852; - let TotallyNotJson.1707 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1707; + let TotallyNotJson.1684 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1684; else - let TotallyNotJson.1722 : Str = "V"; - let TotallyNotJson.1723 : Int1 = lowlevel Eq TotallyNotJson.1722 TotallyNotJson.852; - dec TotallyNotJson.1722; - if TotallyNotJson.1723 then + let TotallyNotJson.1699 : Str = "V"; + let TotallyNotJson.1700 : Int1 = lowlevel Eq TotallyNotJson.1699 TotallyNotJson.852; + dec TotallyNotJson.1699; + if TotallyNotJson.1700 then dec TotallyNotJson.852; - let TotallyNotJson.1708 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1708; + let TotallyNotJson.1685 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1685; else - let TotallyNotJson.1720 : Str = "W"; - let TotallyNotJson.1721 : Int1 = lowlevel Eq TotallyNotJson.1720 TotallyNotJson.852; - dec TotallyNotJson.1720; - if TotallyNotJson.1721 then + let TotallyNotJson.1697 : Str = "W"; + let TotallyNotJson.1698 : Int1 = lowlevel Eq TotallyNotJson.1697 TotallyNotJson.852; + dec TotallyNotJson.1697; + if TotallyNotJson.1698 then dec TotallyNotJson.852; - let TotallyNotJson.1709 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1709; + let TotallyNotJson.1686 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1686; else - let TotallyNotJson.1718 : Str = "X"; - let TotallyNotJson.1719 : Int1 = lowlevel Eq TotallyNotJson.1718 TotallyNotJson.852; - dec TotallyNotJson.1718; - if TotallyNotJson.1719 then + let TotallyNotJson.1695 : Str = "X"; + let TotallyNotJson.1696 : Int1 = lowlevel Eq TotallyNotJson.1695 TotallyNotJson.852; + dec TotallyNotJson.1695; + if TotallyNotJson.1696 then dec TotallyNotJson.852; - let TotallyNotJson.1710 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1710; + let TotallyNotJson.1687 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1687; else - let TotallyNotJson.1716 : Str = "Y"; - let TotallyNotJson.1717 : Int1 = lowlevel Eq TotallyNotJson.1716 TotallyNotJson.852; - dec TotallyNotJson.1716; - if TotallyNotJson.1717 then + let TotallyNotJson.1693 : Str = "Y"; + let TotallyNotJson.1694 : Int1 = lowlevel Eq TotallyNotJson.1693 TotallyNotJson.852; + dec TotallyNotJson.1693; + if TotallyNotJson.1694 then dec TotallyNotJson.852; - let TotallyNotJson.1711 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1711; + let TotallyNotJson.1688 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1688; else - let TotallyNotJson.1714 : Str = "Z"; - let TotallyNotJson.1715 : Int1 = lowlevel Eq TotallyNotJson.1714 TotallyNotJson.852; + let TotallyNotJson.1691 : Str = "Z"; + let TotallyNotJson.1692 : Int1 = lowlevel Eq TotallyNotJson.1691 TotallyNotJson.852; dec TotallyNotJson.852; - dec TotallyNotJson.1714; - if TotallyNotJson.1715 then - let TotallyNotJson.1712 : Int1 = CallByName Bool.2; - ret TotallyNotJson.1712; + dec TotallyNotJson.1691; + if TotallyNotJson.1692 then + let TotallyNotJson.1689 : Int1 = CallByName Bool.2; + ret TotallyNotJson.1689; else - let TotallyNotJson.1713 : Int1 = CallByName Bool.1; - ret TotallyNotJson.1713; + let TotallyNotJson.1690 : Int1 = CallByName Bool.1; + ret TotallyNotJson.1690; -procedure TotallyNotJson.182 (TotallyNotJson.183, TotallyNotJson.1902, TotallyNotJson.181): - let TotallyNotJson.1905 : List U8 = CallByName TotallyNotJson.26 TotallyNotJson.181; - let TotallyNotJson.1904 : List U8 = CallByName List.8 TotallyNotJson.183 TotallyNotJson.1905; - ret TotallyNotJson.1904; +procedure TotallyNotJson.182 (TotallyNotJson.183, TotallyNotJson.1879, TotallyNotJson.181): + let TotallyNotJson.1882 : List U8 = CallByName TotallyNotJson.26 TotallyNotJson.181; + let TotallyNotJson.1881 : List U8 = CallByName List.8 TotallyNotJson.183 TotallyNotJson.1882; + ret TotallyNotJson.1881; -procedure TotallyNotJson.189 (TotallyNotJson.1953, TotallyNotJson.192): - let TotallyNotJson.190 : U64 = StructAtIndex 0 TotallyNotJson.1953; - let TotallyNotJson.191 : Int1 = StructAtIndex 1 TotallyNotJson.1953; +procedure TotallyNotJson.189 (TotallyNotJson.1930, TotallyNotJson.192): + let TotallyNotJson.190 : U64 = StructAtIndex 0 TotallyNotJson.1930; + let TotallyNotJson.191 : Int1 = StructAtIndex 1 TotallyNotJson.1930; switch TotallyNotJson.192: case 34: - let TotallyNotJson.1956 : Int1 = false; - let TotallyNotJson.1955 : {U64, Int1} = Struct {TotallyNotJson.190, TotallyNotJson.1956}; - let TotallyNotJson.1954 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) TotallyNotJson.1955; - ret TotallyNotJson.1954; + let TotallyNotJson.1933 : Int1 = false; + let TotallyNotJson.1932 : {U64, Int1} = Struct {TotallyNotJson.190, TotallyNotJson.1933}; + let TotallyNotJson.1931 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) TotallyNotJson.1932; + ret TotallyNotJson.1931; case 92: - let TotallyNotJson.1959 : Int1 = false; - let TotallyNotJson.1958 : {U64, Int1} = Struct {TotallyNotJson.190, TotallyNotJson.1959}; - let TotallyNotJson.1957 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) TotallyNotJson.1958; - ret TotallyNotJson.1957; + let TotallyNotJson.1936 : Int1 = false; + let TotallyNotJson.1935 : {U64, Int1} = Struct {TotallyNotJson.190, TotallyNotJson.1936}; + let TotallyNotJson.1934 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) TotallyNotJson.1935; + ret TotallyNotJson.1934; case 47: - let TotallyNotJson.1962 : Int1 = false; - let TotallyNotJson.1961 : {U64, Int1} = Struct {TotallyNotJson.190, TotallyNotJson.1962}; - let TotallyNotJson.1960 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) TotallyNotJson.1961; - ret TotallyNotJson.1960; + let TotallyNotJson.1939 : Int1 = false; + let TotallyNotJson.1938 : {U64, Int1} = Struct {TotallyNotJson.190, TotallyNotJson.1939}; + let TotallyNotJson.1937 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) TotallyNotJson.1938; + ret TotallyNotJson.1937; case 8: - let TotallyNotJson.1965 : Int1 = false; - let TotallyNotJson.1964 : {U64, Int1} = Struct {TotallyNotJson.190, TotallyNotJson.1965}; - let TotallyNotJson.1963 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) TotallyNotJson.1964; - ret TotallyNotJson.1963; + let TotallyNotJson.1942 : Int1 = false; + let TotallyNotJson.1941 : {U64, Int1} = Struct {TotallyNotJson.190, TotallyNotJson.1942}; + let TotallyNotJson.1940 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) TotallyNotJson.1941; + ret TotallyNotJson.1940; case 12: - let TotallyNotJson.1968 : Int1 = false; - let TotallyNotJson.1967 : {U64, Int1} = Struct {TotallyNotJson.190, TotallyNotJson.1968}; - let TotallyNotJson.1966 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) TotallyNotJson.1967; - ret TotallyNotJson.1966; + let TotallyNotJson.1945 : Int1 = false; + let TotallyNotJson.1944 : {U64, Int1} = Struct {TotallyNotJson.190, TotallyNotJson.1945}; + let TotallyNotJson.1943 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) TotallyNotJson.1944; + ret TotallyNotJson.1943; case 10: - let TotallyNotJson.1971 : Int1 = false; - let TotallyNotJson.1970 : {U64, Int1} = Struct {TotallyNotJson.190, TotallyNotJson.1971}; - let TotallyNotJson.1969 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) TotallyNotJson.1970; - ret TotallyNotJson.1969; + let TotallyNotJson.1948 : Int1 = false; + let TotallyNotJson.1947 : {U64, Int1} = Struct {TotallyNotJson.190, TotallyNotJson.1948}; + let TotallyNotJson.1946 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) TotallyNotJson.1947; + ret TotallyNotJson.1946; case 13: - let TotallyNotJson.1974 : Int1 = false; - let TotallyNotJson.1973 : {U64, Int1} = Struct {TotallyNotJson.190, TotallyNotJson.1974}; - let TotallyNotJson.1972 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) TotallyNotJson.1973; - ret TotallyNotJson.1972; + let TotallyNotJson.1951 : Int1 = false; + let TotallyNotJson.1950 : {U64, Int1} = Struct {TotallyNotJson.190, TotallyNotJson.1951}; + let TotallyNotJson.1949 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) TotallyNotJson.1950; + ret TotallyNotJson.1949; case 9: - let TotallyNotJson.1977 : Int1 = false; - let TotallyNotJson.1976 : {U64, Int1} = Struct {TotallyNotJson.190, TotallyNotJson.1977}; - let TotallyNotJson.1975 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) TotallyNotJson.1976; - ret TotallyNotJson.1975; + let TotallyNotJson.1954 : Int1 = false; + let TotallyNotJson.1953 : {U64, Int1} = Struct {TotallyNotJson.190, TotallyNotJson.1954}; + let TotallyNotJson.1952 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) TotallyNotJson.1953; + ret TotallyNotJson.1952; default: - let TotallyNotJson.1981 : U64 = 1i64; - let TotallyNotJson.1980 : U64 = CallByName Num.19 TotallyNotJson.190 TotallyNotJson.1981; - let TotallyNotJson.1979 : {U64, Int1} = Struct {TotallyNotJson.1980, TotallyNotJson.191}; - let TotallyNotJson.1978 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) TotallyNotJson.1979; - ret TotallyNotJson.1978; + let TotallyNotJson.1958 : U64 = 1i64; + let TotallyNotJson.1957 : U64 = CallByName Num.19 TotallyNotJson.190 TotallyNotJson.1958; + let TotallyNotJson.1956 : {U64, Int1} = Struct {TotallyNotJson.1957, TotallyNotJson.191}; + let TotallyNotJson.1955 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) TotallyNotJson.1956; + ret TotallyNotJson.1955; procedure TotallyNotJson.2 (): @@ -1098,9 +1098,9 @@ procedure TotallyNotJson.2 (): ret TotallyNotJson.1172; procedure TotallyNotJson.215 (TotallyNotJson.216, TotallyNotJson.217): - let TotallyNotJson.1924 : List U8 = CallByName TotallyNotJson.27 TotallyNotJson.217; - let TotallyNotJson.1923 : List U8 = CallByName List.8 TotallyNotJson.216 TotallyNotJson.1924; - ret TotallyNotJson.1923; + let TotallyNotJson.1901 : List U8 = CallByName TotallyNotJson.27 TotallyNotJson.217; + let TotallyNotJson.1900 : List U8 = CallByName List.8 TotallyNotJson.216 TotallyNotJson.1901; + ret TotallyNotJson.1900; procedure TotallyNotJson.234 (TotallyNotJson.235, TotallyNotJson.1175, TotallyNotJson.233): let TotallyNotJson.1525 : I64 = 123i64; @@ -1116,17 +1116,17 @@ procedure TotallyNotJson.234 (TotallyNotJson.235, TotallyNotJson.1175, TotallyNo ret TotallyNotJson.1179; procedure TotallyNotJson.234 (TotallyNotJson.235, TotallyNotJson.1175, TotallyNotJson.233): - let TotallyNotJson.1899 : I64 = 123i64; - let TotallyNotJson.1898 : U8 = CallByName Num.127 TotallyNotJson.1899; - let TotallyNotJson.238 : List U8 = CallByName List.4 TotallyNotJson.235 TotallyNotJson.1898; - let TotallyNotJson.1897 : U64 = CallByName List.6 TotallyNotJson.233; - let TotallyNotJson.1557 : {List U8, U64} = Struct {TotallyNotJson.238, TotallyNotJson.1897}; - let TotallyNotJson.1556 : {List U8, U64} = CallByName List.18 TotallyNotJson.233 TotallyNotJson.1557 TotallyNotJson.1175; - let TotallyNotJson.240 : List U8 = StructAtIndex 0 TotallyNotJson.1556; - let TotallyNotJson.1555 : I64 = 125i64; - let TotallyNotJson.1554 : U8 = CallByName Num.127 TotallyNotJson.1555; - let TotallyNotJson.1553 : List U8 = CallByName List.4 TotallyNotJson.240 TotallyNotJson.1554; - ret TotallyNotJson.1553; + let TotallyNotJson.1876 : I64 = 123i64; + let TotallyNotJson.1875 : U8 = CallByName Num.127 TotallyNotJson.1876; + let TotallyNotJson.238 : List U8 = CallByName List.4 TotallyNotJson.235 TotallyNotJson.1875; + let TotallyNotJson.1874 : U64 = CallByName List.6 TotallyNotJson.233; + let TotallyNotJson.1534 : {List U8, U64} = Struct {TotallyNotJson.238, TotallyNotJson.1874}; + let TotallyNotJson.1533 : {List U8, U64} = CallByName List.18 TotallyNotJson.233 TotallyNotJson.1534 TotallyNotJson.1175; + let TotallyNotJson.240 : List U8 = StructAtIndex 0 TotallyNotJson.1533; + let TotallyNotJson.1532 : I64 = 125i64; + let TotallyNotJson.1531 : U8 = CallByName Num.127 TotallyNotJson.1532; + let TotallyNotJson.1530 : List U8 = CallByName List.4 TotallyNotJson.240 TotallyNotJson.1531; + ret TotallyNotJson.1530; procedure TotallyNotJson.237 (TotallyNotJson.1177, TotallyNotJson.1178, TotallyNotJson.236): let TotallyNotJson.243 : Str = StructAtIndex 0 TotallyNotJson.1178; @@ -1168,128 +1168,128 @@ procedure TotallyNotJson.237 (TotallyNotJson.1177, TotallyNotJson.1178, TotallyN let TotallyNotJson.241 : List U8 = StructAtIndex 0 TotallyNotJson.1177; let TotallyNotJson.242 : U64 = StructAtIndex 1 TotallyNotJson.1177; let TotallyNotJson.245 : Str = CallByName TotallyNotJson.82 TotallyNotJson.243 TotallyNotJson.236; - let TotallyNotJson.1579 : I64 = 34i64; - let TotallyNotJson.1578 : U8 = CallByName Num.127 TotallyNotJson.1579; - let TotallyNotJson.1576 : List U8 = CallByName List.4 TotallyNotJson.241 TotallyNotJson.1578; - let TotallyNotJson.1577 : List U8 = CallByName Str.12 TotallyNotJson.245; - let TotallyNotJson.1573 : List U8 = CallByName List.8 TotallyNotJson.1576 TotallyNotJson.1577; - let TotallyNotJson.1575 : I64 = 34i64; - let TotallyNotJson.1574 : U8 = CallByName Num.127 TotallyNotJson.1575; - let TotallyNotJson.1570 : List U8 = CallByName List.4 TotallyNotJson.1573 TotallyNotJson.1574; - let TotallyNotJson.1572 : I64 = 58i64; - let TotallyNotJson.1571 : U8 = CallByName Num.127 TotallyNotJson.1572; - let TotallyNotJson.1568 : List U8 = CallByName List.4 TotallyNotJson.1570 TotallyNotJson.1571; - let TotallyNotJson.246 : List U8 = CallByName Encode.24 TotallyNotJson.1568 TotallyNotJson.244 TotallyNotJson.236; - joinpoint TotallyNotJson.1563 TotallyNotJson.247: - let TotallyNotJson.1561 : U64 = 1i64; - let TotallyNotJson.1560 : U64 = CallByName Num.20 TotallyNotJson.242 TotallyNotJson.1561; - let TotallyNotJson.1559 : {List U8, U64} = Struct {TotallyNotJson.247, TotallyNotJson.1560}; - ret TotallyNotJson.1559; + let TotallyNotJson.1556 : I64 = 34i64; + let TotallyNotJson.1555 : U8 = CallByName Num.127 TotallyNotJson.1556; + let TotallyNotJson.1553 : List U8 = CallByName List.4 TotallyNotJson.241 TotallyNotJson.1555; + let TotallyNotJson.1554 : List U8 = CallByName Str.12 TotallyNotJson.245; + let TotallyNotJson.1550 : List U8 = CallByName List.8 TotallyNotJson.1553 TotallyNotJson.1554; + let TotallyNotJson.1552 : I64 = 34i64; + let TotallyNotJson.1551 : U8 = CallByName Num.127 TotallyNotJson.1552; + let TotallyNotJson.1547 : List U8 = CallByName List.4 TotallyNotJson.1550 TotallyNotJson.1551; + let TotallyNotJson.1549 : I64 = 58i64; + let TotallyNotJson.1548 : U8 = CallByName Num.127 TotallyNotJson.1549; + let TotallyNotJson.1545 : List U8 = CallByName List.4 TotallyNotJson.1547 TotallyNotJson.1548; + let TotallyNotJson.246 : List U8 = CallByName Encode.24 TotallyNotJson.1545 TotallyNotJson.244 TotallyNotJson.236; + joinpoint TotallyNotJson.1540 TotallyNotJson.247: + let TotallyNotJson.1538 : U64 = 1i64; + let TotallyNotJson.1537 : U64 = CallByName Num.20 TotallyNotJson.242 TotallyNotJson.1538; + let TotallyNotJson.1536 : {List U8, U64} = Struct {TotallyNotJson.247, TotallyNotJson.1537}; + ret TotallyNotJson.1536; in - let TotallyNotJson.1567 : U64 = 1i64; - let TotallyNotJson.1564 : Int1 = CallByName Num.24 TotallyNotJson.242 TotallyNotJson.1567; - if TotallyNotJson.1564 then - let TotallyNotJson.1566 : I64 = 44i64; - let TotallyNotJson.1565 : U8 = CallByName Num.127 TotallyNotJson.1566; - let TotallyNotJson.1562 : List U8 = CallByName List.4 TotallyNotJson.246 TotallyNotJson.1565; - jump TotallyNotJson.1563 TotallyNotJson.1562; + let TotallyNotJson.1544 : U64 = 1i64; + let TotallyNotJson.1541 : Int1 = CallByName Num.24 TotallyNotJson.242 TotallyNotJson.1544; + if TotallyNotJson.1541 then + let TotallyNotJson.1543 : I64 = 44i64; + let TotallyNotJson.1542 : U8 = CallByName Num.127 TotallyNotJson.1543; + let TotallyNotJson.1539 : List U8 = CallByName List.4 TotallyNotJson.246 TotallyNotJson.1542; + jump TotallyNotJson.1540 TotallyNotJson.1539; else - jump TotallyNotJson.1563 TotallyNotJson.246; + jump TotallyNotJson.1540 TotallyNotJson.246; procedure TotallyNotJson.25 (TotallyNotJson.181): - let TotallyNotJson.1900 : Str = CallByName Encode.23 TotallyNotJson.181; - ret TotallyNotJson.1900; + let TotallyNotJson.1877 : Str = CallByName Encode.23 TotallyNotJson.181; + ret TotallyNotJson.1877; procedure TotallyNotJson.26 (TotallyNotJson.184): let TotallyNotJson.185 : List U8 = CallByName Str.12 TotallyNotJson.184; - let TotallyNotJson.1982 : U64 = 0i64; - let TotallyNotJson.1983 : Int1 = true; - let TotallyNotJson.186 : {U64, Int1} = Struct {TotallyNotJson.1982, TotallyNotJson.1983}; - let TotallyNotJson.1952 : {} = Struct {}; + let TotallyNotJson.1959 : U64 = 0i64; + let TotallyNotJson.1960 : Int1 = true; + let TotallyNotJson.186 : {U64, Int1} = Struct {TotallyNotJson.1959, TotallyNotJson.1960}; + let TotallyNotJson.1929 : {} = Struct {}; inc TotallyNotJson.185; - let TotallyNotJson.187 : {U64, Int1} = CallByName List.26 TotallyNotJson.185 TotallyNotJson.186 TotallyNotJson.1952; - let TotallyNotJson.1906 : Int1 = StructAtIndex 1 TotallyNotJson.187; - let TotallyNotJson.1950 : Int1 = true; - let TotallyNotJson.1951 : Int1 = lowlevel Eq TotallyNotJson.1950 TotallyNotJson.1906; - if TotallyNotJson.1951 then - let TotallyNotJson.1916 : U64 = CallByName List.6 TotallyNotJson.185; - let TotallyNotJson.1917 : U64 = 2i64; - let TotallyNotJson.1915 : U64 = CallByName Num.19 TotallyNotJson.1916 TotallyNotJson.1917; - let TotallyNotJson.1912 : List U8 = CallByName List.68 TotallyNotJson.1915; - let TotallyNotJson.1914 : U8 = 34i64; - let TotallyNotJson.1913 : List U8 = Array [TotallyNotJson.1914]; - let TotallyNotJson.1911 : List U8 = CallByName List.8 TotallyNotJson.1912 TotallyNotJson.1913; - let TotallyNotJson.1908 : List U8 = CallByName List.8 TotallyNotJson.1911 TotallyNotJson.185; - let TotallyNotJson.1910 : U8 = 34i64; - let TotallyNotJson.1909 : List U8 = Array [TotallyNotJson.1910]; - let TotallyNotJson.1907 : List U8 = CallByName List.8 TotallyNotJson.1908 TotallyNotJson.1909; - ret TotallyNotJson.1907; + let TotallyNotJson.187 : {U64, Int1} = CallByName List.26 TotallyNotJson.185 TotallyNotJson.186 TotallyNotJson.1929; + let TotallyNotJson.1883 : Int1 = StructAtIndex 1 TotallyNotJson.187; + let TotallyNotJson.1927 : Int1 = true; + let TotallyNotJson.1928 : Int1 = lowlevel Eq TotallyNotJson.1927 TotallyNotJson.1883; + if TotallyNotJson.1928 then + let TotallyNotJson.1893 : U64 = CallByName List.6 TotallyNotJson.185; + let TotallyNotJson.1894 : U64 = 2i64; + let TotallyNotJson.1892 : U64 = CallByName Num.19 TotallyNotJson.1893 TotallyNotJson.1894; + let TotallyNotJson.1889 : List U8 = CallByName List.68 TotallyNotJson.1892; + let TotallyNotJson.1891 : U8 = 34i64; + let TotallyNotJson.1890 : List U8 = Array [TotallyNotJson.1891]; + let TotallyNotJson.1888 : List U8 = CallByName List.8 TotallyNotJson.1889 TotallyNotJson.1890; + let TotallyNotJson.1885 : List U8 = CallByName List.8 TotallyNotJson.1888 TotallyNotJson.185; + let TotallyNotJson.1887 : U8 = 34i64; + let TotallyNotJson.1886 : List U8 = Array [TotallyNotJson.1887]; + let TotallyNotJson.1884 : List U8 = CallByName List.8 TotallyNotJson.1885 TotallyNotJson.1886; + ret TotallyNotJson.1884; else inc TotallyNotJson.185; - let TotallyNotJson.1949 : U64 = StructAtIndex 0 TotallyNotJson.187; - let TotallyNotJson.1948 : {List U8, List U8} = CallByName List.52 TotallyNotJson.185 TotallyNotJson.1949; - let TotallyNotJson.211 : List U8 = StructAtIndex 0 TotallyNotJson.1948; - let TotallyNotJson.213 : List U8 = StructAtIndex 1 TotallyNotJson.1948; - let TotallyNotJson.1946 : U64 = CallByName List.6 TotallyNotJson.185; + let TotallyNotJson.1926 : U64 = StructAtIndex 0 TotallyNotJson.187; + let TotallyNotJson.1925 : {List U8, List U8} = CallByName List.52 TotallyNotJson.185 TotallyNotJson.1926; + let TotallyNotJson.211 : List U8 = StructAtIndex 0 TotallyNotJson.1925; + let TotallyNotJson.213 : List U8 = StructAtIndex 1 TotallyNotJson.1925; + let TotallyNotJson.1923 : U64 = CallByName List.6 TotallyNotJson.185; dec TotallyNotJson.185; - let TotallyNotJson.1947 : U64 = 120i64; - let TotallyNotJson.1944 : U64 = CallByName Num.21 TotallyNotJson.1946 TotallyNotJson.1947; - let TotallyNotJson.1945 : U64 = 100i64; - let TotallyNotJson.1943 : U64 = CallByName Num.94 TotallyNotJson.1944 TotallyNotJson.1945; - let TotallyNotJson.1940 : List U8 = CallByName List.68 TotallyNotJson.1943; - let TotallyNotJson.1942 : U8 = 34i64; - let TotallyNotJson.1941 : List U8 = Array [TotallyNotJson.1942]; - let TotallyNotJson.1939 : List U8 = CallByName List.8 TotallyNotJson.1940 TotallyNotJson.1941; - let TotallyNotJson.214 : List U8 = CallByName List.8 TotallyNotJson.1939 TotallyNotJson.211; - let TotallyNotJson.1922 : {} = Struct {}; - let TotallyNotJson.1919 : List U8 = CallByName List.18 TotallyNotJson.213 TotallyNotJson.214 TotallyNotJson.1922; - let TotallyNotJson.1921 : U8 = 34i64; - let TotallyNotJson.1920 : List U8 = Array [TotallyNotJson.1921]; - let TotallyNotJson.1918 : List U8 = CallByName List.8 TotallyNotJson.1919 TotallyNotJson.1920; - ret TotallyNotJson.1918; + let TotallyNotJson.1924 : U64 = 120i64; + let TotallyNotJson.1921 : U64 = CallByName Num.21 TotallyNotJson.1923 TotallyNotJson.1924; + let TotallyNotJson.1922 : U64 = 100i64; + let TotallyNotJson.1920 : U64 = CallByName Num.94 TotallyNotJson.1921 TotallyNotJson.1922; + let TotallyNotJson.1917 : List U8 = CallByName List.68 TotallyNotJson.1920; + let TotallyNotJson.1919 : U8 = 34i64; + let TotallyNotJson.1918 : List U8 = Array [TotallyNotJson.1919]; + let TotallyNotJson.1916 : List U8 = CallByName List.8 TotallyNotJson.1917 TotallyNotJson.1918; + let TotallyNotJson.214 : List U8 = CallByName List.8 TotallyNotJson.1916 TotallyNotJson.211; + let TotallyNotJson.1899 : {} = Struct {}; + let TotallyNotJson.1896 : List U8 = CallByName List.18 TotallyNotJson.213 TotallyNotJson.214 TotallyNotJson.1899; + let TotallyNotJson.1898 : U8 = 34i64; + let TotallyNotJson.1897 : List U8 = Array [TotallyNotJson.1898]; + let TotallyNotJson.1895 : List U8 = CallByName List.8 TotallyNotJson.1896 TotallyNotJson.1897; + ret TotallyNotJson.1895; procedure TotallyNotJson.27 (TotallyNotJson.218): switch TotallyNotJson.218: case 34: - let TotallyNotJson.1925 : List U8 = Array [92i64, 34i64]; - ret TotallyNotJson.1925; + let TotallyNotJson.1902 : List U8 = Array [92i64, 34i64]; + ret TotallyNotJson.1902; case 92: - let TotallyNotJson.1926 : List U8 = Array [92i64, 92i64]; - ret TotallyNotJson.1926; + let TotallyNotJson.1903 : List U8 = Array [92i64, 92i64]; + ret TotallyNotJson.1903; case 47: - let TotallyNotJson.1927 : List U8 = Array [92i64, 47i64]; - ret TotallyNotJson.1927; + let TotallyNotJson.1904 : List U8 = Array [92i64, 47i64]; + ret TotallyNotJson.1904; case 8: - let TotallyNotJson.1929 : U8 = 98i64; - let TotallyNotJson.1928 : List U8 = Array [92i64, TotallyNotJson.1929]; - ret TotallyNotJson.1928; + let TotallyNotJson.1906 : U8 = 98i64; + let TotallyNotJson.1905 : List U8 = Array [92i64, TotallyNotJson.1906]; + ret TotallyNotJson.1905; case 12: - let TotallyNotJson.1931 : U8 = 102i64; - let TotallyNotJson.1930 : List U8 = Array [92i64, TotallyNotJson.1931]; - ret TotallyNotJson.1930; + let TotallyNotJson.1908 : U8 = 102i64; + let TotallyNotJson.1907 : List U8 = Array [92i64, TotallyNotJson.1908]; + ret TotallyNotJson.1907; case 10: - let TotallyNotJson.1933 : U8 = 110i64; - let TotallyNotJson.1932 : List U8 = Array [92i64, TotallyNotJson.1933]; - ret TotallyNotJson.1932; + let TotallyNotJson.1910 : U8 = 110i64; + let TotallyNotJson.1909 : List U8 = Array [92i64, TotallyNotJson.1910]; + ret TotallyNotJson.1909; case 13: - let TotallyNotJson.1935 : U8 = 114i64; - let TotallyNotJson.1934 : List U8 = Array [92i64, TotallyNotJson.1935]; - ret TotallyNotJson.1934; + let TotallyNotJson.1912 : U8 = 114i64; + let TotallyNotJson.1911 : List U8 = Array [92i64, TotallyNotJson.1912]; + ret TotallyNotJson.1911; case 9: - let TotallyNotJson.1937 : U8 = 114i64; - let TotallyNotJson.1936 : List U8 = Array [92i64, TotallyNotJson.1937]; - ret TotallyNotJson.1936; + let TotallyNotJson.1914 : U8 = 114i64; + let TotallyNotJson.1913 : List U8 = Array [92i64, TotallyNotJson.1914]; + ret TotallyNotJson.1913; default: - let TotallyNotJson.1938 : List U8 = Array [TotallyNotJson.218]; - ret TotallyNotJson.1938; + let TotallyNotJson.1915 : List U8 = Array [TotallyNotJson.218]; + ret TotallyNotJson.1915; procedure TotallyNotJson.29 (TotallyNotJson.233): @@ -1297,83 +1297,83 @@ procedure TotallyNotJson.29 (TotallyNotJson.233): ret TotallyNotJson.1173; procedure TotallyNotJson.29 (TotallyNotJson.233): - let TotallyNotJson.1549 : List {Str, Str} = CallByName Encode.23 TotallyNotJson.233; - ret TotallyNotJson.1549; + let TotallyNotJson.1526 : List {Str, Str} = CallByName Encode.23 TotallyNotJson.233; + ret TotallyNotJson.1526; procedure TotallyNotJson.82 (TotallyNotJson.802, TotallyNotJson.803): - let TotallyNotJson.1896 : U8 = GetTagId TotallyNotJson.803; - switch TotallyNotJson.1896: + let TotallyNotJson.1873 : U8 = GetTagId TotallyNotJson.803; + switch TotallyNotJson.1873: case 2: ret TotallyNotJson.802; case 5: - let TotallyNotJson.1581 : Str = CallByName TotallyNotJson.87 TotallyNotJson.802; - ret TotallyNotJson.1581; + let TotallyNotJson.1558 : Str = CallByName TotallyNotJson.87 TotallyNotJson.802; + ret TotallyNotJson.1558; case 4: - let TotallyNotJson.1771 : Str = CallByName TotallyNotJson.88 TotallyNotJson.802; - ret TotallyNotJson.1771; + let TotallyNotJson.1748 : Str = CallByName TotallyNotJson.88 TotallyNotJson.802; + ret TotallyNotJson.1748; case 3: - let TotallyNotJson.1860 : Str = CallByName TotallyNotJson.89 TotallyNotJson.802; - ret TotallyNotJson.1860; + let TotallyNotJson.1837 : Str = CallByName TotallyNotJson.89 TotallyNotJson.802; + ret TotallyNotJson.1837; case 0: - let TotallyNotJson.1892 : Str = CallByName TotallyNotJson.90 TotallyNotJson.802; - ret TotallyNotJson.1892; + let TotallyNotJson.1869 : Str = CallByName TotallyNotJson.90 TotallyNotJson.802; + ret TotallyNotJson.1869; default: dec TotallyNotJson.802; let TotallyNotJson.804 : [] = UnionAtIndex (Id 1) (Index 0) TotallyNotJson.803; - let TotallyNotJson.1895 : Str = "a Lambda Set is empty. Most likely there is a type error in your program."; - Crash TotallyNotJson.1895 + let TotallyNotJson.1872 : Str = "a Lambda Set is empty. Most likely there is a type error in your program."; + Crash TotallyNotJson.1872 procedure TotallyNotJson.832 (TotallyNotJson.1493): - let TotallyNotJson.1868 : List Str = StructAtIndex 1 TotallyNotJson.1493; - let #Derived_gen.30 : List Str = StructAtIndex 0 TotallyNotJson.1493; - dec #Derived_gen.30; - ret TotallyNotJson.1868; + let TotallyNotJson.1845 : List Str = StructAtIndex 1 TotallyNotJson.1493; + let #Derived_gen.59 : List Str = StructAtIndex 0 TotallyNotJson.1493; + dec #Derived_gen.59; + ret TotallyNotJson.1845; procedure TotallyNotJson.840 (TotallyNotJson.1214): - let TotallyNotJson.1589 : List Str = StructAtIndex 1 TotallyNotJson.1214; - let #Derived_gen.28 : List Str = StructAtIndex 0 TotallyNotJson.1214; - dec #Derived_gen.28; - ret TotallyNotJson.1589; + let TotallyNotJson.1566 : List Str = StructAtIndex 1 TotallyNotJson.1214; + let #Derived_gen.57 : List Str = StructAtIndex 0 TotallyNotJson.1214; + dec #Derived_gen.57; + ret TotallyNotJson.1566; procedure TotallyNotJson.87 (TotallyNotJson.809): - let TotallyNotJson.1582 : Str = CallByName TotallyNotJson.97 TotallyNotJson.809; - ret TotallyNotJson.1582; + let TotallyNotJson.1559 : Str = CallByName TotallyNotJson.97 TotallyNotJson.809; + ret TotallyNotJson.1559; procedure TotallyNotJson.88 (TotallyNotJson.810): - let TotallyNotJson.1772 : Str = CallByName TotallyNotJson.94 TotallyNotJson.810; - ret TotallyNotJson.1772; + let TotallyNotJson.1749 : Str = CallByName TotallyNotJson.94 TotallyNotJson.810; + ret TotallyNotJson.1749; procedure TotallyNotJson.89 (TotallyNotJson.811): - let TotallyNotJson.1861 : Str = CallByName TotallyNotJson.95 TotallyNotJson.811; - ret TotallyNotJson.1861; + let TotallyNotJson.1838 : Str = CallByName TotallyNotJson.95 TotallyNotJson.811; + ret TotallyNotJson.1838; procedure TotallyNotJson.90 (TotallyNotJson.812): ret TotallyNotJson.812; procedure TotallyNotJson.94 (TotallyNotJson.824): let TotallyNotJson.825 : List Str = CallByName Str.55 TotallyNotJson.824; - let TotallyNotJson.1857 : U64 = lowlevel ListLen TotallyNotJson.825; - let TotallyNotJson.1858 : U64 = 1i64; - let TotallyNotJson.1859 : Int1 = lowlevel NumGte TotallyNotJson.1857 TotallyNotJson.1858; - if TotallyNotJson.1859 then + let TotallyNotJson.1834 : U64 = lowlevel ListLen TotallyNotJson.825; + let TotallyNotJson.1835 : U64 = 1i64; + let TotallyNotJson.1836 : Int1 = lowlevel NumGte TotallyNotJson.1834 TotallyNotJson.1835; + if TotallyNotJson.1836 then dec TotallyNotJson.824; - let TotallyNotJson.1856 : U64 = 0i64; - let TotallyNotJson.826 : Str = lowlevel ListGetUnsafe TotallyNotJson.825 TotallyNotJson.1856; + let TotallyNotJson.1833 : U64 = 0i64; + let TotallyNotJson.826 : Str = lowlevel ListGetUnsafe TotallyNotJson.825 TotallyNotJson.1833; inc TotallyNotJson.826; let TotallyNotJson.827 : Str = CallByName TotallyNotJson.100 TotallyNotJson.826; let TotallyNotJson.828 : List Str = CallByName List.38 TotallyNotJson.825; - let TotallyNotJson.1774 : List Str = CallByName List.13 TotallyNotJson.828 TotallyNotJson.827; - let TotallyNotJson.1775 : Str = ""; - let TotallyNotJson.1773 : Str = CallByName Str.4 TotallyNotJson.1774 TotallyNotJson.1775; - dec TotallyNotJson.1774; - dec TotallyNotJson.1775; - ret TotallyNotJson.1773; + let TotallyNotJson.1751 : List Str = CallByName List.13 TotallyNotJson.828 TotallyNotJson.827; + let TotallyNotJson.1752 : Str = ""; + let TotallyNotJson.1750 : Str = CallByName Str.4 TotallyNotJson.1751 TotallyNotJson.1752; + dec TotallyNotJson.1752; + dec TotallyNotJson.1751; + ret TotallyNotJson.1750; else dec TotallyNotJson.825; ret TotallyNotJson.824; @@ -1381,108 +1381,108 @@ procedure TotallyNotJson.94 (TotallyNotJson.824): procedure TotallyNotJson.95 (TotallyNotJson.829): let TotallyNotJson.830 : List Str = CallByName Str.55 TotallyNotJson.829; dec TotallyNotJson.829; - let TotallyNotJson.1891 : U64 = CallByName List.6 TotallyNotJson.830; - let TotallyNotJson.831 : List Str = CallByName List.68 TotallyNotJson.1891; - let TotallyNotJson.1869 : {List Str, List Str} = Struct {TotallyNotJson.830, TotallyNotJson.831}; - let TotallyNotJson.1865 : {List Str, List Str} = CallByName TotallyNotJson.96 TotallyNotJson.1869; - let TotallyNotJson.1866 : {} = Struct {}; - let TotallyNotJson.1863 : List Str = CallByName TotallyNotJson.832 TotallyNotJson.1865; - let TotallyNotJson.1864 : Str = ""; - let TotallyNotJson.1862 : Str = CallByName Str.4 TotallyNotJson.1863 TotallyNotJson.1864; - dec TotallyNotJson.1864; - dec TotallyNotJson.1863; - ret TotallyNotJson.1862; - -procedure TotallyNotJson.96 (TotallyNotJson.2004): - joinpoint TotallyNotJson.1870 TotallyNotJson.1168: + let TotallyNotJson.1868 : U64 = CallByName List.6 TotallyNotJson.830; + let TotallyNotJson.831 : List Str = CallByName List.68 TotallyNotJson.1868; + let TotallyNotJson.1846 : {List Str, List Str} = Struct {TotallyNotJson.830, TotallyNotJson.831}; + let TotallyNotJson.1842 : {List Str, List Str} = CallByName TotallyNotJson.96 TotallyNotJson.1846; + let TotallyNotJson.1843 : {} = Struct {}; + let TotallyNotJson.1840 : List Str = CallByName TotallyNotJson.832 TotallyNotJson.1842; + let TotallyNotJson.1841 : Str = ""; + let TotallyNotJson.1839 : Str = CallByName Str.4 TotallyNotJson.1840 TotallyNotJson.1841; + dec TotallyNotJson.1840; + dec TotallyNotJson.1841; + ret TotallyNotJson.1839; + +procedure TotallyNotJson.96 (#Derived_gen.41): + joinpoint TotallyNotJson.1847 TotallyNotJson.1168: let TotallyNotJson.834 : List Str = StructAtIndex 0 TotallyNotJson.1168; let TotallyNotJson.833 : List Str = StructAtIndex 1 TotallyNotJson.1168; - let TotallyNotJson.1888 : U64 = lowlevel ListLen TotallyNotJson.834; - let TotallyNotJson.1889 : U64 = 1i64; - let TotallyNotJson.1890 : Int1 = lowlevel NumGte TotallyNotJson.1888 TotallyNotJson.1889; - if TotallyNotJson.1890 then - let TotallyNotJson.1887 : U64 = 0i64; - let TotallyNotJson.835 : Str = lowlevel ListGetUnsafe TotallyNotJson.834 TotallyNotJson.1887; + let TotallyNotJson.1865 : U64 = lowlevel ListLen TotallyNotJson.834; + let TotallyNotJson.1866 : U64 = 1i64; + let TotallyNotJson.1867 : Int1 = lowlevel NumGte TotallyNotJson.1865 TotallyNotJson.1866; + if TotallyNotJson.1867 then + let TotallyNotJson.1864 : U64 = 0i64; + let TotallyNotJson.835 : Str = lowlevel ListGetUnsafe TotallyNotJson.834 TotallyNotJson.1864; inc 2 TotallyNotJson.835; - joinpoint TotallyNotJson.1885 TotallyNotJson.1884: - if TotallyNotJson.1884 then - let TotallyNotJson.1874 : List Str = CallByName List.38 TotallyNotJson.834; - let TotallyNotJson.1877 : Str = "-"; - let TotallyNotJson.1878 : Str = CallByName TotallyNotJson.101 TotallyNotJson.835; - let TotallyNotJson.1876 : List Str = Array [TotallyNotJson.1877, TotallyNotJson.1878]; - let TotallyNotJson.1875 : List Str = CallByName List.8 TotallyNotJson.833 TotallyNotJson.1876; - let TotallyNotJson.1873 : {List Str, List Str} = Struct {TotallyNotJson.1874, TotallyNotJson.1875}; - jump TotallyNotJson.1870 TotallyNotJson.1873; + joinpoint TotallyNotJson.1862 TotallyNotJson.1861: + if TotallyNotJson.1861 then + let TotallyNotJson.1851 : List Str = CallByName List.38 TotallyNotJson.834; + let TotallyNotJson.1854 : Str = "-"; + let TotallyNotJson.1855 : Str = CallByName TotallyNotJson.101 TotallyNotJson.835; + let TotallyNotJson.1853 : List Str = Array [TotallyNotJson.1854, TotallyNotJson.1855]; + let TotallyNotJson.1852 : List Str = CallByName List.8 TotallyNotJson.833 TotallyNotJson.1853; + let TotallyNotJson.1850 : {List Str, List Str} = Struct {TotallyNotJson.1851, TotallyNotJson.1852}; + jump TotallyNotJson.1847 TotallyNotJson.1850; else dec TotallyNotJson.835; - let TotallyNotJson.1883 : U64 = 0i64; - let TotallyNotJson.836 : Str = lowlevel ListGetUnsafe TotallyNotJson.834 TotallyNotJson.1883; + let TotallyNotJson.1860 : U64 = 0i64; + let TotallyNotJson.836 : Str = lowlevel ListGetUnsafe TotallyNotJson.834 TotallyNotJson.1860; inc TotallyNotJson.836; - let TotallyNotJson.1881 : List Str = CallByName List.38 TotallyNotJson.834; - let TotallyNotJson.1882 : List Str = CallByName List.4 TotallyNotJson.833 TotallyNotJson.836; - let TotallyNotJson.1880 : {List Str, List Str} = Struct {TotallyNotJson.1881, TotallyNotJson.1882}; - jump TotallyNotJson.1870 TotallyNotJson.1880; + let TotallyNotJson.1858 : List Str = CallByName List.38 TotallyNotJson.834; + let TotallyNotJson.1859 : List Str = CallByName List.4 TotallyNotJson.833 TotallyNotJson.836; + let TotallyNotJson.1857 : {List Str, List Str} = Struct {TotallyNotJson.1858, TotallyNotJson.1859}; + jump TotallyNotJson.1847 TotallyNotJson.1857; in - let TotallyNotJson.1886 : Int1 = CallByName TotallyNotJson.102 TotallyNotJson.835; - jump TotallyNotJson.1885 TotallyNotJson.1886; + let TotallyNotJson.1863 : Int1 = CallByName TotallyNotJson.102 TotallyNotJson.835; + jump TotallyNotJson.1862 TotallyNotJson.1863; else - let TotallyNotJson.1871 : {List Str, List Str} = Struct {TotallyNotJson.834, TotallyNotJson.833}; - ret TotallyNotJson.1871; + let TotallyNotJson.1848 : {List Str, List Str} = Struct {TotallyNotJson.834, TotallyNotJson.833}; + ret TotallyNotJson.1848; in - jump TotallyNotJson.1870 TotallyNotJson.2004; + jump TotallyNotJson.1847 #Derived_gen.41; procedure TotallyNotJson.97 (TotallyNotJson.837): let TotallyNotJson.838 : List Str = CallByName Str.55 TotallyNotJson.837; dec TotallyNotJson.837; - let TotallyNotJson.1770 : U64 = CallByName List.6 TotallyNotJson.838; - let TotallyNotJson.839 : List Str = CallByName List.68 TotallyNotJson.1770; - let TotallyNotJson.1590 : {List Str, List Str} = Struct {TotallyNotJson.838, TotallyNotJson.839}; - let TotallyNotJson.1586 : {List Str, List Str} = CallByName TotallyNotJson.98 TotallyNotJson.1590; - let TotallyNotJson.1587 : {} = Struct {}; - let TotallyNotJson.1584 : List Str = CallByName TotallyNotJson.840 TotallyNotJson.1586; - let TotallyNotJson.1585 : Str = ""; - let TotallyNotJson.1583 : Str = CallByName Str.4 TotallyNotJson.1584 TotallyNotJson.1585; - dec TotallyNotJson.1585; - dec TotallyNotJson.1584; - ret TotallyNotJson.1583; - -procedure TotallyNotJson.98 (TotallyNotJson.1995): - joinpoint TotallyNotJson.1591 TotallyNotJson.1169: + let TotallyNotJson.1747 : U64 = CallByName List.6 TotallyNotJson.838; + let TotallyNotJson.839 : List Str = CallByName List.68 TotallyNotJson.1747; + let TotallyNotJson.1567 : {List Str, List Str} = Struct {TotallyNotJson.838, TotallyNotJson.839}; + let TotallyNotJson.1563 : {List Str, List Str} = CallByName TotallyNotJson.98 TotallyNotJson.1567; + let TotallyNotJson.1564 : {} = Struct {}; + let TotallyNotJson.1561 : List Str = CallByName TotallyNotJson.840 TotallyNotJson.1563; + let TotallyNotJson.1562 : Str = ""; + let TotallyNotJson.1560 : Str = CallByName Str.4 TotallyNotJson.1561 TotallyNotJson.1562; + dec TotallyNotJson.1561; + dec TotallyNotJson.1562; + ret TotallyNotJson.1560; + +procedure TotallyNotJson.98 (#Derived_gen.47): + joinpoint TotallyNotJson.1568 TotallyNotJson.1169: let TotallyNotJson.842 : List Str = StructAtIndex 0 TotallyNotJson.1169; let TotallyNotJson.841 : List Str = StructAtIndex 1 TotallyNotJson.1169; - let TotallyNotJson.1767 : U64 = lowlevel ListLen TotallyNotJson.842; - let TotallyNotJson.1768 : U64 = 1i64; - let TotallyNotJson.1769 : Int1 = lowlevel NumGte TotallyNotJson.1767 TotallyNotJson.1768; - if TotallyNotJson.1769 then - let TotallyNotJson.1766 : U64 = 0i64; - let TotallyNotJson.843 : Str = lowlevel ListGetUnsafe TotallyNotJson.842 TotallyNotJson.1766; + let TotallyNotJson.1744 : U64 = lowlevel ListLen TotallyNotJson.842; + let TotallyNotJson.1745 : U64 = 1i64; + let TotallyNotJson.1746 : Int1 = lowlevel NumGte TotallyNotJson.1744 TotallyNotJson.1745; + if TotallyNotJson.1746 then + let TotallyNotJson.1743 : U64 = 0i64; + let TotallyNotJson.843 : Str = lowlevel ListGetUnsafe TotallyNotJson.842 TotallyNotJson.1743; inc 2 TotallyNotJson.843; - joinpoint TotallyNotJson.1685 TotallyNotJson.1684: - if TotallyNotJson.1684 then - let TotallyNotJson.1595 : List Str = CallByName List.38 TotallyNotJson.842; - let TotallyNotJson.1598 : Str = "_"; - let TotallyNotJson.1599 : Str = CallByName TotallyNotJson.101 TotallyNotJson.843; - let TotallyNotJson.1597 : List Str = Array [TotallyNotJson.1598, TotallyNotJson.1599]; - let TotallyNotJson.1596 : List Str = CallByName List.8 TotallyNotJson.841 TotallyNotJson.1597; - let TotallyNotJson.1594 : {List Str, List Str} = Struct {TotallyNotJson.1595, TotallyNotJson.1596}; - jump TotallyNotJson.1591 TotallyNotJson.1594; + joinpoint TotallyNotJson.1662 TotallyNotJson.1661: + if TotallyNotJson.1661 then + let TotallyNotJson.1572 : List Str = CallByName List.38 TotallyNotJson.842; + let TotallyNotJson.1575 : Str = "_"; + let TotallyNotJson.1576 : Str = CallByName TotallyNotJson.101 TotallyNotJson.843; + let TotallyNotJson.1574 : List Str = Array [TotallyNotJson.1575, TotallyNotJson.1576]; + let TotallyNotJson.1573 : List Str = CallByName List.8 TotallyNotJson.841 TotallyNotJson.1574; + let TotallyNotJson.1571 : {List Str, List Str} = Struct {TotallyNotJson.1572, TotallyNotJson.1573}; + jump TotallyNotJson.1568 TotallyNotJson.1571; else dec TotallyNotJson.843; - let TotallyNotJson.1683 : U64 = 0i64; - let TotallyNotJson.844 : Str = lowlevel ListGetUnsafe TotallyNotJson.842 TotallyNotJson.1683; + let TotallyNotJson.1660 : U64 = 0i64; + let TotallyNotJson.844 : Str = lowlevel ListGetUnsafe TotallyNotJson.842 TotallyNotJson.1660; inc TotallyNotJson.844; - let TotallyNotJson.1681 : List Str = CallByName List.38 TotallyNotJson.842; - let TotallyNotJson.1682 : List Str = CallByName List.4 TotallyNotJson.841 TotallyNotJson.844; - let TotallyNotJson.1680 : {List Str, List Str} = Struct {TotallyNotJson.1681, TotallyNotJson.1682}; - jump TotallyNotJson.1591 TotallyNotJson.1680; + let TotallyNotJson.1658 : List Str = CallByName List.38 TotallyNotJson.842; + let TotallyNotJson.1659 : List Str = CallByName List.4 TotallyNotJson.841 TotallyNotJson.844; + let TotallyNotJson.1657 : {List Str, List Str} = Struct {TotallyNotJson.1658, TotallyNotJson.1659}; + jump TotallyNotJson.1568 TotallyNotJson.1657; in - let TotallyNotJson.1686 : Int1 = CallByName TotallyNotJson.102 TotallyNotJson.843; - jump TotallyNotJson.1685 TotallyNotJson.1686; + let TotallyNotJson.1663 : Int1 = CallByName TotallyNotJson.102 TotallyNotJson.843; + jump TotallyNotJson.1662 TotallyNotJson.1663; else - let TotallyNotJson.1592 : {List Str, List Str} = Struct {TotallyNotJson.842, TotallyNotJson.841}; - ret TotallyNotJson.1592; + let TotallyNotJson.1569 : {List Str, List Str} = Struct {TotallyNotJson.842, TotallyNotJson.841}; + ret TotallyNotJson.1569; in - jump TotallyNotJson.1591 TotallyNotJson.1995; + jump TotallyNotJson.1568 #Derived_gen.47; procedure Test.0 (): let Test.12 : Str = "bar"; diff --git a/crates/compiler/test_mono/generated/encode_derived_record_one_field_string.txt b/crates/compiler/test_mono/generated/encode_derived_record_one_field_string.txt index 5aff466792c..a8e9541cdfa 100644 --- a/crates/compiler/test_mono/generated/encode_derived_record_one_field_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_record_one_field_string.txt @@ -37,12 +37,12 @@ procedure Encode.24 (Encode.99, Encode.107, Encode.101): ret Encode.111; procedure Encode.24 (Encode.99, Encode.107, Encode.101): - let Encode.118 : List U8 = CallByName TotallyNotJson.234 Encode.99 Encode.101 Encode.107; - ret Encode.118; + let Encode.113 : List U8 = CallByName TotallyNotJson.234 Encode.99 Encode.101 Encode.107; + ret Encode.113; procedure Encode.24 (Encode.99, Encode.107, Encode.101): - let Encode.121 : List U8 = CallByName TotallyNotJson.182 Encode.99 Encode.101 Encode.107; - ret Encode.121; + let Encode.116 : List U8 = CallByName TotallyNotJson.182 Encode.99 Encode.101 Encode.107; + ret Encode.116; procedure Encode.26 (Encode.105, Encode.106): let Encode.109 : List U8 = Array []; @@ -51,221 +51,221 @@ procedure Encode.26 (Encode.105, Encode.106): ret Encode.108; procedure List.13 (#Attr.2, #Attr.3): - let List.622 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; - ret List.622; + let List.621 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; + ret List.621; procedure List.145 (List.146, List.147, List.144): - let List.570 : {List U8, U64} = CallByName TotallyNotJson.237 List.146 List.147 List.144; - ret List.570; + let List.569 : {List U8, U64} = CallByName TotallyNotJson.237 List.146 List.147 List.144; + ret List.569; procedure List.145 (List.146, List.147, List.144): - let List.590 : List U8 = CallByName TotallyNotJson.215 List.146 List.147; - ret List.590; + let List.589 : List U8 = CallByName TotallyNotJson.215 List.146 List.147; + ret List.589; procedure List.18 (List.142, List.143, List.144): - let List.551 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; - ret List.551; + let List.550 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; + ret List.550; procedure List.18 (List.142, List.143, List.144): - let List.571 : List U8 = CallByName List.93 List.142 List.143 List.144; - ret List.571; + let List.570 : List U8 = CallByName List.93 List.142 List.143 List.144; + ret List.570; procedure List.26 (List.159, List.160, List.161): - let List.639 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.93 List.159 List.160 List.161; - let List.642 : U8 = 1i64; - let List.643 : U8 = GetTagId List.639; - let List.644 : Int1 = lowlevel Eq List.642 List.643; - if List.644 then - let List.162 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.639; + let List.638 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.93 List.159 List.160 List.161; + let List.641 : U8 = 1i64; + let List.642 : U8 = GetTagId List.638; + let List.643 : Int1 = lowlevel Eq List.641 List.642; + if List.643 then + let List.162 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.638; ret List.162; else - let List.163 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.639; + let List.163 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.638; ret List.163; procedure List.31 (#Attr.2, #Attr.3): - let List.604 : List Str = lowlevel ListDropAt #Attr.2 #Attr.3; - ret List.604; + let List.603 : List Str = lowlevel ListDropAt #Attr.2 #Attr.3; + ret List.603; procedure List.38 (List.298): - let List.612 : U64 = 0i64; - let List.611 : List Str = CallByName List.31 List.298 List.612; - ret List.611; + let List.611 : U64 = 0i64; + let List.610 : List Str = CallByName List.31 List.298 List.611; + ret List.610; procedure List.4 (List.113, List.114): - let List.547 : U64 = 1i64; - let List.546 : List Str = CallByName List.70 List.113 List.547; - let List.545 : List Str = CallByName List.71 List.546 List.114; - ret List.545; + let List.546 : U64 = 1i64; + let List.545 : List Str = CallByName List.70 List.113 List.546; + let List.544 : List Str = CallByName List.71 List.545 List.114; + ret List.544; procedure List.4 (List.113, List.114): - let List.550 : U64 = 1i64; - let List.549 : List U8 = CallByName List.70 List.113 List.550; - let List.548 : List U8 = CallByName List.71 List.549 List.114; - ret List.548; + let List.549 : U64 = 1i64; + let List.548 : List U8 = CallByName List.70 List.113 List.549; + let List.547 : List U8 = CallByName List.71 List.548 List.114; + ret List.547; procedure List.49 (List.376, List.377): - let List.631 : U64 = StructAtIndex 0 List.377; - let List.632 : U64 = 0i64; - let List.629 : Int1 = CallByName Bool.11 List.631 List.632; - if List.629 then + let List.630 : U64 = StructAtIndex 0 List.377; + let List.631 : U64 = 0i64; + let List.628 : Int1 = CallByName Bool.11 List.630 List.631; + if List.628 then dec List.376; - let List.630 : List U8 = Array []; - ret List.630; + let List.629 : List U8 = Array []; + ret List.629; else - let List.626 : U64 = StructAtIndex 1 List.377; - let List.627 : U64 = StructAtIndex 0 List.377; - let List.625 : List U8 = CallByName List.72 List.376 List.626 List.627; - ret List.625; + let List.625 : U64 = StructAtIndex 1 List.377; + let List.626 : U64 = StructAtIndex 0 List.377; + let List.624 : List U8 = CallByName List.72 List.376 List.625 List.626; + ret List.624; procedure List.52 (List.391, List.392): let List.393 : U64 = CallByName List.6 List.391; - joinpoint List.637 List.394: - let List.635 : U64 = 0i64; - let List.634 : {U64, U64} = Struct {List.394, List.635}; + joinpoint List.636 List.394: + let List.634 : U64 = 0i64; + let List.633 : {U64, U64} = Struct {List.394, List.634}; inc List.391; - let List.395 : List U8 = CallByName List.49 List.391 List.634; - let List.633 : U64 = CallByName Num.20 List.393 List.394; - let List.624 : {U64, U64} = Struct {List.633, List.394}; - let List.396 : List U8 = CallByName List.49 List.391 List.624; - let List.623 : {List U8, List U8} = Struct {List.395, List.396}; - ret List.623; + let List.395 : List U8 = CallByName List.49 List.391 List.633; + let List.632 : U64 = CallByName Num.20 List.393 List.394; + let List.623 : {U64, U64} = Struct {List.632, List.394}; + let List.396 : List U8 = CallByName List.49 List.391 List.623; + let List.622 : {List U8, List U8} = Struct {List.395, List.396}; + ret List.622; in - let List.638 : Int1 = CallByName Num.24 List.393 List.392; - if List.638 then - jump List.637 List.392; + let List.637 : Int1 = CallByName Num.24 List.393 List.392; + if List.637 then + jump List.636 List.392; else - jump List.637 List.393; + jump List.636 List.393; procedure List.6 (#Attr.2): - let List.618 : U64 = lowlevel ListLen #Attr.2; - ret List.618; + let List.617 : U64 = lowlevel ListLen #Attr.2; + ret List.617; procedure List.6 (#Attr.2): - let List.619 : U64 = lowlevel ListLen #Attr.2; - ret List.619; + let List.618 : U64 = lowlevel ListLen #Attr.2; + ret List.618; procedure List.6 (#Attr.2): - let List.621 : U64 = lowlevel ListLen #Attr.2; - ret List.621; + let List.620 : U64 = lowlevel ListLen #Attr.2; + ret List.620; procedure List.66 (#Attr.2, #Attr.3): - let List.567 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.567; + let List.566 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.566; procedure List.66 (#Attr.2, #Attr.3): - let List.587 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.587; + let List.586 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.586; procedure List.68 (#Attr.2): - let List.614 : List Str = lowlevel ListWithCapacity #Attr.2; - ret List.614; + let List.613 : List Str = lowlevel ListWithCapacity #Attr.2; + ret List.613; procedure List.68 (#Attr.2): - let List.616 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.616; + let List.615 : List U8 = lowlevel ListWithCapacity #Attr.2; + ret List.615; procedure List.70 (#Attr.2, #Attr.3): - let List.527 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.527; + let List.526 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.526; procedure List.70 (#Attr.2, #Attr.3): - let List.544 : List Str = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.544; + let List.543 : List Str = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.543; procedure List.71 (#Attr.2, #Attr.3): - let List.525 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.525; + let List.524 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.524; procedure List.71 (#Attr.2, #Attr.3): - let List.542 : List Str = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.542; + let List.541 : List Str = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.541; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.628 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.628; + let List.627 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.627; procedure List.8 (#Attr.2, #Attr.3): - let List.593 : List Str = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.593; + let List.592 : List Str = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.592; procedure List.8 (#Attr.2, #Attr.3): - let List.601 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.601; - -procedure List.80 (List.675, List.676, List.677, List.678, List.679): - joinpoint List.557 List.439 List.440 List.441 List.442 List.443: - let List.559 : Int1 = CallByName Num.22 List.442 List.443; - if List.559 then - let List.566 : {Str, Str} = CallByName List.66 List.439 List.442; - inc List.566; - let List.560 : {List U8, U64} = CallByName List.145 List.440 List.566 List.441; - let List.563 : U64 = 1i64; - let List.562 : U64 = CallByName Num.19 List.442 List.563; - jump List.557 List.439 List.560 List.441 List.562 List.443; + let List.600 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.600; + +procedure List.80 (#Derived_gen.11, #Derived_gen.12, #Derived_gen.13, #Derived_gen.14, #Derived_gen.15): + joinpoint List.556 List.439 List.440 List.441 List.442 List.443: + let List.558 : Int1 = CallByName Num.22 List.442 List.443; + if List.558 then + let List.565 : {Str, Str} = CallByName List.66 List.439 List.442; + inc List.565; + let List.559 : {List U8, U64} = CallByName List.145 List.440 List.565 List.441; + let List.562 : U64 = 1i64; + let List.561 : U64 = CallByName Num.19 List.442 List.562; + jump List.556 List.439 List.559 List.441 List.561 List.443; else dec List.439; ret List.440; in - jump List.557 List.675 List.676 List.677 List.678 List.679; - -procedure List.80 (List.692, List.693, List.694, List.695, List.696): - joinpoint List.577 List.439 List.440 List.441 List.442 List.443: - let List.579 : Int1 = CallByName Num.22 List.442 List.443; - if List.579 then - let List.586 : U8 = CallByName List.66 List.439 List.442; - let List.580 : List U8 = CallByName List.145 List.440 List.586 List.441; - let List.583 : U64 = 1i64; - let List.582 : U64 = CallByName Num.19 List.442 List.583; - jump List.577 List.439 List.580 List.441 List.582 List.443; + jump List.556 #Derived_gen.11 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14 #Derived_gen.15; + +procedure List.80 (#Derived_gen.16, #Derived_gen.17, #Derived_gen.18, #Derived_gen.19, #Derived_gen.20): + joinpoint List.647 List.439 List.440 List.441 List.442 List.443: + let List.649 : Int1 = CallByName Num.22 List.442 List.443; + if List.649 then + let List.658 : U8 = CallByName List.66 List.439 List.442; + let List.650 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.440 List.658; + let List.655 : U8 = 1i64; + let List.656 : U8 = GetTagId List.650; + let List.657 : Int1 = lowlevel Eq List.655 List.656; + if List.657 then + let List.444 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.650; + let List.653 : U64 = 1i64; + let List.652 : U64 = CallByName Num.19 List.442 List.653; + jump List.647 List.439 List.444 List.441 List.652 List.443; + else + dec List.439; + let List.445 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.650; + let List.654 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.445; + ret List.654; else dec List.439; - ret List.440; + let List.648 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; + ret List.648; in - jump List.577 List.692 List.693 List.694 List.695 List.696; - -procedure List.80 (List.728, List.729, List.730, List.731, List.732): - joinpoint List.648 List.439 List.440 List.441 List.442 List.443: - let List.650 : Int1 = CallByName Num.22 List.442 List.443; - if List.650 then - let List.659 : U8 = CallByName List.66 List.439 List.442; - let List.651 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.440 List.659; - let List.656 : U8 = 1i64; - let List.657 : U8 = GetTagId List.651; - let List.658 : Int1 = lowlevel Eq List.656 List.657; - if List.658 then - let List.444 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.651; - let List.654 : U64 = 1i64; - let List.653 : U64 = CallByName Num.19 List.442 List.654; - jump List.648 List.439 List.444 List.441 List.653 List.443; - else - dec List.439; - let List.445 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.651; - let List.655 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.445; - ret List.655; + jump List.647 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20; + +procedure List.80 (#Derived_gen.21, #Derived_gen.22, #Derived_gen.23, #Derived_gen.24, #Derived_gen.25): + joinpoint List.576 List.439 List.440 List.441 List.442 List.443: + let List.578 : Int1 = CallByName Num.22 List.442 List.443; + if List.578 then + let List.585 : U8 = CallByName List.66 List.439 List.442; + let List.579 : List U8 = CallByName List.145 List.440 List.585 List.441; + let List.582 : U64 = 1i64; + let List.581 : U64 = CallByName Num.19 List.442 List.582; + jump List.576 List.439 List.579 List.441 List.581 List.443; else dec List.439; - let List.649 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; - ret List.649; + ret List.440; in - jump List.648 List.728 List.729 List.730 List.731 List.732; + jump List.576 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23 #Derived_gen.24 #Derived_gen.25; procedure List.93 (List.436, List.437, List.438): - let List.555 : U64 = 0i64; - let List.556 : U64 = CallByName List.6 List.436; - let List.554 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.555 List.556; - ret List.554; + let List.554 : U64 = 0i64; + let List.555 : U64 = CallByName List.6 List.436; + let List.553 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.554 List.555; + ret List.553; procedure List.93 (List.436, List.437, List.438): - let List.575 : U64 = 0i64; - let List.576 : U64 = CallByName List.6 List.436; - let List.574 : List U8 = CallByName List.80 List.436 List.437 List.438 List.575 List.576; - ret List.574; + let List.574 : U64 = 0i64; + let List.575 : U64 = CallByName List.6 List.436; + let List.573 : List U8 = CallByName List.80 List.436 List.437 List.438 List.574 List.575; + ret List.573; procedure List.93 (List.436, List.437, List.438): - let List.646 : U64 = 0i64; - let List.647 : U64 = CallByName List.6 List.436; - let List.645 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.436 List.437 List.438 List.646 List.647; - ret List.645; + let List.645 : U64 = 0i64; + let List.646 : U64 = CallByName List.6 List.436; + let List.644 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.436 List.437 List.438 List.645 List.646; + ret List.644; procedure Num.127 (#Attr.2): let Num.297 : U8 = lowlevel NumIntCast #Attr.2; @@ -296,20 +296,20 @@ procedure Num.94 (#Attr.2, #Attr.3): ret Num.302; procedure Str.12 (#Attr.2): - let Str.313 : List U8 = lowlevel StrToUtf8 #Attr.2; - ret Str.313; + let Str.309 : List U8 = lowlevel StrToUtf8 #Attr.2; + ret Str.309; procedure Str.4 (#Attr.2, #Attr.3): - let Str.316 : Str = lowlevel StrJoinWith #Attr.2 #Attr.3; - ret Str.316; + let Str.312 : Str = lowlevel StrJoinWith #Attr.2 #Attr.3; + ret Str.312; procedure Str.48 (#Attr.2, #Attr.3, #Attr.4): let Str.307 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8Range #Attr.2 #Attr.3 #Attr.4; ret Str.307; procedure Str.55 (#Attr.2): - let Str.319 : List Str = lowlevel StrGraphemes #Attr.2; - ret Str.319; + let Str.315 : List Str = lowlevel StrGraphemes #Attr.2; + ret Str.315; procedure Str.9 (Str.79): let Str.305 : U64 = 0i64; @@ -323,8 +323,8 @@ procedure Str.9 (Str.79): else let Str.300 : U8 = StructAtIndex 3 Str.80; let Str.301 : U64 = StructAtIndex 0 Str.80; - let #Derived_gen.16 : Str = StructAtIndex 1 Str.80; - dec #Derived_gen.16; + let #Derived_gen.38 : Str = StructAtIndex 1 Str.80; + dec #Derived_gen.38; let Str.299 : {U64, U8} = Struct {Str.301, Str.300}; let Str.298 : [C {U64, U8}, C Str] = TagId(0) Str.299; ret Str.298; @@ -1215,14 +1215,14 @@ procedure TotallyNotJson.82 (TotallyNotJson.802, TotallyNotJson.803): procedure TotallyNotJson.832 (TotallyNotJson.1493): let TotallyNotJson.1494 : List Str = StructAtIndex 1 TotallyNotJson.1493; - let #Derived_gen.14 : List Str = StructAtIndex 0 TotallyNotJson.1493; - dec #Derived_gen.14; + let #Derived_gen.36 : List Str = StructAtIndex 0 TotallyNotJson.1493; + dec #Derived_gen.36; ret TotallyNotJson.1494; procedure TotallyNotJson.840 (TotallyNotJson.1214): let TotallyNotJson.1215 : List Str = StructAtIndex 1 TotallyNotJson.1214; - let #Derived_gen.15 : List Str = StructAtIndex 0 TotallyNotJson.1214; - dec #Derived_gen.15; + let #Derived_gen.37 : List Str = StructAtIndex 0 TotallyNotJson.1214; + dec #Derived_gen.37; ret TotallyNotJson.1215; procedure TotallyNotJson.87 (TotallyNotJson.809): @@ -1277,7 +1277,7 @@ procedure TotallyNotJson.95 (TotallyNotJson.829): dec TotallyNotJson.1489; ret TotallyNotJson.1488; -procedure TotallyNotJson.96 (TotallyNotJson.1630): +procedure TotallyNotJson.96 (#Derived_gen.32): joinpoint TotallyNotJson.1496 TotallyNotJson.1168: let TotallyNotJson.834 : List Str = StructAtIndex 0 TotallyNotJson.1168; let TotallyNotJson.833 : List Str = StructAtIndex 1 TotallyNotJson.1168; @@ -1313,7 +1313,7 @@ procedure TotallyNotJson.96 (TotallyNotJson.1630): let TotallyNotJson.1497 : {List Str, List Str} = Struct {TotallyNotJson.834, TotallyNotJson.833}; ret TotallyNotJson.1497; in - jump TotallyNotJson.1496 TotallyNotJson.1630; + jump TotallyNotJson.1496 #Derived_gen.32; procedure TotallyNotJson.97 (TotallyNotJson.837): let TotallyNotJson.838 : List Str = CallByName Str.55 TotallyNotJson.837; @@ -1330,7 +1330,7 @@ procedure TotallyNotJson.97 (TotallyNotJson.837): dec TotallyNotJson.1210; ret TotallyNotJson.1209; -procedure TotallyNotJson.98 (TotallyNotJson.1621): +procedure TotallyNotJson.98 (#Derived_gen.10): joinpoint TotallyNotJson.1217 TotallyNotJson.1169: let TotallyNotJson.842 : List Str = StructAtIndex 0 TotallyNotJson.1169; let TotallyNotJson.841 : List Str = StructAtIndex 1 TotallyNotJson.1169; @@ -1366,7 +1366,7 @@ procedure TotallyNotJson.98 (TotallyNotJson.1621): let TotallyNotJson.1218 : {List Str, List Str} = Struct {TotallyNotJson.842, TotallyNotJson.841}; ret TotallyNotJson.1218; in - jump TotallyNotJson.1217 TotallyNotJson.1621; + jump TotallyNotJson.1217 #Derived_gen.10; procedure Test.0 (): let Test.11 : Str = "foo"; diff --git a/crates/compiler/test_mono/generated/encode_derived_record_two_field_strings.txt b/crates/compiler/test_mono/generated/encode_derived_record_two_field_strings.txt index 6ee53cde33a..5069fc23e17 100644 --- a/crates/compiler/test_mono/generated/encode_derived_record_two_field_strings.txt +++ b/crates/compiler/test_mono/generated/encode_derived_record_two_field_strings.txt @@ -44,12 +44,12 @@ procedure Encode.24 (Encode.99, Encode.107, Encode.101): ret Encode.111; procedure Encode.24 (Encode.99, Encode.107, Encode.101): - let Encode.118 : List U8 = CallByName TotallyNotJson.234 Encode.99 Encode.101 Encode.107; - ret Encode.118; + let Encode.113 : List U8 = CallByName TotallyNotJson.234 Encode.99 Encode.101 Encode.107; + ret Encode.113; procedure Encode.24 (Encode.99, Encode.107, Encode.101): - let Encode.122 : List U8 = CallByName TotallyNotJson.182 Encode.99 Encode.101 Encode.107; - ret Encode.122; + let Encode.117 : List U8 = CallByName TotallyNotJson.182 Encode.99 Encode.101 Encode.107; + ret Encode.117; procedure Encode.26 (Encode.105, Encode.106): let Encode.109 : List U8 = Array []; @@ -58,221 +58,221 @@ procedure Encode.26 (Encode.105, Encode.106): ret Encode.108; procedure List.13 (#Attr.2, #Attr.3): - let List.622 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; - ret List.622; + let List.621 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; + ret List.621; procedure List.145 (List.146, List.147, List.144): - let List.570 : {List U8, U64} = CallByName TotallyNotJson.237 List.146 List.147 List.144; - ret List.570; + let List.569 : {List U8, U64} = CallByName TotallyNotJson.237 List.146 List.147 List.144; + ret List.569; procedure List.145 (List.146, List.147, List.144): - let List.590 : List U8 = CallByName TotallyNotJson.215 List.146 List.147; - ret List.590; + let List.589 : List U8 = CallByName TotallyNotJson.215 List.146 List.147; + ret List.589; procedure List.18 (List.142, List.143, List.144): - let List.551 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; - ret List.551; + let List.550 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; + ret List.550; procedure List.18 (List.142, List.143, List.144): - let List.571 : List U8 = CallByName List.93 List.142 List.143 List.144; - ret List.571; + let List.570 : List U8 = CallByName List.93 List.142 List.143 List.144; + ret List.570; procedure List.26 (List.159, List.160, List.161): - let List.639 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.93 List.159 List.160 List.161; - let List.642 : U8 = 1i64; - let List.643 : U8 = GetTagId List.639; - let List.644 : Int1 = lowlevel Eq List.642 List.643; - if List.644 then - let List.162 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.639; + let List.638 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.93 List.159 List.160 List.161; + let List.641 : U8 = 1i64; + let List.642 : U8 = GetTagId List.638; + let List.643 : Int1 = lowlevel Eq List.641 List.642; + if List.643 then + let List.162 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.638; ret List.162; else - let List.163 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.639; + let List.163 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.638; ret List.163; procedure List.31 (#Attr.2, #Attr.3): - let List.604 : List Str = lowlevel ListDropAt #Attr.2 #Attr.3; - ret List.604; + let List.603 : List Str = lowlevel ListDropAt #Attr.2 #Attr.3; + ret List.603; procedure List.38 (List.298): - let List.612 : U64 = 0i64; - let List.611 : List Str = CallByName List.31 List.298 List.612; - ret List.611; + let List.611 : U64 = 0i64; + let List.610 : List Str = CallByName List.31 List.298 List.611; + ret List.610; procedure List.4 (List.113, List.114): - let List.547 : U64 = 1i64; - let List.546 : List Str = CallByName List.70 List.113 List.547; - let List.545 : List Str = CallByName List.71 List.546 List.114; - ret List.545; + let List.546 : U64 = 1i64; + let List.545 : List Str = CallByName List.70 List.113 List.546; + let List.544 : List Str = CallByName List.71 List.545 List.114; + ret List.544; procedure List.4 (List.113, List.114): - let List.550 : U64 = 1i64; - let List.549 : List U8 = CallByName List.70 List.113 List.550; - let List.548 : List U8 = CallByName List.71 List.549 List.114; - ret List.548; + let List.549 : U64 = 1i64; + let List.548 : List U8 = CallByName List.70 List.113 List.549; + let List.547 : List U8 = CallByName List.71 List.548 List.114; + ret List.547; procedure List.49 (List.376, List.377): - let List.631 : U64 = StructAtIndex 0 List.377; - let List.632 : U64 = 0i64; - let List.629 : Int1 = CallByName Bool.11 List.631 List.632; - if List.629 then + let List.630 : U64 = StructAtIndex 0 List.377; + let List.631 : U64 = 0i64; + let List.628 : Int1 = CallByName Bool.11 List.630 List.631; + if List.628 then dec List.376; - let List.630 : List U8 = Array []; - ret List.630; + let List.629 : List U8 = Array []; + ret List.629; else - let List.626 : U64 = StructAtIndex 1 List.377; - let List.627 : U64 = StructAtIndex 0 List.377; - let List.625 : List U8 = CallByName List.72 List.376 List.626 List.627; - ret List.625; + let List.625 : U64 = StructAtIndex 1 List.377; + let List.626 : U64 = StructAtIndex 0 List.377; + let List.624 : List U8 = CallByName List.72 List.376 List.625 List.626; + ret List.624; procedure List.52 (List.391, List.392): let List.393 : U64 = CallByName List.6 List.391; - joinpoint List.637 List.394: - let List.635 : U64 = 0i64; - let List.634 : {U64, U64} = Struct {List.394, List.635}; + joinpoint List.636 List.394: + let List.634 : U64 = 0i64; + let List.633 : {U64, U64} = Struct {List.394, List.634}; inc List.391; - let List.395 : List U8 = CallByName List.49 List.391 List.634; - let List.633 : U64 = CallByName Num.20 List.393 List.394; - let List.624 : {U64, U64} = Struct {List.633, List.394}; - let List.396 : List U8 = CallByName List.49 List.391 List.624; - let List.623 : {List U8, List U8} = Struct {List.395, List.396}; - ret List.623; + let List.395 : List U8 = CallByName List.49 List.391 List.633; + let List.632 : U64 = CallByName Num.20 List.393 List.394; + let List.623 : {U64, U64} = Struct {List.632, List.394}; + let List.396 : List U8 = CallByName List.49 List.391 List.623; + let List.622 : {List U8, List U8} = Struct {List.395, List.396}; + ret List.622; in - let List.638 : Int1 = CallByName Num.24 List.393 List.392; - if List.638 then - jump List.637 List.392; + let List.637 : Int1 = CallByName Num.24 List.393 List.392; + if List.637 then + jump List.636 List.392; else - jump List.637 List.393; + jump List.636 List.393; procedure List.6 (#Attr.2): - let List.618 : U64 = lowlevel ListLen #Attr.2; - ret List.618; + let List.617 : U64 = lowlevel ListLen #Attr.2; + ret List.617; procedure List.6 (#Attr.2): - let List.619 : U64 = lowlevel ListLen #Attr.2; - ret List.619; + let List.618 : U64 = lowlevel ListLen #Attr.2; + ret List.618; procedure List.6 (#Attr.2): - let List.621 : U64 = lowlevel ListLen #Attr.2; - ret List.621; + let List.620 : U64 = lowlevel ListLen #Attr.2; + ret List.620; procedure List.66 (#Attr.2, #Attr.3): - let List.567 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.567; + let List.566 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.566; procedure List.66 (#Attr.2, #Attr.3): - let List.587 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.587; + let List.586 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.586; procedure List.68 (#Attr.2): - let List.614 : List Str = lowlevel ListWithCapacity #Attr.2; - ret List.614; + let List.613 : List Str = lowlevel ListWithCapacity #Attr.2; + ret List.613; procedure List.68 (#Attr.2): - let List.616 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.616; + let List.615 : List U8 = lowlevel ListWithCapacity #Attr.2; + ret List.615; procedure List.70 (#Attr.2, #Attr.3): - let List.527 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.527; + let List.526 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.526; procedure List.70 (#Attr.2, #Attr.3): - let List.544 : List Str = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.544; + let List.543 : List Str = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.543; procedure List.71 (#Attr.2, #Attr.3): - let List.525 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.525; + let List.524 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.524; procedure List.71 (#Attr.2, #Attr.3): - let List.542 : List Str = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.542; + let List.541 : List Str = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.541; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.628 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.628; + let List.627 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.627; procedure List.8 (#Attr.2, #Attr.3): - let List.593 : List Str = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.593; + let List.592 : List Str = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.592; procedure List.8 (#Attr.2, #Attr.3): - let List.601 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.601; - -procedure List.80 (List.675, List.676, List.677, List.678, List.679): - joinpoint List.557 List.439 List.440 List.441 List.442 List.443: - let List.559 : Int1 = CallByName Num.22 List.442 List.443; - if List.559 then - let List.566 : {Str, Str} = CallByName List.66 List.439 List.442; - inc List.566; - let List.560 : {List U8, U64} = CallByName List.145 List.440 List.566 List.441; - let List.563 : U64 = 1i64; - let List.562 : U64 = CallByName Num.19 List.442 List.563; - jump List.557 List.439 List.560 List.441 List.562 List.443; + let List.600 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.600; + +procedure List.80 (#Derived_gen.15, #Derived_gen.16, #Derived_gen.17, #Derived_gen.18, #Derived_gen.19): + joinpoint List.556 List.439 List.440 List.441 List.442 List.443: + let List.558 : Int1 = CallByName Num.22 List.442 List.443; + if List.558 then + let List.565 : {Str, Str} = CallByName List.66 List.439 List.442; + inc List.565; + let List.559 : {List U8, U64} = CallByName List.145 List.440 List.565 List.441; + let List.562 : U64 = 1i64; + let List.561 : U64 = CallByName Num.19 List.442 List.562; + jump List.556 List.439 List.559 List.441 List.561 List.443; else dec List.439; ret List.440; in - jump List.557 List.675 List.676 List.677 List.678 List.679; - -procedure List.80 (List.692, List.693, List.694, List.695, List.696): - joinpoint List.577 List.439 List.440 List.441 List.442 List.443: - let List.579 : Int1 = CallByName Num.22 List.442 List.443; - if List.579 then - let List.586 : U8 = CallByName List.66 List.439 List.442; - let List.580 : List U8 = CallByName List.145 List.440 List.586 List.441; - let List.583 : U64 = 1i64; - let List.582 : U64 = CallByName Num.19 List.442 List.583; - jump List.577 List.439 List.580 List.441 List.582 List.443; + jump List.556 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18 #Derived_gen.19; + +procedure List.80 (#Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_gen.23, #Derived_gen.24): + joinpoint List.647 List.439 List.440 List.441 List.442 List.443: + let List.649 : Int1 = CallByName Num.22 List.442 List.443; + if List.649 then + let List.658 : U8 = CallByName List.66 List.439 List.442; + let List.650 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.440 List.658; + let List.655 : U8 = 1i64; + let List.656 : U8 = GetTagId List.650; + let List.657 : Int1 = lowlevel Eq List.655 List.656; + if List.657 then + let List.444 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.650; + let List.653 : U64 = 1i64; + let List.652 : U64 = CallByName Num.19 List.442 List.653; + jump List.647 List.439 List.444 List.441 List.652 List.443; + else + dec List.439; + let List.445 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.650; + let List.654 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.445; + ret List.654; else dec List.439; - ret List.440; + let List.648 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; + ret List.648; in - jump List.577 List.692 List.693 List.694 List.695 List.696; - -procedure List.80 (List.728, List.729, List.730, List.731, List.732): - joinpoint List.648 List.439 List.440 List.441 List.442 List.443: - let List.650 : Int1 = CallByName Num.22 List.442 List.443; - if List.650 then - let List.659 : U8 = CallByName List.66 List.439 List.442; - let List.651 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.440 List.659; - let List.656 : U8 = 1i64; - let List.657 : U8 = GetTagId List.651; - let List.658 : Int1 = lowlevel Eq List.656 List.657; - if List.658 then - let List.444 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.651; - let List.654 : U64 = 1i64; - let List.653 : U64 = CallByName Num.19 List.442 List.654; - jump List.648 List.439 List.444 List.441 List.653 List.443; - else - dec List.439; - let List.445 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.651; - let List.655 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.445; - ret List.655; + jump List.647 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23 #Derived_gen.24; + +procedure List.80 (#Derived_gen.25, #Derived_gen.26, #Derived_gen.27, #Derived_gen.28, #Derived_gen.29): + joinpoint List.576 List.439 List.440 List.441 List.442 List.443: + let List.578 : Int1 = CallByName Num.22 List.442 List.443; + if List.578 then + let List.585 : U8 = CallByName List.66 List.439 List.442; + let List.579 : List U8 = CallByName List.145 List.440 List.585 List.441; + let List.582 : U64 = 1i64; + let List.581 : U64 = CallByName Num.19 List.442 List.582; + jump List.576 List.439 List.579 List.441 List.581 List.443; else dec List.439; - let List.649 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; - ret List.649; + ret List.440; in - jump List.648 List.728 List.729 List.730 List.731 List.732; + jump List.576 #Derived_gen.25 #Derived_gen.26 #Derived_gen.27 #Derived_gen.28 #Derived_gen.29; procedure List.93 (List.436, List.437, List.438): - let List.555 : U64 = 0i64; - let List.556 : U64 = CallByName List.6 List.436; - let List.554 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.555 List.556; - ret List.554; + let List.554 : U64 = 0i64; + let List.555 : U64 = CallByName List.6 List.436; + let List.553 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.554 List.555; + ret List.553; procedure List.93 (List.436, List.437, List.438): - let List.575 : U64 = 0i64; - let List.576 : U64 = CallByName List.6 List.436; - let List.574 : List U8 = CallByName List.80 List.436 List.437 List.438 List.575 List.576; - ret List.574; + let List.574 : U64 = 0i64; + let List.575 : U64 = CallByName List.6 List.436; + let List.573 : List U8 = CallByName List.80 List.436 List.437 List.438 List.574 List.575; + ret List.573; procedure List.93 (List.436, List.437, List.438): - let List.646 : U64 = 0i64; - let List.647 : U64 = CallByName List.6 List.436; - let List.645 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.436 List.437 List.438 List.646 List.647; - ret List.645; + let List.645 : U64 = 0i64; + let List.646 : U64 = CallByName List.6 List.436; + let List.644 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.436 List.437 List.438 List.645 List.646; + ret List.644; procedure Num.127 (#Attr.2): let Num.297 : U8 = lowlevel NumIntCast #Attr.2; @@ -303,20 +303,20 @@ procedure Num.94 (#Attr.2, #Attr.3): ret Num.302; procedure Str.12 (#Attr.2): - let Str.313 : List U8 = lowlevel StrToUtf8 #Attr.2; - ret Str.313; + let Str.309 : List U8 = lowlevel StrToUtf8 #Attr.2; + ret Str.309; procedure Str.4 (#Attr.2, #Attr.3): - let Str.316 : Str = lowlevel StrJoinWith #Attr.2 #Attr.3; - ret Str.316; + let Str.312 : Str = lowlevel StrJoinWith #Attr.2 #Attr.3; + ret Str.312; procedure Str.48 (#Attr.2, #Attr.3, #Attr.4): let Str.307 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8Range #Attr.2 #Attr.3 #Attr.4; ret Str.307; procedure Str.55 (#Attr.2): - let Str.319 : List Str = lowlevel StrGraphemes #Attr.2; - ret Str.319; + let Str.315 : List Str = lowlevel StrGraphemes #Attr.2; + ret Str.315; procedure Str.9 (Str.79): let Str.305 : U64 = 0i64; @@ -330,8 +330,8 @@ procedure Str.9 (Str.79): else let Str.300 : U8 = StructAtIndex 3 Str.80; let Str.301 : U64 = StructAtIndex 0 Str.80; - let #Derived_gen.20 : Str = StructAtIndex 1 Str.80; - dec #Derived_gen.20; + let #Derived_gen.42 : Str = StructAtIndex 1 Str.80; + dec #Derived_gen.42; let Str.299 : {U64, U8} = Struct {Str.301, Str.300}; let Str.298 : [C {U64, U8}, C Str] = TagId(0) Str.299; ret Str.298; @@ -1222,14 +1222,14 @@ procedure TotallyNotJson.82 (TotallyNotJson.802, TotallyNotJson.803): procedure TotallyNotJson.832 (TotallyNotJson.1493): let TotallyNotJson.1494 : List Str = StructAtIndex 1 TotallyNotJson.1493; - let #Derived_gen.18 : List Str = StructAtIndex 0 TotallyNotJson.1493; - dec #Derived_gen.18; + let #Derived_gen.40 : List Str = StructAtIndex 0 TotallyNotJson.1493; + dec #Derived_gen.40; ret TotallyNotJson.1494; procedure TotallyNotJson.840 (TotallyNotJson.1214): let TotallyNotJson.1215 : List Str = StructAtIndex 1 TotallyNotJson.1214; - let #Derived_gen.19 : List Str = StructAtIndex 0 TotallyNotJson.1214; - dec #Derived_gen.19; + let #Derived_gen.41 : List Str = StructAtIndex 0 TotallyNotJson.1214; + dec #Derived_gen.41; ret TotallyNotJson.1215; procedure TotallyNotJson.87 (TotallyNotJson.809): @@ -1284,7 +1284,7 @@ procedure TotallyNotJson.95 (TotallyNotJson.829): dec TotallyNotJson.1489; ret TotallyNotJson.1488; -procedure TotallyNotJson.96 (TotallyNotJson.1633): +procedure TotallyNotJson.96 (#Derived_gen.36): joinpoint TotallyNotJson.1496 TotallyNotJson.1168: let TotallyNotJson.834 : List Str = StructAtIndex 0 TotallyNotJson.1168; let TotallyNotJson.833 : List Str = StructAtIndex 1 TotallyNotJson.1168; @@ -1320,7 +1320,7 @@ procedure TotallyNotJson.96 (TotallyNotJson.1633): let TotallyNotJson.1497 : {List Str, List Str} = Struct {TotallyNotJson.834, TotallyNotJson.833}; ret TotallyNotJson.1497; in - jump TotallyNotJson.1496 TotallyNotJson.1633; + jump TotallyNotJson.1496 #Derived_gen.36; procedure TotallyNotJson.97 (TotallyNotJson.837): let TotallyNotJson.838 : List Str = CallByName Str.55 TotallyNotJson.837; @@ -1337,7 +1337,7 @@ procedure TotallyNotJson.97 (TotallyNotJson.837): dec TotallyNotJson.1210; ret TotallyNotJson.1209; -procedure TotallyNotJson.98 (TotallyNotJson.1624): +procedure TotallyNotJson.98 (#Derived_gen.14): joinpoint TotallyNotJson.1217 TotallyNotJson.1169: let TotallyNotJson.842 : List Str = StructAtIndex 0 TotallyNotJson.1169; let TotallyNotJson.841 : List Str = StructAtIndex 1 TotallyNotJson.1169; @@ -1373,7 +1373,7 @@ procedure TotallyNotJson.98 (TotallyNotJson.1624): let TotallyNotJson.1218 : {List Str, List Str} = Struct {TotallyNotJson.842, TotallyNotJson.841}; ret TotallyNotJson.1218; in - jump TotallyNotJson.1217 TotallyNotJson.1624; + jump TotallyNotJson.1217 #Derived_gen.14; procedure Test.0 (): let Test.11 : Str = "foo"; diff --git a/crates/compiler/test_mono/generated/encode_derived_string.txt b/crates/compiler/test_mono/generated/encode_derived_string.txt index 5685ff13aed..57d54ca67a8 100644 --- a/crates/compiler/test_mono/generated/encode_derived_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_string.txt @@ -16,130 +16,130 @@ procedure Encode.26 (Encode.105, Encode.106): ret Encode.108; procedure List.145 (List.146, List.147, List.144): - let List.553 : List U8 = CallByName TotallyNotJson.215 List.146 List.147; - ret List.553; + let List.552 : List U8 = CallByName TotallyNotJson.215 List.146 List.147; + ret List.552; procedure List.18 (List.142, List.143, List.144): - let List.535 : List U8 = CallByName List.93 List.142 List.143 List.144; - ret List.535; + let List.534 : List U8 = CallByName List.93 List.142 List.143 List.144; + ret List.534; procedure List.26 (List.159, List.160, List.161): - let List.570 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.93 List.159 List.160 List.161; - let List.573 : U8 = 1i64; - let List.574 : U8 = GetTagId List.570; - let List.575 : Int1 = lowlevel Eq List.573 List.574; - if List.575 then - let List.162 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.570; + let List.569 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.93 List.159 List.160 List.161; + let List.572 : U8 = 1i64; + let List.573 : U8 = GetTagId List.569; + let List.574 : Int1 = lowlevel Eq List.572 List.573; + if List.574 then + let List.162 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.569; ret List.162; else - let List.163 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.570; + let List.163 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.569; ret List.163; procedure List.49 (List.376, List.377): - let List.562 : U64 = StructAtIndex 0 List.377; - let List.563 : U64 = 0i64; - let List.560 : Int1 = CallByName Bool.11 List.562 List.563; - if List.560 then + let List.561 : U64 = StructAtIndex 0 List.377; + let List.562 : U64 = 0i64; + let List.559 : Int1 = CallByName Bool.11 List.561 List.562; + if List.559 then dec List.376; - let List.561 : List U8 = Array []; - ret List.561; + let List.560 : List U8 = Array []; + ret List.560; else - let List.557 : U64 = StructAtIndex 1 List.377; - let List.558 : U64 = StructAtIndex 0 List.377; - let List.556 : List U8 = CallByName List.72 List.376 List.557 List.558; - ret List.556; + let List.556 : U64 = StructAtIndex 1 List.377; + let List.557 : U64 = StructAtIndex 0 List.377; + let List.555 : List U8 = CallByName List.72 List.376 List.556 List.557; + ret List.555; procedure List.52 (List.391, List.392): let List.393 : U64 = CallByName List.6 List.391; - joinpoint List.568 List.394: - let List.566 : U64 = 0i64; - let List.565 : {U64, U64} = Struct {List.394, List.566}; + joinpoint List.567 List.394: + let List.565 : U64 = 0i64; + let List.564 : {U64, U64} = Struct {List.394, List.565}; inc List.391; - let List.395 : List U8 = CallByName List.49 List.391 List.565; - let List.564 : U64 = CallByName Num.20 List.393 List.394; - let List.555 : {U64, U64} = Struct {List.564, List.394}; - let List.396 : List U8 = CallByName List.49 List.391 List.555; - let List.554 : {List U8, List U8} = Struct {List.395, List.396}; - ret List.554; + let List.395 : List U8 = CallByName List.49 List.391 List.564; + let List.563 : U64 = CallByName Num.20 List.393 List.394; + let List.554 : {U64, U64} = Struct {List.563, List.394}; + let List.396 : List U8 = CallByName List.49 List.391 List.554; + let List.553 : {List U8, List U8} = Struct {List.395, List.396}; + ret List.553; in - let List.569 : Int1 = CallByName Num.24 List.393 List.392; - if List.569 then - jump List.568 List.392; + let List.568 : Int1 = CallByName Num.24 List.393 List.392; + if List.568 then + jump List.567 List.392; else - jump List.568 List.393; + jump List.567 List.393; procedure List.6 (#Attr.2): - let List.534 : U64 = lowlevel ListLen #Attr.2; - ret List.534; + let List.533 : U64 = lowlevel ListLen #Attr.2; + ret List.533; procedure List.66 (#Attr.2, #Attr.3): - let List.551 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.551; + let List.550 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.550; procedure List.68 (#Attr.2): - let List.532 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.532; + let List.531 : List U8 = lowlevel ListWithCapacity #Attr.2; + ret List.531; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.559 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.559; + let List.558 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.558; procedure List.8 (#Attr.2, #Attr.3): - let List.530 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.530; - -procedure List.80 (List.598, List.599, List.600, List.601, List.602): - joinpoint List.541 List.439 List.440 List.441 List.442 List.443: - let List.543 : Int1 = CallByName Num.22 List.442 List.443; - if List.543 then - let List.550 : U8 = CallByName List.66 List.439 List.442; - let List.544 : List U8 = CallByName List.145 List.440 List.550 List.441; - let List.547 : U64 = 1i64; - let List.546 : U64 = CallByName Num.19 List.442 List.547; - jump List.541 List.439 List.544 List.441 List.546 List.443; + let List.529 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.529; + +procedure List.80 (#Derived_gen.3, #Derived_gen.4, #Derived_gen.5, #Derived_gen.6, #Derived_gen.7): + joinpoint List.578 List.439 List.440 List.441 List.442 List.443: + let List.580 : Int1 = CallByName Num.22 List.442 List.443; + if List.580 then + let List.589 : U8 = CallByName List.66 List.439 List.442; + let List.581 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.440 List.589; + let List.586 : U8 = 1i64; + let List.587 : U8 = GetTagId List.581; + let List.588 : Int1 = lowlevel Eq List.586 List.587; + if List.588 then + let List.444 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.581; + let List.584 : U64 = 1i64; + let List.583 : U64 = CallByName Num.19 List.442 List.584; + jump List.578 List.439 List.444 List.441 List.583 List.443; + else + dec List.439; + let List.445 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.581; + let List.585 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.445; + ret List.585; else dec List.439; - ret List.440; + let List.579 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; + ret List.579; in - jump List.541 List.598 List.599 List.600 List.601 List.602; - -procedure List.80 (List.621, List.622, List.623, List.624, List.625): - joinpoint List.579 List.439 List.440 List.441 List.442 List.443: - let List.581 : Int1 = CallByName Num.22 List.442 List.443; - if List.581 then - let List.590 : U8 = CallByName List.66 List.439 List.442; - let List.582 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.440 List.590; - let List.587 : U8 = 1i64; - let List.588 : U8 = GetTagId List.582; - let List.589 : Int1 = lowlevel Eq List.587 List.588; - if List.589 then - let List.444 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.582; - let List.585 : U64 = 1i64; - let List.584 : U64 = CallByName Num.19 List.442 List.585; - jump List.579 List.439 List.444 List.441 List.584 List.443; - else - dec List.439; - let List.445 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.582; - let List.586 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.445; - ret List.586; + jump List.578 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7; + +procedure List.80 (#Derived_gen.8, #Derived_gen.9, #Derived_gen.10, #Derived_gen.11, #Derived_gen.12): + joinpoint List.540 List.439 List.440 List.441 List.442 List.443: + let List.542 : Int1 = CallByName Num.22 List.442 List.443; + if List.542 then + let List.549 : U8 = CallByName List.66 List.439 List.442; + let List.543 : List U8 = CallByName List.145 List.440 List.549 List.441; + let List.546 : U64 = 1i64; + let List.545 : U64 = CallByName Num.19 List.442 List.546; + jump List.540 List.439 List.543 List.441 List.545 List.443; else dec List.439; - let List.580 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; - ret List.580; + ret List.440; in - jump List.579 List.621 List.622 List.623 List.624 List.625; + jump List.540 #Derived_gen.8 #Derived_gen.9 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12; procedure List.93 (List.436, List.437, List.438): - let List.539 : U64 = 0i64; - let List.540 : U64 = CallByName List.6 List.436; - let List.538 : List U8 = CallByName List.80 List.436 List.437 List.438 List.539 List.540; - ret List.538; + let List.538 : U64 = 0i64; + let List.539 : U64 = CallByName List.6 List.436; + let List.537 : List U8 = CallByName List.80 List.436 List.437 List.438 List.538 List.539; + ret List.537; procedure List.93 (List.436, List.437, List.438): - let List.577 : U64 = 0i64; - let List.578 : U64 = CallByName List.6 List.436; - let List.576 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.436 List.437 List.438 List.577 List.578; - ret List.576; + let List.576 : U64 = 0i64; + let List.577 : U64 = CallByName List.6 List.436; + let List.575 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.436 List.437 List.438 List.576 List.577; + ret List.575; procedure Num.19 (#Attr.2, #Attr.3): let Num.297 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; @@ -166,8 +166,8 @@ procedure Num.94 (#Attr.2, #Attr.3): ret Num.294; procedure Str.12 (#Attr.2): - let Str.312 : List U8 = lowlevel StrToUtf8 #Attr.2; - ret Str.312; + let Str.308 : List U8 = lowlevel StrToUtf8 #Attr.2; + ret Str.308; procedure Str.48 (#Attr.2, #Attr.3, #Attr.4): let Str.307 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8Range #Attr.2 #Attr.3 #Attr.4; @@ -185,8 +185,8 @@ procedure Str.9 (Str.79): else let Str.300 : U8 = StructAtIndex 3 Str.80; let Str.301 : U64 = StructAtIndex 0 Str.80; - let #Derived_gen.0 : Str = StructAtIndex 1 Str.80; - dec #Derived_gen.0; + let #Derived_gen.13 : Str = StructAtIndex 1 Str.80; + dec #Derived_gen.13; let Str.299 : {U64, U8} = Struct {Str.301, Str.300}; let Str.298 : [C {U64, U8}, C Str] = TagId(0) Str.299; ret Str.298; diff --git a/crates/compiler/test_mono/generated/encode_derived_tag_one_field_string.txt b/crates/compiler/test_mono/generated/encode_derived_tag_one_field_string.txt index 1908d7dc0a7..8ec699d6a79 100644 --- a/crates/compiler/test_mono/generated/encode_derived_tag_one_field_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_tag_one_field_string.txt @@ -31,12 +31,12 @@ procedure Encode.24 (Encode.99, Encode.107, Encode.101): ret Encode.111; procedure Encode.24 (Encode.99, Encode.107, Encode.101): - let Encode.118 : List U8 = CallByName TotallyNotJson.264 Encode.99 Encode.101 Encode.107; - ret Encode.118; + let Encode.113 : List U8 = CallByName TotallyNotJson.264 Encode.99 Encode.101 Encode.107; + ret Encode.113; procedure Encode.24 (Encode.99, Encode.107, Encode.101): - let Encode.121 : List U8 = CallByName TotallyNotJson.182 Encode.99 Encode.101 Encode.107; - ret Encode.121; + let Encode.116 : List U8 = CallByName TotallyNotJson.182 Encode.99 Encode.101 Encode.107; + ret Encode.116; procedure Encode.26 (Encode.105, Encode.106): let Encode.109 : List U8 = Array []; @@ -45,182 +45,182 @@ procedure Encode.26 (Encode.105, Encode.106): ret Encode.108; procedure List.145 (List.146, List.147, List.144): - let List.568 : {List U8, U64} = CallByName TotallyNotJson.267 List.146 List.147 List.144; - ret List.568; + let List.567 : {List U8, U64} = CallByName TotallyNotJson.267 List.146 List.147 List.144; + ret List.567; procedure List.145 (List.146, List.147, List.144): - let List.588 : List U8 = CallByName TotallyNotJson.215 List.146 List.147; - ret List.588; + let List.587 : List U8 = CallByName TotallyNotJson.215 List.146 List.147; + ret List.587; procedure List.18 (List.142, List.143, List.144): - let List.549 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; - ret List.549; + let List.548 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; + ret List.548; procedure List.18 (List.142, List.143, List.144): - let List.569 : List U8 = CallByName List.93 List.142 List.143 List.144; - ret List.569; + let List.568 : List U8 = CallByName List.93 List.142 List.143 List.144; + ret List.568; procedure List.26 (List.159, List.160, List.161): - let List.619 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.93 List.159 List.160 List.161; - let List.622 : U8 = 1i64; - let List.623 : U8 = GetTagId List.619; - let List.624 : Int1 = lowlevel Eq List.622 List.623; - if List.624 then - let List.162 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.619; + let List.618 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.93 List.159 List.160 List.161; + let List.621 : U8 = 1i64; + let List.622 : U8 = GetTagId List.618; + let List.623 : Int1 = lowlevel Eq List.621 List.622; + if List.623 then + let List.162 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.618; ret List.162; else - let List.163 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.619; + let List.163 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.618; ret List.163; procedure List.4 (List.113, List.114): - let List.548 : U64 = 1i64; - let List.547 : List U8 = CallByName List.70 List.113 List.548; - let List.546 : List U8 = CallByName List.71 List.547 List.114; - ret List.546; + let List.547 : U64 = 1i64; + let List.546 : List U8 = CallByName List.70 List.113 List.547; + let List.545 : List U8 = CallByName List.71 List.546 List.114; + ret List.545; procedure List.49 (List.376, List.377): - let List.611 : U64 = StructAtIndex 0 List.377; - let List.612 : U64 = 0i64; - let List.609 : Int1 = CallByName Bool.11 List.611 List.612; - if List.609 then + let List.610 : U64 = StructAtIndex 0 List.377; + let List.611 : U64 = 0i64; + let List.608 : Int1 = CallByName Bool.11 List.610 List.611; + if List.608 then dec List.376; - let List.610 : List U8 = Array []; - ret List.610; + let List.609 : List U8 = Array []; + ret List.609; else - let List.606 : U64 = StructAtIndex 1 List.377; - let List.607 : U64 = StructAtIndex 0 List.377; - let List.605 : List U8 = CallByName List.72 List.376 List.606 List.607; - ret List.605; + let List.605 : U64 = StructAtIndex 1 List.377; + let List.606 : U64 = StructAtIndex 0 List.377; + let List.604 : List U8 = CallByName List.72 List.376 List.605 List.606; + ret List.604; procedure List.52 (List.391, List.392): let List.393 : U64 = CallByName List.6 List.391; - joinpoint List.617 List.394: - let List.615 : U64 = 0i64; - let List.614 : {U64, U64} = Struct {List.394, List.615}; + joinpoint List.616 List.394: + let List.614 : U64 = 0i64; + let List.613 : {U64, U64} = Struct {List.394, List.614}; inc List.391; - let List.395 : List U8 = CallByName List.49 List.391 List.614; - let List.613 : U64 = CallByName Num.20 List.393 List.394; - let List.604 : {U64, U64} = Struct {List.613, List.394}; - let List.396 : List U8 = CallByName List.49 List.391 List.604; - let List.603 : {List U8, List U8} = Struct {List.395, List.396}; - ret List.603; + let List.395 : List U8 = CallByName List.49 List.391 List.613; + let List.612 : U64 = CallByName Num.20 List.393 List.394; + let List.603 : {U64, U64} = Struct {List.612, List.394}; + let List.396 : List U8 = CallByName List.49 List.391 List.603; + let List.602 : {List U8, List U8} = Struct {List.395, List.396}; + ret List.602; in - let List.618 : Int1 = CallByName Num.24 List.393 List.392; - if List.618 then - jump List.617 List.392; + let List.617 : Int1 = CallByName Num.24 List.393 List.392; + if List.617 then + jump List.616 List.392; else - jump List.617 List.393; + jump List.616 List.393; procedure List.6 (#Attr.2): - let List.589 : U64 = lowlevel ListLen #Attr.2; - ret List.589; + let List.588 : U64 = lowlevel ListLen #Attr.2; + ret List.588; procedure List.6 (#Attr.2): - let List.591 : U64 = lowlevel ListLen #Attr.2; - ret List.591; + let List.590 : U64 = lowlevel ListLen #Attr.2; + ret List.590; procedure List.66 (#Attr.2, #Attr.3): - let List.565 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.565; + let List.564 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.564; procedure List.66 (#Attr.2, #Attr.3): - let List.585 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.585; + let List.584 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.584; procedure List.68 (#Attr.2): - let List.602 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.602; + let List.601 : List U8 = lowlevel ListWithCapacity #Attr.2; + ret List.601; procedure List.70 (#Attr.2, #Attr.3): - let List.527 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.527; + let List.526 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.526; procedure List.71 (#Attr.2, #Attr.3): - let List.525 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.525; + let List.524 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.524; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.608 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.608; + let List.607 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.607; procedure List.8 (#Attr.2, #Attr.3): - let List.600 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.600; - -procedure List.80 (List.649, List.650, List.651, List.652, List.653): - joinpoint List.555 List.439 List.440 List.441 List.442 List.443: - let List.557 : Int1 = CallByName Num.22 List.442 List.443; - if List.557 then - let List.564 : Str = CallByName List.66 List.439 List.442; - inc List.564; - let List.558 : {List U8, U64} = CallByName List.145 List.440 List.564 List.441; - let List.561 : U64 = 1i64; - let List.560 : U64 = CallByName Num.19 List.442 List.561; - jump List.555 List.439 List.558 List.441 List.560 List.443; + let List.599 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.599; + +procedure List.80 (#Derived_gen.10, #Derived_gen.11, #Derived_gen.12, #Derived_gen.13, #Derived_gen.14): + joinpoint List.554 List.439 List.440 List.441 List.442 List.443: + let List.556 : Int1 = CallByName Num.22 List.442 List.443; + if List.556 then + let List.563 : Str = CallByName List.66 List.439 List.442; + inc List.563; + let List.557 : {List U8, U64} = CallByName List.145 List.440 List.563 List.441; + let List.560 : U64 = 1i64; + let List.559 : U64 = CallByName Num.19 List.442 List.560; + jump List.554 List.439 List.557 List.441 List.559 List.443; else dec List.439; ret List.440; in - jump List.555 List.649 List.650 List.651 List.652 List.653; - -procedure List.80 (List.666, List.667, List.668, List.669, List.670): - joinpoint List.575 List.439 List.440 List.441 List.442 List.443: - let List.577 : Int1 = CallByName Num.22 List.442 List.443; - if List.577 then - let List.584 : U8 = CallByName List.66 List.439 List.442; - let List.578 : List U8 = CallByName List.145 List.440 List.584 List.441; - let List.581 : U64 = 1i64; - let List.580 : U64 = CallByName Num.19 List.442 List.581; - jump List.575 List.439 List.578 List.441 List.580 List.443; + jump List.554 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14; + +procedure List.80 (#Derived_gen.18, #Derived_gen.19, #Derived_gen.20, #Derived_gen.21, #Derived_gen.22): + joinpoint List.574 List.439 List.440 List.441 List.442 List.443: + let List.576 : Int1 = CallByName Num.22 List.442 List.443; + if List.576 then + let List.583 : U8 = CallByName List.66 List.439 List.442; + let List.577 : List U8 = CallByName List.145 List.440 List.583 List.441; + let List.580 : U64 = 1i64; + let List.579 : U64 = CallByName Num.19 List.442 List.580; + jump List.574 List.439 List.577 List.441 List.579 List.443; else dec List.439; ret List.440; in - jump List.575 List.666 List.667 List.668 List.669 List.670; - -procedure List.80 (List.693, List.694, List.695, List.696, List.697): - joinpoint List.628 List.439 List.440 List.441 List.442 List.443: - let List.630 : Int1 = CallByName Num.22 List.442 List.443; - if List.630 then - let List.639 : U8 = CallByName List.66 List.439 List.442; - let List.631 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.440 List.639; - let List.636 : U8 = 1i64; - let List.637 : U8 = GetTagId List.631; - let List.638 : Int1 = lowlevel Eq List.636 List.637; - if List.638 then - let List.444 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.631; - let List.634 : U64 = 1i64; - let List.633 : U64 = CallByName Num.19 List.442 List.634; - jump List.628 List.439 List.444 List.441 List.633 List.443; + jump List.574 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22; + +procedure List.80 (#Derived_gen.29, #Derived_gen.30, #Derived_gen.31, #Derived_gen.32, #Derived_gen.33): + joinpoint List.627 List.439 List.440 List.441 List.442 List.443: + let List.629 : Int1 = CallByName Num.22 List.442 List.443; + if List.629 then + let List.638 : U8 = CallByName List.66 List.439 List.442; + let List.630 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.440 List.638; + let List.635 : U8 = 1i64; + let List.636 : U8 = GetTagId List.630; + let List.637 : Int1 = lowlevel Eq List.635 List.636; + if List.637 then + let List.444 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.630; + let List.633 : U64 = 1i64; + let List.632 : U64 = CallByName Num.19 List.442 List.633; + jump List.627 List.439 List.444 List.441 List.632 List.443; else dec List.439; - let List.445 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.631; - let List.635 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.445; - ret List.635; + let List.445 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.630; + let List.634 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.445; + ret List.634; else dec List.439; - let List.629 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; - ret List.629; + let List.628 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; + ret List.628; in - jump List.628 List.693 List.694 List.695 List.696 List.697; + jump List.627 #Derived_gen.29 #Derived_gen.30 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33; procedure List.93 (List.436, List.437, List.438): - let List.553 : U64 = 0i64; - let List.554 : U64 = CallByName List.6 List.436; - let List.552 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.553 List.554; - ret List.552; + let List.552 : U64 = 0i64; + let List.553 : U64 = CallByName List.6 List.436; + let List.551 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.552 List.553; + ret List.551; procedure List.93 (List.436, List.437, List.438): - let List.573 : U64 = 0i64; - let List.574 : U64 = CallByName List.6 List.436; - let List.572 : List U8 = CallByName List.80 List.436 List.437 List.438 List.573 List.574; - ret List.572; + let List.572 : U64 = 0i64; + let List.573 : U64 = CallByName List.6 List.436; + let List.571 : List U8 = CallByName List.80 List.436 List.437 List.438 List.572 List.573; + ret List.571; procedure List.93 (List.436, List.437, List.438): - let List.626 : U64 = 0i64; - let List.627 : U64 = CallByName List.6 List.436; - let List.625 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.436 List.437 List.438 List.626 List.627; - ret List.625; + let List.625 : U64 = 0i64; + let List.626 : U64 = CallByName List.6 List.436; + let List.624 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.436 List.437 List.438 List.625 List.626; + ret List.624; procedure Num.127 (#Attr.2): let Num.299 : U8 = lowlevel NumIntCast #Attr.2; @@ -251,8 +251,8 @@ procedure Num.94 (#Attr.2, #Attr.3): ret Num.304; procedure Str.12 (#Attr.2): - let Str.313 : List U8 = lowlevel StrToUtf8 #Attr.2; - ret Str.313; + let Str.309 : List U8 = lowlevel StrToUtf8 #Attr.2; + ret Str.309; procedure Str.48 (#Attr.2, #Attr.3, #Attr.4): let Str.307 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8Range #Attr.2 #Attr.3 #Attr.4; @@ -270,8 +270,8 @@ procedure Str.9 (Str.79): else let Str.300 : U8 = StructAtIndex 3 Str.80; let Str.301 : U64 = StructAtIndex 0 Str.80; - let #Derived_gen.14 : Str = StructAtIndex 1 Str.80; - dec #Derived_gen.14; + let #Derived_gen.34 : Str = StructAtIndex 1 Str.80; + dec #Derived_gen.34; let Str.299 : {U64, U8} = Struct {Str.301, Str.300}; let Str.298 : [C {U64, U8}, C Str] = TagId(0) Str.299; ret Str.298; diff --git a/crates/compiler/test_mono/generated/encode_derived_tag_two_payloads_string.txt b/crates/compiler/test_mono/generated/encode_derived_tag_two_payloads_string.txt index 147632f0945..c0ccba518fc 100644 --- a/crates/compiler/test_mono/generated/encode_derived_tag_two_payloads_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_tag_two_payloads_string.txt @@ -34,12 +34,12 @@ procedure Encode.24 (Encode.99, Encode.107, Encode.101): ret Encode.111; procedure Encode.24 (Encode.99, Encode.107, Encode.101): - let Encode.118 : List U8 = CallByName TotallyNotJson.264 Encode.99 Encode.101 Encode.107; - ret Encode.118; + let Encode.113 : List U8 = CallByName TotallyNotJson.264 Encode.99 Encode.101 Encode.107; + ret Encode.113; procedure Encode.24 (Encode.99, Encode.107, Encode.101): - let Encode.122 : List U8 = CallByName TotallyNotJson.182 Encode.99 Encode.101 Encode.107; - ret Encode.122; + let Encode.117 : List U8 = CallByName TotallyNotJson.182 Encode.99 Encode.101 Encode.107; + ret Encode.117; procedure Encode.26 (Encode.105, Encode.106): let Encode.109 : List U8 = Array []; @@ -48,182 +48,182 @@ procedure Encode.26 (Encode.105, Encode.106): ret Encode.108; procedure List.145 (List.146, List.147, List.144): - let List.568 : {List U8, U64} = CallByName TotallyNotJson.267 List.146 List.147 List.144; - ret List.568; + let List.567 : {List U8, U64} = CallByName TotallyNotJson.267 List.146 List.147 List.144; + ret List.567; procedure List.145 (List.146, List.147, List.144): - let List.588 : List U8 = CallByName TotallyNotJson.215 List.146 List.147; - ret List.588; + let List.587 : List U8 = CallByName TotallyNotJson.215 List.146 List.147; + ret List.587; procedure List.18 (List.142, List.143, List.144): - let List.549 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; - ret List.549; + let List.548 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; + ret List.548; procedure List.18 (List.142, List.143, List.144): - let List.569 : List U8 = CallByName List.93 List.142 List.143 List.144; - ret List.569; + let List.568 : List U8 = CallByName List.93 List.142 List.143 List.144; + ret List.568; procedure List.26 (List.159, List.160, List.161): - let List.619 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.93 List.159 List.160 List.161; - let List.622 : U8 = 1i64; - let List.623 : U8 = GetTagId List.619; - let List.624 : Int1 = lowlevel Eq List.622 List.623; - if List.624 then - let List.162 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.619; + let List.618 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.93 List.159 List.160 List.161; + let List.621 : U8 = 1i64; + let List.622 : U8 = GetTagId List.618; + let List.623 : Int1 = lowlevel Eq List.621 List.622; + if List.623 then + let List.162 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.618; ret List.162; else - let List.163 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.619; + let List.163 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.618; ret List.163; procedure List.4 (List.113, List.114): - let List.548 : U64 = 1i64; - let List.547 : List U8 = CallByName List.70 List.113 List.548; - let List.546 : List U8 = CallByName List.71 List.547 List.114; - ret List.546; + let List.547 : U64 = 1i64; + let List.546 : List U8 = CallByName List.70 List.113 List.547; + let List.545 : List U8 = CallByName List.71 List.546 List.114; + ret List.545; procedure List.49 (List.376, List.377): - let List.611 : U64 = StructAtIndex 0 List.377; - let List.612 : U64 = 0i64; - let List.609 : Int1 = CallByName Bool.11 List.611 List.612; - if List.609 then + let List.610 : U64 = StructAtIndex 0 List.377; + let List.611 : U64 = 0i64; + let List.608 : Int1 = CallByName Bool.11 List.610 List.611; + if List.608 then dec List.376; - let List.610 : List U8 = Array []; - ret List.610; + let List.609 : List U8 = Array []; + ret List.609; else - let List.606 : U64 = StructAtIndex 1 List.377; - let List.607 : U64 = StructAtIndex 0 List.377; - let List.605 : List U8 = CallByName List.72 List.376 List.606 List.607; - ret List.605; + let List.605 : U64 = StructAtIndex 1 List.377; + let List.606 : U64 = StructAtIndex 0 List.377; + let List.604 : List U8 = CallByName List.72 List.376 List.605 List.606; + ret List.604; procedure List.52 (List.391, List.392): let List.393 : U64 = CallByName List.6 List.391; - joinpoint List.617 List.394: - let List.615 : U64 = 0i64; - let List.614 : {U64, U64} = Struct {List.394, List.615}; + joinpoint List.616 List.394: + let List.614 : U64 = 0i64; + let List.613 : {U64, U64} = Struct {List.394, List.614}; inc List.391; - let List.395 : List U8 = CallByName List.49 List.391 List.614; - let List.613 : U64 = CallByName Num.20 List.393 List.394; - let List.604 : {U64, U64} = Struct {List.613, List.394}; - let List.396 : List U8 = CallByName List.49 List.391 List.604; - let List.603 : {List U8, List U8} = Struct {List.395, List.396}; - ret List.603; + let List.395 : List U8 = CallByName List.49 List.391 List.613; + let List.612 : U64 = CallByName Num.20 List.393 List.394; + let List.603 : {U64, U64} = Struct {List.612, List.394}; + let List.396 : List U8 = CallByName List.49 List.391 List.603; + let List.602 : {List U8, List U8} = Struct {List.395, List.396}; + ret List.602; in - let List.618 : Int1 = CallByName Num.24 List.393 List.392; - if List.618 then - jump List.617 List.392; + let List.617 : Int1 = CallByName Num.24 List.393 List.392; + if List.617 then + jump List.616 List.392; else - jump List.617 List.393; + jump List.616 List.393; procedure List.6 (#Attr.2): - let List.589 : U64 = lowlevel ListLen #Attr.2; - ret List.589; + let List.588 : U64 = lowlevel ListLen #Attr.2; + ret List.588; procedure List.6 (#Attr.2): - let List.591 : U64 = lowlevel ListLen #Attr.2; - ret List.591; + let List.590 : U64 = lowlevel ListLen #Attr.2; + ret List.590; procedure List.66 (#Attr.2, #Attr.3): - let List.565 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.565; + let List.564 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.564; procedure List.66 (#Attr.2, #Attr.3): - let List.585 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.585; + let List.584 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.584; procedure List.68 (#Attr.2): - let List.602 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.602; + let List.601 : List U8 = lowlevel ListWithCapacity #Attr.2; + ret List.601; procedure List.70 (#Attr.2, #Attr.3): - let List.527 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.527; + let List.526 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.526; procedure List.71 (#Attr.2, #Attr.3): - let List.525 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.525; + let List.524 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.524; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.608 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.608; + let List.607 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.607; procedure List.8 (#Attr.2, #Attr.3): - let List.600 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.600; - -procedure List.80 (List.649, List.650, List.651, List.652, List.653): - joinpoint List.555 List.439 List.440 List.441 List.442 List.443: - let List.557 : Int1 = CallByName Num.22 List.442 List.443; - if List.557 then - let List.564 : Str = CallByName List.66 List.439 List.442; - inc List.564; - let List.558 : {List U8, U64} = CallByName List.145 List.440 List.564 List.441; - let List.561 : U64 = 1i64; - let List.560 : U64 = CallByName Num.19 List.442 List.561; - jump List.555 List.439 List.558 List.441 List.560 List.443; + let List.599 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.599; + +procedure List.80 (#Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_gen.23, #Derived_gen.24): + joinpoint List.574 List.439 List.440 List.441 List.442 List.443: + let List.576 : Int1 = CallByName Num.22 List.442 List.443; + if List.576 then + let List.583 : U8 = CallByName List.66 List.439 List.442; + let List.577 : List U8 = CallByName List.145 List.440 List.583 List.441; + let List.580 : U64 = 1i64; + let List.579 : U64 = CallByName Num.19 List.442 List.580; + jump List.574 List.439 List.577 List.441 List.579 List.443; else dec List.439; ret List.440; in - jump List.555 List.649 List.650 List.651 List.652 List.653; - -procedure List.80 (List.666, List.667, List.668, List.669, List.670): - joinpoint List.575 List.439 List.440 List.441 List.442 List.443: - let List.577 : Int1 = CallByName Num.22 List.442 List.443; - if List.577 then - let List.584 : U8 = CallByName List.66 List.439 List.442; - let List.578 : List U8 = CallByName List.145 List.440 List.584 List.441; - let List.581 : U64 = 1i64; - let List.580 : U64 = CallByName Num.19 List.442 List.581; - jump List.575 List.439 List.578 List.441 List.580 List.443; + jump List.574 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23 #Derived_gen.24; + +procedure List.80 (#Derived_gen.25, #Derived_gen.26, #Derived_gen.27, #Derived_gen.28, #Derived_gen.29): + joinpoint List.627 List.439 List.440 List.441 List.442 List.443: + let List.629 : Int1 = CallByName Num.22 List.442 List.443; + if List.629 then + let List.638 : U8 = CallByName List.66 List.439 List.442; + let List.630 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.440 List.638; + let List.635 : U8 = 1i64; + let List.636 : U8 = GetTagId List.630; + let List.637 : Int1 = lowlevel Eq List.635 List.636; + if List.637 then + let List.444 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.630; + let List.633 : U64 = 1i64; + let List.632 : U64 = CallByName Num.19 List.442 List.633; + jump List.627 List.439 List.444 List.441 List.632 List.443; + else + dec List.439; + let List.445 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.630; + let List.634 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.445; + ret List.634; else dec List.439; - ret List.440; + let List.628 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; + ret List.628; in - jump List.575 List.666 List.667 List.668 List.669 List.670; - -procedure List.80 (List.693, List.694, List.695, List.696, List.697): - joinpoint List.628 List.439 List.440 List.441 List.442 List.443: - let List.630 : Int1 = CallByName Num.22 List.442 List.443; - if List.630 then - let List.639 : U8 = CallByName List.66 List.439 List.442; - let List.631 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.440 List.639; - let List.636 : U8 = 1i64; - let List.637 : U8 = GetTagId List.631; - let List.638 : Int1 = lowlevel Eq List.636 List.637; - if List.638 then - let List.444 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.631; - let List.634 : U64 = 1i64; - let List.633 : U64 = CallByName Num.19 List.442 List.634; - jump List.628 List.439 List.444 List.441 List.633 List.443; - else - dec List.439; - let List.445 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.631; - let List.635 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.445; - ret List.635; + jump List.627 #Derived_gen.25 #Derived_gen.26 #Derived_gen.27 #Derived_gen.28 #Derived_gen.29; + +procedure List.80 (#Derived_gen.30, #Derived_gen.31, #Derived_gen.32, #Derived_gen.33, #Derived_gen.34): + joinpoint List.554 List.439 List.440 List.441 List.442 List.443: + let List.556 : Int1 = CallByName Num.22 List.442 List.443; + if List.556 then + let List.563 : Str = CallByName List.66 List.439 List.442; + inc List.563; + let List.557 : {List U8, U64} = CallByName List.145 List.440 List.563 List.441; + let List.560 : U64 = 1i64; + let List.559 : U64 = CallByName Num.19 List.442 List.560; + jump List.554 List.439 List.557 List.441 List.559 List.443; else dec List.439; - let List.629 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; - ret List.629; + ret List.440; in - jump List.628 List.693 List.694 List.695 List.696 List.697; + jump List.554 #Derived_gen.30 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33 #Derived_gen.34; procedure List.93 (List.436, List.437, List.438): - let List.553 : U64 = 0i64; - let List.554 : U64 = CallByName List.6 List.436; - let List.552 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.553 List.554; - ret List.552; + let List.552 : U64 = 0i64; + let List.553 : U64 = CallByName List.6 List.436; + let List.551 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.552 List.553; + ret List.551; procedure List.93 (List.436, List.437, List.438): - let List.573 : U64 = 0i64; - let List.574 : U64 = CallByName List.6 List.436; - let List.572 : List U8 = CallByName List.80 List.436 List.437 List.438 List.573 List.574; - ret List.572; + let List.572 : U64 = 0i64; + let List.573 : U64 = CallByName List.6 List.436; + let List.571 : List U8 = CallByName List.80 List.436 List.437 List.438 List.572 List.573; + ret List.571; procedure List.93 (List.436, List.437, List.438): - let List.626 : U64 = 0i64; - let List.627 : U64 = CallByName List.6 List.436; - let List.625 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.436 List.437 List.438 List.626 List.627; - ret List.625; + let List.625 : U64 = 0i64; + let List.626 : U64 = CallByName List.6 List.436; + let List.624 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.436 List.437 List.438 List.625 List.626; + ret List.624; procedure Num.127 (#Attr.2): let Num.299 : U8 = lowlevel NumIntCast #Attr.2; @@ -254,8 +254,8 @@ procedure Num.94 (#Attr.2, #Attr.3): ret Num.304; procedure Str.12 (#Attr.2): - let Str.313 : List U8 = lowlevel StrToUtf8 #Attr.2; - ret Str.313; + let Str.309 : List U8 = lowlevel StrToUtf8 #Attr.2; + ret Str.309; procedure Str.48 (#Attr.2, #Attr.3, #Attr.4): let Str.307 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8Range #Attr.2 #Attr.3 #Attr.4; @@ -273,8 +273,8 @@ procedure Str.9 (Str.79): else let Str.300 : U8 = StructAtIndex 3 Str.80; let Str.301 : U64 = StructAtIndex 0 Str.80; - let #Derived_gen.15 : Str = StructAtIndex 1 Str.80; - dec #Derived_gen.15; + let #Derived_gen.35 : Str = StructAtIndex 1 Str.80; + dec #Derived_gen.35; let Str.299 : {U64, U8} = Struct {Str.301, Str.300}; let Str.298 : [C {U64, U8}, C Str] = TagId(0) Str.299; ret Str.298; diff --git a/crates/compiler/test_mono/generated/factorial.txt b/crates/compiler/test_mono/generated/factorial.txt index bc43696252d..5b844fd3d9d 100644 --- a/crates/compiler/test_mono/generated/factorial.txt +++ b/crates/compiler/test_mono/generated/factorial.txt @@ -6,7 +6,7 @@ procedure Num.21 (#Attr.2, #Attr.3): let Num.292 : I64 = lowlevel NumMul #Attr.2 #Attr.3; ret Num.292; -procedure Test.1 (Test.15, Test.16): +procedure Test.1 (#Derived_gen.0, #Derived_gen.1): joinpoint Test.7 Test.2 Test.3: let Test.13 : I64 = 0i64; let Test.14 : Int1 = lowlevel Eq Test.13 Test.2; @@ -18,7 +18,7 @@ procedure Test.1 (Test.15, Test.16): let Test.11 : I64 = CallByName Num.21 Test.2 Test.3; jump Test.7 Test.10 Test.11; in - jump Test.7 Test.15 Test.16; + jump Test.7 #Derived_gen.0 #Derived_gen.1; procedure Test.0 (): let Test.5 : I64 = 10i64; diff --git a/crates/compiler/test_mono/generated/inline_return_joinpoints_in_bool_lambda_set.txt b/crates/compiler/test_mono/generated/inline_return_joinpoints_in_bool_lambda_set.txt index 16466af3715..6f8a56f0cbe 100644 --- a/crates/compiler/test_mono/generated/inline_return_joinpoints_in_bool_lambda_set.txt +++ b/crates/compiler/test_mono/generated/inline_return_joinpoints_in_bool_lambda_set.txt @@ -9,7 +9,7 @@ procedure Num.19 (#Attr.2, #Attr.3): procedure Test.3 (Test.4): ret Test.4; -procedure Test.0 (Test.14): +procedure Test.0 (#Derived_gen.0): joinpoint Test.5 Test.1: joinpoint Test.10 Test.2: let Test.8 : I64 = 1i64; @@ -31,4 +31,4 @@ procedure Test.0 (Test.14): let Test.9 : Int1 = true; jump Test.10 Test.9; in - jump Test.5 Test.14; + jump Test.5 #Derived_gen.0; diff --git a/crates/compiler/test_mono/generated/inline_return_joinpoints_in_enum_lambda_set.txt b/crates/compiler/test_mono/generated/inline_return_joinpoints_in_enum_lambda_set.txt index bf4dcfca155..5265cdc174d 100644 --- a/crates/compiler/test_mono/generated/inline_return_joinpoints_in_enum_lambda_set.txt +++ b/crates/compiler/test_mono/generated/inline_return_joinpoints_in_enum_lambda_set.txt @@ -34,7 +34,7 @@ procedure Test.8 (Test.9): let Test.23 : I64 = CallByName Num.19 Test.9 Test.24; ret Test.23; -procedure Test.0 (Test.30): +procedure Test.0 (#Derived_gen.0): joinpoint Test.11 Test.1: let Test.25 : I64 = 1i64; let Test.13 : I64 = CallByName Num.19 Test.1 Test.25; @@ -57,4 +57,4 @@ procedure Test.0 (Test.30): ret Test.12; in - jump Test.11 Test.30; + jump Test.11 #Derived_gen.0; diff --git a/crates/compiler/test_mono/generated/inline_return_joinpoints_in_union_lambda_set.txt b/crates/compiler/test_mono/generated/inline_return_joinpoints_in_union_lambda_set.txt index cc5f96b3e6c..6ab49274c59 100644 --- a/crates/compiler/test_mono/generated/inline_return_joinpoints_in_union_lambda_set.txt +++ b/crates/compiler/test_mono/generated/inline_return_joinpoints_in_union_lambda_set.txt @@ -17,7 +17,7 @@ procedure Test.4 (Test.5, #Attr.12): let Test.16 : I64 = CallByName Num.19 Test.5 Test.1; ret Test.16; -procedure Test.0 (Test.25): +procedure Test.0 (#Derived_gen.0): joinpoint Test.7 Test.1: let Test.20 : I64 = 1i64; let Test.9 : I64 = CallByName Num.19 Test.1 Test.20; @@ -33,4 +33,4 @@ procedure Test.0 (Test.25): ret Test.8; in - jump Test.7 Test.25; + jump Test.7 #Derived_gen.0; diff --git a/crates/compiler/test_mono/generated/issue_3669.txt b/crates/compiler/test_mono/generated/issue_3669.txt index fd2126b6c9e..03438ca1040 100644 --- a/crates/compiler/test_mono/generated/issue_3669.txt +++ b/crates/compiler/test_mono/generated/issue_3669.txt @@ -2,7 +2,7 @@ procedure Bool.11 (#Attr.2, #Attr.3): let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3; ret Bool.23; -procedure Test.2 (Test.19): +procedure Test.2 (#Derived_gen.0): joinpoint Test.13 Test.7: let Test.16 : U8 = 1i64; let Test.17 : U8 = GetTagId Test.7; @@ -13,8 +13,8 @@ procedure Test.2 (Test.19): ret Test.14; else let Test.5 : [, C *self] = UnionAtIndex (Id 0) (Index 0) Test.7; - let #Derived_gen.0 : Int1 = lowlevel RefCountIsUnique Test.7; - if #Derived_gen.0 then + let #Derived_gen.1 : Int1 = lowlevel RefCountIsUnique Test.7; + if #Derived_gen.1 then decref Test.7; jump Test.13 Test.5; else @@ -22,7 +22,7 @@ procedure Test.2 (Test.19): decref Test.7; jump Test.13 Test.5; in - jump Test.13 Test.19; + jump Test.13 #Derived_gen.0; procedure Test.0 (): let Test.12 : [, C *self] = TagId(1) ; diff --git a/crates/compiler/test_mono/generated/issue_4749.txt b/crates/compiler/test_mono/generated/issue_4749.txt index 82602e8a385..f43c0ae8dc4 100644 --- a/crates/compiler/test_mono/generated/issue_4749.txt +++ b/crates/compiler/test_mono/generated/issue_4749.txt @@ -1,30 +1,30 @@ procedure Bool.1 (): - let Bool.55 : Int1 = false; - ret Bool.55; + let Bool.51 : Int1 = false; + ret Bool.51; procedure Bool.11 (#Attr.2, #Attr.3): let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3; ret Bool.23; procedure Bool.11 (#Attr.2, #Attr.3): - let Bool.46 : Int1 = lowlevel Eq #Attr.2 #Attr.3; - ret Bool.46; + let Bool.42 : Int1 = lowlevel Eq #Attr.2 #Attr.3; + ret Bool.42; procedure Bool.11 (#Attr.2, #Attr.3): - let Bool.67 : Int1 = lowlevel Eq #Attr.2 #Attr.3; - ret Bool.67; + let Bool.57 : Int1 = lowlevel Eq #Attr.2 #Attr.3; + ret Bool.57; procedure Bool.2 (): - let Bool.54 : Int1 = true; - ret Bool.54; + let Bool.50 : Int1 = true; + ret Bool.50; procedure Bool.3 (#Attr.2, #Attr.3): - let Bool.37 : Int1 = lowlevel And #Attr.2 #Attr.3; - ret Bool.37; + let Bool.33 : Int1 = lowlevel And #Attr.2 #Attr.3; + ret Bool.33; procedure Bool.4 (#Attr.2, #Attr.3): - let Bool.57 : Int1 = lowlevel Or #Attr.2 #Attr.3; - ret Bool.57; + let Bool.53 : Int1 = lowlevel Or #Attr.2 #Attr.3; + ret Bool.53; procedure Decode.24 (Decode.101): ret Decode.101; @@ -65,151 +65,151 @@ procedure Decode.27 (Decode.107, Decode.108): ret Decode.123; procedure List.1 (List.96): - let List.590 : U64 = CallByName List.6 List.96; + let List.588 : U64 = CallByName List.6 List.96; dec List.96; - let List.591 : U64 = 0i64; - let List.589 : Int1 = CallByName Bool.11 List.590 List.591; - ret List.589; + let List.589 : U64 = 0i64; + let List.587 : Int1 = CallByName Bool.11 List.588 List.589; + ret List.587; procedure List.2 (List.97, List.98): - let List.573 : U64 = CallByName List.6 List.97; - let List.570 : Int1 = CallByName Num.22 List.98 List.573; - if List.570 then - let List.572 : U8 = CallByName List.66 List.97 List.98; + let List.571 : U64 = CallByName List.6 List.97; + let List.568 : Int1 = CallByName Num.22 List.98 List.571; + if List.568 then + let List.570 : U8 = CallByName List.66 List.97 List.98; dec List.97; - let List.571 : [C {}, C U8] = TagId(1) List.572; - ret List.571; + let List.569 : [C {}, C U8] = TagId(1) List.570; + ret List.569; else dec List.97; - let List.569 : {} = Struct {}; - let List.568 : [C {}, C U8] = TagId(0) List.569; - ret List.568; + let List.567 : {} = Struct {}; + let List.566 : [C {}, C U8] = TagId(0) List.567; + ret List.566; procedure List.26 (List.159, List.160, List.161): - let List.592 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.93 List.159 List.160 List.161; - let List.595 : U8 = 1i64; - let List.596 : U8 = GetTagId List.592; - let List.597 : Int1 = lowlevel Eq List.595 List.596; - if List.597 then - let List.162 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.592; + let List.590 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.93 List.159 List.160 List.161; + let List.593 : U8 = 1i64; + let List.594 : U8 = GetTagId List.590; + let List.595 : Int1 = lowlevel Eq List.593 List.594; + if List.595 then + let List.162 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.590; ret List.162; else - let List.163 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.592; + let List.163 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.590; ret List.163; procedure List.29 (List.304, List.305): - let List.547 : U64 = CallByName List.6 List.304; - let List.306 : U64 = CallByName Num.77 List.547 List.305; - let List.546 : List U8 = CallByName List.43 List.304 List.306; - ret List.546; + let List.545 : U64 = CallByName List.6 List.304; + let List.306 : U64 = CallByName Num.77 List.545 List.305; + let List.544 : List U8 = CallByName List.43 List.304 List.306; + ret List.544; procedure List.31 (#Attr.2, #Attr.3): - let List.560 : List U8 = lowlevel ListDropAt #Attr.2 #Attr.3; - ret List.560; + let List.558 : List U8 = lowlevel ListDropAt #Attr.2 #Attr.3; + ret List.558; procedure List.38 (List.298): - let List.559 : U64 = 0i64; - let List.558 : List U8 = CallByName List.31 List.298 List.559; - ret List.558; + let List.557 : U64 = 0i64; + let List.556 : List U8 = CallByName List.31 List.298 List.557; + ret List.556; procedure List.4 (List.113, List.114): - let List.557 : U64 = 1i64; - let List.556 : List U8 = CallByName List.70 List.113 List.557; - let List.555 : List U8 = CallByName List.71 List.556 List.114; - ret List.555; + let List.555 : U64 = 1i64; + let List.554 : List U8 = CallByName List.70 List.113 List.555; + let List.553 : List U8 = CallByName List.71 List.554 List.114; + ret List.553; procedure List.43 (List.302, List.303): - let List.539 : U64 = CallByName List.6 List.302; - let List.538 : U64 = CallByName Num.77 List.539 List.303; - let List.529 : {U64, U64} = Struct {List.303, List.538}; - let List.528 : List U8 = CallByName List.49 List.302 List.529; - ret List.528; + let List.537 : U64 = CallByName List.6 List.302; + let List.536 : U64 = CallByName Num.77 List.537 List.303; + let List.527 : {U64, U64} = Struct {List.303, List.536}; + let List.526 : List U8 = CallByName List.49 List.302 List.527; + ret List.526; procedure List.49 (List.376, List.377): - let List.586 : U64 = StructAtIndex 0 List.377; - let List.587 : U64 = 0i64; - let List.584 : Int1 = CallByName Bool.11 List.586 List.587; - if List.584 then + let List.584 : U64 = StructAtIndex 0 List.377; + let List.585 : U64 = 0i64; + let List.582 : Int1 = CallByName Bool.11 List.584 List.585; + if List.582 then dec List.376; - let List.585 : List U8 = Array []; - ret List.585; + let List.583 : List U8 = Array []; + ret List.583; else - let List.582 : U64 = StructAtIndex 1 List.377; - let List.583 : U64 = StructAtIndex 0 List.377; - let List.581 : List U8 = CallByName List.72 List.376 List.582 List.583; - ret List.581; + let List.580 : U64 = StructAtIndex 1 List.377; + let List.581 : U64 = StructAtIndex 0 List.377; + let List.579 : List U8 = CallByName List.72 List.376 List.580 List.581; + ret List.579; procedure List.6 (#Attr.2): - let List.650 : U64 = lowlevel ListLen #Attr.2; - ret List.650; + let List.611 : U64 = lowlevel ListLen #Attr.2; + ret List.611; procedure List.66 (#Attr.2, #Attr.3): - let List.566 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.566; + let List.564 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.564; procedure List.70 (#Attr.2, #Attr.3): - let List.554 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.554; + let List.552 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.552; procedure List.71 (#Attr.2, #Attr.3): - let List.552 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.552; + let List.550 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.550; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.533 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.533; + let List.531 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.531; procedure List.8 (#Attr.2, #Attr.3): - let List.549 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.549; - -procedure List.80 (List.642, List.643, List.644, List.645, List.646): - joinpoint List.601 List.439 List.440 List.441 List.442 List.443: - let List.603 : Int1 = CallByName Num.22 List.442 List.443; - if List.603 then - let List.612 : U8 = CallByName List.66 List.439 List.442; - let List.604 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName TotallyNotJson.62 List.440 List.612; - let List.609 : U8 = 1i64; - let List.610 : U8 = GetTagId List.604; - let List.611 : Int1 = lowlevel Eq List.609 List.610; - if List.611 then - let List.444 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.604; - let List.607 : U64 = 1i64; - let List.606 : U64 = CallByName Num.19 List.442 List.607; - jump List.601 List.439 List.444 List.441 List.606 List.443; + let List.547 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.547; + +procedure List.80 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): + joinpoint List.599 List.439 List.440 List.441 List.442 List.443: + let List.601 : Int1 = CallByName Num.22 List.442 List.443; + if List.601 then + let List.610 : U8 = CallByName List.66 List.439 List.442; + let List.602 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName TotallyNotJson.62 List.440 List.610; + let List.607 : U8 = 1i64; + let List.608 : U8 = GetTagId List.602; + let List.609 : Int1 = lowlevel Eq List.607 List.608; + if List.609 then + let List.444 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.602; + let List.605 : U64 = 1i64; + let List.604 : U64 = CallByName Num.19 List.442 List.605; + jump List.599 List.439 List.444 List.441 List.604 List.443; else dec List.439; - let List.445 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.604; - let List.608 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(0) List.445; - ret List.608; + let List.445 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.602; + let List.606 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(0) List.445; + ret List.606; else dec List.439; - let List.602 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(1) List.440; - ret List.602; + let List.600 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(1) List.440; + ret List.600; in - jump List.601 List.642 List.643 List.644 List.645 List.646; + jump List.599 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; procedure List.93 (List.436, List.437, List.438): - let List.599 : U64 = 0i64; - let List.600 : U64 = CallByName List.6 List.436; - let List.598 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.80 List.436 List.437 List.438 List.599 List.600; - ret List.598; + let List.597 : U64 = 0i64; + let List.598 : U64 = CallByName List.6 List.436; + let List.596 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.80 List.436 List.437 List.438 List.597 List.598; + ret List.596; procedure Num.19 (#Attr.2, #Attr.3): let Num.295 : U8 = lowlevel NumAdd #Attr.2 #Attr.3; ret Num.295; procedure Num.19 (#Attr.2, #Attr.3): - let Num.345 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.345; + let Num.329 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.329; procedure Num.20 (#Attr.2, #Attr.3): let Num.307 : U8 = lowlevel NumSub #Attr.2 #Attr.3; ret Num.307; procedure Num.22 (#Attr.2, #Attr.3): - let Num.344 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.344; + let Num.328 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.328; procedure Num.23 (#Attr.2, #Attr.3): let Num.313 : Int1 = lowlevel NumLte #Attr.2 #Attr.3; @@ -228,8 +228,8 @@ procedure Num.72 (#Attr.2, #Attr.3): ret Num.293; procedure Num.77 (#Attr.2, #Attr.3): - let Num.341 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3; - ret Num.341; + let Num.325 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3; + ret Num.325; procedure Str.48 (#Attr.2, #Attr.3, #Attr.4): let Str.307 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8Range #Attr.2 #Attr.3 #Attr.4; @@ -247,8 +247,8 @@ procedure Str.9 (Str.79): else let Str.300 : U8 = StructAtIndex 3 Str.80; let Str.301 : U64 = StructAtIndex 0 Str.80; - let #Derived_gen.1 : Str = StructAtIndex 1 Str.80; - dec #Derived_gen.1; + let #Derived_gen.7 : Str = StructAtIndex 1 Str.80; + dec #Derived_gen.7; let Str.299 : {U64, U8} = Struct {Str.301, Str.300}; let Str.298 : [C {U64, U8}, C Str] = TagId(0) Str.299; ret Str.298; @@ -365,8 +365,8 @@ procedure TotallyNotJson.534 (TotallyNotJson.535): procedure TotallyNotJson.536 (TotallyNotJson.1192): let TotallyNotJson.1193 : List U8 = StructAtIndex 1 TotallyNotJson.1192; - let #Derived_gen.0 : List U8 = StructAtIndex 0 TotallyNotJson.1192; - dec #Derived_gen.0; + let #Derived_gen.6 : List U8 = StructAtIndex 0 TotallyNotJson.1192; + dec #Derived_gen.6; ret TotallyNotJson.1193; procedure TotallyNotJson.60 (): @@ -733,7 +733,7 @@ procedure TotallyNotJson.69 (): let TotallyNotJson.1247 : List U8 = CallByName TotallyNotJson.68 TotallyNotJson.1248 TotallyNotJson.1249 TotallyNotJson.1250 TotallyNotJson.1251; ret TotallyNotJson.1247; -procedure TotallyNotJson.70 (TotallyNotJson.1468): +procedure TotallyNotJson.70 (#Derived_gen.5): joinpoint TotallyNotJson.1198 TotallyNotJson.1166: let TotallyNotJson.600 : List U8 = StructAtIndex 0 TotallyNotJson.1166; inc 4 TotallyNotJson.600; @@ -834,4 +834,4 @@ procedure TotallyNotJson.70 (TotallyNotJson.1468): let TotallyNotJson.1276 : {List U8, List U8} = Struct {TotallyNotJson.600, TotallyNotJson.601}; ret TotallyNotJson.1276; in - jump TotallyNotJson.1198 TotallyNotJson.1468; + jump TotallyNotJson.1198 #Derived_gen.5; diff --git a/crates/compiler/test_mono/generated/issue_4770.txt b/crates/compiler/test_mono/generated/issue_4770.txt index 7c43ab26ff1..4f1d14165db 100644 --- a/crates/compiler/test_mono/generated/issue_4770.txt +++ b/crates/compiler/test_mono/generated/issue_4770.txt @@ -48,7 +48,7 @@ procedure List.66 (#Attr.2, #Attr.3): let List.549 : {[C I64, C List *self], [C I64, C List *self]} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.549; -procedure List.80 (List.561, List.562, List.563, List.564, List.565): +procedure List.80 (#Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4, #Derived_gen.5): joinpoint List.537 List.439 List.440 List.441 List.442 List.443: let List.539 : Int1 = CallByName Num.22 List.442 List.443; if List.539 then @@ -73,7 +73,7 @@ procedure List.80 (List.561, List.562, List.563, List.564, List.565): let List.538 : [C {}, C {}] = TagId(1) List.440; ret List.538; in - jump List.537 List.561 List.562 List.563 List.564 List.565; + jump List.537 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5; procedure List.93 (List.436, List.437, List.438): let List.535 : U64 = 0i64; @@ -93,7 +93,7 @@ procedure Num.22 (#Attr.2, #Attr.3): let Num.295 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; ret Num.295; -procedure Test.1 (Test.77): +procedure Test.1 (#Derived_gen.0): joinpoint Test.26 Test.6: let Test.65 : [C I64, C List *self] = StructAtIndex 1 Test.6; let Test.66 : U8 = 0i64; @@ -110,17 +110,17 @@ procedure Test.1 (Test.77): let Test.49 : [C I64, C List *self] = StructAtIndex 1 Test.6; dec Test.50; let Test.10 : I64 = UnionAtIndex (Id 0) (Index 0) Test.49; - joinpoint #Derived_gen.0: + joinpoint #Derived_gen.6: let Test.27 : Int1 = CallByName Num.22 Test.8 Test.10; ret Test.27; in - let #Derived_gen.1 : Int1 = lowlevel RefCountIsUnique Test.49; - if #Derived_gen.1 then + let #Derived_gen.7 : Int1 = lowlevel RefCountIsUnique Test.49; + if #Derived_gen.7 then decref Test.49; - jump #Derived_gen.0; + jump #Derived_gen.6; else decref Test.49; - jump #Derived_gen.0; + jump #Derived_gen.6; else let Test.39 : [C I64, C List *self] = StructAtIndex 0 Test.6; let Test.42 : [C I64, C List *self] = StructAtIndex 1 Test.6; @@ -141,7 +141,7 @@ procedure Test.1 (Test.77): dec Test.52; let Test.14 : List [C I64, C List *self] = UnionAtIndex (Id 1) (Index 0) Test.51; inc Test.14; - joinpoint #Derived_gen.2: + joinpoint #Derived_gen.8: let Test.35 : {} = Struct {}; let Test.33 : List {[C I64, C List *self], [C I64, C List *self]} = CallByName List.23 Test.12 Test.14 Test.35; let Test.34 : {} = Struct {}; @@ -159,14 +159,14 @@ procedure Test.1 (Test.77): let Test.28 : Int1 = CallByName Bool.1; ret Test.28; in - let #Derived_gen.3 : Int1 = lowlevel RefCountIsUnique Test.51; - if #Derived_gen.3 then + let #Derived_gen.9 : Int1 = lowlevel RefCountIsUnique Test.51; + if #Derived_gen.9 then decref Test.51; - jump #Derived_gen.2; + jump #Derived_gen.8; else inc Test.14; decref Test.51; - jump #Derived_gen.2; + jump #Derived_gen.8; else let Test.48 : [C I64, C List *self] = StructAtIndex 0 Test.6; let Test.47 : List [C I64, C List *self] = Array [Test.48]; @@ -175,7 +175,7 @@ procedure Test.1 (Test.77): let Test.44 : {[C I64, C List *self], [C I64, C List *self]} = Struct {Test.45, Test.46}; jump Test.26 Test.44; in - jump Test.26 Test.77; + jump Test.26 #Derived_gen.0; procedure Test.15 (Test.16, Test.17): let Test.36 : {[C I64, C List *self], [C I64, C List *self]} = Struct {Test.16, Test.17}; diff --git a/crates/compiler/test_mono/generated/issue_4772_weakened_monomorphic_destructure.txt b/crates/compiler/test_mono/generated/issue_4772_weakened_monomorphic_destructure.txt index d94e756d715..9e4b221fed2 100644 --- a/crates/compiler/test_mono/generated/issue_4772_weakened_monomorphic_destructure.txt +++ b/crates/compiler/test_mono/generated/issue_4772_weakened_monomorphic_destructure.txt @@ -1,30 +1,30 @@ procedure Bool.1 (): - let Bool.55 : Int1 = false; - ret Bool.55; + let Bool.51 : Int1 = false; + ret Bool.51; procedure Bool.11 (#Attr.2, #Attr.3): let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3; ret Bool.23; procedure Bool.11 (#Attr.2, #Attr.3): - let Bool.46 : Int1 = lowlevel Eq #Attr.2 #Attr.3; - ret Bool.46; + let Bool.42 : Int1 = lowlevel Eq #Attr.2 #Attr.3; + ret Bool.42; procedure Bool.11 (#Attr.2, #Attr.3): - let Bool.67 : Int1 = lowlevel Eq #Attr.2 #Attr.3; - ret Bool.67; + let Bool.57 : Int1 = lowlevel Eq #Attr.2 #Attr.3; + ret Bool.57; procedure Bool.2 (): - let Bool.54 : Int1 = true; - ret Bool.54; + let Bool.50 : Int1 = true; + ret Bool.50; procedure Bool.3 (#Attr.2, #Attr.3): - let Bool.37 : Int1 = lowlevel And #Attr.2 #Attr.3; - ret Bool.37; + let Bool.33 : Int1 = lowlevel And #Attr.2 #Attr.3; + ret Bool.33; procedure Bool.4 (#Attr.2, #Attr.3): - let Bool.57 : Int1 = lowlevel Or #Attr.2 #Attr.3; - ret Bool.57; + let Bool.53 : Int1 = lowlevel Or #Attr.2 #Attr.3; + ret Bool.53; procedure Decode.24 (Decode.101): ret Decode.101; @@ -114,8 +114,8 @@ procedure List.49 (List.376, List.377): ret List.575; procedure List.6 (#Attr.2): - let List.644 : U64 = lowlevel ListLen #Attr.2; - ret List.644; + let List.607 : U64 = lowlevel ListLen #Attr.2; + ret List.607; procedure List.66 (#Attr.2, #Attr.3): let List.560 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; @@ -137,7 +137,7 @@ procedure List.8 (#Attr.2, #Attr.3): let List.543 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; ret List.543; -procedure List.80 (List.636, List.637, List.638, List.639, List.640): +procedure List.80 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): joinpoint List.595 List.439 List.440 List.441 List.442 List.443: let List.597 : Int1 = CallByName Num.22 List.442 List.443; if List.597 then @@ -161,7 +161,7 @@ procedure List.80 (List.636, List.637, List.638, List.639, List.640): let List.596 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(1) List.440; ret List.596; in - jump List.595 List.636 List.637 List.638 List.639 List.640; + jump List.595 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; procedure List.93 (List.436, List.437, List.438): let List.593 : U64 = 0i64; @@ -174,16 +174,16 @@ procedure Num.19 (#Attr.2, #Attr.3): ret Num.295; procedure Num.19 (#Attr.2, #Attr.3): - let Num.345 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.345; + let Num.329 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.329; procedure Num.20 (#Attr.2, #Attr.3): let Num.307 : U8 = lowlevel NumSub #Attr.2 #Attr.3; ret Num.307; procedure Num.22 (#Attr.2, #Attr.3): - let Num.344 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.344; + let Num.328 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.328; procedure Num.23 (#Attr.2, #Attr.3): let Num.313 : Int1 = lowlevel NumLte #Attr.2 #Attr.3; @@ -202,8 +202,8 @@ procedure Num.72 (#Attr.2, #Attr.3): ret Num.293; procedure Num.77 (#Attr.2, #Attr.3): - let Num.341 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3; - ret Num.341; + let Num.325 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3; + ret Num.325; procedure Str.12 (#Attr.2): let Str.307 : List U8 = lowlevel StrToUtf8 #Attr.2; @@ -218,8 +218,8 @@ procedure Str.47 (#Attr.2): ret Str.306; procedure Str.48 (#Attr.2, #Attr.3, #Attr.4): - let Str.321 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8Range #Attr.2 #Attr.3 #Attr.4; - ret Str.321; + let Str.317 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8Range #Attr.2 #Attr.3 #Attr.4; + ret Str.317; procedure Str.72 (Str.244): let Str.245 : {I64, U8} = CallByName Str.47 Str.244; @@ -237,22 +237,22 @@ procedure Str.72 (Str.244): ret Str.299; procedure Str.9 (Str.79): - let Str.319 : U64 = 0i64; - let Str.320 : U64 = CallByName List.6 Str.79; - let Str.80 : {U64, Str, Int1, U8} = CallByName Str.48 Str.79 Str.319 Str.320; - let Str.316 : Int1 = StructAtIndex 2 Str.80; - if Str.316 then - let Str.318 : Str = StructAtIndex 1 Str.80; - let Str.317 : [C {U64, U8}, C Str] = TagId(1) Str.318; - ret Str.317; + let Str.315 : U64 = 0i64; + let Str.316 : U64 = CallByName List.6 Str.79; + let Str.80 : {U64, Str, Int1, U8} = CallByName Str.48 Str.79 Str.315 Str.316; + let Str.312 : Int1 = StructAtIndex 2 Str.80; + if Str.312 then + let Str.314 : Str = StructAtIndex 1 Str.80; + let Str.313 : [C {U64, U8}, C Str] = TagId(1) Str.314; + ret Str.313; else - let Str.314 : U8 = StructAtIndex 3 Str.80; - let Str.315 : U64 = StructAtIndex 0 Str.80; - let #Derived_gen.0 : Str = StructAtIndex 1 Str.80; - dec #Derived_gen.0; - let Str.313 : {U64, U8} = Struct {Str.315, Str.314}; - let Str.312 : [C {U64, U8}, C Str] = TagId(0) Str.313; - ret Str.312; + let Str.310 : U8 = StructAtIndex 3 Str.80; + let Str.311 : U64 = StructAtIndex 0 Str.80; + let #Derived_gen.6 : Str = StructAtIndex 1 Str.80; + dec #Derived_gen.6; + let Str.309 : {U64, U8} = Struct {Str.311, Str.310}; + let Str.308 : [C {U64, U8}, C Str] = TagId(0) Str.309; + ret Str.308; procedure Test.0 (): let Test.37 : Str = "-1234"; @@ -397,8 +397,8 @@ procedure TotallyNotJson.534 (TotallyNotJson.535): procedure TotallyNotJson.536 (TotallyNotJson.1192): let TotallyNotJson.1193 : List U8 = StructAtIndex 1 TotallyNotJson.1192; - let #Derived_gen.1 : List U8 = StructAtIndex 0 TotallyNotJson.1192; - dec #Derived_gen.1; + let #Derived_gen.7 : List U8 = StructAtIndex 0 TotallyNotJson.1192; + dec #Derived_gen.7; ret TotallyNotJson.1193; procedure TotallyNotJson.60 (): @@ -765,7 +765,7 @@ procedure TotallyNotJson.69 (): let TotallyNotJson.1247 : List U8 = CallByName TotallyNotJson.68 TotallyNotJson.1248 TotallyNotJson.1249 TotallyNotJson.1250 TotallyNotJson.1251; ret TotallyNotJson.1247; -procedure TotallyNotJson.70 (TotallyNotJson.1468): +procedure TotallyNotJson.70 (#Derived_gen.5): joinpoint TotallyNotJson.1198 TotallyNotJson.1166: let TotallyNotJson.600 : List U8 = StructAtIndex 0 TotallyNotJson.1166; inc 4 TotallyNotJson.600; @@ -866,4 +866,4 @@ procedure TotallyNotJson.70 (TotallyNotJson.1468): let TotallyNotJson.1276 : {List U8, List U8} = Struct {TotallyNotJson.600, TotallyNotJson.601}; ret TotallyNotJson.1276; in - jump TotallyNotJson.1198 TotallyNotJson.1468; + jump TotallyNotJson.1198 #Derived_gen.5; diff --git a/crates/compiler/test_mono/generated/layout_cache_structure_with_multiple_recursive_structures.txt b/crates/compiler/test_mono/generated/layout_cache_structure_with_multiple_recursive_structures.txt index 96ce04fefab..d94a1b57be2 100644 --- a/crates/compiler/test_mono/generated/layout_cache_structure_with_multiple_recursive_structures.txt +++ b/crates/compiler/test_mono/generated/layout_cache_structure_with_multiple_recursive_structures.txt @@ -14,7 +14,7 @@ procedure List.66 (#Attr.2, #Attr.3): let List.537 : [C *self, ] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.537; -procedure List.80 (List.544, List.545, List.546, List.547, List.548): +procedure List.80 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): joinpoint List.527 List.439 List.440 List.441 List.442 List.443: let List.529 : Int1 = CallByName Num.22 List.442 List.443; if List.529 then @@ -28,7 +28,7 @@ procedure List.80 (List.544, List.545, List.546, List.547, List.548): dec List.439; ret List.440; in - jump List.527 List.544 List.545 List.546 List.547 List.548; + jump List.527 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; procedure List.93 (List.436, List.437, List.438): let List.525 : U64 = 0i64; diff --git a/crates/compiler/test_mono/generated/quicksort_help.txt b/crates/compiler/test_mono/generated/quicksort_help.txt index 9afb51dda4f..8f8eb676946 100644 --- a/crates/compiler/test_mono/generated/quicksort_help.txt +++ b/crates/compiler/test_mono/generated/quicksort_help.txt @@ -10,7 +10,7 @@ procedure Num.22 (#Attr.2, #Attr.3): let Num.294 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; ret Num.294; -procedure Test.1 (Test.24, Test.25, Test.26): +procedure Test.1 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): joinpoint Test.12 Test.2 Test.3 Test.4: let Test.14 : Int1 = CallByName Num.22 Test.3 Test.4; if Test.14 then @@ -29,7 +29,7 @@ procedure Test.1 (Test.24, Test.25, Test.26): else ret Test.2; in - jump Test.12 Test.24 Test.25 Test.26; + jump Test.12 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2; procedure Test.0 (): let Test.9 : List I64 = Array []; diff --git a/crates/compiler/test_mono/generated/rb_tree_fbip.txt b/crates/compiler/test_mono/generated/rb_tree_fbip.txt index 5a6b8aed152..58b1e0a37fe 100644 --- a/crates/compiler/test_mono/generated/rb_tree_fbip.txt +++ b/crates/compiler/test_mono/generated/rb_tree_fbip.txt @@ -6,415 +6,450 @@ procedure Num.24 (#Attr.2, #Attr.3): let Num.293 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; ret Num.293; -procedure Test.3 (Test.9, Test.10, Test.11): - let Test.254 : U8 = 0i64; - let Test.255 : U8 = GetTagId Test.9; - let Test.256 : Int1 = lowlevel Eq Test.254 Test.255; - if Test.256 then - let Test.113 : [C *self I64 *self I32 Int1, ] = TagId(0) ; - let Test.114 : [C *self I64 *self I32 Int1, ] = TagId(0) ; - let Test.112 : Int1 = true; - let Test.111 : [C *self I64 *self I32 Int1, ] = TagId(1) Test.113 Test.11 Test.114 Test.10 Test.112; - ret Test.111; - else - let Test.251 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.9; - let Test.252 : Int1 = false; - let Test.253 : Int1 = lowlevel Eq Test.252 Test.251; - if Test.253 then - let Test.16 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.9; - let Test.18 : I64 = UnionAtIndex (Id 1) (Index 1) Test.9; - let Test.19 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.9; - let Test.17 : I32 = UnionAtIndex (Id 1) (Index 3) Test.9; - joinpoint #Derived_gen.72 #Derived_gen.77: - let Test.179 : Int1 = CallByName Num.22 Test.10 Test.17; - if Test.179 then - joinpoint Test.238 #Derived_gen.139: - let Test.233 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.16 Test.10 Test.11; - let Test.232 : Int1 = false; - let Test.231 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.139 UpdateModeId { id: 56 } TagId(1) Test.233 Test.18 Test.19 Test.17 Test.232; - ret Test.231; - in - let Test.236 : U8 = 1i64; - let Test.237 : U8 = GetTagId Test.16; - let Test.240 : Int1 = lowlevel Eq Test.236 Test.237; - if Test.240 then - let Test.234 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.16; - let Test.235 : Int1 = true; - let Test.239 : Int1 = lowlevel Eq Test.235 Test.234; - if Test.239 then - let Test.180 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.16 Test.10 Test.11; - joinpoint Test.199 #Derived_gen.166: - let Test.198 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.20 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.198; - inc Test.20; - let Test.22 : I64 = UnionAtIndex (Id 1) (Index 1) Test.198; - let Test.23 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.198; - inc Test.23; - let Test.21 : I32 = UnionAtIndex (Id 1) (Index 3) Test.198; - let Test.25 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; - let Test.26 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; - let Test.24 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; - joinpoint #Derived_gen.30 #Derived_gen.169 #Derived_gen.170 #Derived_gen.171: - let Test.186 : Int1 = false; - let Test.183 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.171 UpdateModeId { id: 85 } TagId(1) Test.20 Test.22 Test.23 Test.21 Test.186; - let Test.185 : Int1 = false; - let Test.184 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.170 UpdateModeId { id: 84 } TagId(1) Test.26 Test.18 Test.19 Test.17 Test.185; - let Test.182 : Int1 = true; - let Test.181 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.169 UpdateModeId { id: 83 } TagId(1) Test.183 Test.25 Test.184 Test.24 Test.182; - ret Test.181; - in - let #Derived_gen.31 : Int1 = lowlevel RefCountIsUnique Test.180; - if #Derived_gen.31 then - let #Derived_gen.172 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.198, id: UpdateModeId { id: 86 } }; - let #Derived_gen.173 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 87 } }; - jump #Derived_gen.30 #Derived_gen.166 #Derived_gen.172 #Derived_gen.173; - else - inc Test.26; - decref Test.180; - let #Derived_gen.174 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.30 #Derived_gen.174 #Derived_gen.174 #Derived_gen.166; - in - let Test.228 : U8 = 1i64; - let Test.229 : U8 = GetTagId Test.180; - let Test.230 : Int1 = lowlevel Eq Test.228 Test.229; - if Test.230 then - joinpoint Test.225 #Derived_gen.184: - joinpoint Test.216 #Derived_gen.185: - let Test.46 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.48 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; - let Test.49 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; - let Test.47 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; - joinpoint #Derived_gen.24 #Derived_gen.187 #Derived_gen.188: - let Test.196 : Int1 = true; - let Test.195 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.188 UpdateModeId { id: 100 } TagId(1) Test.46 Test.48 Test.49 Test.47 Test.196; - let Test.194 : Int1 = false; - let Test.193 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.187 UpdateModeId { id: 99 } TagId(1) Test.195 Test.18 Test.19 Test.17 Test.194; - ret Test.193; - in - let #Derived_gen.25 : Int1 = lowlevel RefCountIsUnique Test.180; - if #Derived_gen.25 then - let #Derived_gen.189 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 101 } }; - jump #Derived_gen.24 #Derived_gen.185 #Derived_gen.189; - else - inc Test.46; - inc Test.49; - decref Test.180; - let #Derived_gen.190 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.24 #Derived_gen.190 #Derived_gen.185; +procedure Test.3 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): + let #Derived_gen.4 : [C *self I64 *self I32 Int1, ] = NullPointer; + let #Derived_gen.3 : Ptr([C *self I64 *self I32 Int1, ]) = lowlevel PtrToStackValue #Derived_gen.4; + joinpoint #Derived_gen.5 Test.9 Test.10 Test.11 #Derived_gen.6: + let Test.254 : U8 = 0i64; + let Test.255 : U8 = GetTagId Test.9; + let Test.256 : Int1 = lowlevel Eq Test.254 Test.255; + if Test.256 then + let Test.113 : [C *self I64 *self I32 Int1, ] = TagId(0) ; + let Test.114 : [C *self I64 *self I32 Int1, ] = TagId(0) ; + let Test.112 : Int1 = true; + let Test.111 : [C *self I64 *self I32 Int1, ] = TagId(1) Test.113 Test.11 Test.114 Test.10 Test.112; + let #Derived_gen.8 : {} = lowlevel PtrStore #Derived_gen.6 Test.111; + let #Derived_gen.7 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; + ret #Derived_gen.7; + else + let Test.251 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.9; + let Test.252 : Int1 = false; + let Test.253 : Int1 = lowlevel Eq Test.252 Test.251; + if Test.253 then + let Test.16 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.9; + let Test.18 : I64 = UnionAtIndex (Id 1) (Index 1) Test.9; + let Test.19 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.9; + let Test.17 : I32 = UnionAtIndex (Id 1) (Index 3) Test.9; + joinpoint #Derived_gen.109 #Derived_gen.114: + let Test.179 : Int1 = CallByName Num.22 Test.10 Test.17; + if Test.179 then + joinpoint Test.238 #Derived_gen.176: + let Test.233 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.16 Test.10 Test.11; + let Test.232 : Int1 = false; + let Test.231 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.176 UpdateModeId { id: 56 } TagId(1) Test.233 Test.18 Test.19 Test.17 Test.232; + let #Derived_gen.10 : {} = lowlevel PtrStore #Derived_gen.6 Test.231; + let #Derived_gen.9 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; + ret #Derived_gen.9; + in + let Test.236 : U8 = 1i64; + let Test.237 : U8 = GetTagId Test.16; + let Test.240 : Int1 = lowlevel Eq Test.236 Test.237; + if Test.240 then + let Test.234 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.16; + let Test.235 : Int1 = true; + let Test.239 : Int1 = lowlevel Eq Test.235 Test.234; + if Test.239 then + let Test.180 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.16 Test.10 Test.11; + joinpoint Test.199 #Derived_gen.203: + let Test.198 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.20 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.198; + inc Test.20; + let Test.22 : I64 = UnionAtIndex (Id 1) (Index 1) Test.198; + let Test.23 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.198; + inc Test.23; + let Test.21 : I32 = UnionAtIndex (Id 1) (Index 3) Test.198; + let Test.25 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; + let Test.26 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; + let Test.24 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; + joinpoint #Derived_gen.67 #Derived_gen.206 #Derived_gen.207 #Derived_gen.208: + let Test.186 : Int1 = false; + let Test.183 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.208 UpdateModeId { id: 85 } TagId(1) Test.20 Test.22 Test.23 Test.21 Test.186; + let Test.185 : Int1 = false; + let Test.184 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.207 UpdateModeId { id: 84 } TagId(1) Test.26 Test.18 Test.19 Test.17 Test.185; + let Test.182 : Int1 = true; + let Test.181 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.206 UpdateModeId { id: 83 } TagId(1) Test.183 Test.25 Test.184 Test.24 Test.182; + let #Derived_gen.12 : {} = lowlevel PtrStore #Derived_gen.6 Test.181; + let #Derived_gen.11 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; + ret #Derived_gen.11; in - let Test.213 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.214 : U8 = 1i64; - let Test.215 : U8 = GetTagId Test.213; - let Test.218 : Int1 = lowlevel Eq Test.214 Test.215; - if Test.218 then - let Test.210 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.211 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.210; - let Test.212 : Int1 = true; - let Test.217 : Int1 = lowlevel Eq Test.212 Test.211; - if Test.217 then - jump Test.199 #Derived_gen.184; - else - jump Test.216 #Derived_gen.184; + let #Derived_gen.68 : Int1 = lowlevel RefCountIsUnique Test.180; + if #Derived_gen.68 then + let #Derived_gen.209 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.198, id: UpdateModeId { id: 86 } }; + let #Derived_gen.210 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 87 } }; + jump #Derived_gen.67 #Derived_gen.203 #Derived_gen.209 #Derived_gen.210; else - jump Test.216 #Derived_gen.184; + inc Test.26; + decref Test.180; + let #Derived_gen.211 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.67 #Derived_gen.211 #Derived_gen.211 #Derived_gen.203; in - let Test.222 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; - let Test.223 : U8 = 1i64; - let Test.224 : U8 = GetTagId Test.222; - let Test.227 : Int1 = lowlevel Eq Test.223 Test.224; - if Test.227 then - let Test.219 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; - let Test.220 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.219; - let Test.221 : Int1 = true; - let Test.226 : Int1 = lowlevel Eq Test.221 Test.220; - if Test.226 then - joinpoint Test.207 #Derived_gen.191: - let Test.33 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.35 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; - let Test.200 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; - let Test.36 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.200; - inc Test.36; - let Test.38 : I64 = UnionAtIndex (Id 1) (Index 1) Test.200; - let Test.39 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.200; - inc Test.39; - let Test.37 : I32 = UnionAtIndex (Id 1) (Index 3) Test.200; - let Test.34 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; - joinpoint #Derived_gen.28 #Derived_gen.194 #Derived_gen.195 #Derived_gen.196: - let Test.192 : Int1 = false; - let Test.189 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.196 UpdateModeId { id: 107 } TagId(1) Test.33 Test.35 Test.36 Test.34 Test.192; - let Test.191 : Int1 = false; - let Test.190 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.195 UpdateModeId { id: 106 } TagId(1) Test.39 Test.18 Test.19 Test.17 Test.191; - let Test.188 : Int1 = true; - let Test.187 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.194 UpdateModeId { id: 105 } TagId(1) Test.189 Test.38 Test.190 Test.37 Test.188; - ret Test.187; + let Test.228 : U8 = 1i64; + let Test.229 : U8 = GetTagId Test.180; + let Test.230 : Int1 = lowlevel Eq Test.228 Test.229; + if Test.230 then + joinpoint Test.225 #Derived_gen.221: + joinpoint Test.216 #Derived_gen.222: + let Test.46 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.48 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; + let Test.49 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; + let Test.47 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; + joinpoint #Derived_gen.61 #Derived_gen.224 #Derived_gen.225: + let Test.196 : Int1 = true; + let Test.195 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.225 UpdateModeId { id: 100 } TagId(1) Test.46 Test.48 Test.49 Test.47 Test.196; + let Test.194 : Int1 = false; + let Test.193 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.224 UpdateModeId { id: 99 } TagId(1) Test.195 Test.18 Test.19 Test.17 Test.194; + let #Derived_gen.14 : {} = lowlevel PtrStore #Derived_gen.6 Test.193; + let #Derived_gen.13 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; + ret #Derived_gen.13; in - let #Derived_gen.29 : Int1 = lowlevel RefCountIsUnique Test.180; - if #Derived_gen.29 then - let #Derived_gen.197 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.200, id: UpdateModeId { id: 108 } }; - let #Derived_gen.198 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 109 } }; - jump #Derived_gen.28 #Derived_gen.191 #Derived_gen.197 #Derived_gen.198; + let #Derived_gen.62 : Int1 = lowlevel RefCountIsUnique Test.180; + if #Derived_gen.62 then + let #Derived_gen.226 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 101 } }; + jump #Derived_gen.61 #Derived_gen.222 #Derived_gen.226; else - inc Test.33; + inc Test.46; + inc Test.49; decref Test.180; - let #Derived_gen.199 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.28 #Derived_gen.199 #Derived_gen.199 #Derived_gen.191; + let #Derived_gen.227 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.61 #Derived_gen.227 #Derived_gen.222; in - let Test.204 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.205 : U8 = 1i64; - let Test.206 : U8 = GetTagId Test.204; - let Test.209 : Int1 = lowlevel Eq Test.205 Test.206; - if Test.209 then - let Test.201 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.202 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.201; - let Test.203 : Int1 = true; - let Test.208 : Int1 = lowlevel Eq Test.203 Test.202; - if Test.208 then - jump Test.199 #Derived_gen.77; + let Test.213 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.214 : U8 = 1i64; + let Test.215 : U8 = GetTagId Test.213; + let Test.218 : Int1 = lowlevel Eq Test.214 Test.215; + if Test.218 then + let Test.210 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.211 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.210; + let Test.212 : Int1 = true; + let Test.217 : Int1 = lowlevel Eq Test.212 Test.211; + if Test.217 then + jump Test.199 #Derived_gen.221; + else + jump Test.216 #Derived_gen.221; + else + jump Test.216 #Derived_gen.221; + in + let Test.222 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; + let Test.223 : U8 = 1i64; + let Test.224 : U8 = GetTagId Test.222; + let Test.227 : Int1 = lowlevel Eq Test.223 Test.224; + if Test.227 then + let Test.219 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; + let Test.220 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.219; + let Test.221 : Int1 = true; + let Test.226 : Int1 = lowlevel Eq Test.221 Test.220; + if Test.226 then + joinpoint Test.207 #Derived_gen.228: + let Test.33 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.35 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; + let Test.200 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; + let Test.36 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.200; + inc Test.36; + let Test.38 : I64 = UnionAtIndex (Id 1) (Index 1) Test.200; + let Test.39 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.200; + inc Test.39; + let Test.37 : I32 = UnionAtIndex (Id 1) (Index 3) Test.200; + let Test.34 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; + joinpoint #Derived_gen.65 #Derived_gen.231 #Derived_gen.232 #Derived_gen.233: + let Test.192 : Int1 = false; + let Test.189 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.233 UpdateModeId { id: 107 } TagId(1) Test.33 Test.35 Test.36 Test.34 Test.192; + let Test.191 : Int1 = false; + let Test.190 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.232 UpdateModeId { id: 106 } TagId(1) Test.39 Test.18 Test.19 Test.17 Test.191; + let Test.188 : Int1 = true; + let Test.187 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.231 UpdateModeId { id: 105 } TagId(1) Test.189 Test.38 Test.190 Test.37 Test.188; + let #Derived_gen.16 : {} = lowlevel PtrStore #Derived_gen.6 Test.187; + let #Derived_gen.15 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; + ret #Derived_gen.15; + in + let #Derived_gen.66 : Int1 = lowlevel RefCountIsUnique Test.180; + if #Derived_gen.66 then + let #Derived_gen.234 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.200, id: UpdateModeId { id: 108 } }; + let #Derived_gen.235 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 109 } }; + jump #Derived_gen.65 #Derived_gen.228 #Derived_gen.234 #Derived_gen.235; + else + inc Test.33; + decref Test.180; + let #Derived_gen.236 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.65 #Derived_gen.236 #Derived_gen.236 #Derived_gen.228; + in + let Test.204 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.205 : U8 = 1i64; + let Test.206 : U8 = GetTagId Test.204; + let Test.209 : Int1 = lowlevel Eq Test.205 Test.206; + if Test.209 then + let Test.201 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.202 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.201; + let Test.203 : Int1 = true; + let Test.208 : Int1 = lowlevel Eq Test.203 Test.202; + if Test.208 then + jump Test.199 #Derived_gen.114; + else + jump Test.207 #Derived_gen.114; else - jump Test.207 #Derived_gen.77; + jump Test.207 #Derived_gen.114; else - jump Test.207 #Derived_gen.77; + jump Test.225 #Derived_gen.114; else - jump Test.225 #Derived_gen.77; + jump Test.225 #Derived_gen.114; else - jump Test.225 #Derived_gen.77; + decref #Derived_gen.114; + dec Test.19; + let Test.197 : [C *self I64 *self I32 Int1, ] = TagId(0) ; + let #Derived_gen.18 : {} = lowlevel PtrStore #Derived_gen.6 Test.197; + let #Derived_gen.17 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; + ret #Derived_gen.17; else - decref #Derived_gen.77; - dec Test.19; - let Test.197 : [C *self I64 *self I32 Int1, ] = TagId(0) ; - ret Test.197; + jump Test.238 #Derived_gen.114; else - jump Test.238 #Derived_gen.77; + jump Test.238 #Derived_gen.114; else - jump Test.238 #Derived_gen.77; - else - let Test.117 : Int1 = CallByName Num.24 Test.10 Test.17; - if Test.117 then - joinpoint Test.176 #Derived_gen.291: - let Test.171 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.19 Test.10 Test.11; - let Test.170 : Int1 = false; - let Test.169 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.291 UpdateModeId { id: 196 } TagId(1) Test.16 Test.18 Test.171 Test.17 Test.170; - ret Test.169; - in - let Test.174 : U8 = 1i64; - let Test.175 : U8 = GetTagId Test.19; - let Test.178 : Int1 = lowlevel Eq Test.174 Test.175; - if Test.178 then - let Test.172 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.19; - let Test.173 : Int1 = true; - let Test.177 : Int1 = lowlevel Eq Test.173 Test.172; - if Test.177 then - inc Test.19; - let #Derived_gen.292 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.16, id: UpdateModeId { id: 197 } }; - let Test.118 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.19 Test.10 Test.11; - joinpoint Test.137 #Derived_gen.332 #Derived_gen.333: - let Test.136 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.57 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.136; - inc Test.57; - let Test.59 : I64 = UnionAtIndex (Id 1) (Index 1) Test.136; - let Test.60 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.136; - inc Test.60; - let Test.58 : I32 = UnionAtIndex (Id 1) (Index 3) Test.136; - let Test.62 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; - let Test.63 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; - let Test.61 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; - joinpoint #Derived_gen.70 #Derived_gen.337 #Derived_gen.338 #Derived_gen.339: - let Test.124 : Int1 = false; - let Test.121 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.339 UpdateModeId { id: 242 } TagId(1) Test.57 Test.59 Test.60 Test.58 Test.124; - let Test.123 : Int1 = false; - let Test.122 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.338 UpdateModeId { id: 241 } TagId(1) Test.63 Test.18 Test.19 Test.17 Test.123; - let Test.120 : Int1 = true; - let Test.119 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.337 UpdateModeId { id: 240 } TagId(1) Test.121 Test.62 Test.122 Test.61 Test.120; - ret Test.119; - in - let #Derived_gen.71 : Int1 = lowlevel RefCountIsUnique Test.118; - if #Derived_gen.71 then - decref #Derived_gen.332; - let #Derived_gen.340 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.136, id: UpdateModeId { id: 243 } }; - let #Derived_gen.341 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 244 } }; - jump #Derived_gen.70 #Derived_gen.333 #Derived_gen.340 #Derived_gen.341; - else - inc Test.63; - decref Test.118; - let #Derived_gen.342 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.70 #Derived_gen.342 #Derived_gen.332 #Derived_gen.333; - in - let Test.166 : U8 = 1i64; - let Test.167 : U8 = GetTagId Test.118; - let Test.168 : Int1 = lowlevel Eq Test.166 Test.167; - if Test.168 then - joinpoint Test.163 #Derived_gen.354 #Derived_gen.355: - joinpoint Test.154 #Derived_gen.356 #Derived_gen.357: - let Test.83 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.85 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; - let Test.86 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; - let Test.84 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; - joinpoint #Derived_gen.60 #Derived_gen.360 #Derived_gen.361: - let Test.134 : Int1 = true; - let Test.133 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.361 UpdateModeId { id: 262 } TagId(1) Test.83 Test.85 Test.86 Test.84 Test.134; - let Test.132 : Int1 = false; - let Test.131 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.360 UpdateModeId { id: 261 } TagId(1) Test.133 Test.18 Test.19 Test.17 Test.132; - ret Test.131; - in - let #Derived_gen.61 : Int1 = lowlevel RefCountIsUnique Test.118; - if #Derived_gen.61 then - decref #Derived_gen.356; - let #Derived_gen.362 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 263 } }; - jump #Derived_gen.60 #Derived_gen.357 #Derived_gen.362; - else - inc Test.83; - inc Test.86; - decref Test.118; - jump #Derived_gen.60 #Derived_gen.356 #Derived_gen.357; + let Test.117 : Int1 = CallByName Num.24 Test.10 Test.17; + if Test.117 then + joinpoint Test.176 #Derived_gen.328: + let Test.171 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.19 Test.10 Test.11; + let Test.170 : Int1 = false; + let Test.169 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.328 UpdateModeId { id: 196 } TagId(1) Test.16 Test.18 Test.171 Test.17 Test.170; + let #Derived_gen.20 : {} = lowlevel PtrStore #Derived_gen.6 Test.169; + let #Derived_gen.19 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; + ret #Derived_gen.19; + in + let Test.174 : U8 = 1i64; + let Test.175 : U8 = GetTagId Test.19; + let Test.178 : Int1 = lowlevel Eq Test.174 Test.175; + if Test.178 then + let Test.172 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.19; + let Test.173 : Int1 = true; + let Test.177 : Int1 = lowlevel Eq Test.173 Test.172; + if Test.177 then + inc Test.19; + let #Derived_gen.329 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.16, id: UpdateModeId { id: 197 } }; + let Test.118 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.19 Test.10 Test.11; + joinpoint Test.137 #Derived_gen.369 #Derived_gen.370: + let Test.136 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.57 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.136; + inc Test.57; + let Test.59 : I64 = UnionAtIndex (Id 1) (Index 1) Test.136; + let Test.60 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.136; + inc Test.60; + let Test.58 : I32 = UnionAtIndex (Id 1) (Index 3) Test.136; + let Test.62 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; + let Test.63 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; + let Test.61 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; + joinpoint #Derived_gen.107 #Derived_gen.374 #Derived_gen.375 #Derived_gen.376: + let Test.124 : Int1 = false; + let Test.121 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.376 UpdateModeId { id: 242 } TagId(1) Test.57 Test.59 Test.60 Test.58 Test.124; + let Test.123 : Int1 = false; + let Test.122 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.375 UpdateModeId { id: 241 } TagId(1) Test.63 Test.18 Test.19 Test.17 Test.123; + let Test.120 : Int1 = true; + let Test.119 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.374 UpdateModeId { id: 240 } TagId(1) Test.121 Test.62 Test.122 Test.61 Test.120; + let #Derived_gen.22 : {} = lowlevel PtrStore #Derived_gen.6 Test.119; + let #Derived_gen.21 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; + ret #Derived_gen.21; in - let Test.151 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.152 : U8 = 1i64; - let Test.153 : U8 = GetTagId Test.151; - let Test.156 : Int1 = lowlevel Eq Test.152 Test.153; - if Test.156 then - let Test.148 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.149 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.148; - let Test.150 : Int1 = true; - let Test.155 : Int1 = lowlevel Eq Test.150 Test.149; - if Test.155 then - jump Test.137 #Derived_gen.354 #Derived_gen.355; - else - jump Test.154 #Derived_gen.354 #Derived_gen.355; + let #Derived_gen.108 : Int1 = lowlevel RefCountIsUnique Test.118; + if #Derived_gen.108 then + decref #Derived_gen.369; + let #Derived_gen.377 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.136, id: UpdateModeId { id: 243 } }; + let #Derived_gen.378 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 244 } }; + jump #Derived_gen.107 #Derived_gen.370 #Derived_gen.377 #Derived_gen.378; else - jump Test.154 #Derived_gen.354 #Derived_gen.355; + inc Test.63; + decref Test.118; + let #Derived_gen.379 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.107 #Derived_gen.379 #Derived_gen.369 #Derived_gen.370; in - let Test.160 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; - let Test.161 : U8 = 1i64; - let Test.162 : U8 = GetTagId Test.160; - let Test.165 : Int1 = lowlevel Eq Test.161 Test.162; - if Test.165 then - let Test.157 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; - let Test.158 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.157; - let Test.159 : Int1 = true; - let Test.164 : Int1 = lowlevel Eq Test.159 Test.158; - if Test.164 then - joinpoint Test.145 #Derived_gen.363 #Derived_gen.364: - let Test.70 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.72 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; - let Test.138 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; - let Test.73 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.138; - inc Test.73; - let Test.75 : I64 = UnionAtIndex (Id 1) (Index 1) Test.138; - let Test.76 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.138; - inc Test.76; - let Test.74 : I32 = UnionAtIndex (Id 1) (Index 3) Test.138; - let Test.71 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; - joinpoint #Derived_gen.64 #Derived_gen.368 #Derived_gen.369 #Derived_gen.370: - let Test.130 : Int1 = false; - let Test.127 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.370 UpdateModeId { id: 271 } TagId(1) Test.70 Test.72 Test.73 Test.71 Test.130; - let Test.129 : Int1 = false; - let Test.128 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.369 UpdateModeId { id: 270 } TagId(1) Test.76 Test.18 Test.19 Test.17 Test.129; - let Test.126 : Int1 = true; - let Test.125 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.368 UpdateModeId { id: 269 } TagId(1) Test.127 Test.75 Test.128 Test.74 Test.126; - ret Test.125; + let Test.166 : U8 = 1i64; + let Test.167 : U8 = GetTagId Test.118; + let Test.168 : Int1 = lowlevel Eq Test.166 Test.167; + if Test.168 then + joinpoint Test.163 #Derived_gen.391 #Derived_gen.392: + joinpoint Test.154 #Derived_gen.393 #Derived_gen.394: + let Test.83 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.85 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; + let Test.86 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; + let Test.84 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; + joinpoint #Derived_gen.97 #Derived_gen.397 #Derived_gen.398: + let Test.134 : Int1 = true; + let Test.133 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.398 UpdateModeId { id: 262 } TagId(1) Test.83 Test.85 Test.86 Test.84 Test.134; + let Test.132 : Int1 = false; + let Test.131 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.397 UpdateModeId { id: 261 } TagId(1) Test.133 Test.18 Test.19 Test.17 Test.132; + let #Derived_gen.24 : {} = lowlevel PtrStore #Derived_gen.6 Test.131; + let #Derived_gen.23 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; + ret #Derived_gen.23; in - let #Derived_gen.65 : Int1 = lowlevel RefCountIsUnique Test.118; - if #Derived_gen.65 then - decref #Derived_gen.363; - let #Derived_gen.371 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.138, id: UpdateModeId { id: 272 } }; - let #Derived_gen.372 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 273 } }; - jump #Derived_gen.64 #Derived_gen.364 #Derived_gen.371 #Derived_gen.372; + let #Derived_gen.98 : Int1 = lowlevel RefCountIsUnique Test.118; + if #Derived_gen.98 then + decref #Derived_gen.393; + let #Derived_gen.399 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 263 } }; + jump #Derived_gen.97 #Derived_gen.394 #Derived_gen.399; else - inc Test.70; + inc Test.83; + inc Test.86; decref Test.118; - let #Derived_gen.373 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.64 #Derived_gen.373 #Derived_gen.363 #Derived_gen.364; + jump #Derived_gen.97 #Derived_gen.393 #Derived_gen.394; in - let Test.142 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.143 : U8 = 1i64; - let Test.144 : U8 = GetTagId Test.142; - let Test.147 : Int1 = lowlevel Eq Test.143 Test.144; - if Test.147 then - let Test.139 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.140 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.139; - let Test.141 : Int1 = true; - let Test.146 : Int1 = lowlevel Eq Test.141 Test.140; - if Test.146 then - jump Test.137 #Derived_gen.77 #Derived_gen.292; + let Test.151 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.152 : U8 = 1i64; + let Test.153 : U8 = GetTagId Test.151; + let Test.156 : Int1 = lowlevel Eq Test.152 Test.153; + if Test.156 then + let Test.148 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.149 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.148; + let Test.150 : Int1 = true; + let Test.155 : Int1 = lowlevel Eq Test.150 Test.149; + if Test.155 then + jump Test.137 #Derived_gen.391 #Derived_gen.392; + else + jump Test.154 #Derived_gen.391 #Derived_gen.392; + else + jump Test.154 #Derived_gen.391 #Derived_gen.392; + in + let Test.160 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; + let Test.161 : U8 = 1i64; + let Test.162 : U8 = GetTagId Test.160; + let Test.165 : Int1 = lowlevel Eq Test.161 Test.162; + if Test.165 then + let Test.157 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; + let Test.158 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.157; + let Test.159 : Int1 = true; + let Test.164 : Int1 = lowlevel Eq Test.159 Test.158; + if Test.164 then + joinpoint Test.145 #Derived_gen.400 #Derived_gen.401: + let Test.70 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.72 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; + let Test.138 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; + let Test.73 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.138; + inc Test.73; + let Test.75 : I64 = UnionAtIndex (Id 1) (Index 1) Test.138; + let Test.76 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.138; + inc Test.76; + let Test.74 : I32 = UnionAtIndex (Id 1) (Index 3) Test.138; + let Test.71 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; + joinpoint #Derived_gen.101 #Derived_gen.405 #Derived_gen.406 #Derived_gen.407: + let Test.130 : Int1 = false; + let Test.127 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.407 UpdateModeId { id: 271 } TagId(1) Test.70 Test.72 Test.73 Test.71 Test.130; + let Test.129 : Int1 = false; + let Test.128 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.406 UpdateModeId { id: 270 } TagId(1) Test.76 Test.18 Test.19 Test.17 Test.129; + let Test.126 : Int1 = true; + let Test.125 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.405 UpdateModeId { id: 269 } TagId(1) Test.127 Test.75 Test.128 Test.74 Test.126; + let #Derived_gen.26 : {} = lowlevel PtrStore #Derived_gen.6 Test.125; + let #Derived_gen.25 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; + ret #Derived_gen.25; + in + let #Derived_gen.102 : Int1 = lowlevel RefCountIsUnique Test.118; + if #Derived_gen.102 then + decref #Derived_gen.400; + let #Derived_gen.408 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.138, id: UpdateModeId { id: 272 } }; + let #Derived_gen.409 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 273 } }; + jump #Derived_gen.101 #Derived_gen.401 #Derived_gen.408 #Derived_gen.409; + else + inc Test.70; + decref Test.118; + let #Derived_gen.410 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.101 #Derived_gen.410 #Derived_gen.400 #Derived_gen.401; + in + let Test.142 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.143 : U8 = 1i64; + let Test.144 : U8 = GetTagId Test.142; + let Test.147 : Int1 = lowlevel Eq Test.143 Test.144; + if Test.147 then + let Test.139 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.140 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.139; + let Test.141 : Int1 = true; + let Test.146 : Int1 = lowlevel Eq Test.141 Test.140; + if Test.146 then + jump Test.137 #Derived_gen.114 #Derived_gen.329; + else + jump Test.145 #Derived_gen.114 #Derived_gen.329; else - jump Test.145 #Derived_gen.77 #Derived_gen.292; + jump Test.145 #Derived_gen.114 #Derived_gen.329; else - jump Test.145 #Derived_gen.77 #Derived_gen.292; + jump Test.163 #Derived_gen.114 #Derived_gen.329; else - jump Test.163 #Derived_gen.77 #Derived_gen.292; + jump Test.163 #Derived_gen.114 #Derived_gen.329; else - jump Test.163 #Derived_gen.77 #Derived_gen.292; + decref #Derived_gen.329; + decref #Derived_gen.114; + joinpoint #Derived_gen.103: + let Test.135 : [C *self I64 *self I32 Int1, ] = TagId(0) ; + let #Derived_gen.28 : {} = lowlevel PtrStore #Derived_gen.6 Test.135; + let #Derived_gen.27 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; + ret #Derived_gen.27; + in + let #Derived_gen.106 : Int1 = lowlevel RefCountIsUnique Test.19; + if #Derived_gen.106 then + let #Derived_gen.105 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.19; + dec #Derived_gen.105; + let #Derived_gen.104 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.19; + dec #Derived_gen.104; + decref Test.19; + jump #Derived_gen.103; + else + decref Test.19; + jump #Derived_gen.103; else - decref #Derived_gen.292; - decref #Derived_gen.77; - joinpoint #Derived_gen.66: - let Test.135 : [C *self I64 *self I32 Int1, ] = TagId(0) ; - ret Test.135; - in - let #Derived_gen.69 : Int1 = lowlevel RefCountIsUnique Test.19; - if #Derived_gen.69 then - let #Derived_gen.68 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.19; - dec #Derived_gen.68; - let #Derived_gen.67 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.19; - dec #Derived_gen.67; - decref Test.19; - jump #Derived_gen.66; - else - decref Test.19; - jump #Derived_gen.66; + jump Test.176 #Derived_gen.114; else - jump Test.176 #Derived_gen.77; + jump Test.176 #Derived_gen.114; else - jump Test.176 #Derived_gen.77; - else - let Test.116 : Int1 = false; - let Test.115 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.77 UpdateModeId { id: 1 } TagId(1) Test.16 Test.11 Test.19 Test.10 Test.116; - ret Test.115; - in - let #Derived_gen.73 : Int1 = lowlevel RefCountIsUnique Test.9; - if #Derived_gen.73 then - let #Derived_gen.382 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.9, id: UpdateModeId { id: 282 } }; - jump #Derived_gen.72 #Derived_gen.382; - else - inc Test.16; - inc Test.19; - decref Test.9; - let #Derived_gen.383 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.72 #Derived_gen.383; - else - let Test.96 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.9; - let Test.98 : I64 = UnionAtIndex (Id 1) (Index 1) Test.9; - let Test.99 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.9; - let Test.97 : I32 = UnionAtIndex (Id 1) (Index 3) Test.9; - joinpoint #Derived_gen.74 #Derived_gen.385: - let Test.247 : Int1 = CallByName Num.22 Test.10 Test.97; - if Test.247 then - let Test.250 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.96 Test.10 Test.11; - let Test.249 : Int1 = true; - let Test.248 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.385 UpdateModeId { id: 284 } TagId(1) Test.250 Test.98 Test.99 Test.97 Test.249; - ret Test.248; + let Test.116 : Int1 = false; + let Test.115 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.114 UpdateModeId { id: 1 } TagId(1) Test.16 Test.11 Test.19 Test.10 Test.116; + let #Derived_gen.30 : {} = lowlevel PtrStore #Derived_gen.6 Test.115; + let #Derived_gen.29 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; + ret #Derived_gen.29; + in + let #Derived_gen.110 : Int1 = lowlevel RefCountIsUnique Test.9; + if #Derived_gen.110 then + let #Derived_gen.419 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.9, id: UpdateModeId { id: 282 } }; + jump #Derived_gen.109 #Derived_gen.419; else - let Test.243 : Int1 = CallByName Num.24 Test.10 Test.97; - if Test.243 then - let Test.246 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.99 Test.10 Test.11; - let Test.245 : Int1 = true; - let Test.244 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.385 UpdateModeId { id: 284 } TagId(1) Test.96 Test.98 Test.246 Test.97 Test.245; - ret Test.244; - else - let Test.242 : Int1 = true; - let Test.241 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.385 UpdateModeId { id: 284 } TagId(1) Test.96 Test.11 Test.99 Test.10 Test.242; - ret Test.241; - in - let #Derived_gen.75 : Int1 = lowlevel RefCountIsUnique Test.9; - if #Derived_gen.75 then - let #Derived_gen.386 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.9, id: UpdateModeId { id: 285 } }; - jump #Derived_gen.74 #Derived_gen.386; + inc Test.16; + inc Test.19; + decref Test.9; + let #Derived_gen.420 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.109 #Derived_gen.420; else - inc Test.96; - inc Test.99; - decref Test.9; - let #Derived_gen.387 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.74 #Derived_gen.387; + let Test.96 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.9; + let Test.98 : I64 = UnionAtIndex (Id 1) (Index 1) Test.9; + let Test.99 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.9; + let Test.97 : I32 = UnionAtIndex (Id 1) (Index 3) Test.9; + joinpoint #Derived_gen.111 #Derived_gen.422: + let Test.247 : Int1 = CallByName Num.22 Test.10 Test.97; + if Test.247 then + let Test.250 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.96 Test.10 Test.11; + let Test.249 : Int1 = true; + let Test.248 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.422 UpdateModeId { id: 284 } TagId(1) Test.250 Test.98 Test.99 Test.97 Test.249; + let #Derived_gen.32 : {} = lowlevel PtrStore #Derived_gen.6 Test.248; + let #Derived_gen.31 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; + ret #Derived_gen.31; + else + let Test.243 : Int1 = CallByName Num.24 Test.10 Test.97; + if Test.243 then + let Test.246 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.99 Test.10 Test.11; + let Test.245 : Int1 = true; + let Test.244 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.422 UpdateModeId { id: 284 } TagId(1) Test.96 Test.98 Test.246 Test.97 Test.245; + let #Derived_gen.34 : {} = lowlevel PtrStore #Derived_gen.6 Test.244; + let #Derived_gen.33 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; + ret #Derived_gen.33; + else + let Test.242 : Int1 = true; + let Test.241 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.422 UpdateModeId { id: 284 } TagId(1) Test.96 Test.11 Test.99 Test.10 Test.242; + let #Derived_gen.36 : {} = lowlevel PtrStore #Derived_gen.6 Test.241; + let #Derived_gen.35 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; + ret #Derived_gen.35; + in + let #Derived_gen.112 : Int1 = lowlevel RefCountIsUnique Test.9; + if #Derived_gen.112 then + let #Derived_gen.423 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.9, id: UpdateModeId { id: 285 } }; + jump #Derived_gen.111 #Derived_gen.423; + else + inc Test.96; + inc Test.99; + decref Test.9; + let #Derived_gen.424 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.111 #Derived_gen.424; + in + jump #Derived_gen.5 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3; procedure Test.0 (): let Test.281 : [C *self I64 *self I32 Int1, ] = TagId(0) ; diff --git a/crates/compiler/test_mono/generated/recursive_call_capturing_function.txt b/crates/compiler/test_mono/generated/recursive_call_capturing_function.txt index 333be0ae754..44abe4f94b7 100644 --- a/crates/compiler/test_mono/generated/recursive_call_capturing_function.txt +++ b/crates/compiler/test_mono/generated/recursive_call_capturing_function.txt @@ -11,7 +11,7 @@ procedure Test.1 (Test.2): let Test.7 : U32 = CallByName Test.3 Test.8 Test.2; ret Test.7; -procedure Test.3 (Test.17, Test.18): +procedure Test.3 (#Derived_gen.0, #Derived_gen.1): joinpoint Test.9 Test.4 Test.2: let Test.13 : Int1 = CallByName Bool.2; if Test.13 then @@ -20,7 +20,7 @@ procedure Test.3 (Test.17, Test.18): let Test.11 : U32 = CallByName Num.19 Test.4 Test.2; jump Test.9 Test.11 Test.2; in - jump Test.9 Test.17 Test.18; + jump Test.9 #Derived_gen.0 #Derived_gen.1; procedure Test.0 (): let Test.6 : U32 = 6i64; diff --git a/crates/compiler/test_mono/generated/recursive_function_and_union_with_inference_hole.txt b/crates/compiler/test_mono/generated/recursive_function_and_union_with_inference_hole.txt index 341384e835f..32b22743616 100644 --- a/crates/compiler/test_mono/generated/recursive_function_and_union_with_inference_hole.txt +++ b/crates/compiler/test_mono/generated/recursive_function_and_union_with_inference_hole.txt @@ -6,10 +6,10 @@ procedure List.5 (#Attr.2, #Attr.3): procedure Test.2 (Test.5): let Test.6 : List [C List *self] = UnionAtIndex (Id 0) (Index 0) Test.5; inc Test.6; - let #Derived_gen.0 : [C List *self] = Reset { symbol: Test.5, id: UpdateModeId { id: 0 } }; + let #Derived_gen.1 : [C List *self] = Reset { symbol: Test.5, id: UpdateModeId { id: 0 } }; let Test.15 : {} = Struct {}; let Test.7 : List [C List *self] = CallByName List.5 Test.6 Test.15; - let Test.14 : [C List *self] = Reuse #Derived_gen.0 UpdateModeId { id: 0 } TagId(0) Test.7; + let Test.14 : [C List *self] = Reuse #Derived_gen.1 UpdateModeId { id: 0 } TagId(0) Test.7; ret Test.14; procedure Test.0 (): diff --git a/crates/compiler/test_mono/generated/recursive_lambda_set_has_nested_non_recursive_lambda_sets_issue_5026.txt b/crates/compiler/test_mono/generated/recursive_lambda_set_has_nested_non_recursive_lambda_sets_issue_5026.txt index 858df4d18a7..3e08cd465da 100644 --- a/crates/compiler/test_mono/generated/recursive_lambda_set_has_nested_non_recursive_lambda_sets_issue_5026.txt +++ b/crates/compiler/test_mono/generated/recursive_lambda_set_has_nested_non_recursive_lambda_sets_issue_5026.txt @@ -26,7 +26,7 @@ procedure Test.3 (Test.7): procedure Test.6 (Test.16, #Attr.12): let Test.5 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12; - joinpoint #Derived_gen.0: + joinpoint #Derived_gen.2: let Test.19 : {} = Struct {}; let Test.22 : Str = "foobar"; let Test.20 : [, C {}] = CallByName Test.8 Test.22 Test.5; @@ -42,13 +42,13 @@ procedure Test.6 (Test.16, #Attr.12): ret Test.18; in - let #Derived_gen.1 : Int1 = lowlevel RefCountIsUnique #Attr.12; - if #Derived_gen.1 then + let #Derived_gen.3 : Int1 = lowlevel RefCountIsUnique #Attr.12; + if #Derived_gen.3 then decref #Attr.12; - jump #Derived_gen.0; + jump #Derived_gen.2; else decref #Attr.12; - jump #Derived_gen.0; + jump #Derived_gen.2; procedure Test.8 (Test.9, Test.7): let Test.24 : [, C {}] = CallByName Test.10 Test.9; diff --git a/crates/compiler/test_mono/generated/recursive_lambda_set_resolved_only_upon_specialization.txt b/crates/compiler/test_mono/generated/recursive_lambda_set_resolved_only_upon_specialization.txt index e46d5fb2253..f053cf0a19c 100644 --- a/crates/compiler/test_mono/generated/recursive_lambda_set_resolved_only_upon_specialization.txt +++ b/crates/compiler/test_mono/generated/recursive_lambda_set_resolved_only_upon_specialization.txt @@ -10,7 +10,7 @@ procedure Num.21 (#Attr.2, #Attr.3): let Num.292 : U8 = lowlevel NumMul #Attr.2 #Attr.3; ret Num.292; -procedure Test.1 (Test.26, Test.27): +procedure Test.1 (#Derived_gen.0, #Derived_gen.1): joinpoint Test.11 Test.2 Test.3: let Test.24 : U8 = 0i64; let Test.20 : Int1 = CallByName Bool.11 Test.2 Test.24; @@ -33,13 +33,13 @@ procedure Test.1 (Test.26, Test.27): let Test.14 : [, C *self U8] = TagId(0) Test.3 Test.2; jump Test.11 Test.13 Test.14; in - jump Test.11 Test.26 Test.27; + jump Test.11 #Derived_gen.0 #Derived_gen.1; -procedure Test.4 (Test.28, Test.29): +procedure Test.4 (#Derived_gen.2, #Derived_gen.3): joinpoint Test.15 Test.5 #Attr.12: let Test.2 : U8 = UnionAtIndex (Id 0) (Index 1) #Attr.12; let Test.3 : [, C *self U8] = UnionAtIndex (Id 0) (Index 0) #Attr.12; - joinpoint #Derived_gen.0: + joinpoint #Derived_gen.4: let Test.17 : U8 = CallByName Num.21 Test.2 Test.5; let Test.18 : U8 = GetTagId Test.3; switch Test.18: @@ -52,16 +52,16 @@ procedure Test.4 (Test.28, Test.29): ret Test.16; in - let #Derived_gen.1 : Int1 = lowlevel RefCountIsUnique #Attr.12; - if #Derived_gen.1 then + let #Derived_gen.5 : Int1 = lowlevel RefCountIsUnique #Attr.12; + if #Derived_gen.5 then decref #Attr.12; - jump #Derived_gen.0; + jump #Derived_gen.4; else inc Test.3; decref #Attr.12; - jump #Derived_gen.0; + jump #Derived_gen.4; in - jump Test.15 Test.28 Test.29; + jump Test.15 #Derived_gen.2 #Derived_gen.3; procedure Test.6 (Test.7): ret Test.7; diff --git a/crates/compiler/test_mono/generated/recursively_build_effect.txt b/crates/compiler/test_mono/generated/recursively_build_effect.txt index 5e4853903c6..72edafead47 100644 --- a/crates/compiler/test_mono/generated/recursively_build_effect.txt +++ b/crates/compiler/test_mono/generated/recursively_build_effect.txt @@ -8,8 +8,8 @@ procedure Str.3 (#Attr.2, #Attr.3): procedure Test.11 (Test.29, #Attr.12): let Test.10 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12; - let #Derived_gen.0 : Int1 = lowlevel RefCountIsUnique #Attr.12; - if #Derived_gen.0 then + let #Derived_gen.9 : Int1 = lowlevel RefCountIsUnique #Attr.12; + if #Derived_gen.9 then decref #Attr.12; ret Test.10; else @@ -19,11 +19,11 @@ procedure Test.11 (Test.29, #Attr.12): procedure Test.11 (Test.29, Test.10): ret Test.10; -procedure Test.14 (Test.62, Test.63): +procedure Test.14 (#Derived_gen.2, #Derived_gen.3): joinpoint Test.37 Test.36 #Attr.12: let Test.12 : {} = UnionAtIndex (Id 1) (Index 1) #Attr.12; let Test.13 : I64 = UnionAtIndex (Id 1) (Index 0) #Attr.12; - joinpoint #Derived_gen.1: + joinpoint #Derived_gen.10: let Test.43 : {} = Struct {}; let Test.42 : {} = CallByName Test.11 Test.43 Test.12; let Test.38 : [C {}, C I64 {}] = CallByName Test.9 Test.42 Test.13; @@ -38,15 +38,15 @@ procedure Test.14 (Test.62, Test.63): jump Test.37 Test.40 Test.38; in - let #Derived_gen.2 : Int1 = lowlevel RefCountIsUnique #Attr.12; - if #Derived_gen.2 then + let #Derived_gen.11 : Int1 = lowlevel RefCountIsUnique #Attr.12; + if #Derived_gen.11 then decref #Attr.12; - jump #Derived_gen.1; + jump #Derived_gen.10; else decref #Attr.12; - jump #Derived_gen.1; + jump #Derived_gen.10; in - jump Test.37 Test.62 Test.63; + jump Test.37 #Derived_gen.2 #Derived_gen.3; procedure Test.2 (): let Test.6 : Str = "Hello"; diff --git a/crates/compiler/test_mono/generated/specialize_after_match.txt b/crates/compiler/test_mono/generated/specialize_after_match.txt index d64d3bbf985..7dd9c9c5eb0 100644 --- a/crates/compiler/test_mono/generated/specialize_after_match.txt +++ b/crates/compiler/test_mono/generated/specialize_after_match.txt @@ -23,7 +23,7 @@ procedure Test.2 (Test.9, Test.10): let Test.29 : U64 = CallByName Test.3 Test.9; ret Test.29; else - joinpoint #Derived_gen.3: + joinpoint #Derived_gen.4: let Test.13 : Str = UnionAtIndex (Id 0) (Index 0) Test.10; let Test.14 : [, C Str *self] = UnionAtIndex (Id 0) (Index 1) Test.10; let Test.33 : U64 = CallByName Test.3 Test.12; @@ -36,15 +36,15 @@ procedure Test.2 (Test.9, Test.10): else ret Test.16; in - let #Derived_gen.4 : Int1 = lowlevel RefCountIsUnique Test.9; - if #Derived_gen.4 then + let #Derived_gen.5 : Int1 = lowlevel RefCountIsUnique Test.9; + if #Derived_gen.5 then dec Test.11; decref Test.9; - jump #Derived_gen.3; + jump #Derived_gen.4; else inc Test.12; decref Test.9; - jump #Derived_gen.3; + jump #Derived_gen.4; procedure Test.3 (Test.17): let Test.26 : U8 = 1i64; @@ -55,22 +55,22 @@ procedure Test.3 (Test.17): ret Test.22; else let Test.18 : [, C Str *self] = UnionAtIndex (Id 0) (Index 1) Test.17; - joinpoint #Derived_gen.0: + joinpoint #Derived_gen.1: let Test.24 : U64 = 1i64; let Test.25 : U64 = CallByName Test.3 Test.18; let Test.23 : U64 = CallByName Num.19 Test.24 Test.25; ret Test.23; in - let #Derived_gen.2 : Int1 = lowlevel RefCountIsUnique Test.17; - if #Derived_gen.2 then - let #Derived_gen.1 : Str = UnionAtIndex (Id 0) (Index 0) Test.17; - dec #Derived_gen.1; + let #Derived_gen.3 : Int1 = lowlevel RefCountIsUnique Test.17; + if #Derived_gen.3 then + let #Derived_gen.2 : Str = UnionAtIndex (Id 0) (Index 0) Test.17; + dec #Derived_gen.2; decref Test.17; - jump #Derived_gen.0; + jump #Derived_gen.1; else inc Test.18; decref Test.17; - jump #Derived_gen.0; + jump #Derived_gen.1; procedure Test.0 (): let Test.5 : [, C Str *self] = TagId(1) ; diff --git a/crates/compiler/test_mono/generated/tail_call_elimination.txt b/crates/compiler/test_mono/generated/tail_call_elimination.txt index ede33bf2bcf..798de03e174 100644 --- a/crates/compiler/test_mono/generated/tail_call_elimination.txt +++ b/crates/compiler/test_mono/generated/tail_call_elimination.txt @@ -6,7 +6,7 @@ procedure Num.20 (#Attr.2, #Attr.3): let Num.293 : I64 = lowlevel NumSub #Attr.2 #Attr.3; ret Num.293; -procedure Test.1 (Test.15, Test.16): +procedure Test.1 (#Derived_gen.0, #Derived_gen.1): joinpoint Test.7 Test.2 Test.3: let Test.13 : I64 = 0i64; let Test.14 : Int1 = lowlevel Eq Test.13 Test.2; @@ -18,7 +18,7 @@ procedure Test.1 (Test.15, Test.16): let Test.11 : I64 = CallByName Num.19 Test.2 Test.3; jump Test.7 Test.10 Test.11; in - jump Test.7 Test.15 Test.16; + jump Test.7 #Derived_gen.0 #Derived_gen.1; procedure Test.0 (): let Test.5 : I64 = 1000000i64; diff --git a/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_does_not_duplicate_identical_concrete_types.txt b/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_does_not_duplicate_identical_concrete_types.txt index 14474338b6e..1bc8990f43f 100644 --- a/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_does_not_duplicate_identical_concrete_types.txt +++ b/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_does_not_duplicate_identical_concrete_types.txt @@ -20,12 +20,12 @@ procedure Encode.24 (Encode.99, Encode.107, Encode.101): ret Encode.111; procedure Encode.24 (Encode.99, Encode.107, Encode.101): - let Encode.118 : List U8 = CallByName TotallyNotJson.264 Encode.99 Encode.101 Encode.107; - ret Encode.118; + let Encode.113 : List U8 = CallByName TotallyNotJson.264 Encode.99 Encode.101 Encode.107; + ret Encode.113; procedure Encode.24 (Encode.99, Encode.107, Encode.101): - let Encode.123 : List U8 = CallByName TotallyNotJson.182 Encode.99 Encode.101 Encode.107; - ret Encode.123; + let Encode.118 : List U8 = CallByName TotallyNotJson.182 Encode.99 Encode.101 Encode.107; + ret Encode.118; procedure Encode.26 (Encode.105, Encode.106): let Encode.109 : List U8 = Array []; @@ -136,23 +136,7 @@ procedure List.8 (#Attr.2, #Attr.3): let List.598 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; ret List.598; -procedure List.80 (List.647, List.648, List.649, List.650, List.651): - joinpoint List.553 List.439 List.440 List.441 List.442 List.443: - let List.555 : Int1 = CallByName Num.22 List.442 List.443; - if List.555 then - let List.562 : Str = CallByName List.66 List.439 List.442; - inc List.562; - let List.556 : {List U8, U64} = CallByName List.145 List.440 List.562 List.441; - let List.559 : U64 = 1i64; - let List.558 : U64 = CallByName Num.19 List.442 List.559; - jump List.553 List.439 List.556 List.441 List.558 List.443; - else - dec List.439; - ret List.440; - in - jump List.553 List.647 List.648 List.649 List.650 List.651; - -procedure List.80 (List.664, List.665, List.666, List.667, List.668): +procedure List.80 (#Derived_gen.11, #Derived_gen.12, #Derived_gen.13, #Derived_gen.14, #Derived_gen.15): joinpoint List.573 List.439 List.440 List.441 List.442 List.443: let List.575 : Int1 = CallByName Num.22 List.442 List.443; if List.575 then @@ -165,9 +149,9 @@ procedure List.80 (List.664, List.665, List.666, List.667, List.668): dec List.439; ret List.440; in - jump List.573 List.664 List.665 List.666 List.667 List.668; + jump List.573 #Derived_gen.11 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14 #Derived_gen.15; -procedure List.80 (List.691, List.692, List.693, List.694, List.695): +procedure List.80 (#Derived_gen.16, #Derived_gen.17, #Derived_gen.18, #Derived_gen.19, #Derived_gen.20): joinpoint List.626 List.439 List.440 List.441 List.442 List.443: let List.628 : Int1 = CallByName Num.22 List.442 List.443; if List.628 then @@ -191,7 +175,23 @@ procedure List.80 (List.691, List.692, List.693, List.694, List.695): let List.627 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; ret List.627; in - jump List.626 List.691 List.692 List.693 List.694 List.695; + jump List.626 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20; + +procedure List.80 (#Derived_gen.6, #Derived_gen.7, #Derived_gen.8, #Derived_gen.9, #Derived_gen.10): + joinpoint List.553 List.439 List.440 List.441 List.442 List.443: + let List.555 : Int1 = CallByName Num.22 List.442 List.443; + if List.555 then + let List.562 : Str = CallByName List.66 List.439 List.442; + inc List.562; + let List.556 : {List U8, U64} = CallByName List.145 List.440 List.562 List.441; + let List.559 : U64 = 1i64; + let List.558 : U64 = CallByName Num.19 List.442 List.559; + jump List.553 List.439 List.556 List.441 List.558 List.443; + else + dec List.439; + ret List.440; + in + jump List.553 #Derived_gen.6 #Derived_gen.7 #Derived_gen.8 #Derived_gen.9 #Derived_gen.10; procedure List.93 (List.436, List.437, List.438): let List.551 : U64 = 0i64; @@ -262,8 +262,8 @@ procedure Test.5 (Test.6, Test.7, Test.4): if Test.25 then let Test.26 : Str = "A"; let Test.29 : Str = StructAtIndex 0 Test.4; - let #Derived_gen.0 : Str = StructAtIndex 1 Test.4; - dec #Derived_gen.0; + let #Derived_gen.24 : Str = StructAtIndex 1 Test.4; + dec #Derived_gen.24; let Test.28 : Str = CallByName TotallyNotJson.25 Test.29; let Test.27 : List Str = Array [Test.28]; let Test.19 : {Str, List Str} = CallByName TotallyNotJson.32 Test.26 Test.27; @@ -271,8 +271,8 @@ procedure Test.5 (Test.6, Test.7, Test.4): else let Test.21 : Str = "B"; let Test.24 : Str = StructAtIndex 1 Test.4; - let #Derived_gen.1 : Str = StructAtIndex 0 Test.4; - dec #Derived_gen.1; + let #Derived_gen.25 : Str = StructAtIndex 0 Test.4; + dec #Derived_gen.25; let Test.23 : Str = CallByName TotallyNotJson.25 Test.24; let Test.22 : List Str = Array [Test.23]; let Test.19 : {Str, List Str} = CallByName TotallyNotJson.32 Test.21 Test.22; diff --git a/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification.txt b/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification.txt index a71c0661a45..f81285c492c 100644 --- a/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification.txt +++ b/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification.txt @@ -59,8 +59,8 @@ procedure Test.43 (Test.44, Test.42): jump Test.62 Test.61; else let Test.69 : U8 = StructAtIndex 1 Test.42; - let #Derived_gen.0 : Str = StructAtIndex 0 Test.42; - dec #Derived_gen.0; + let #Derived_gen.5 : Str = StructAtIndex 0 Test.42; + dec #Derived_gen.5; let Test.63 : Int1 = CallByName Test.15 Test.69; let Test.61 : Int1 = CallByName Test.14 Test.63; jump Test.62 Test.61; diff --git a/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification_of_unifiable.txt b/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification_of_unifiable.txt index 8b07ca09815..f61f2ffa113 100644 --- a/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification_of_unifiable.txt +++ b/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification_of_unifiable.txt @@ -48,32 +48,32 @@ procedure Encode.23 (Encode.98): procedure Encode.24 (Encode.99, Encode.107, Encode.101): dec Encode.99; - let Encode.138 : Str = "a Lambda Set is empty. Most likely there is a type error in your program."; - Crash Encode.138 + let Encode.125 : Str = "a Lambda Set is empty. Most likely there is a type error in your program."; + Crash Encode.125 procedure Encode.24 (Encode.99, Encode.107, Encode.101): let Encode.111 : List U8 = CallByName Test.5 Encode.99 Encode.101 Encode.107; ret Encode.111; procedure Encode.24 (Encode.99, Encode.107, Encode.101): - let Encode.118 : List U8 = CallByName TotallyNotJson.264 Encode.99 Encode.101 Encode.107; - ret Encode.118; + let Encode.113 : List U8 = CallByName TotallyNotJson.264 Encode.99 Encode.101 Encode.107; + ret Encode.113; procedure Encode.24 (Encode.99, Encode.107, Encode.101): - let Encode.122 : U8 = GetTagId Encode.107; - switch Encode.122: + let Encode.117 : U8 = GetTagId Encode.107; + switch Encode.117: case 0: - let Encode.121 : List U8 = CallByName #Derived.2 Encode.99 Encode.101 Encode.107; - ret Encode.121; + let Encode.116 : List U8 = CallByName #Derived.2 Encode.99 Encode.101 Encode.107; + ret Encode.116; default: - let Encode.121 : List U8 = CallByName #Derived.7 Encode.99 Encode.101 Encode.107; - ret Encode.121; + let Encode.116 : List U8 = CallByName #Derived.7 Encode.99 Encode.101 Encode.107; + ret Encode.116; procedure Encode.24 (Encode.99, Encode.107, Encode.101): - let Encode.134 : List U8 = CallByName TotallyNotJson.264 Encode.99 Encode.101 Encode.107; - ret Encode.134; + let Encode.121 : List U8 = CallByName TotallyNotJson.264 Encode.99 Encode.101 Encode.107; + ret Encode.121; procedure Encode.26 (Encode.105, Encode.106): let Encode.109 : List U8 = Array []; @@ -86,52 +86,67 @@ procedure List.145 (List.146, List.147, List.144): ret List.566; procedure List.145 (List.146, List.147, List.144): - let List.639 : {List U8, U64} = CallByName TotallyNotJson.267 List.146 List.147 List.144; - ret List.639; + let List.614 : {List U8, U64} = CallByName TotallyNotJson.267 List.146 List.147 List.144; + ret List.614; procedure List.18 (List.142, List.143, List.144): let List.547 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; ret List.547; procedure List.18 (List.142, List.143, List.144): - let List.620 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; - ret List.620; + let List.595 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; + ret List.595; procedure List.4 (List.113, List.114): - let List.619 : U64 = 1i64; - let List.618 : List U8 = CallByName List.70 List.113 List.619; - let List.617 : List U8 = CallByName List.71 List.618 List.114; - ret List.617; + let List.594 : U64 = 1i64; + let List.593 : List U8 = CallByName List.70 List.113 List.594; + let List.592 : List U8 = CallByName List.71 List.593 List.114; + ret List.592; procedure List.6 (#Attr.2): let List.567 : U64 = lowlevel ListLen #Attr.2; ret List.567; procedure List.6 (#Attr.2): - let List.640 : U64 = lowlevel ListLen #Attr.2; - ret List.640; + let List.615 : U64 = lowlevel ListLen #Attr.2; + ret List.615; procedure List.66 (#Attr.2, #Attr.3): let List.563 : [C {}, C {}] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.563; procedure List.66 (#Attr.2, #Attr.3): - let List.636 : [] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.636; + let List.611 : [] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.611; procedure List.70 (#Attr.2, #Attr.3): - let List.598 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.598; + let List.573 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.573; procedure List.71 (#Attr.2, #Attr.3): - let List.596 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.596; + let List.571 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.571; procedure List.8 (#Attr.2, #Attr.3): - let List.641 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.641; + let List.616 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.616; + +procedure List.80 (#Derived_gen.21, #Derived_gen.22, #Derived_gen.23, #Derived_gen.24, #Derived_gen.25): + joinpoint List.601 List.439 List.440 List.441 List.442 List.443: + let List.603 : Int1 = CallByName Num.22 List.442 List.443; + if List.603 then + let List.610 : [] = CallByName List.66 List.439 List.442; + let List.604 : {List U8, U64} = CallByName List.145 List.440 List.610 List.441; + let List.607 : U64 = 1i64; + let List.606 : U64 = CallByName Num.19 List.442 List.607; + jump List.601 List.439 List.604 List.441 List.606 List.443; + else + dec List.439; + ret List.440; + in + jump List.601 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23 #Derived_gen.24 #Derived_gen.25; -procedure List.80 (List.578, List.579, List.580, List.581, List.582): +procedure List.80 (#Derived_gen.29, #Derived_gen.30, #Derived_gen.31, #Derived_gen.32, #Derived_gen.33): joinpoint List.553 List.439 List.440 List.441 List.442 List.443: let List.555 : Int1 = CallByName Num.22 List.442 List.443; if List.555 then @@ -144,22 +159,7 @@ procedure List.80 (List.578, List.579, List.580, List.581, List.582): dec List.439; ret List.440; in - jump List.553 List.578 List.579 List.580 List.581 List.582; - -procedure List.80 (List.651, List.652, List.653, List.654, List.655): - joinpoint List.626 List.439 List.440 List.441 List.442 List.443: - let List.628 : Int1 = CallByName Num.22 List.442 List.443; - if List.628 then - let List.635 : [] = CallByName List.66 List.439 List.442; - let List.629 : {List U8, U64} = CallByName List.145 List.440 List.635 List.441; - let List.632 : U64 = 1i64; - let List.631 : U64 = CallByName Num.19 List.442 List.632; - jump List.626 List.439 List.629 List.441 List.631 List.443; - else - dec List.439; - ret List.440; - in - jump List.626 List.651 List.652 List.653 List.654 List.655; + jump List.553 #Derived_gen.29 #Derived_gen.30 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33; procedure List.93 (List.436, List.437, List.438): let List.551 : U64 = 0i64; @@ -168,34 +168,34 @@ procedure List.93 (List.436, List.437, List.438): ret List.550; procedure List.93 (List.436, List.437, List.438): - let List.624 : U64 = 0i64; - let List.625 : U64 = CallByName List.6 List.436; - let List.623 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.624 List.625; - ret List.623; + let List.599 : U64 = 0i64; + let List.600 : U64 = CallByName List.6 List.436; + let List.598 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.599 List.600; + ret List.598; procedure Num.127 (#Attr.2): - let Num.320 : U8 = lowlevel NumIntCast #Attr.2; - ret Num.320; + let Num.311 : U8 = lowlevel NumIntCast #Attr.2; + ret Num.311; procedure Num.19 (#Attr.2, #Attr.3): - let Num.323 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.323; + let Num.314 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.314; procedure Num.20 (#Attr.2, #Attr.3): - let Num.321 : U64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.321; + let Num.312 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.312; procedure Num.22 (#Attr.2, #Attr.3): - let Num.324 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; - ret Num.324; + let Num.315 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.315; procedure Num.24 (#Attr.2, #Attr.3): - let Num.322 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; - ret Num.322; + let Num.313 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; + ret Num.313; procedure Str.12 (#Attr.2): - let Str.300 : List U8 = lowlevel StrToUtf8 #Attr.2; - ret Str.300; + let Str.299 : List U8 = lowlevel StrToUtf8 #Attr.2; + ret Str.299; procedure Test.2 (Test.11): let Test.18 : {{}, {}} = CallByName Encode.23 Test.11; @@ -267,34 +267,34 @@ procedure TotallyNotJson.264 (TotallyNotJson.265, TotallyNotJson.1175, #Attr.12) procedure TotallyNotJson.264 (TotallyNotJson.265, TotallyNotJson.1175, #Attr.12): let TotallyNotJson.263 : List [] = StructAtIndex 1 #Attr.12; let TotallyNotJson.262 : Str = StructAtIndex 0 #Attr.12; - let TotallyNotJson.1264 : I64 = 123i64; - let TotallyNotJson.1263 : U8 = CallByName Num.127 TotallyNotJson.1264; - let TotallyNotJson.1260 : List U8 = CallByName List.4 TotallyNotJson.265 TotallyNotJson.1263; - let TotallyNotJson.1262 : I64 = 34i64; - let TotallyNotJson.1261 : U8 = CallByName Num.127 TotallyNotJson.1262; - let TotallyNotJson.1258 : List U8 = CallByName List.4 TotallyNotJson.1260 TotallyNotJson.1261; - let TotallyNotJson.1259 : List U8 = CallByName Str.12 TotallyNotJson.262; - let TotallyNotJson.1255 : List U8 = CallByName List.8 TotallyNotJson.1258 TotallyNotJson.1259; - let TotallyNotJson.1257 : I64 = 34i64; - let TotallyNotJson.1256 : U8 = CallByName Num.127 TotallyNotJson.1257; - let TotallyNotJson.1252 : List U8 = CallByName List.4 TotallyNotJson.1255 TotallyNotJson.1256; - let TotallyNotJson.1254 : I64 = 58i64; + let TotallyNotJson.1256 : I64 = 123i64; + let TotallyNotJson.1255 : U8 = CallByName Num.127 TotallyNotJson.1256; + let TotallyNotJson.1252 : List U8 = CallByName List.4 TotallyNotJson.265 TotallyNotJson.1255; + let TotallyNotJson.1254 : I64 = 34i64; let TotallyNotJson.1253 : U8 = CallByName Num.127 TotallyNotJson.1254; - let TotallyNotJson.1249 : List U8 = CallByName List.4 TotallyNotJson.1252 TotallyNotJson.1253; - let TotallyNotJson.1251 : I64 = 91i64; - let TotallyNotJson.1250 : U8 = CallByName Num.127 TotallyNotJson.1251; - let TotallyNotJson.268 : List U8 = CallByName List.4 TotallyNotJson.1249 TotallyNotJson.1250; - let TotallyNotJson.1248 : U64 = CallByName List.6 TotallyNotJson.263; - let TotallyNotJson.1236 : {List U8, U64} = Struct {TotallyNotJson.268, TotallyNotJson.1248}; - let TotallyNotJson.1235 : {List U8, U64} = CallByName List.18 TotallyNotJson.263 TotallyNotJson.1236 TotallyNotJson.1175; - let TotallyNotJson.270 : List U8 = StructAtIndex 0 TotallyNotJson.1235; - let TotallyNotJson.1234 : I64 = 93i64; - let TotallyNotJson.1233 : U8 = CallByName Num.127 TotallyNotJson.1234; - let TotallyNotJson.1230 : List U8 = CallByName List.4 TotallyNotJson.270 TotallyNotJson.1233; - let TotallyNotJson.1232 : I64 = 125i64; - let TotallyNotJson.1231 : U8 = CallByName Num.127 TotallyNotJson.1232; - let TotallyNotJson.1229 : List U8 = CallByName List.4 TotallyNotJson.1230 TotallyNotJson.1231; - ret TotallyNotJson.1229; + let TotallyNotJson.1250 : List U8 = CallByName List.4 TotallyNotJson.1252 TotallyNotJson.1253; + let TotallyNotJson.1251 : List U8 = CallByName Str.12 TotallyNotJson.262; + let TotallyNotJson.1247 : List U8 = CallByName List.8 TotallyNotJson.1250 TotallyNotJson.1251; + let TotallyNotJson.1249 : I64 = 34i64; + let TotallyNotJson.1248 : U8 = CallByName Num.127 TotallyNotJson.1249; + let TotallyNotJson.1244 : List U8 = CallByName List.4 TotallyNotJson.1247 TotallyNotJson.1248; + let TotallyNotJson.1246 : I64 = 58i64; + let TotallyNotJson.1245 : U8 = CallByName Num.127 TotallyNotJson.1246; + let TotallyNotJson.1241 : List U8 = CallByName List.4 TotallyNotJson.1244 TotallyNotJson.1245; + let TotallyNotJson.1243 : I64 = 91i64; + let TotallyNotJson.1242 : U8 = CallByName Num.127 TotallyNotJson.1243; + let TotallyNotJson.268 : List U8 = CallByName List.4 TotallyNotJson.1241 TotallyNotJson.1242; + let TotallyNotJson.1240 : U64 = CallByName List.6 TotallyNotJson.263; + let TotallyNotJson.1228 : {List U8, U64} = Struct {TotallyNotJson.268, TotallyNotJson.1240}; + let TotallyNotJson.1227 : {List U8, U64} = CallByName List.18 TotallyNotJson.263 TotallyNotJson.1228 TotallyNotJson.1175; + let TotallyNotJson.270 : List U8 = StructAtIndex 0 TotallyNotJson.1227; + let TotallyNotJson.1226 : I64 = 93i64; + let TotallyNotJson.1225 : U8 = CallByName Num.127 TotallyNotJson.1226; + let TotallyNotJson.1222 : List U8 = CallByName List.4 TotallyNotJson.270 TotallyNotJson.1225; + let TotallyNotJson.1224 : I64 = 125i64; + let TotallyNotJson.1223 : U8 = CallByName Num.127 TotallyNotJson.1224; + let TotallyNotJson.1221 : List U8 = CallByName List.4 TotallyNotJson.1222 TotallyNotJson.1223; + ret TotallyNotJson.1221; procedure TotallyNotJson.267 (TotallyNotJson.1177, TotallyNotJson.273, TotallyNotJson.266): let TotallyNotJson.271 : List U8 = StructAtIndex 0 TotallyNotJson.1177; @@ -320,21 +320,21 @@ procedure TotallyNotJson.267 (TotallyNotJson.1177, TotallyNotJson.273, TotallyNo let TotallyNotJson.271 : List U8 = StructAtIndex 0 TotallyNotJson.1177; let TotallyNotJson.272 : U64 = StructAtIndex 1 TotallyNotJson.1177; let TotallyNotJson.274 : List U8 = CallByName Encode.24 TotallyNotJson.271 TotallyNotJson.273 TotallyNotJson.266; - joinpoint TotallyNotJson.1242 TotallyNotJson.275: - let TotallyNotJson.1240 : U64 = 1i64; - let TotallyNotJson.1239 : U64 = CallByName Num.20 TotallyNotJson.272 TotallyNotJson.1240; - let TotallyNotJson.1238 : {List U8, U64} = Struct {TotallyNotJson.275, TotallyNotJson.1239}; - ret TotallyNotJson.1238; + joinpoint TotallyNotJson.1234 TotallyNotJson.275: + let TotallyNotJson.1232 : U64 = 1i64; + let TotallyNotJson.1231 : U64 = CallByName Num.20 TotallyNotJson.272 TotallyNotJson.1232; + let TotallyNotJson.1230 : {List U8, U64} = Struct {TotallyNotJson.275, TotallyNotJson.1231}; + ret TotallyNotJson.1230; in - let TotallyNotJson.1246 : U64 = 1i64; - let TotallyNotJson.1243 : Int1 = CallByName Num.24 TotallyNotJson.272 TotallyNotJson.1246; - if TotallyNotJson.1243 then - let TotallyNotJson.1245 : I64 = 44i64; - let TotallyNotJson.1244 : U8 = CallByName Num.127 TotallyNotJson.1245; - let TotallyNotJson.1241 : List U8 = CallByName List.4 TotallyNotJson.274 TotallyNotJson.1244; - jump TotallyNotJson.1242 TotallyNotJson.1241; + let TotallyNotJson.1238 : U64 = 1i64; + let TotallyNotJson.1235 : Int1 = CallByName Num.24 TotallyNotJson.272 TotallyNotJson.1238; + if TotallyNotJson.1235 then + let TotallyNotJson.1237 : I64 = 44i64; + let TotallyNotJson.1236 : U8 = CallByName Num.127 TotallyNotJson.1237; + let TotallyNotJson.1233 : List U8 = CallByName List.4 TotallyNotJson.274 TotallyNotJson.1236; + jump TotallyNotJson.1234 TotallyNotJson.1233; else - jump TotallyNotJson.1242 TotallyNotJson.274; + jump TotallyNotJson.1234 TotallyNotJson.274; procedure TotallyNotJson.32 (TotallyNotJson.262, TotallyNotJson.263): let TotallyNotJson.1215 : {Str, List [C {}, C {}]} = Struct {TotallyNotJson.262, TotallyNotJson.263}; @@ -342,9 +342,9 @@ procedure TotallyNotJson.32 (TotallyNotJson.262, TotallyNotJson.263): ret TotallyNotJson.1214; procedure TotallyNotJson.32 (TotallyNotJson.262, TotallyNotJson.263): - let TotallyNotJson.1266 : {Str, List []} = Struct {TotallyNotJson.262, TotallyNotJson.263}; - let TotallyNotJson.1265 : {Str, List []} = CallByName Encode.23 TotallyNotJson.1266; - ret TotallyNotJson.1265; + let TotallyNotJson.1258 : {Str, List []} = Struct {TotallyNotJson.262, TotallyNotJson.263}; + let TotallyNotJson.1257 : {Str, List []} = CallByName Encode.23 TotallyNotJson.1258; + ret TotallyNotJson.1257; procedure Test.0 (): let Test.13 : {{}, {}} = CallByName Test.3; diff --git a/crates/compiler/test_mono/generated/weakening_avoids_overspecialization.txt b/crates/compiler/test_mono/generated/weakening_avoids_overspecialization.txt index 151d18ae6dd..1396a444e32 100644 --- a/crates/compiler/test_mono/generated/weakening_avoids_overspecialization.txt +++ b/crates/compiler/test_mono/generated/weakening_avoids_overspecialization.txt @@ -53,7 +53,7 @@ procedure List.72 (#Attr.2, #Attr.3, #Attr.4): let List.527 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; ret List.527; -procedure List.80 (List.571, List.572, List.573, List.574, List.575): +procedure List.80 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): joinpoint List.545 List.439 List.440 List.441 List.442 List.443: let List.547 : Int1 = CallByName Num.22 List.442 List.443; if List.547 then @@ -77,7 +77,7 @@ procedure List.80 (List.571, List.572, List.573, List.574, List.575): let List.546 : [C U64, C U64] = TagId(1) List.440; ret List.546; in - jump List.545 List.571 List.572 List.573 List.574 List.575; + jump List.545 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; procedure List.93 (List.436, List.437, List.438): let List.543 : U64 = 0i64; diff --git a/crates/compiler/test_mono/src/tests.rs b/crates/compiler/test_mono/src/tests.rs index bbe0b5c213e..88a1109b6d5 100644 --- a/crates/compiler/test_mono/src/tests.rs +++ b/crates/compiler/test_mono/src/tests.rs @@ -3147,6 +3147,29 @@ fn dbg_str_followed_by_number() { ) } +#[mono_test] +fn linked_list_reverse() { + indoc!( + r#" + app "test" provides [main] to "./platform" + + LinkedList a : [Nil, Cons a (LinkedList a)] + + reverse : LinkedList a -> LinkedList a + reverse = \list -> reverseHelp Nil list + + reverseHelp : LinkedList a, LinkedList a -> LinkedList a + reverseHelp = \accum, list -> + when list is + Nil -> accum + Cons first rest -> reverseHelp (Cons first accum) rest + + main : LinkedList I64 + main = reverse (Cons 42 Nil) + "# + ) +} + #[mono_test] fn linked_list_map() { indoc!( diff --git a/examples/platform-switching/zig-platform/host.zig b/examples/platform-switching/zig-platform/host.zig index 6025d07d157..d7589e269c0 100644 --- a/examples/platform-switching/zig-platform/host.zig +++ b/examples/platform-switching/zig-platform/host.zig @@ -27,7 +27,7 @@ extern fn free(c_ptr: [*]align(Align) u8) callconv(.C) void; extern fn memcpy(dst: [*]u8, src: [*]u8, size: usize) callconv(.C) void; extern fn memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void; -const DEBUG: bool = false; +const DEBUG: bool = true; export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*anyopaque { if (DEBUG) { From 51f3752c94185b3454d6b194995190554d2ce151 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 18 Jun 2023 21:14:25 +0200 Subject: [PATCH 025/140] wasm backend struggles --- crates/compiler/gen_dev/src/generic64/mod.rs | 60 ++++++++++---- crates/compiler/gen_dev/src/lib.rs | 26 ++++-- crates/compiler/gen_wasm/src/backend.rs | 76 +++++++++++++++++- crates/compiler/gen_wasm/src/lib.rs | 2 +- crates/compiler/gen_wasm/src/low_level.rs | 80 ++++++++++++++++++- crates/compiler/mono/src/tail_recursion.rs | 13 ++- .../compiler/test_gen/src/gen_primitives.rs | 40 ++++++++++ 7 files changed, 262 insertions(+), 35 deletions(-) diff --git a/crates/compiler/gen_dev/src/generic64/mod.rs b/crates/compiler/gen_dev/src/generic64/mod.rs index db2508b990e..b8bd7a916fb 100644 --- a/crates/compiler/gen_dev/src/generic64/mod.rs +++ b/crates/compiler/gen_dev/src/generic64/mod.rs @@ -2852,7 +2852,7 @@ impl< } } - fn build_ptr_write( + fn build_ptr_store( &mut self, sym: Symbol, ptr: Symbol, @@ -2888,6 +2888,46 @@ impl< ASM::mov_base32_reg64(&mut self.buf, base_offset, ptr_reg); } + fn build_ptr_load(&mut self, sym: Symbol, ptr: Symbol, element_layout: InLayout<'a>) { + let ptr_reg = self + .storage_manager + .load_to_general_reg(&mut self.buf, &ptr); + + let offset = 0; + + Self::ptr_read( + &mut self.buf, + &mut self.storage_manager, + self.layout_interner, + ptr_reg, + offset, + element_layout, + sym, + ); + } + + fn build_ptr_to_stack_value( + &mut self, + sym: Symbol, + value: Symbol, + element_layout: InLayout<'a>, + ) { + // 1. aquire some stack space + let element_width = self.interner().stack_size(element_layout); + let allocation = self.debug_symbol("stack_allocation"); + let ptr = self.debug_symbol("ptr"); + let base_offset = self + .storage_manager + .claim_stack_area(&allocation, element_width); + + let ptr_reg = self.storage_manager.claim_general_reg(&mut self.buf, &ptr); + + ASM::mov_reg64_reg64(&mut self.buf, ptr_reg, CC::STACK_PTR_REG); + ASM::sub_reg64_reg64_imm32(&mut self.buf, ptr_reg, ptr_reg, base_offset); + + self.build_ptr_store(sym, ptr, value, element_layout); + } + fn expr_box( &mut self, sym: Symbol, @@ -2920,27 +2960,13 @@ impl< self.free_symbol(&element_width_symbol); self.free_symbol(&element_alignment_symbol); - self.build_ptr_write(sym, allocation, value, element_layout); + self.build_ptr_store(sym, allocation, value, element_layout); self.free_symbol(&allocation); } fn expr_unbox(&mut self, dst: Symbol, ptr: Symbol, element_layout: InLayout<'a>) { - let ptr_reg = self - .storage_manager - .load_to_general_reg(&mut self.buf, &ptr); - - let offset = 0; - - Self::ptr_read( - &mut self.buf, - &mut self.storage_manager, - self.layout_interner, - ptr_reg, - offset, - element_layout, - dst, - ); + self.build_ptr_load(dst, ptr, element_layout) } fn get_tag_id(&mut self, sym: &Symbol, structure: &Symbol, union_layout: &UnionLayout<'a>) { diff --git a/crates/compiler/gen_dev/src/lib.rs b/crates/compiler/gen_dev/src/lib.rs index fd63a1d95f4..c8349794354 100644 --- a/crates/compiler/gen_dev/src/lib.rs +++ b/crates/compiler/gen_dev/src/lib.rs @@ -1593,17 +1593,22 @@ trait Backend<'a> { self.build_ptr_cast(sym, &args[0]) } LowLevel::PtrStore => { - let element_layout = match self.interner().get_repr(*ret_layout) { - LayoutRepr::Boxed(boxed) => boxed, + let element_layout = match self.interner().get_repr(arg_layouts[0]) { + LayoutRepr::Ptr(inner) => inner, + LayoutRepr::Boxed(inner) => inner, _ => unreachable!("cannot write to {:?}", self.interner().dbg(*ret_layout)), }; - self.build_ptr_write(*sym, args[0], args[1], element_layout); + self.build_ptr_store(*sym, args[0], args[1], element_layout); } LowLevel::PtrLoad => { - // - todo!() + self.build_ptr_load(*sym, args[0], *ret_layout); + } + + LowLevel::PtrToStackValue => { + self.build_ptr_to_stack_value(*sym, args[0], arg_layouts[0]); } + LowLevel::RefCountDecRcPtr => self.build_fn_call( sym, bitcode::UTILS_DECREF_RC_PTR.to_string(), @@ -2232,7 +2237,7 @@ trait Backend<'a> { /// build_refcount_getptr loads the pointer to the reference count of src into dst. fn build_ptr_cast(&mut self, dst: &Symbol, src: &Symbol); - fn build_ptr_write( + fn build_ptr_store( &mut self, sym: Symbol, ptr: Symbol, @@ -2240,6 +2245,15 @@ trait Backend<'a> { element_layout: InLayout<'a>, ); + fn build_ptr_load(&mut self, sym: Symbol, ptr: Symbol, element_layout: InLayout<'a>); + + fn build_ptr_to_stack_value( + &mut self, + sym: Symbol, + value: Symbol, + element_layout: InLayout<'a>, + ); + /// literal_map gets the map from symbol to literal and layout, used for lazy loading and literal folding. fn literal_map(&mut self) -> &mut MutMap, *const InLayout<'a>)>; diff --git a/crates/compiler/gen_wasm/src/backend.rs b/crates/compiler/gen_wasm/src/backend.rs index dde79f02bd6..36f7ae94453 100644 --- a/crates/compiler/gen_wasm/src/backend.rs +++ b/crates/compiler/gen_wasm/src/backend.rs @@ -1084,7 +1084,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> { tag_id, union_layout, index, - } => todo!(), + } => self.expr_union_field_ptr_at_index(*structure, *tag_id, union_layout, *index, sym), Expr::ExprBox { symbol: arg_sym } => self.expr_box(sym, *arg_sym, layout, storage), @@ -1878,11 +1878,81 @@ impl<'a, 'r> WasmBackend<'a, 'r> { ); } + fn expr_union_field_ptr_at_index( + &mut self, + structure: Symbol, + tag_id: TagIdIntType, + union_layout: &UnionLayout<'a>, + index: u64, + symbol: Symbol, + ) { + use UnionLayout::*; + + debug_assert!(!union_layout.tag_is_null(tag_id)); + + let tag_index = tag_id as usize; + let field_layouts = match union_layout { + NonRecursive(tags) => tags[tag_index], + Recursive(tags) => tags[tag_index], + NonNullableUnwrapped(layouts) => *layouts, + NullableWrapped { + other_tags, + nullable_id, + } => { + let index = if tag_index > *nullable_id as usize { + tag_index - 1 + } else { + tag_index + }; + other_tags[index] + } + NullableUnwrapped { other_fields, .. } => *other_fields, + }; + + let field_offset: u32 = field_layouts + .iter() + .take(index as usize) + .map(|field_layout| self.layout_interner.stack_size(*field_layout)) + .sum(); + + // Get pointer and offset to the tag's data + let structure_storage = self.storage.get(&structure).to_owned(); + let stored_with_local = self.storage.ensure_value_has_local( + &mut self.code_builder, + structure, + structure_storage, + ); + let (tag_local_id, tag_offset) = match stored_with_local { + StoredValue::StackMemory { location, .. } => { + location.local_and_offset(self.storage.stack_frame_pointer) + } + StoredValue::Local { local_id, .. } => (local_id, 0), + StoredValue::VirtualMachineStack { .. } => { + internal_error!("{:?} should have a local variable", structure) + } + }; + + let stores_tag_id_in_pointer = union_layout.stores_tag_id_in_pointer(TARGET_INFO); + + let from_addr_val = if stores_tag_id_in_pointer { + self.code_builder.get_local(tag_local_id); + self.code_builder.i32_const(-4); // 11111111...1100 + self.code_builder.i32_and(); + AddressValue::Loaded + } else { + AddressValue::NotLoaded(tag_local_id) + }; + + let from_offset = tag_offset + field_offset; + + self.code_builder.i32_const(from_offset as i32) + } + /******************************************************************* * Box *******************************************************************/ - fn expr_box( + pub(crate) fn expr_box( &mut self, ret_sym: Symbol, arg_sym: Symbol, @@ -1915,7 +1985,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> { .copy_value_to_memory(&mut self.code_builder, ptr_local_id, 0, arg_sym); } - fn expr_unbox(&mut self, ret_sym: Symbol, arg_sym: Symbol) { + pub(crate) fn expr_unbox(&mut self, ret_sym: Symbol, arg_sym: Symbol) { let (from_addr_val, from_offset) = match self.storage.get(&arg_sym) { StoredValue::VirtualMachineStack { .. } => { self.storage diff --git a/crates/compiler/gen_wasm/src/lib.rs b/crates/compiler/gen_wasm/src/lib.rs index 5dfb7551471..ae86fccc1cd 100644 --- a/crates/compiler/gen_wasm/src/lib.rs +++ b/crates/compiler/gen_wasm/src/lib.rs @@ -249,7 +249,7 @@ pub const DEBUG_SETTINGS: WasmDebugSettings = WasmDebugSettings { let_stmt_ir: false && cfg!(debug_assertions), instructions: false && cfg!(debug_assertions), storage_map: false && cfg!(debug_assertions), - keep_test_binary: false && cfg!(debug_assertions), // see also ROC_WRITE_FINAL_WASM + keep_test_binary: true && cfg!(debug_assertions), // see also ROC_WRITE_FINAL_WASM }; #[cfg(test)] diff --git a/crates/compiler/gen_wasm/src/low_level.rs b/crates/compiler/gen_wasm/src/low_level.rs index 2096b30bc04..76b6d943924 100644 --- a/crates/compiler/gen_wasm/src/low_level.rs +++ b/crates/compiler/gen_wasm/src/low_level.rs @@ -11,7 +11,7 @@ use roc_mono::low_level::HigherOrder; use crate::backend::{ProcLookupData, ProcSource, WasmBackend}; use crate::layout::{CallConv, StackMemoryFormat, WasmLayout}; -use crate::storage::{AddressValue, StackMemoryLocation, StoredValue}; +use crate::storage::{AddressValue, StackMemoryLocation, StoredValue, StoredVarKind}; use crate::PTR_TYPE; use roc_wasm_module::{Align, LocalId, ValueType}; @@ -1960,9 +1960,81 @@ impl<'a> LowLevelCall<'a> { backend.storage.load_symbols(code_builder, self.arguments); } - PtrStore => todo!("{:?}", self.lowlevel), - PtrLoad => todo!("{:?}", self.lowlevel), - PtrToStackValue => todo!("{:?}", self.lowlevel), + PtrStore => { + // PtrStore : Ptr a, a -> {} + let ptr_sym = self.arguments[0]; + let value_sym = self.arguments[1]; + let layout = self.ret_layout; + + // create a local variable for the heap pointer + let ptr_local_id = match backend.storage.ensure_value_has_local( + &mut backend.code_builder, + ptr_sym, + self.ret_storage.clone(), + ) { + StoredValue::Local { local_id, .. } => local_id, + StoredValue::StackMemory { location, .. } => { + location + .local_and_offset(backend.storage.stack_frame_pointer) + .0 + } + other => internal_error!( + "Struct should be allocated in stack memory, but it's in {:?}", + other + ), + }; + + dbg!(ptr_local_id); + + // store the pointer value from the value stack into the local variable + backend.code_builder.set_local(ptr_local_id); + + // copy the argument to the pointer address + backend.storage.copy_value_to_memory( + &mut backend.code_builder, + ptr_local_id, + 0, + value_sym, + ); + } + PtrLoad => backend.expr_unbox(self.ret_symbol, self.arguments[0]), + PtrToStackValue => { + let arg = self.arguments[0]; + let arg_layout = backend.storage.symbol_layouts.get(&arg).unwrap(); + + let (size, alignment_bytes) = backend + .layout_interner + .stack_size_and_alignment(*arg_layout); + + let (frame_ptr, offset) = backend + .storage + .allocate_anonymous_stack_memory(size, alignment_bytes); + + backend.storage.copy_value_to_memory( + &mut backend.code_builder, + frame_ptr, + offset, + arg, + ); + + // create a local variable for the pointer + let ptr_local_id = match backend.storage.ensure_value_has_local( + &mut backend.code_builder, + self.ret_symbol, + self.ret_storage.clone(), + ) { + StoredValue::Local { local_id, .. } => local_id, + _ => internal_error!("A pointer will always be an i32"), + }; + + // store the pointer value from the value stack into the local variable + dbg!(offset, size, alignment_bytes); + + backend.code_builder.get_local(frame_ptr); + backend.code_builder.i32_const(offset as i32); + backend.code_builder.i32_add(); + backend.code_builder.set_local(ptr_local_id); + } Hash => todo!("{:?}", self.lowlevel), diff --git a/crates/compiler/mono/src/tail_recursion.rs b/crates/compiler/mono/src/tail_recursion.rs index 09a48d17497..cf759e2f104 100644 --- a/crates/compiler/mono/src/tail_recursion.rs +++ b/crates/compiler/mono/src/tail_recursion.rs @@ -420,16 +420,20 @@ where return false; } - has_cons_in_tail_position(&proc.body, proc.name) + has_cons_in_tail_position(&proc.body, proc.name, None) } -fn has_cons_in_tail_position(initial_stmt: &Stmt<'_>, function_name: LambdaName) -> bool { +fn has_cons_in_tail_position( + initial_stmt: &Stmt<'_>, + function_name: LambdaName, + initial_recursive_call: Option, +) -> bool { // we are looking for code of the form // // let x = Tag a b c // ret x - let mut stack = vec![(None, initial_stmt)]; + let mut stack = vec![(initial_recursive_call, initial_stmt)]; while let Some((recursive_call, stmt)) = stack.pop() { match stmt { @@ -674,7 +678,7 @@ impl<'a> TrmcEnv<'a> { Stmt::Let(symbol, expr, layout, next) => { if self.recursive_call.is_none() { if let Some(call) = Self::is_recursive_expr(expr, self.function_name) { - if has_cons_in_tail_position(next, self.function_name) { + if has_cons_in_tail_position(next, self.function_name, Some(*symbol)) { self.recursive_call = Some((*symbol, call)); return self.walk_stmt(env, next); } @@ -682,6 +686,7 @@ impl<'a> TrmcEnv<'a> { } if let Some(cons_info) = Self::is_terminal_constructor(stmt) { + dbg!(&cons_info, &self.recursive_call); match &self.recursive_call { None => { // this control flow path did not encounter a recursive call. Just diff --git a/crates/compiler/test_gen/src/gen_primitives.rs b/crates/compiler/test_gen/src/gen_primitives.rs index 587134965e7..371825d1f27 100644 --- a/crates/compiler/test_gen/src/gen_primitives.rs +++ b/crates/compiler/test_gen/src/gen_primitives.rs @@ -4499,3 +4499,43 @@ fn pass_lambda_set_to_function() { i64 ); } + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] +fn linked_list_trmc() { + assert_evals_to!( + indoc!( + r#" + app "test" provides [main] to "./platform" + + LinkedList a : [Nil, Cons a (LinkedList a)] + + # map : LinkedList a, (a -> b) -> LinkedList b + # map = \list, f -> + # when list is + # Nil -> Nil + # Cons x xs -> Cons (f x) (map xs f) + + unfold : a, Nat -> LinkedList a + unfold = \value, n -> + when n is + 0 -> Nil + _ -> Cons value (unfold value (n - 1)) + + length : LinkedList a -> I64 + length = \list -> + when list is + Nil -> 0 + Cons _ rest -> 1 + length rest + + main : I64 + main = + unfold 32 1 + # |> map (\x -> x + 1i64) + |> length + "# + ), + 5, + i64 + ); +} From 052ce8f2aaefb9f0a3e06dfb75f90f27c2301852 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 18 Jun 2023 22:05:27 +0200 Subject: [PATCH 026/140] clippy --- crates/compiler/gen_dev/src/generic64/mod.rs | 96 ++++++++++++++++++++ crates/compiler/gen_dev/src/lib.rs | 12 ++- crates/compiler/gen_llvm/src/llvm/build.rs | 5 +- crates/compiler/gen_wasm/src/backend.rs | 2 +- crates/compiler/gen_wasm/src/low_level.rs | 3 +- crates/compiler/load_internal/src/file.rs | 3 +- crates/compiler/mono/src/ir.rs | 6 +- crates/compiler/mono/src/tail_recursion.rs | 5 +- 8 files changed, 114 insertions(+), 18 deletions(-) diff --git a/crates/compiler/gen_dev/src/generic64/mod.rs b/crates/compiler/gen_dev/src/generic64/mod.rs index b8bd7a916fb..8d94425cdff 100644 --- a/crates/compiler/gen_dev/src/generic64/mod.rs +++ b/crates/compiler/gen_dev/src/generic64/mod.rs @@ -2852,6 +2852,102 @@ impl< } } + fn load_union_field_ptr_at_index( + &mut self, + sym: &Symbol, + structure: &Symbol, + tag_id: TagIdIntType, + index: u64, + union_layout: &UnionLayout<'a>, + ) { + let ptr_reg = self + .storage_manager + .load_to_general_reg(&mut self.buf, structure); + + let sym_reg = self.storage_manager.claim_general_reg(&mut self.buf, sym); + + match union_layout { + UnionLayout::NonRecursive(_) => { + unreachable!("operation not supported") + } + UnionLayout::NonNullableUnwrapped(field_layouts) => { + let mut offset = 0; + for field in &field_layouts[..index as usize] { + offset += self.layout_interner.stack_size(*field); + } + + ASM::add_reg64_reg64_imm32(&mut self.buf, sym_reg, ptr_reg, offset as i32); + } + UnionLayout::NullableUnwrapped { + nullable_id, + other_fields, + } => { + debug_assert_ne!(tag_id, *nullable_id as TagIdIntType); + + let mut offset = 0; + for field in &other_fields[..index as usize] { + offset += self.layout_interner.stack_size(*field); + } + + ASM::add_reg64_reg64_imm32(&mut self.buf, sym_reg, ptr_reg, offset as i32); + } + + UnionLayout::NullableWrapped { + nullable_id, + other_tags, + } => { + debug_assert_ne!(tag_id, *nullable_id as TagIdIntType); + + let other_fields = if tag_id < *nullable_id { + other_tags[tag_id as usize] + } else { + other_tags[tag_id as usize - 1] + }; + + let mask_symbol = self.debug_symbol("tag_id_mask"); + let mask_reg = self + .storage_manager + .claim_general_reg(&mut self.buf, &mask_symbol); + ASM::mov_reg64_imm64(&mut self.buf, mask_reg, (!0b111) as _); + + // mask out the tag id bits + ASM::and_reg64_reg64_reg64(&mut self.buf, ptr_reg, ptr_reg, mask_reg); + + let mut offset = 0; + for field in &other_fields[..index as usize] { + offset += self.layout_interner.stack_size(*field); + } + + ASM::add_reg64_reg64_imm32(&mut self.buf, sym_reg, ptr_reg, offset as i32); + } + UnionLayout::Recursive(tag_layouts) => { + let other_fields = tag_layouts[tag_id as usize]; + + let ptr_reg = self + .storage_manager + .load_to_general_reg(&mut self.buf, structure); + + // mask out the tag id bits + if !union_layout.stores_tag_id_as_data(self.storage_manager.target_info) { + let mask_symbol = self.debug_symbol("tag_id_mask"); + let mask_reg = self + .storage_manager + .claim_general_reg(&mut self.buf, &mask_symbol); + ASM::mov_reg64_imm64(&mut self.buf, mask_reg, (!0b111) as _); + + ASM::and_reg64_reg64_reg64(&mut self.buf, ptr_reg, ptr_reg, mask_reg); + } + + let mut offset = 0; + for field in &other_fields[..index as usize] { + offset += self.layout_interner.stack_size(*field); + } + + ASM::add_reg64_reg64_imm32(&mut self.buf, sym_reg, ptr_reg, offset as i32); + } + } + } + fn build_ptr_store( &mut self, sym: Symbol, diff --git a/crates/compiler/gen_dev/src/lib.rs b/crates/compiler/gen_dev/src/lib.rs index c8349794354..dab8eb6b93a 100644 --- a/crates/compiler/gen_dev/src/lib.rs +++ b/crates/compiler/gen_dev/src/lib.rs @@ -803,7 +803,7 @@ trait Backend<'a> { union_layout, index, } => { - todo!(); + self.load_union_field_ptr_at_index(sym, structure, *tag_id, *index, union_layout); } Expr::GetTagId { structure, @@ -2331,6 +2331,16 @@ trait Backend<'a> { union_layout: &UnionLayout<'a>, ); + /// load_union_at_index loads into `sym` the value at `index` for `tag_id`. + fn load_union_field_ptr_at_index( + &mut self, + sym: &Symbol, + structure: &Symbol, + tag_id: TagIdIntType, + index: u64, + union_layout: &UnionLayout<'a>, + ); + /// get_tag_id loads the tag id from a the union. fn get_tag_id(&mut self, sym: &Symbol, structure: &Symbol, union_layout: &UnionLayout<'a>); diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index b7f91ddff01..0e9a151ebb2 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -1479,7 +1479,7 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( union_layout, } => { // cast the argument bytes into the desired shape for this tag - let (argument, structure_layout) = scope.load_symbol_and_layout(structure); + let argument = scope.load_symbol(structure); let ret_repr = layout_interner.get_repr(layout); let pointer_value = match union_layout { @@ -1545,7 +1545,6 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( ptr, target_loaded_type, ) - .into() } UnionLayout::NullableUnwrapped { nullable_id, @@ -2134,8 +2133,6 @@ fn lookup_at_index_ptr<'a, 'ctx>( struct_type: Option>, target_loaded_type: BasicTypeEnum<'ctx>, ) -> BasicValueEnum<'ctx> { - let builder = env.builder; - let elem_ptr = union_field_at_index_help( env, layout_interner, diff --git a/crates/compiler/gen_wasm/src/backend.rs b/crates/compiler/gen_wasm/src/backend.rs index 36f7ae94453..e288774ad40 100644 --- a/crates/compiler/gen_wasm/src/backend.rs +++ b/crates/compiler/gen_wasm/src/backend.rs @@ -1945,7 +1945,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> { let from_offset = tag_offset + field_offset; - self.code_builder.i32_const(from_offset as i32) + self.code_builder.i32_const(from_offset as i32); } /******************************************************************* diff --git a/crates/compiler/gen_wasm/src/low_level.rs b/crates/compiler/gen_wasm/src/low_level.rs index 76b6d943924..dbd04fdd277 100644 --- a/crates/compiler/gen_wasm/src/low_level.rs +++ b/crates/compiler/gen_wasm/src/low_level.rs @@ -11,7 +11,7 @@ use roc_mono::low_level::HigherOrder; use crate::backend::{ProcLookupData, ProcSource, WasmBackend}; use crate::layout::{CallConv, StackMemoryFormat, WasmLayout}; -use crate::storage::{AddressValue, StackMemoryLocation, StoredValue, StoredVarKind}; +use crate::storage::{AddressValue, StackMemoryLocation, StoredValue}; use crate::PTR_TYPE; use roc_wasm_module::{Align, LocalId, ValueType}; @@ -1964,7 +1964,6 @@ impl<'a> LowLevelCall<'a> { // PtrStore : Ptr a, a -> {} let ptr_sym = self.arguments[0]; let value_sym = self.arguments[1]; - let layout = self.ret_layout; // create a local variable for the heap pointer let ptr_local_id = match backend.storage.ensure_value_has_local( diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index 86d9805786b..9867c63d1b8 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -5827,8 +5827,7 @@ fn make_specializations<'a>( ); let external_specializations_requested = procs.externals_we_need.clone(); - let (procedures, restored_procs_base) = - procs.get_specialized_procs_without_rc(&mut layout_cache, &mut mono_env); + let (procedures, restored_procs_base) = procs.get_specialized_procs_without_rc(); // Turn `Bytes.Decode.IdentId(238)` into `Bytes.Decode.238`, we rely on this in mono tests mono_env.home.register_debug_idents(mono_env.ident_ids); diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index 39a25f6815d..5c6ba99250c 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -990,15 +990,11 @@ impl<'a> Procs<'a> { pub fn get_specialized_procs_without_rc( self, - layout_cache: &mut LayoutCache<'a>, - env: &mut Env<'a, '_>, ) -> (MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>, ProcsBase<'a>) { let mut specialized_procs = MutMap::with_capacity_and_hasher(self.specialized.len(), default_hasher()); - for (symbol, layout, mut proc) in self.specialized.into_iter_assert_done() { - // proc.make_tail_recursive(&mut layout_cache.interner, env); - + for (symbol, layout, proc) in self.specialized.into_iter_assert_done() { let key = (symbol, layout); specialized_procs.insert(key, proc); } diff --git a/crates/compiler/mono/src/tail_recursion.rs b/crates/compiler/mono/src/tail_recursion.rs index cf759e2f104..aec5b38c76b 100644 --- a/crates/compiler/mono/src/tail_recursion.rs +++ b/crates/compiler/mono/src/tail_recursion.rs @@ -50,7 +50,7 @@ pub fn apply_trmc<'a, 'i>( let env = &mut env; - for (_, proc) in procs { + for proc in procs.values_mut() { use self::SelfRecursive::*; if let SelfRecursive(id) = proc.is_self_recursive { if crate::tail_recursion::is_trmc_candidate(env.interner, proc) { @@ -686,7 +686,6 @@ impl<'a> TrmcEnv<'a> { } if let Some(cons_info) = Self::is_terminal_constructor(stmt) { - dbg!(&cons_info, &self.recursive_call); match &self.recursive_call { None => { // this control flow path did not encounter a recursive call. Just @@ -815,7 +814,7 @@ impl<'a> TrmcEnv<'a> { Stmt::Switch { cond_symbol: *cond_symbol, cond_layout: *cond_layout, - branches: &*arena.alloc(new_branches.into_bump_slice()), + branches: arena.alloc(new_branches.into_bump_slice()), default_branch: (default_branch.0.clone(), new_default_branch), ret_layout: *ret_layout, } From 21d1835406bf9671dcf6f99d634d9e0e8c5e81b5 Mon Sep 17 00:00:00 2001 From: "J.Teeuwissen" Date: Tue, 6 Jun 2023 16:10:12 +0200 Subject: [PATCH 027/140] use build_gep to avoid build_int_to_ptr --- crates/compiler/gen_llvm/src/llvm/build.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 0e9a151ebb2..7c32fe283ad 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -1961,20 +1961,28 @@ pub fn tag_pointer_clear_tag_id<'ctx>( ) -> PointerValue<'ctx> { let ptr_int = env.ptr_int(); - let (tag_id_bits_mask, _) = tag_pointer_tag_id_bits_and_mask(env.target_info); + let (_, tag_id_bits_mask) = tag_pointer_tag_id_bits_and_mask(env.target_info); let as_int = env.builder.build_ptr_to_int(pointer, ptr_int, "to_int"); - let mask = { - let a = env.ptr_int().const_all_ones(); - let tag_id_bits = env.ptr_int().const_int(tag_id_bits_mask, false); - env.builder.build_left_shift(a, tag_id_bits, "make_mask") - }; + let mask = env.ptr_int().const_int(tag_id_bits_mask, false); let masked = env.builder.build_and(as_int, mask, "masked"); + let zero = env.ptr_int().const_zero(); + + let index = env.builder.build_int_sub(zero, masked, "index"); + + let cast_pointer = env.builder.build_pointer_cast( + pointer, + env.context.i8_type().ptr_type(AddressSpace::default()), + "cast_to_i8_ptr", + ); + + let indexed_pointer = unsafe { env.builder.build_gep(cast_pointer, &[index], "new_ptr") }; + env.builder - .build_int_to_ptr(masked, pointer.get_type(), "to_ptr") + .build_pointer_cast(indexed_pointer, pointer.get_type(), "cast_from_i8_ptr") } fn allocate_tag<'a, 'ctx>( From 2d9fdf03386cdbe3983ad867cfdf32825aadefb7 Mon Sep 17 00:00:00 2001 From: "J.Teeuwissen" Date: Tue, 6 Jun 2023 16:29:49 +0200 Subject: [PATCH 028/140] updated tag_pointer_set_tag_id --- crates/compiler/gen_llvm/src/llvm/build.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 7c32fe283ad..0989caeb078 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -1921,15 +1921,30 @@ fn tag_pointer_set_tag_id<'ctx>( // we only have 3 bits, so can encode only 0..7 (or on 32-bit targets, 2 bits to encode 0..3) debug_assert!((tag_id as u32) < env.target_info.ptr_width() as u32); + let (_, tag_id_bits_mask) = tag_pointer_tag_id_bits_and_mask(env.target_info); + let ptr_int = env.ptr_int(); let as_int = env.builder.build_ptr_to_int(pointer, ptr_int, "to_int"); + let mask = env.ptr_int().const_int(tag_id_bits_mask, false); + + let masked = env.builder.build_and(as_int, mask, "masked"); + let tag_id_intval = ptr_int.const_int(tag_id as u64, false); - let combined = env.builder.build_or(as_int, tag_id_intval, "store_tag_id"); + + let index = env.builder.build_int_sub(tag_id_intval, masked, "index"); + + let cast_pointer = env.builder.build_pointer_cast( + pointer, + env.context.i8_type().ptr_type(AddressSpace::default()), + "cast_to_i8_ptr", + ); + + let indexed_pointer = unsafe { env.builder.build_gep(cast_pointer, &[index], "new_ptr") }; env.builder - .build_int_to_ptr(combined, pointer.get_type(), "to_ptr") + .build_pointer_cast(indexed_pointer, pointer.get_type(), "cast_from_i8_ptr") } pub fn tag_pointer_tag_id_bits_and_mask(target_info: TargetInfo) -> (u64, u64) { From 9955fe581b4bccc944017ec5905dc4926a1daa4f Mon Sep 17 00:00:00 2001 From: Folkert Date: Tue, 6 Jun 2023 18:45:44 +0200 Subject: [PATCH 029/140] attempt to simplify logic --- crates/compiler/gen_llvm/src/llvm/build.rs | 32 ++++++++-------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 0989caeb078..3af9acaeebf 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -1921,19 +1921,7 @@ fn tag_pointer_set_tag_id<'ctx>( // we only have 3 bits, so can encode only 0..7 (or on 32-bit targets, 2 bits to encode 0..3) debug_assert!((tag_id as u32) < env.target_info.ptr_width() as u32); - let (_, tag_id_bits_mask) = tag_pointer_tag_id_bits_and_mask(env.target_info); - - let ptr_int = env.ptr_int(); - - let as_int = env.builder.build_ptr_to_int(pointer, ptr_int, "to_int"); - - let mask = env.ptr_int().const_int(tag_id_bits_mask, false); - - let masked = env.builder.build_and(as_int, mask, "masked"); - - let tag_id_intval = ptr_int.const_int(tag_id as u64, false); - - let index = env.builder.build_int_sub(tag_id_intval, masked, "index"); + let tag_id_intval = env.ptr_int().const_int(tag_id as u64, false); let cast_pointer = env.builder.build_pointer_cast( pointer, @@ -1941,7 +1929,11 @@ fn tag_pointer_set_tag_id<'ctx>( "cast_to_i8_ptr", ); - let indexed_pointer = unsafe { env.builder.build_gep(cast_pointer, &[index], "new_ptr") }; + // NOTE: assumes the lower bits of `cast_pointer` are all 0 + let indexed_pointer = unsafe { + env.builder + .build_in_bounds_gep(cast_pointer, &[tag_id_intval], "indexed_pointer") + }; env.builder .build_pointer_cast(indexed_pointer, pointer.get_type(), "cast_from_i8_ptr") @@ -1974,19 +1966,17 @@ pub fn tag_pointer_clear_tag_id<'ctx>( env: &Env<'_, 'ctx, '_>, pointer: PointerValue<'ctx>, ) -> PointerValue<'ctx> { - let ptr_int = env.ptr_int(); - let (_, tag_id_bits_mask) = tag_pointer_tag_id_bits_and_mask(env.target_info); - let as_int = env.builder.build_ptr_to_int(pointer, ptr_int, "to_int"); + let as_int = env + .builder + .build_ptr_to_int(pointer, env.ptr_int(), "to_int"); let mask = env.ptr_int().const_int(tag_id_bits_mask, false); - let masked = env.builder.build_and(as_int, mask, "masked"); - - let zero = env.ptr_int().const_zero(); + let current_tag_id = env.builder.build_and(as_int, mask, "masked"); - let index = env.builder.build_int_sub(zero, masked, "index"); + let index = env.builder.build_int_neg(current_tag_id, "index"); let cast_pointer = env.builder.build_pointer_cast( pointer, From 76375060373bd3632452509a0729ddc6ca3b358a Mon Sep 17 00:00:00 2001 From: Folkert Date: Mon, 19 Jun 2023 19:32:00 +0200 Subject: [PATCH 030/140] skip is_null check if possible --- crates/compiler/gen_llvm/src/llvm/build.rs | 14 ++++++++++++-- crates/compiler/mono/src/layout.rs | 16 ++++++++++++++++ crates/compiler/mono/src/layout/intern.rs | 4 ++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 3af9acaeebf..9718c8863ce 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -1165,7 +1165,12 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( env.builder.position_at_end(check_if_null); env.builder.build_conditional_branch( - env.builder.build_is_null(tag_ptr, "is_tag_null"), + // have llvm optimizations clean this up + if layout_interner.is_nullable(layout) { + env.builder.build_is_null(tag_ptr, "is_tag_null") + } else { + env.context.bool_type().const_int(false as _, false) + }, cont_block, check_if_unique, ); @@ -1246,7 +1251,12 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( env.builder.position_at_end(check_if_null); env.builder.build_conditional_branch( - env.builder.build_is_null(tag_ptr, "is_tag_null"), + // have llvm optimizations clean this up + if layout_interner.is_nullable(layout) { + env.builder.build_is_null(tag_ptr, "is_tag_null") + } else { + env.context.bool_type().const_int(false as _, false) + }, cont_block, check_if_unique, ); diff --git a/crates/compiler/mono/src/layout.rs b/crates/compiler/mono/src/layout.rs index f2ddd9c3a8c..905b1cbb280 100644 --- a/crates/compiler/mono/src/layout.rs +++ b/crates/compiler/mono/src/layout.rs @@ -2759,6 +2759,22 @@ impl<'a> LayoutRepr<'a> { } } + pub fn is_nullable(&self) -> bool { + use LayoutRepr::*; + + match self { + Union(union_layout) => match union_layout { + UnionLayout::NonRecursive(_) => false, + UnionLayout::Recursive(_) => false, + UnionLayout::NonNullableUnwrapped(_) => false, + UnionLayout::NullableWrapped { .. } => true, + UnionLayout::NullableUnwrapped { .. } => true, + }, + + _ => false, + } + } + /// Even if a value (say, a record) is not itself reference counted, /// it may contains values/fields that are. Therefore when this record /// goes out of scope, the refcount on those values/fields must be decremented. diff --git a/crates/compiler/mono/src/layout/intern.rs b/crates/compiler/mono/src/layout/intern.rs index 175893fc504..024f32b63b4 100644 --- a/crates/compiler/mono/src/layout/intern.rs +++ b/crates/compiler/mono/src/layout/intern.rs @@ -230,6 +230,10 @@ pub trait LayoutInterner<'a>: Sized { self.get_repr(layout).is_refcounted() } + fn is_nullable(&self, layout: InLayout<'a>) -> bool { + self.get_repr(layout).is_nullable() + } + fn is_passed_by_reference(&self, layout: InLayout<'a>) -> bool { self.get_repr(layout).is_passed_by_reference(self) } From 4a5b6a7a0a8365e397978184562e81a6c2241b69 Mon Sep 17 00:00:00 2001 From: Folkert Date: Tue, 20 Jun 2023 14:46:12 +0200 Subject: [PATCH 031/140] never inline overflow panicking code it creates too many allocas, growing the stack frame --- crates/compiler/gen_llvm/src/llvm/lowlevel.rs | 69 ++++++++++++++++++- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs index 7d6145e8391..0c862d51cc8 100644 --- a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs +++ b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs @@ -1,4 +1,6 @@ use inkwell::{ + attributes::{Attribute, AttributeLoc}, + module::Linkage, types::{BasicType, IntType}, values::{ BasicValue, BasicValueEnum, FloatValue, FunctionValue, InstructionOpcode, IntValue, @@ -54,12 +56,15 @@ use crate::llvm::{ refcounting::PointerToRefcount, }; -use super::{build::Env, convert::zig_dec_type}; use super::{ - build::{throw_internal_exception, use_roc_value}, + build::{throw_internal_exception, use_roc_value, FAST_CALL_CONV}, convert::zig_with_overflow_roc_dec, scope::Scope, }; +use super::{ + build::{Env, FunctionSpec}, + convert::zig_dec_type, +}; pub(crate) fn run_low_level<'a, 'ctx>( env: &Env<'a, 'ctx, '_>, @@ -1816,7 +1821,7 @@ fn throw_on_overflow<'ctx>( bd.position_at_end(throw_block); - throw_internal_exception(env, parent, message); + throw_on_overflow_help(env, result, message); bd.position_at_end(then_block); @@ -1824,6 +1829,64 @@ fn throw_on_overflow<'ctx>( .unwrap() } +fn throw_on_overflow_help<'ctx>( + env: &Env<'_, 'ctx, '_>, + result: StructValue<'ctx>, // of the form { value: T, has_overflowed: bool } + message: &str, +) { + let block = env.builder.get_insert_block().expect("to be in a function"); + let di_location = env.builder.get_current_debug_location().unwrap(); + + let function_name = "throw_on_overflow"; + let function = match env.module.get_function(function_name) { + Some(function_value) => function_value, + None => { + let function_type = env.context.void_type().fn_type(&[], false); + let function_value = + env.module + .add_function(function_name, function_type, Some(Linkage::Internal)); + + function_value.set_call_conventions(FAST_CALL_CONV); + + // prevent inlining of this function + let kind_id = Attribute::get_named_enum_kind_id("noinline"); + debug_assert!(kind_id > 0); + let enum_attr = env.context.create_enum_attribute(kind_id, 1); + function_value.add_attribute(AttributeLoc::Function, enum_attr); + + // calling this function is unlikely + let kind_id = Attribute::get_named_enum_kind_id("cold"); + debug_assert!(kind_id > 0); + let enum_attr = env.context.create_enum_attribute(kind_id, 1); + function_value.add_attribute(AttributeLoc::Function, enum_attr); + + // this function never returns + let kind_id = Attribute::get_named_enum_kind_id("noreturn"); + debug_assert!(kind_id > 0); + let enum_attr = env.context.create_enum_attribute(kind_id, 1); + function_value.add_attribute(AttributeLoc::Function, enum_attr); + + // Add a basic block for the entry point + let entry = env.context.append_basic_block(function_value, "entry"); + + env.builder.position_at_end(entry); + + // ends in unreachable, so no return is needed + throw_internal_exception(env, function_value, message); + + function_value + } + }; + + env.builder.position_at_end(block); + env.builder.set_current_debug_location(di_location); + + let call = env.builder.build_call(function, &[], "overflow"); + call.set_call_convention(FAST_CALL_CONV); + + env.builder.build_unreachable(); +} + fn dec_split_into_words<'ctx>( env: &Env<'_, 'ctx, '_>, value: IntValue<'ctx>, From 9ab4413beb9b227ea7a7f04f91b8f4ce3597f091 Mon Sep 17 00:00:00 2001 From: Folkert Date: Tue, 20 Jun 2023 14:47:37 +0200 Subject: [PATCH 032/140] rewrite constFolding logic --- .../cli_testing_examples/benchmarks/CFold.roc | 36 ++++++++----------- crates/compiler/mono/src/inc_dec.rs | 7 ++-- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/crates/cli_testing_examples/benchmarks/CFold.roc b/crates/cli_testing_examples/benchmarks/CFold.roc index 8fbb087e337..8c496c6f9c4 100644 --- a/crates/cli_testing_examples/benchmarks/CFold.roc +++ b/crates/cli_testing_examples/benchmarks/CFold.roc @@ -100,35 +100,27 @@ constFolding = \e -> x1 = constFolding e1 x2 = constFolding e2 - when Pair x1 x2 is - Pair (Val a) (Val b) -> - Val (a + b) + when x1 is + Val a -> + when x2 is + Val b -> Val (a + b) + Add (Val b) x | Add x (Val b) -> Add (Val (a + b)) x + _ -> Add x1 x2 - Pair (Val a) (Add (Val b) x) -> - Add (Val (a + b)) x - - Pair (Val a) (Add x (Val b)) -> - Add (Val (a + b)) x - - Pair y1 y2 -> - Add y1 y2 + _ -> Add x1 x2 Mul e1 e2 -> x1 = constFolding e1 x2 = constFolding e2 - when Pair x1 x2 is - Pair (Val a) (Val b) -> - Val (a * b) - - Pair (Val a) (Mul (Val b) x) -> - Mul (Val (a * b)) x - - Pair (Val a) (Mul x (Val b)) -> - Mul (Val (a * b)) x + when x1 is + Val a -> + when x2 is + Val b -> Val (a * b) + Mul (Val b) x | Mul x (Val b) -> Mul (Val (a * b)) x + _ -> Mul x1 x2 - Pair y1 y2 -> - Add y1 y2 + _ -> Mul x1 x2 _ -> e diff --git a/crates/compiler/mono/src/inc_dec.rs b/crates/compiler/mono/src/inc_dec.rs index e02b53e1f2e..960a45bf10e 100644 --- a/crates/compiler/mono/src/inc_dec.rs +++ b/crates/compiler/mono/src/inc_dec.rs @@ -272,9 +272,10 @@ impl<'v> RefcountEnvironment<'v> { */ fn consume_rc_symbol(&mut self, symbol: Symbol) -> Ownership { // Consume the symbol by setting it to borrowed (if it was owned before), and return the previous ownership. - self.symbols_ownership - .insert(symbol, Ownership::Borrowed) - .expect("Expected symbol to be in environment") + match self.symbols_ownership.insert(symbol, Ownership::Borrowed) { + Some(ownership) => ownership, + None => internal_error!("Expected symbol {symbol:?} to be in environment"), + } } /** From 880d2ef788e9da3f3d256afeb3ea2235cc520297 Mon Sep 17 00:00:00 2001 From: Folkert Date: Tue, 20 Jun 2023 21:20:33 +0200 Subject: [PATCH 033/140] invalidate TRMC attempt when symbol is used before TRMC opportunity --- crates/compiler/mono/src/tail_recursion.rs | 206 ++++++++++++++++----- 1 file changed, 159 insertions(+), 47 deletions(-) diff --git a/crates/compiler/mono/src/tail_recursion.rs b/crates/compiler/mono/src/tail_recursion.rs index aec5b38c76b..f2afbc9c7ee 100644 --- a/crates/compiler/mono/src/tail_recursion.rs +++ b/crates/compiler/mono/src/tail_recursion.rs @@ -420,67 +420,124 @@ where return false; } - has_cons_in_tail_position(&proc.body, proc.name, None) + match has_cons_in_tail_position(&proc.body, proc.name, None) { + SymbolUse::NotUsed | SymbolUse::Used => false, + SymbolUse::TrmcOppotunity => true, + } +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)] +#[repr(C)] +enum SymbolUse { + #[default] + NotUsed = 0, + TrmcOppotunity = 1, + Used = 2, +} + +impl SymbolUse { + #[must_use] + fn mappend(self, y: Self) -> Self { + debug_assert_eq!(self.mappend_slow(y), Ord::max(self, y)); + + Ord::max(self, y) + } + + fn mappend_slow(self, y: Self) -> Self { + use SymbolUse::*; + + match (self, y) { + (Used, _) | (_, Used) => Used, + (TrmcOppotunity, _) | (_, TrmcOppotunity) => TrmcOppotunity, + (NotUsed, NotUsed) => NotUsed, + } + } } fn has_cons_in_tail_position( - initial_stmt: &Stmt<'_>, + stmt: &Stmt<'_>, function_name: LambdaName, - initial_recursive_call: Option, -) -> bool { + recursive_call: Option, +) -> SymbolUse { // we are looking for code of the form // // let x = Tag a b c // ret x - let mut stack = vec![(initial_recursive_call, initial_stmt)]; + // if this stmt is the literal tail tag application and return, then this is a TRMC opportunity + if let Some(cons_info) = TrmcEnv::is_terminal_constructor(stmt) { + // must use the result of a recursive call directly as an argument + if let Some(recursive_call) = recursive_call { + if cons_info.arguments.contains(&recursive_call) { + return SymbolUse::TrmcOppotunity; + } + } + } - while let Some((recursive_call, stmt)) = stack.pop() { - match stmt { - Stmt::Let(symbol, expr, _, next) => { - if let Some(cons_info) = TrmcEnv::is_terminal_constructor(stmt) { - // must use the result of a recursive call directly as an argument - if let Some(recursive_call) = recursive_call { - if cons_info.arguments.contains(&recursive_call) { - return true; - } - } - } + // if the stmt uses the active recursive call, that invalidates the recursive call for this branch + if let Some(recursive_call) = recursive_call { + if stmt_contains_symbol_nonrec(stmt, recursive_call) { + // this means we really only check for the first recursive call (in each branch) + // whether it presents a TRMC opportunity. In theory we can look at all recursive calls + // this is future work. + return SymbolUse::Used; + } + } - let recursive_call = recursive_call - .or_else(|| TrmcEnv::is_recursive_expr(expr, function_name).map(|_| *symbol)); + match stmt { + Stmt::Let(symbol, expr, _, next) => { + // find a new recursive call if we currently have none + // that means we generally pick the first recursive call we find + let recursive_call = recursive_call + .or_else(|| TrmcEnv::is_recursive_expr(expr, function_name).map(|_| *symbol)); - stack.push((recursive_call, next)); - } - Stmt::Switch { - branches, - default_branch, - .. - } => { - for (_, _, stmt) in branches.iter() { - stack.push((recursive_call, stmt)); + has_cons_in_tail_position(next, function_name, recursive_call) + } + Stmt::Switch { + branches, + default_branch, + .. + } => { + let it = branches + .iter() + .map(|(_, _, stmt)| stmt) + .chain([default_branch.1]); + + let mut accum = SymbolUse::NotUsed; + + for next in it { + let x = has_cons_in_tail_position(next, function_name, recursive_call); + accum = accum.mappend(x); + + if let SymbolUse::Used = accum { + return SymbolUse::Used; } - stack.push((recursive_call, default_branch.1)); - } - Stmt::Refcounting(_, next) => { - stack.push((recursive_call, next)); - } - Stmt::Expect { remainder, .. } - | Stmt::ExpectFx { remainder, .. } - | Stmt::Dbg { remainder, .. } => { - stack.push((recursive_call, remainder)); } - Stmt::Join { - body, remainder, .. - } => { - stack.push((recursive_call, body)); - stack.push((recursive_call, remainder)); + + accum + } + Stmt::Refcounting(_, next) => { + has_cons_in_tail_position(next, function_name, recursive_call) + } + Stmt::Expect { remainder, .. } + | Stmt::ExpectFx { remainder, .. } + | Stmt::Dbg { remainder, .. } => { + has_cons_in_tail_position(remainder, function_name, recursive_call) + } + Stmt::Join { + body, remainder, .. + } => { + let x = has_cons_in_tail_position(body, function_name, recursive_call); + + if let SymbolUse::Used = x { + SymbolUse::Used + } else { + let y = has_cons_in_tail_position(remainder, function_name, recursive_call); + x.mappend(y) } - Stmt::Ret(_) | Stmt::Jump(_, _) | Stmt::Crash(_, _) => { /* terminal */ } } + Stmt::Ret(_) | Stmt::Jump(_, _) | Stmt::Crash(_, _) => SymbolUse::NotUsed, } - - false } #[derive(Clone)] @@ -678,9 +735,16 @@ impl<'a> TrmcEnv<'a> { Stmt::Let(symbol, expr, layout, next) => { if self.recursive_call.is_none() { if let Some(call) = Self::is_recursive_expr(expr, self.function_name) { - if has_cons_in_tail_position(next, self.function_name, Some(*symbol)) { - self.recursive_call = Some((*symbol, call)); - return self.walk_stmt(env, next); + let can_trmc = + has_cons_in_tail_position(next, self.function_name, Some(*symbol)); + + match can_trmc { + SymbolUse::NotUsed => { /* the variable is dead */ } + SymbolUse::TrmcOppotunity => { + self.recursive_call = Some((*symbol, call)); + return self.walk_stmt(env, next); + } + SymbolUse::Used => { /* the variable is used making TRMC invaid */ } } } } @@ -911,3 +975,51 @@ impl<'a> TrmcEnv<'a> { ) } } + +fn expr_contains_symbol(expr: &Expr, needle: Symbol) -> bool { + match expr { + Expr::Literal(_) => false, + Expr::Call(call) => call.arguments.contains(&needle), + Expr::Tag { arguments, .. } => arguments.contains(&needle), + Expr::Struct(fields) => fields.contains(&needle), + Expr::NullPointer => false, + Expr::StructAtIndex { structure, .. } + | Expr::GetTagId { structure, .. } + | Expr::UnionAtIndex { structure, .. } + | Expr::UnionFieldPtrAtIndex { structure, .. } => needle == *structure, + Expr::Array { elems, .. } => elems.iter().any(|element| match element { + crate::ir::ListLiteralElement::Literal(_) => false, + crate::ir::ListLiteralElement::Symbol(symbol) => needle == *symbol, + }), + Expr::EmptyArray => false, + Expr::ExprBox { symbol } | Expr::ExprUnbox { symbol } => needle == *symbol, + Expr::Reuse { + symbol, arguments, .. + } => needle == *symbol || arguments.contains(&needle), + Expr::Reset { symbol, .. } | Expr::ResetRef { symbol, .. } => needle == *symbol, + Expr::RuntimeErrorFunction(_) => false, + } +} + +fn stmt_contains_symbol_nonrec(stmt: &Stmt, needle: Symbol) -> bool { + use crate::ir::ModifyRc::*; + + match stmt { + Stmt::Let(_, expr, _, _) => expr_contains_symbol(expr, needle), + Stmt::Switch { cond_symbol, .. } => needle == *cond_symbol, + Stmt::Ret(symbol) => needle == *symbol, + Stmt::Refcounting(modify, _) => { + matches!( modify, Inc(symbol, _) | Dec(symbol) | DecRef(symbol) if needle == *symbol ) + } + Stmt::Expect { + condition, lookups, .. + } + | Stmt::ExpectFx { + condition, lookups, .. + } => needle == *condition || lookups.contains(&needle), + Stmt::Dbg { symbol, .. } => needle == *symbol, + Stmt::Join { .. } => false, + Stmt::Jump(_, arguments) => arguments.contains(&needle), + Stmt::Crash(symbol, _) => needle == *symbol, + } +} From bb335469e048de7ce7d5eee953c88f688c66c22d Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 21 Jun 2023 00:55:58 +0200 Subject: [PATCH 034/140] working wasm implementation (for one example) --- crates/compiler/gen_wasm/src/backend.rs | 36 ++++++++++++++++------ crates/compiler/gen_wasm/src/low_level.rs | 37 ++++++----------------- 2 files changed, 36 insertions(+), 37 deletions(-) diff --git a/crates/compiler/gen_wasm/src/backend.rs b/crates/compiler/gen_wasm/src/backend.rs index e288774ad40..4997e54426d 100644 --- a/crates/compiler/gen_wasm/src/backend.rs +++ b/crates/compiler/gen_wasm/src/backend.rs @@ -1084,7 +1084,14 @@ impl<'a, 'r> WasmBackend<'a, 'r> { tag_id, union_layout, index, - } => self.expr_union_field_ptr_at_index(*structure, *tag_id, union_layout, *index, sym), + } => self.expr_union_field_ptr_at_index( + *structure, + *tag_id, + union_layout, + *index, + sym, + storage, + ), Expr::ExprBox { symbol: arg_sym } => self.expr_box(sym, *arg_sym, layout, storage), @@ -1885,6 +1892,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> { union_layout: &UnionLayout<'a>, index: u64, symbol: Symbol, + storage: &StoredValue, ) { use UnionLayout::*; @@ -1934,18 +1942,28 @@ impl<'a, 'r> WasmBackend<'a, 'r> { let stores_tag_id_in_pointer = union_layout.stores_tag_id_in_pointer(TARGET_INFO); - let from_addr_val = if stores_tag_id_in_pointer { - self.code_builder.get_local(tag_local_id); + let from_offset = tag_offset + field_offset; + + self.code_builder.get_local(tag_local_id); + + if stores_tag_id_in_pointer { self.code_builder.i32_const(-4); // 11111111...1100 self.code_builder.i32_and(); - AddressValue::Loaded - } else { - AddressValue::NotLoaded(tag_local_id) - }; + } - let from_offset = tag_offset + field_offset; + self.code_builder.i32_const(from_offset as _); + self.code_builder.i32_add(); + + let symbol_local = match self.storage.ensure_value_has_local( + &mut self.code_builder, + symbol, + storage.clone(), + ) { + StoredValue::Local { local_id, .. } => local_id, + _ => internal_error!("A heap pointer will always be an i32"), + }; - self.code_builder.i32_const(from_offset as i32); + self.code_builder.set_local(symbol_local); } /******************************************************************* diff --git a/crates/compiler/gen_wasm/src/low_level.rs b/crates/compiler/gen_wasm/src/low_level.rs index dbd04fdd277..8e76474d6dd 100644 --- a/crates/compiler/gen_wasm/src/low_level.rs +++ b/crates/compiler/gen_wasm/src/low_level.rs @@ -1962,42 +1962,25 @@ impl<'a> LowLevelCall<'a> { PtrStore => { // PtrStore : Ptr a, a -> {} - let ptr_sym = self.arguments[0]; - let value_sym = self.arguments[1]; + let ptr = self.arguments[0]; + let value = self.arguments[1]; - // create a local variable for the heap pointer - let ptr_local_id = match backend.storage.ensure_value_has_local( - &mut backend.code_builder, - ptr_sym, - self.ret_storage.clone(), - ) { - StoredValue::Local { local_id, .. } => local_id, - StoredValue::StackMemory { location, .. } => { - location - .local_and_offset(backend.storage.stack_frame_pointer) - .0 - } - other => internal_error!( - "Struct should be allocated in stack memory, but it's in {:?}", - other - ), + let (ptr_local_id, offset) = match backend.storage.get(&ptr) { + StoredValue::Local { local_id, .. } => (*local_id, 0), + _ => internal_error!("A pointer will always be an i32"), }; - dbg!(ptr_local_id); - - // store the pointer value from the value stack into the local variable - backend.code_builder.set_local(ptr_local_id); - // copy the argument to the pointer address backend.storage.copy_value_to_memory( &mut backend.code_builder, ptr_local_id, - 0, - value_sym, + offset, + value, ); } PtrLoad => backend.expr_unbox(self.ret_symbol, self.arguments[0]), PtrToStackValue => { + // PtrToStackValue : a -> Ptr a let arg = self.arguments[0]; let arg_layout = backend.storage.symbol_layouts.get(&arg).unwrap(); @@ -2009,6 +1992,7 @@ impl<'a> LowLevelCall<'a> { .storage .allocate_anonymous_stack_memory(size, alignment_bytes); + // write the default value into the stack memory backend.storage.copy_value_to_memory( &mut backend.code_builder, frame_ptr, @@ -2026,9 +2010,6 @@ impl<'a> LowLevelCall<'a> { _ => internal_error!("A pointer will always be an i32"), }; - // store the pointer value from the value stack into the local variable - dbg!(offset, size, alignment_bytes); - backend.code_builder.get_local(frame_ptr); backend.code_builder.i32_const(offset as i32); backend.code_builder.i32_add(); From b9b486e4b0301bdc717c16b124268c3ef6816034 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 21 Jun 2023 00:56:37 +0200 Subject: [PATCH 035/140] clean up linked_list_trmc test --- crates/compiler/test_gen/src/gen_primitives.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/crates/compiler/test_gen/src/gen_primitives.rs b/crates/compiler/test_gen/src/gen_primitives.rs index 371825d1f27..952a4a61d78 100644 --- a/crates/compiler/test_gen/src/gen_primitives.rs +++ b/crates/compiler/test_gen/src/gen_primitives.rs @@ -4510,17 +4510,11 @@ fn linked_list_trmc() { LinkedList a : [Nil, Cons a (LinkedList a)] - # map : LinkedList a, (a -> b) -> LinkedList b - # map = \list, f -> - # when list is - # Nil -> Nil - # Cons x xs -> Cons (f x) (map xs f) - - unfold : a, Nat -> LinkedList a - unfold = \value, n -> + repeat : a, Nat -> LinkedList a + repeat = \value, n -> when n is 0 -> Nil - _ -> Cons value (unfold value (n - 1)) + _ -> Cons value (repeat value (n - 1)) length : LinkedList a -> I64 length = \list -> @@ -4530,8 +4524,7 @@ fn linked_list_trmc() { main : I64 main = - unfold 32 1 - # |> map (\x -> x + 1i64) + repeat "foo" 5 |> length "# ), From b497c76e4483ffa29368f1958c1af99aa3181e70 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 21 Jun 2023 00:58:36 +0200 Subject: [PATCH 036/140] clippy --- crates/compiler/gen_llvm/src/llvm/lowlevel.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs index 0c862d51cc8..241d0e7a537 100644 --- a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs +++ b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs @@ -56,15 +56,12 @@ use crate::llvm::{ refcounting::PointerToRefcount, }; +use super::{build::Env, convert::zig_dec_type}; use super::{ build::{throw_internal_exception, use_roc_value, FAST_CALL_CONV}, convert::zig_with_overflow_roc_dec, scope::Scope, }; -use super::{ - build::{Env, FunctionSpec}, - convert::zig_dec_type, -}; pub(crate) fn run_low_level<'a, 'ctx>( env: &Env<'a, 'ctx, '_>, @@ -1821,7 +1818,7 @@ fn throw_on_overflow<'ctx>( bd.position_at_end(throw_block); - throw_on_overflow_help(env, result, message); + throw_because_overflow(env, message); bd.position_at_end(then_block); @@ -1829,11 +1826,7 @@ fn throw_on_overflow<'ctx>( .unwrap() } -fn throw_on_overflow_help<'ctx>( - env: &Env<'_, 'ctx, '_>, - result: StructValue<'ctx>, // of the form { value: T, has_overflowed: bool } - message: &str, -) { +fn throw_because_overflow<'ctx>(env: &Env<'_, 'ctx, '_>, message: &str) { let block = env.builder.get_insert_block().expect("to be in a function"); let di_location = env.builder.get_current_debug_location().unwrap(); From 8fc4a426646549aee85814b57557b412b8c96417 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 21 Jun 2023 01:23:33 +0200 Subject: [PATCH 037/140] spelling --- crates/compiler/gen_dev/src/generic64/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/compiler/gen_dev/src/generic64/mod.rs b/crates/compiler/gen_dev/src/generic64/mod.rs index 8d94425cdff..d19fc976890 100644 --- a/crates/compiler/gen_dev/src/generic64/mod.rs +++ b/crates/compiler/gen_dev/src/generic64/mod.rs @@ -3008,7 +3008,7 @@ impl< value: Symbol, element_layout: InLayout<'a>, ) { - // 1. aquire some stack space + // 1. acquire some stack space let element_width = self.interner().stack_size(element_layout); let allocation = self.debug_symbol("stack_allocation"); let ptr = self.debug_symbol("ptr"); From f797b59d82d6765ee769aab669cfb453d39e54f9 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 21 Jun 2023 01:23:47 +0200 Subject: [PATCH 038/140] mono test --- .../test_mono/generated/rb_tree_fbip.txt | 793 +++++++++--------- 1 file changed, 379 insertions(+), 414 deletions(-) diff --git a/crates/compiler/test_mono/generated/rb_tree_fbip.txt b/crates/compiler/test_mono/generated/rb_tree_fbip.txt index 58b1e0a37fe..a56c6fd2faa 100644 --- a/crates/compiler/test_mono/generated/rb_tree_fbip.txt +++ b/crates/compiler/test_mono/generated/rb_tree_fbip.txt @@ -6,450 +6,415 @@ procedure Num.24 (#Attr.2, #Attr.3): let Num.293 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; ret Num.293; -procedure Test.3 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): - let #Derived_gen.4 : [C *self I64 *self I32 Int1, ] = NullPointer; - let #Derived_gen.3 : Ptr([C *self I64 *self I32 Int1, ]) = lowlevel PtrToStackValue #Derived_gen.4; - joinpoint #Derived_gen.5 Test.9 Test.10 Test.11 #Derived_gen.6: - let Test.254 : U8 = 0i64; - let Test.255 : U8 = GetTagId Test.9; - let Test.256 : Int1 = lowlevel Eq Test.254 Test.255; - if Test.256 then - let Test.113 : [C *self I64 *self I32 Int1, ] = TagId(0) ; - let Test.114 : [C *self I64 *self I32 Int1, ] = TagId(0) ; - let Test.112 : Int1 = true; - let Test.111 : [C *self I64 *self I32 Int1, ] = TagId(1) Test.113 Test.11 Test.114 Test.10 Test.112; - let #Derived_gen.8 : {} = lowlevel PtrStore #Derived_gen.6 Test.111; - let #Derived_gen.7 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; - ret #Derived_gen.7; - else - let Test.251 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.9; - let Test.252 : Int1 = false; - let Test.253 : Int1 = lowlevel Eq Test.252 Test.251; - if Test.253 then - let Test.16 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.9; - let Test.18 : I64 = UnionAtIndex (Id 1) (Index 1) Test.9; - let Test.19 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.9; - let Test.17 : I32 = UnionAtIndex (Id 1) (Index 3) Test.9; - joinpoint #Derived_gen.109 #Derived_gen.114: - let Test.179 : Int1 = CallByName Num.22 Test.10 Test.17; - if Test.179 then - joinpoint Test.238 #Derived_gen.176: - let Test.233 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.16 Test.10 Test.11; - let Test.232 : Int1 = false; - let Test.231 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.176 UpdateModeId { id: 56 } TagId(1) Test.233 Test.18 Test.19 Test.17 Test.232; - let #Derived_gen.10 : {} = lowlevel PtrStore #Derived_gen.6 Test.231; - let #Derived_gen.9 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; - ret #Derived_gen.9; - in - let Test.236 : U8 = 1i64; - let Test.237 : U8 = GetTagId Test.16; - let Test.240 : Int1 = lowlevel Eq Test.236 Test.237; - if Test.240 then - let Test.234 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.16; - let Test.235 : Int1 = true; - let Test.239 : Int1 = lowlevel Eq Test.235 Test.234; - if Test.239 then - let Test.180 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.16 Test.10 Test.11; - joinpoint Test.199 #Derived_gen.203: - let Test.198 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.20 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.198; - inc Test.20; - let Test.22 : I64 = UnionAtIndex (Id 1) (Index 1) Test.198; - let Test.23 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.198; - inc Test.23; - let Test.21 : I32 = UnionAtIndex (Id 1) (Index 3) Test.198; - let Test.25 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; - let Test.26 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; - let Test.24 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; - joinpoint #Derived_gen.67 #Derived_gen.206 #Derived_gen.207 #Derived_gen.208: - let Test.186 : Int1 = false; - let Test.183 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.208 UpdateModeId { id: 85 } TagId(1) Test.20 Test.22 Test.23 Test.21 Test.186; - let Test.185 : Int1 = false; - let Test.184 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.207 UpdateModeId { id: 84 } TagId(1) Test.26 Test.18 Test.19 Test.17 Test.185; - let Test.182 : Int1 = true; - let Test.181 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.206 UpdateModeId { id: 83 } TagId(1) Test.183 Test.25 Test.184 Test.24 Test.182; - let #Derived_gen.12 : {} = lowlevel PtrStore #Derived_gen.6 Test.181; - let #Derived_gen.11 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; - ret #Derived_gen.11; +procedure Test.3 (Test.9, Test.10, Test.11): + let Test.254 : U8 = 0i64; + let Test.255 : U8 = GetTagId Test.9; + let Test.256 : Int1 = lowlevel Eq Test.254 Test.255; + if Test.256 then + let Test.113 : [C *self I64 *self I32 Int1, ] = TagId(0) ; + let Test.114 : [C *self I64 *self I32 Int1, ] = TagId(0) ; + let Test.112 : Int1 = true; + let Test.111 : [C *self I64 *self I32 Int1, ] = TagId(1) Test.113 Test.11 Test.114 Test.10 Test.112; + ret Test.111; + else + let Test.251 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.9; + let Test.252 : Int1 = false; + let Test.253 : Int1 = lowlevel Eq Test.252 Test.251; + if Test.253 then + let Test.16 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.9; + let Test.18 : I64 = UnionAtIndex (Id 1) (Index 1) Test.9; + let Test.19 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.9; + let Test.17 : I32 = UnionAtIndex (Id 1) (Index 3) Test.9; + joinpoint #Derived_gen.75 #Derived_gen.80: + let Test.179 : Int1 = CallByName Num.22 Test.10 Test.17; + if Test.179 then + joinpoint Test.238 #Derived_gen.142: + let Test.233 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.16 Test.10 Test.11; + let Test.232 : Int1 = false; + let Test.231 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.142 UpdateModeId { id: 56 } TagId(1) Test.233 Test.18 Test.19 Test.17 Test.232; + ret Test.231; + in + let Test.236 : U8 = 1i64; + let Test.237 : U8 = GetTagId Test.16; + let Test.240 : Int1 = lowlevel Eq Test.236 Test.237; + if Test.240 then + let Test.234 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.16; + let Test.235 : Int1 = true; + let Test.239 : Int1 = lowlevel Eq Test.235 Test.234; + if Test.239 then + let Test.180 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.16 Test.10 Test.11; + joinpoint Test.199 #Derived_gen.169: + let Test.198 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.20 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.198; + inc Test.20; + let Test.22 : I64 = UnionAtIndex (Id 1) (Index 1) Test.198; + let Test.23 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.198; + inc Test.23; + let Test.21 : I32 = UnionAtIndex (Id 1) (Index 3) Test.198; + let Test.25 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; + let Test.26 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; + let Test.24 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; + joinpoint #Derived_gen.33 #Derived_gen.172 #Derived_gen.173 #Derived_gen.174: + let Test.186 : Int1 = false; + let Test.183 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.174 UpdateModeId { id: 85 } TagId(1) Test.20 Test.22 Test.23 Test.21 Test.186; + let Test.185 : Int1 = false; + let Test.184 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.173 UpdateModeId { id: 84 } TagId(1) Test.26 Test.18 Test.19 Test.17 Test.185; + let Test.182 : Int1 = true; + let Test.181 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.172 UpdateModeId { id: 83 } TagId(1) Test.183 Test.25 Test.184 Test.24 Test.182; + ret Test.181; + in + let #Derived_gen.34 : Int1 = lowlevel RefCountIsUnique Test.180; + if #Derived_gen.34 then + let #Derived_gen.175 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.198, id: UpdateModeId { id: 86 } }; + let #Derived_gen.176 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 87 } }; + jump #Derived_gen.33 #Derived_gen.169 #Derived_gen.175 #Derived_gen.176; + else + inc Test.26; + decref Test.180; + let #Derived_gen.177 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.33 #Derived_gen.177 #Derived_gen.177 #Derived_gen.169; + in + let Test.228 : U8 = 1i64; + let Test.229 : U8 = GetTagId Test.180; + let Test.230 : Int1 = lowlevel Eq Test.228 Test.229; + if Test.230 then + joinpoint Test.225 #Derived_gen.187: + joinpoint Test.216 #Derived_gen.188: + let Test.46 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.48 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; + let Test.49 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; + let Test.47 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; + joinpoint #Derived_gen.27 #Derived_gen.190 #Derived_gen.191: + let Test.196 : Int1 = true; + let Test.195 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.191 UpdateModeId { id: 100 } TagId(1) Test.46 Test.48 Test.49 Test.47 Test.196; + let Test.194 : Int1 = false; + let Test.193 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.190 UpdateModeId { id: 99 } TagId(1) Test.195 Test.18 Test.19 Test.17 Test.194; + ret Test.193; + in + let #Derived_gen.28 : Int1 = lowlevel RefCountIsUnique Test.180; + if #Derived_gen.28 then + let #Derived_gen.192 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 101 } }; + jump #Derived_gen.27 #Derived_gen.188 #Derived_gen.192; + else + inc Test.46; + inc Test.49; + decref Test.180; + let #Derived_gen.193 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.27 #Derived_gen.193 #Derived_gen.188; in - let #Derived_gen.68 : Int1 = lowlevel RefCountIsUnique Test.180; - if #Derived_gen.68 then - let #Derived_gen.209 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.198, id: UpdateModeId { id: 86 } }; - let #Derived_gen.210 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 87 } }; - jump #Derived_gen.67 #Derived_gen.203 #Derived_gen.209 #Derived_gen.210; + let Test.213 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.214 : U8 = 1i64; + let Test.215 : U8 = GetTagId Test.213; + let Test.218 : Int1 = lowlevel Eq Test.214 Test.215; + if Test.218 then + let Test.210 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.211 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.210; + let Test.212 : Int1 = true; + let Test.217 : Int1 = lowlevel Eq Test.212 Test.211; + if Test.217 then + jump Test.199 #Derived_gen.187; + else + jump Test.216 #Derived_gen.187; else - inc Test.26; - decref Test.180; - let #Derived_gen.211 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.67 #Derived_gen.211 #Derived_gen.211 #Derived_gen.203; + jump Test.216 #Derived_gen.187; in - let Test.228 : U8 = 1i64; - let Test.229 : U8 = GetTagId Test.180; - let Test.230 : Int1 = lowlevel Eq Test.228 Test.229; - if Test.230 then - joinpoint Test.225 #Derived_gen.221: - joinpoint Test.216 #Derived_gen.222: - let Test.46 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.48 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; - let Test.49 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; - let Test.47 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; - joinpoint #Derived_gen.61 #Derived_gen.224 #Derived_gen.225: - let Test.196 : Int1 = true; - let Test.195 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.225 UpdateModeId { id: 100 } TagId(1) Test.46 Test.48 Test.49 Test.47 Test.196; - let Test.194 : Int1 = false; - let Test.193 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.224 UpdateModeId { id: 99 } TagId(1) Test.195 Test.18 Test.19 Test.17 Test.194; - let #Derived_gen.14 : {} = lowlevel PtrStore #Derived_gen.6 Test.193; - let #Derived_gen.13 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; - ret #Derived_gen.13; + let Test.222 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; + let Test.223 : U8 = 1i64; + let Test.224 : U8 = GetTagId Test.222; + let Test.227 : Int1 = lowlevel Eq Test.223 Test.224; + if Test.227 then + let Test.219 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; + let Test.220 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.219; + let Test.221 : Int1 = true; + let Test.226 : Int1 = lowlevel Eq Test.221 Test.220; + if Test.226 then + joinpoint Test.207 #Derived_gen.194: + let Test.33 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.35 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; + let Test.200 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; + let Test.36 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.200; + inc Test.36; + let Test.38 : I64 = UnionAtIndex (Id 1) (Index 1) Test.200; + let Test.39 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.200; + inc Test.39; + let Test.37 : I32 = UnionAtIndex (Id 1) (Index 3) Test.200; + let Test.34 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; + joinpoint #Derived_gen.31 #Derived_gen.197 #Derived_gen.198 #Derived_gen.199: + let Test.192 : Int1 = false; + let Test.189 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.199 UpdateModeId { id: 107 } TagId(1) Test.33 Test.35 Test.36 Test.34 Test.192; + let Test.191 : Int1 = false; + let Test.190 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.198 UpdateModeId { id: 106 } TagId(1) Test.39 Test.18 Test.19 Test.17 Test.191; + let Test.188 : Int1 = true; + let Test.187 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.197 UpdateModeId { id: 105 } TagId(1) Test.189 Test.38 Test.190 Test.37 Test.188; + ret Test.187; in - let #Derived_gen.62 : Int1 = lowlevel RefCountIsUnique Test.180; - if #Derived_gen.62 then - let #Derived_gen.226 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 101 } }; - jump #Derived_gen.61 #Derived_gen.222 #Derived_gen.226; + let #Derived_gen.32 : Int1 = lowlevel RefCountIsUnique Test.180; + if #Derived_gen.32 then + let #Derived_gen.200 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.200, id: UpdateModeId { id: 108 } }; + let #Derived_gen.201 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 109 } }; + jump #Derived_gen.31 #Derived_gen.194 #Derived_gen.200 #Derived_gen.201; else - inc Test.46; - inc Test.49; + inc Test.33; decref Test.180; - let #Derived_gen.227 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.61 #Derived_gen.227 #Derived_gen.222; + let #Derived_gen.202 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.31 #Derived_gen.202 #Derived_gen.202 #Derived_gen.194; in - let Test.213 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.214 : U8 = 1i64; - let Test.215 : U8 = GetTagId Test.213; - let Test.218 : Int1 = lowlevel Eq Test.214 Test.215; - if Test.218 then - let Test.210 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.211 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.210; - let Test.212 : Int1 = true; - let Test.217 : Int1 = lowlevel Eq Test.212 Test.211; - if Test.217 then - jump Test.199 #Derived_gen.221; - else - jump Test.216 #Derived_gen.221; - else - jump Test.216 #Derived_gen.221; - in - let Test.222 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; - let Test.223 : U8 = 1i64; - let Test.224 : U8 = GetTagId Test.222; - let Test.227 : Int1 = lowlevel Eq Test.223 Test.224; - if Test.227 then - let Test.219 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; - let Test.220 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.219; - let Test.221 : Int1 = true; - let Test.226 : Int1 = lowlevel Eq Test.221 Test.220; - if Test.226 then - joinpoint Test.207 #Derived_gen.228: - let Test.33 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.35 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; - let Test.200 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; - let Test.36 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.200; - inc Test.36; - let Test.38 : I64 = UnionAtIndex (Id 1) (Index 1) Test.200; - let Test.39 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.200; - inc Test.39; - let Test.37 : I32 = UnionAtIndex (Id 1) (Index 3) Test.200; - let Test.34 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; - joinpoint #Derived_gen.65 #Derived_gen.231 #Derived_gen.232 #Derived_gen.233: - let Test.192 : Int1 = false; - let Test.189 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.233 UpdateModeId { id: 107 } TagId(1) Test.33 Test.35 Test.36 Test.34 Test.192; - let Test.191 : Int1 = false; - let Test.190 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.232 UpdateModeId { id: 106 } TagId(1) Test.39 Test.18 Test.19 Test.17 Test.191; - let Test.188 : Int1 = true; - let Test.187 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.231 UpdateModeId { id: 105 } TagId(1) Test.189 Test.38 Test.190 Test.37 Test.188; - let #Derived_gen.16 : {} = lowlevel PtrStore #Derived_gen.6 Test.187; - let #Derived_gen.15 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; - ret #Derived_gen.15; - in - let #Derived_gen.66 : Int1 = lowlevel RefCountIsUnique Test.180; - if #Derived_gen.66 then - let #Derived_gen.234 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.200, id: UpdateModeId { id: 108 } }; - let #Derived_gen.235 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 109 } }; - jump #Derived_gen.65 #Derived_gen.228 #Derived_gen.234 #Derived_gen.235; - else - inc Test.33; - decref Test.180; - let #Derived_gen.236 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.65 #Derived_gen.236 #Derived_gen.236 #Derived_gen.228; - in - let Test.204 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.205 : U8 = 1i64; - let Test.206 : U8 = GetTagId Test.204; - let Test.209 : Int1 = lowlevel Eq Test.205 Test.206; - if Test.209 then - let Test.201 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.202 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.201; - let Test.203 : Int1 = true; - let Test.208 : Int1 = lowlevel Eq Test.203 Test.202; - if Test.208 then - jump Test.199 #Derived_gen.114; - else - jump Test.207 #Derived_gen.114; + let Test.204 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.205 : U8 = 1i64; + let Test.206 : U8 = GetTagId Test.204; + let Test.209 : Int1 = lowlevel Eq Test.205 Test.206; + if Test.209 then + let Test.201 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.202 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.201; + let Test.203 : Int1 = true; + let Test.208 : Int1 = lowlevel Eq Test.203 Test.202; + if Test.208 then + jump Test.199 #Derived_gen.80; else - jump Test.207 #Derived_gen.114; + jump Test.207 #Derived_gen.80; else - jump Test.225 #Derived_gen.114; + jump Test.207 #Derived_gen.80; else - jump Test.225 #Derived_gen.114; + jump Test.225 #Derived_gen.80; else - decref #Derived_gen.114; - dec Test.19; - let Test.197 : [C *self I64 *self I32 Int1, ] = TagId(0) ; - let #Derived_gen.18 : {} = lowlevel PtrStore #Derived_gen.6 Test.197; - let #Derived_gen.17 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; - ret #Derived_gen.17; + jump Test.225 #Derived_gen.80; else - jump Test.238 #Derived_gen.114; + decref #Derived_gen.80; + dec Test.19; + let Test.197 : [C *self I64 *self I32 Int1, ] = TagId(0) ; + ret Test.197; else - jump Test.238 #Derived_gen.114; + jump Test.238 #Derived_gen.80; else - let Test.117 : Int1 = CallByName Num.24 Test.10 Test.17; - if Test.117 then - joinpoint Test.176 #Derived_gen.328: - let Test.171 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.19 Test.10 Test.11; - let Test.170 : Int1 = false; - let Test.169 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.328 UpdateModeId { id: 196 } TagId(1) Test.16 Test.18 Test.171 Test.17 Test.170; - let #Derived_gen.20 : {} = lowlevel PtrStore #Derived_gen.6 Test.169; - let #Derived_gen.19 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; - ret #Derived_gen.19; - in - let Test.174 : U8 = 1i64; - let Test.175 : U8 = GetTagId Test.19; - let Test.178 : Int1 = lowlevel Eq Test.174 Test.175; - if Test.178 then - let Test.172 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.19; - let Test.173 : Int1 = true; - let Test.177 : Int1 = lowlevel Eq Test.173 Test.172; - if Test.177 then - inc Test.19; - let #Derived_gen.329 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.16, id: UpdateModeId { id: 197 } }; - let Test.118 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.19 Test.10 Test.11; - joinpoint Test.137 #Derived_gen.369 #Derived_gen.370: - let Test.136 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.57 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.136; - inc Test.57; - let Test.59 : I64 = UnionAtIndex (Id 1) (Index 1) Test.136; - let Test.60 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.136; - inc Test.60; - let Test.58 : I32 = UnionAtIndex (Id 1) (Index 3) Test.136; - let Test.62 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; - let Test.63 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; - let Test.61 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; - joinpoint #Derived_gen.107 #Derived_gen.374 #Derived_gen.375 #Derived_gen.376: - let Test.124 : Int1 = false; - let Test.121 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.376 UpdateModeId { id: 242 } TagId(1) Test.57 Test.59 Test.60 Test.58 Test.124; - let Test.123 : Int1 = false; - let Test.122 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.375 UpdateModeId { id: 241 } TagId(1) Test.63 Test.18 Test.19 Test.17 Test.123; - let Test.120 : Int1 = true; - let Test.119 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.374 UpdateModeId { id: 240 } TagId(1) Test.121 Test.62 Test.122 Test.61 Test.120; - let #Derived_gen.22 : {} = lowlevel PtrStore #Derived_gen.6 Test.119; - let #Derived_gen.21 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; - ret #Derived_gen.21; + jump Test.238 #Derived_gen.80; + else + let Test.117 : Int1 = CallByName Num.24 Test.10 Test.17; + if Test.117 then + joinpoint Test.176 #Derived_gen.294: + let Test.171 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.19 Test.10 Test.11; + let Test.170 : Int1 = false; + let Test.169 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.294 UpdateModeId { id: 196 } TagId(1) Test.16 Test.18 Test.171 Test.17 Test.170; + ret Test.169; + in + let Test.174 : U8 = 1i64; + let Test.175 : U8 = GetTagId Test.19; + let Test.178 : Int1 = lowlevel Eq Test.174 Test.175; + if Test.178 then + let Test.172 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.19; + let Test.173 : Int1 = true; + let Test.177 : Int1 = lowlevel Eq Test.173 Test.172; + if Test.177 then + inc Test.19; + let #Derived_gen.295 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.16, id: UpdateModeId { id: 197 } }; + let Test.118 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.19 Test.10 Test.11; + joinpoint Test.137 #Derived_gen.335 #Derived_gen.336: + let Test.136 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.57 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.136; + inc Test.57; + let Test.59 : I64 = UnionAtIndex (Id 1) (Index 1) Test.136; + let Test.60 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.136; + inc Test.60; + let Test.58 : I32 = UnionAtIndex (Id 1) (Index 3) Test.136; + let Test.62 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; + let Test.63 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; + let Test.61 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; + joinpoint #Derived_gen.73 #Derived_gen.340 #Derived_gen.341 #Derived_gen.342: + let Test.124 : Int1 = false; + let Test.121 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.342 UpdateModeId { id: 242 } TagId(1) Test.57 Test.59 Test.60 Test.58 Test.124; + let Test.123 : Int1 = false; + let Test.122 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.341 UpdateModeId { id: 241 } TagId(1) Test.63 Test.18 Test.19 Test.17 Test.123; + let Test.120 : Int1 = true; + let Test.119 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.340 UpdateModeId { id: 240 } TagId(1) Test.121 Test.62 Test.122 Test.61 Test.120; + ret Test.119; + in + let #Derived_gen.74 : Int1 = lowlevel RefCountIsUnique Test.118; + if #Derived_gen.74 then + decref #Derived_gen.335; + let #Derived_gen.343 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.136, id: UpdateModeId { id: 243 } }; + let #Derived_gen.344 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 244 } }; + jump #Derived_gen.73 #Derived_gen.336 #Derived_gen.343 #Derived_gen.344; + else + inc Test.63; + decref Test.118; + let #Derived_gen.345 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.73 #Derived_gen.345 #Derived_gen.335 #Derived_gen.336; + in + let Test.166 : U8 = 1i64; + let Test.167 : U8 = GetTagId Test.118; + let Test.168 : Int1 = lowlevel Eq Test.166 Test.167; + if Test.168 then + joinpoint Test.163 #Derived_gen.357 #Derived_gen.358: + joinpoint Test.154 #Derived_gen.359 #Derived_gen.360: + let Test.83 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.85 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; + let Test.86 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; + let Test.84 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; + joinpoint #Derived_gen.63 #Derived_gen.363 #Derived_gen.364: + let Test.134 : Int1 = true; + let Test.133 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.364 UpdateModeId { id: 262 } TagId(1) Test.83 Test.85 Test.86 Test.84 Test.134; + let Test.132 : Int1 = false; + let Test.131 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.363 UpdateModeId { id: 261 } TagId(1) Test.133 Test.18 Test.19 Test.17 Test.132; + ret Test.131; + in + let #Derived_gen.64 : Int1 = lowlevel RefCountIsUnique Test.118; + if #Derived_gen.64 then + decref #Derived_gen.359; + let #Derived_gen.365 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 263 } }; + jump #Derived_gen.63 #Derived_gen.360 #Derived_gen.365; + else + inc Test.83; + inc Test.86; + decref Test.118; + jump #Derived_gen.63 #Derived_gen.359 #Derived_gen.360; in - let #Derived_gen.108 : Int1 = lowlevel RefCountIsUnique Test.118; - if #Derived_gen.108 then - decref #Derived_gen.369; - let #Derived_gen.377 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.136, id: UpdateModeId { id: 243 } }; - let #Derived_gen.378 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 244 } }; - jump #Derived_gen.107 #Derived_gen.370 #Derived_gen.377 #Derived_gen.378; + let Test.151 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.152 : U8 = 1i64; + let Test.153 : U8 = GetTagId Test.151; + let Test.156 : Int1 = lowlevel Eq Test.152 Test.153; + if Test.156 then + let Test.148 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.149 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.148; + let Test.150 : Int1 = true; + let Test.155 : Int1 = lowlevel Eq Test.150 Test.149; + if Test.155 then + jump Test.137 #Derived_gen.357 #Derived_gen.358; + else + jump Test.154 #Derived_gen.357 #Derived_gen.358; else - inc Test.63; - decref Test.118; - let #Derived_gen.379 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.107 #Derived_gen.379 #Derived_gen.369 #Derived_gen.370; + jump Test.154 #Derived_gen.357 #Derived_gen.358; in - let Test.166 : U8 = 1i64; - let Test.167 : U8 = GetTagId Test.118; - let Test.168 : Int1 = lowlevel Eq Test.166 Test.167; - if Test.168 then - joinpoint Test.163 #Derived_gen.391 #Derived_gen.392: - joinpoint Test.154 #Derived_gen.393 #Derived_gen.394: - let Test.83 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.85 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; - let Test.86 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; - let Test.84 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; - joinpoint #Derived_gen.97 #Derived_gen.397 #Derived_gen.398: - let Test.134 : Int1 = true; - let Test.133 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.398 UpdateModeId { id: 262 } TagId(1) Test.83 Test.85 Test.86 Test.84 Test.134; - let Test.132 : Int1 = false; - let Test.131 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.397 UpdateModeId { id: 261 } TagId(1) Test.133 Test.18 Test.19 Test.17 Test.132; - let #Derived_gen.24 : {} = lowlevel PtrStore #Derived_gen.6 Test.131; - let #Derived_gen.23 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; - ret #Derived_gen.23; + let Test.160 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; + let Test.161 : U8 = 1i64; + let Test.162 : U8 = GetTagId Test.160; + let Test.165 : Int1 = lowlevel Eq Test.161 Test.162; + if Test.165 then + let Test.157 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; + let Test.158 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.157; + let Test.159 : Int1 = true; + let Test.164 : Int1 = lowlevel Eq Test.159 Test.158; + if Test.164 then + joinpoint Test.145 #Derived_gen.366 #Derived_gen.367: + let Test.70 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.72 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; + let Test.138 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; + let Test.73 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.138; + inc Test.73; + let Test.75 : I64 = UnionAtIndex (Id 1) (Index 1) Test.138; + let Test.76 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.138; + inc Test.76; + let Test.74 : I32 = UnionAtIndex (Id 1) (Index 3) Test.138; + let Test.71 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; + joinpoint #Derived_gen.67 #Derived_gen.371 #Derived_gen.372 #Derived_gen.373: + let Test.130 : Int1 = false; + let Test.127 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.373 UpdateModeId { id: 271 } TagId(1) Test.70 Test.72 Test.73 Test.71 Test.130; + let Test.129 : Int1 = false; + let Test.128 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.372 UpdateModeId { id: 270 } TagId(1) Test.76 Test.18 Test.19 Test.17 Test.129; + let Test.126 : Int1 = true; + let Test.125 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.371 UpdateModeId { id: 269 } TagId(1) Test.127 Test.75 Test.128 Test.74 Test.126; + ret Test.125; in - let #Derived_gen.98 : Int1 = lowlevel RefCountIsUnique Test.118; - if #Derived_gen.98 then - decref #Derived_gen.393; - let #Derived_gen.399 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 263 } }; - jump #Derived_gen.97 #Derived_gen.394 #Derived_gen.399; + let #Derived_gen.68 : Int1 = lowlevel RefCountIsUnique Test.118; + if #Derived_gen.68 then + decref #Derived_gen.366; + let #Derived_gen.374 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.138, id: UpdateModeId { id: 272 } }; + let #Derived_gen.375 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 273 } }; + jump #Derived_gen.67 #Derived_gen.367 #Derived_gen.374 #Derived_gen.375; else - inc Test.83; - inc Test.86; + inc Test.70; decref Test.118; - jump #Derived_gen.97 #Derived_gen.393 #Derived_gen.394; + let #Derived_gen.376 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.67 #Derived_gen.376 #Derived_gen.366 #Derived_gen.367; in - let Test.151 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.152 : U8 = 1i64; - let Test.153 : U8 = GetTagId Test.151; - let Test.156 : Int1 = lowlevel Eq Test.152 Test.153; - if Test.156 then - let Test.148 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.149 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.148; - let Test.150 : Int1 = true; - let Test.155 : Int1 = lowlevel Eq Test.150 Test.149; - if Test.155 then - jump Test.137 #Derived_gen.391 #Derived_gen.392; - else - jump Test.154 #Derived_gen.391 #Derived_gen.392; - else - jump Test.154 #Derived_gen.391 #Derived_gen.392; - in - let Test.160 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; - let Test.161 : U8 = 1i64; - let Test.162 : U8 = GetTagId Test.160; - let Test.165 : Int1 = lowlevel Eq Test.161 Test.162; - if Test.165 then - let Test.157 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; - let Test.158 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.157; - let Test.159 : Int1 = true; - let Test.164 : Int1 = lowlevel Eq Test.159 Test.158; - if Test.164 then - joinpoint Test.145 #Derived_gen.400 #Derived_gen.401: - let Test.70 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.72 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; - let Test.138 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; - let Test.73 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.138; - inc Test.73; - let Test.75 : I64 = UnionAtIndex (Id 1) (Index 1) Test.138; - let Test.76 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.138; - inc Test.76; - let Test.74 : I32 = UnionAtIndex (Id 1) (Index 3) Test.138; - let Test.71 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; - joinpoint #Derived_gen.101 #Derived_gen.405 #Derived_gen.406 #Derived_gen.407: - let Test.130 : Int1 = false; - let Test.127 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.407 UpdateModeId { id: 271 } TagId(1) Test.70 Test.72 Test.73 Test.71 Test.130; - let Test.129 : Int1 = false; - let Test.128 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.406 UpdateModeId { id: 270 } TagId(1) Test.76 Test.18 Test.19 Test.17 Test.129; - let Test.126 : Int1 = true; - let Test.125 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.405 UpdateModeId { id: 269 } TagId(1) Test.127 Test.75 Test.128 Test.74 Test.126; - let #Derived_gen.26 : {} = lowlevel PtrStore #Derived_gen.6 Test.125; - let #Derived_gen.25 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; - ret #Derived_gen.25; - in - let #Derived_gen.102 : Int1 = lowlevel RefCountIsUnique Test.118; - if #Derived_gen.102 then - decref #Derived_gen.400; - let #Derived_gen.408 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.138, id: UpdateModeId { id: 272 } }; - let #Derived_gen.409 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 273 } }; - jump #Derived_gen.101 #Derived_gen.401 #Derived_gen.408 #Derived_gen.409; - else - inc Test.70; - decref Test.118; - let #Derived_gen.410 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.101 #Derived_gen.410 #Derived_gen.400 #Derived_gen.401; - in - let Test.142 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.143 : U8 = 1i64; - let Test.144 : U8 = GetTagId Test.142; - let Test.147 : Int1 = lowlevel Eq Test.143 Test.144; - if Test.147 then - let Test.139 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.140 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.139; - let Test.141 : Int1 = true; - let Test.146 : Int1 = lowlevel Eq Test.141 Test.140; - if Test.146 then - jump Test.137 #Derived_gen.114 #Derived_gen.329; - else - jump Test.145 #Derived_gen.114 #Derived_gen.329; + let Test.142 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.143 : U8 = 1i64; + let Test.144 : U8 = GetTagId Test.142; + let Test.147 : Int1 = lowlevel Eq Test.143 Test.144; + if Test.147 then + let Test.139 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.140 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.139; + let Test.141 : Int1 = true; + let Test.146 : Int1 = lowlevel Eq Test.141 Test.140; + if Test.146 then + jump Test.137 #Derived_gen.80 #Derived_gen.295; else - jump Test.145 #Derived_gen.114 #Derived_gen.329; + jump Test.145 #Derived_gen.80 #Derived_gen.295; else - jump Test.163 #Derived_gen.114 #Derived_gen.329; + jump Test.145 #Derived_gen.80 #Derived_gen.295; else - jump Test.163 #Derived_gen.114 #Derived_gen.329; + jump Test.163 #Derived_gen.80 #Derived_gen.295; else - decref #Derived_gen.329; - decref #Derived_gen.114; - joinpoint #Derived_gen.103: - let Test.135 : [C *self I64 *self I32 Int1, ] = TagId(0) ; - let #Derived_gen.28 : {} = lowlevel PtrStore #Derived_gen.6 Test.135; - let #Derived_gen.27 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; - ret #Derived_gen.27; - in - let #Derived_gen.106 : Int1 = lowlevel RefCountIsUnique Test.19; - if #Derived_gen.106 then - let #Derived_gen.105 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.19; - dec #Derived_gen.105; - let #Derived_gen.104 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.19; - dec #Derived_gen.104; - decref Test.19; - jump #Derived_gen.103; - else - decref Test.19; - jump #Derived_gen.103; + jump Test.163 #Derived_gen.80 #Derived_gen.295; else - jump Test.176 #Derived_gen.114; + decref #Derived_gen.295; + decref #Derived_gen.80; + joinpoint #Derived_gen.69: + let Test.135 : [C *self I64 *self I32 Int1, ] = TagId(0) ; + ret Test.135; + in + let #Derived_gen.72 : Int1 = lowlevel RefCountIsUnique Test.19; + if #Derived_gen.72 then + let #Derived_gen.71 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.19; + dec #Derived_gen.71; + let #Derived_gen.70 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.19; + dec #Derived_gen.70; + decref Test.19; + jump #Derived_gen.69; + else + decref Test.19; + jump #Derived_gen.69; else - jump Test.176 #Derived_gen.114; + jump Test.176 #Derived_gen.80; else - let Test.116 : Int1 = false; - let Test.115 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.114 UpdateModeId { id: 1 } TagId(1) Test.16 Test.11 Test.19 Test.10 Test.116; - let #Derived_gen.30 : {} = lowlevel PtrStore #Derived_gen.6 Test.115; - let #Derived_gen.29 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; - ret #Derived_gen.29; - in - let #Derived_gen.110 : Int1 = lowlevel RefCountIsUnique Test.9; - if #Derived_gen.110 then - let #Derived_gen.419 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.9, id: UpdateModeId { id: 282 } }; - jump #Derived_gen.109 #Derived_gen.419; - else - inc Test.16; - inc Test.19; - decref Test.9; - let #Derived_gen.420 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.109 #Derived_gen.420; - else - let Test.96 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.9; - let Test.98 : I64 = UnionAtIndex (Id 1) (Index 1) Test.9; - let Test.99 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.9; - let Test.97 : I32 = UnionAtIndex (Id 1) (Index 3) Test.9; - joinpoint #Derived_gen.111 #Derived_gen.422: - let Test.247 : Int1 = CallByName Num.22 Test.10 Test.97; - if Test.247 then - let Test.250 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.96 Test.10 Test.11; - let Test.249 : Int1 = true; - let Test.248 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.422 UpdateModeId { id: 284 } TagId(1) Test.250 Test.98 Test.99 Test.97 Test.249; - let #Derived_gen.32 : {} = lowlevel PtrStore #Derived_gen.6 Test.248; - let #Derived_gen.31 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; - ret #Derived_gen.31; + jump Test.176 #Derived_gen.80; else - let Test.243 : Int1 = CallByName Num.24 Test.10 Test.97; - if Test.243 then - let Test.246 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.99 Test.10 Test.11; - let Test.245 : Int1 = true; - let Test.244 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.422 UpdateModeId { id: 284 } TagId(1) Test.96 Test.98 Test.246 Test.97 Test.245; - let #Derived_gen.34 : {} = lowlevel PtrStore #Derived_gen.6 Test.244; - let #Derived_gen.33 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; - ret #Derived_gen.33; - else - let Test.242 : Int1 = true; - let Test.241 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.422 UpdateModeId { id: 284 } TagId(1) Test.96 Test.11 Test.99 Test.10 Test.242; - let #Derived_gen.36 : {} = lowlevel PtrStore #Derived_gen.6 Test.241; - let #Derived_gen.35 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.3; - ret #Derived_gen.35; - in - let #Derived_gen.112 : Int1 = lowlevel RefCountIsUnique Test.9; - if #Derived_gen.112 then - let #Derived_gen.423 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.9, id: UpdateModeId { id: 285 } }; - jump #Derived_gen.111 #Derived_gen.423; + let Test.116 : Int1 = false; + let Test.115 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.80 UpdateModeId { id: 1 } TagId(1) Test.16 Test.11 Test.19 Test.10 Test.116; + ret Test.115; + in + let #Derived_gen.76 : Int1 = lowlevel RefCountIsUnique Test.9; + if #Derived_gen.76 then + let #Derived_gen.385 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.9, id: UpdateModeId { id: 282 } }; + jump #Derived_gen.75 #Derived_gen.385; + else + inc Test.16; + inc Test.19; + decref Test.9; + let #Derived_gen.386 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.75 #Derived_gen.386; + else + let Test.96 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.9; + let Test.98 : I64 = UnionAtIndex (Id 1) (Index 1) Test.9; + let Test.99 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.9; + let Test.97 : I32 = UnionAtIndex (Id 1) (Index 3) Test.9; + joinpoint #Derived_gen.77 #Derived_gen.388: + let Test.247 : Int1 = CallByName Num.22 Test.10 Test.97; + if Test.247 then + let Test.250 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.96 Test.10 Test.11; + let Test.249 : Int1 = true; + let Test.248 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.388 UpdateModeId { id: 284 } TagId(1) Test.250 Test.98 Test.99 Test.97 Test.249; + ret Test.248; else - inc Test.96; - inc Test.99; - decref Test.9; - let #Derived_gen.424 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.111 #Derived_gen.424; - in - jump #Derived_gen.5 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3; + let Test.243 : Int1 = CallByName Num.24 Test.10 Test.97; + if Test.243 then + let Test.246 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.99 Test.10 Test.11; + let Test.245 : Int1 = true; + let Test.244 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.388 UpdateModeId { id: 284 } TagId(1) Test.96 Test.98 Test.246 Test.97 Test.245; + ret Test.244; + else + let Test.242 : Int1 = true; + let Test.241 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.388 UpdateModeId { id: 284 } TagId(1) Test.96 Test.11 Test.99 Test.10 Test.242; + ret Test.241; + in + let #Derived_gen.78 : Int1 = lowlevel RefCountIsUnique Test.9; + if #Derived_gen.78 then + let #Derived_gen.389 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.9, id: UpdateModeId { id: 285 } }; + jump #Derived_gen.77 #Derived_gen.389; + else + inc Test.96; + inc Test.99; + decref Test.9; + let #Derived_gen.390 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.77 #Derived_gen.390; procedure Test.0 (): let Test.281 : [C *self I64 *self I32 Int1, ] = TagId(0) ; From 2332ec3133aa7030decfbabe55374d7e3db800e3 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 21 Jun 2023 01:26:33 +0200 Subject: [PATCH 039/140] revert debug flags --- crates/compiler/gen_wasm/src/backend.rs | 2 +- crates/compiler/gen_wasm/src/lib.rs | 2 +- examples/platform-switching/rocLovesZig.roc | 27 +-------------------- 3 files changed, 3 insertions(+), 28 deletions(-) diff --git a/crates/compiler/gen_wasm/src/backend.rs b/crates/compiler/gen_wasm/src/backend.rs index 4997e54426d..b333a73999e 100644 --- a/crates/compiler/gen_wasm/src/backend.rs +++ b/crates/compiler/gen_wasm/src/backend.rs @@ -1970,7 +1970,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> { * Box *******************************************************************/ - pub(crate) fn expr_box( + pub fn expr_box( &mut self, ret_sym: Symbol, arg_sym: Symbol, diff --git a/crates/compiler/gen_wasm/src/lib.rs b/crates/compiler/gen_wasm/src/lib.rs index ae86fccc1cd..5dfb7551471 100644 --- a/crates/compiler/gen_wasm/src/lib.rs +++ b/crates/compiler/gen_wasm/src/lib.rs @@ -249,7 +249,7 @@ pub const DEBUG_SETTINGS: WasmDebugSettings = WasmDebugSettings { let_stmt_ir: false && cfg!(debug_assertions), instructions: false && cfg!(debug_assertions), storage_map: false && cfg!(debug_assertions), - keep_test_binary: true && cfg!(debug_assertions), // see also ROC_WRITE_FINAL_WASM + keep_test_binary: false && cfg!(debug_assertions), // see also ROC_WRITE_FINAL_WASM }; #[cfg(test)] diff --git a/examples/platform-switching/rocLovesZig.roc b/examples/platform-switching/rocLovesZig.roc index 39bab4d9861..fe838c5396c 100644 --- a/examples/platform-switching/rocLovesZig.roc +++ b/examples/platform-switching/rocLovesZig.roc @@ -3,29 +3,4 @@ app "rocLovesZig" imports [] provides [main] to pf -LinkedList a : [Nil, Cons a (LinkedList a)] - -map : LinkedList a, (a -> b) -> LinkedList b -map = \list, f -> - when list is - Nil -> Nil - Cons x xs -> Cons (f x) (map xs f) - -unfold : a, Nat -> LinkedList a -unfold = \value, n -> - when n is - 0 -> Nil - _ -> Cons value (unfold value (n - 1)) - -length : LinkedList a -> I64 -length = \list -> - when list is - Nil -> 0 - Cons _ rest -> 1 + length rest - -main : Str -main = - unfold 42 5 - |> map (\x -> x + 1i64) - |> length - |> Num.toStr +main = "Roc <3 Zig!\n" From c21f80ea2442e918dc1bc5c92a42579402c2cb55 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 21 Jun 2023 01:27:32 +0200 Subject: [PATCH 040/140] don't use pointer as union child --- crates/compiler/mono/src/drop_specialization.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/compiler/mono/src/drop_specialization.rs b/crates/compiler/mono/src/drop_specialization.rs index a695c89ac65..2be4cfb76e6 100644 --- a/crates/compiler/mono/src/drop_specialization.rs +++ b/crates/compiler/mono/src/drop_specialization.rs @@ -219,10 +219,8 @@ fn specialize_drops_stmt<'a, 'i>( structure, tag_id, union_layout: _, - index, + index: _, } => { - // TODO perhaps we need the union_layout later as well? if so, create a new function/map to store it. - environment.add_union_child(*structure, *binding, *tag_id, *index); // Generated code might know the tag of the union without switching on it. // So if we UnionFieldPtrAtIndex, we must know the tag and we can use it to specialize the drop. environment.symbol_tag.insert(*structure, *tag_id); From a3b2de147ecafa4ef8a47af93e2c15382cec3dd8 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 21 Jun 2023 12:52:51 +0200 Subject: [PATCH 041/140] clippy --- crates/compiler/load_internal/src/file.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index 9867c63d1b8..087b556de24 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -16,11 +16,12 @@ use roc_can::module::{ }; use roc_collections::{default_hasher, BumpMap, MutMap, MutSet, VecMap, VecSet}; use roc_constrain::module::constrain_module; -use roc_debug_flags::{dbg_do, ROC_PRINT_IR_AFTER_TRMC}; +use roc_debug_flags::dbg_do; #[cfg(debug_assertions)] use roc_debug_flags::{ ROC_CHECK_MONO_IR, ROC_PRINT_IR_AFTER_DROP_SPECIALIZATION, ROC_PRINT_IR_AFTER_REFCOUNT, - ROC_PRINT_IR_AFTER_RESET_REUSE, ROC_PRINT_IR_AFTER_SPECIALIZATION, ROC_PRINT_LOAD_LOG, + ROC_PRINT_IR_AFTER_RESET_REUSE, ROC_PRINT_IR_AFTER_SPECIALIZATION, ROC_PRINT_IR_AFTER_TRMC, + ROC_PRINT_LOAD_LOG, }; use roc_derive::SharedDerivedModule; use roc_error_macros::internal_error; From f4310c65f5beaf815829d55684f7bf441ec72c20 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 21 Jun 2023 12:56:05 +0200 Subject: [PATCH 042/140] disable debug flag --- examples/platform-switching/zig-platform/host.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/platform-switching/zig-platform/host.zig b/examples/platform-switching/zig-platform/host.zig index d7589e269c0..6025d07d157 100644 --- a/examples/platform-switching/zig-platform/host.zig +++ b/examples/platform-switching/zig-platform/host.zig @@ -27,7 +27,7 @@ extern fn free(c_ptr: [*]align(Align) u8) callconv(.C) void; extern fn memcpy(dst: [*]u8, src: [*]u8, size: usize) callconv(.C) void; extern fn memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void; -const DEBUG: bool = true; +const DEBUG: bool = false; export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*anyopaque { if (DEBUG) { From bc64e4b92bd3f81828c109a323048692f3491114 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 21 Jun 2023 13:45:19 +0200 Subject: [PATCH 043/140] fix layout check issue --- crates/compiler/mono/src/debug/checker.rs | 55 ++++++++++++++++++- .../test_mono/generated/linked_list_map.txt | 51 +++++++++++++++++ .../generated/linked_list_reverse.txt | 37 +++++++++++++ 3 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 crates/compiler/test_mono/generated/linked_list_map.txt create mode 100644 crates/compiler/test_mono/generated/linked_list_reverse.txt diff --git a/crates/compiler/mono/src/debug/checker.rs b/crates/compiler/mono/src/debug/checker.rs index d6f872ffc17..1012fa0842c 100644 --- a/crates/compiler/mono/src/debug/checker.rs +++ b/crates/compiler/mono/src/debug/checker.rs @@ -435,8 +435,7 @@ impl<'a, 'r> Ctx<'a, 'r> { union_layout, index, } => self.with_sym_layout(structure, |ctx, _def_line, layout| { - // TODO: I suspect this will fail because the output layout has an extra Box layer? - ctx.check_union_at_index(structure, layout, union_layout, tag_id, index) + ctx.check_union_field_ptr_at_index(structure, layout, union_layout, tag_id, index) }), Expr::Array { elem_layout, elems } => { for elem in elems.iter() { @@ -575,6 +574,58 @@ impl<'a, 'r> Ctx<'a, 'r> { }) } + fn check_union_field_ptr_at_index( + &mut self, + structure: Symbol, + interned_union_layout: InLayout<'a>, + union_layout: UnionLayout<'a>, + tag_id: u16, + index: u64, + ) -> Option> { + let union = self + .interner + .insert_direct_no_semantic(LayoutRepr::Union(union_layout)); + + let field_ptr_layout = match get_tag_id_payloads(union_layout, tag_id) { + TagPayloads::IdNotInUnion => None, + TagPayloads::Payloads(payloads) => payloads.get(index as usize).map(|field_layout| { + self.interner + .insert_direct_no_semantic(LayoutRepr::Ptr(*field_layout)) + }), + }; + + self.with_sym_layout(structure, |ctx, def_line, _layout| { + ctx.check_sym_layout(structure, union, UseKind::TagExpr); + + match get_tag_id_payloads(union_layout, tag_id) { + TagPayloads::IdNotInUnion => { + ctx.problem(ProblemKind::IndexingTagIdNotInUnion { + structure, + def_line, + tag_id, + union_layout: interned_union_layout, + }); + None + } + TagPayloads::Payloads(payloads) => { + if field_ptr_layout.is_none() { + ctx.problem(ProblemKind::TagUnionStructIndexOOB { + structure, + def_line, + tag_id, + index, + size: payloads.len(), + }); + + None + } else { + field_ptr_layout + } + } + } + }) + } + fn check_call(&mut self, call: &Call<'a>) -> Option> { let Call { call_type, diff --git a/crates/compiler/test_mono/generated/linked_list_map.txt b/crates/compiler/test_mono/generated/linked_list_map.txt new file mode 100644 index 00000000000..f10aaf4b9bd --- /dev/null +++ b/crates/compiler/test_mono/generated/linked_list_map.txt @@ -0,0 +1,51 @@ +procedure Num.19 (#Attr.2, #Attr.3): + let Num.292 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.292; + +procedure Test.10 (Test.11): + let Test.28 : I64 = 1i64; + let Test.27 : I64 = CallByName Num.19 Test.11 Test.28; + ret Test.27; + +procedure Test.2 (#Derived_gen.0, #Derived_gen.1): + let #Derived_gen.3 : [, C I64 *self] = NullPointer; + let #Derived_gen.2 : Ptr([, C I64 *self]) = lowlevel PtrToStackValue #Derived_gen.3; + joinpoint #Derived_gen.4 Test.4 Test.5 #Derived_gen.5: + let Test.22 : U8 = 1i64; + let Test.23 : U8 = GetTagId Test.5; + let Test.24 : Int1 = lowlevel Eq Test.22 Test.23; + if Test.24 then + let Test.18 : [, C I64 *self] = TagId(1) ; + let #Derived_gen.7 : {} = lowlevel PtrStore #Derived_gen.5 Test.18; + let #Derived_gen.6 : [, C I64 *self] = lowlevel PtrLoad #Derived_gen.2; + ret #Derived_gen.6; + else + let Test.7 : I64 = UnionAtIndex (Id 0) (Index 0) Test.5; + let Test.8 : [, C I64 *self] = UnionAtIndex (Id 0) (Index 1) Test.5; + joinpoint #Derived_gen.11 #Derived_gen.14: + let Test.20 : I64 = CallByName Test.10 Test.7; + let #Derived_gen.8 : [, C I64 *self] = NullPointer; + let Test.19 : [, C I64 *self] = Reuse #Derived_gen.14 UpdateModeId { id: 1 } TagId(0) Test.20 #Derived_gen.8; + let #Derived_gen.9 : Ptr([, C I64 *self]) = UnionFieldPtrAtIndex (Id 0) (Index 1) Test.19; + let #Derived_gen.10 : {} = lowlevel PtrStore #Derived_gen.5 Test.19; + jump #Derived_gen.4 Test.4 Test.8 #Derived_gen.9; + in + let #Derived_gen.12 : Int1 = lowlevel RefCountIsUnique Test.5; + if #Derived_gen.12 then + let #Derived_gen.15 : [, C I64 *self] = ResetRef { symbol: Test.5, id: UpdateModeId { id: 2 } }; + jump #Derived_gen.11 #Derived_gen.15; + else + inc Test.8; + decref Test.5; + let #Derived_gen.16 : [, C I64 *self] = NullPointer; + jump #Derived_gen.11 #Derived_gen.16; + in + jump #Derived_gen.4 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2; + +procedure Test.0 (): + let Test.15 : {} = Struct {}; + let Test.25 : I64 = 42i64; + let Test.26 : [, C I64 *self] = TagId(1) ; + let Test.16 : [, C I64 *self] = TagId(0) Test.25 Test.26; + let Test.14 : [, C I64 *self] = CallByName Test.2 Test.15 Test.16; + ret Test.14; diff --git a/crates/compiler/test_mono/generated/linked_list_reverse.txt b/crates/compiler/test_mono/generated/linked_list_reverse.txt new file mode 100644 index 00000000000..00461392a9b --- /dev/null +++ b/crates/compiler/test_mono/generated/linked_list_reverse.txt @@ -0,0 +1,37 @@ +procedure Test.2 (Test.5): + let Test.17 : [, C I64 *self] = TagId(1) ; + let Test.16 : [, C I64 *self] = CallByName Test.3 Test.17 Test.5; + ret Test.16; + +procedure Test.3 (#Derived_gen.0, #Derived_gen.1): + joinpoint Test.18 Test.7 Test.8: + let Test.22 : U8 = 1i64; + let Test.23 : U8 = GetTagId Test.8; + let Test.24 : Int1 = lowlevel Eq Test.22 Test.23; + if Test.24 then + ret Test.7; + else + let Test.9 : I64 = UnionAtIndex (Id 0) (Index 0) Test.8; + let Test.10 : [, C I64 *self] = UnionAtIndex (Id 0) (Index 1) Test.8; + joinpoint #Derived_gen.2 #Derived_gen.5: + let Test.21 : [, C I64 *self] = Reuse #Derived_gen.5 UpdateModeId { id: 1 } TagId(0) Test.9 Test.7; + jump Test.18 Test.21 Test.10; + in + let #Derived_gen.3 : Int1 = lowlevel RefCountIsUnique Test.8; + if #Derived_gen.3 then + let #Derived_gen.6 : [, C I64 *self] = ResetRef { symbol: Test.8, id: UpdateModeId { id: 2 } }; + jump #Derived_gen.2 #Derived_gen.6; + else + inc Test.10; + decref Test.8; + let #Derived_gen.7 : [, C I64 *self] = NullPointer; + jump #Derived_gen.2 #Derived_gen.7; + in + jump Test.18 #Derived_gen.0 #Derived_gen.1; + +procedure Test.0 (): + let Test.25 : I64 = 42i64; + let Test.26 : [, C I64 *self] = TagId(1) ; + let Test.15 : [, C I64 *self] = TagId(0) Test.25 Test.26; + let Test.14 : [, C I64 *self] = CallByName Test.2 Test.15; + ret Test.14; From 249f9bcf1ea5285f3dab386a7f68ac0616c6e4d7 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 21 Jun 2023 14:36:57 +0200 Subject: [PATCH 044/140] use base pointer, not stack pointer --- crates/compiler/gen_dev/src/generic64/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/compiler/gen_dev/src/generic64/mod.rs b/crates/compiler/gen_dev/src/generic64/mod.rs index d19fc976890..b933ca70dc5 100644 --- a/crates/compiler/gen_dev/src/generic64/mod.rs +++ b/crates/compiler/gen_dev/src/generic64/mod.rs @@ -3018,8 +3018,8 @@ impl< let ptr_reg = self.storage_manager.claim_general_reg(&mut self.buf, &ptr); - ASM::mov_reg64_reg64(&mut self.buf, ptr_reg, CC::STACK_PTR_REG); - ASM::sub_reg64_reg64_imm32(&mut self.buf, ptr_reg, ptr_reg, base_offset); + ASM::mov_reg64_reg64(&mut self.buf, ptr_reg, CC::BASE_PTR_REG); + ASM::add_reg64_reg64_imm32(&mut self.buf, ptr_reg, ptr_reg, base_offset); self.build_ptr_store(sym, ptr, value, element_layout); } From 284fd3ee6ce35613959e7adf06e020b6f56381f5 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 21 Jun 2023 17:12:37 +0200 Subject: [PATCH 045/140] disable dev test for now --- crates/compiler/test_gen/src/gen_primitives.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/compiler/test_gen/src/gen_primitives.rs b/crates/compiler/test_gen/src/gen_primitives.rs index 952a4a61d78..568a893dead 100644 --- a/crates/compiler/test_gen/src/gen_primitives.rs +++ b/crates/compiler/test_gen/src/gen_primitives.rs @@ -795,7 +795,7 @@ fn linked_list_sum_int() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] fn linked_list_map() { assert_evals_to!( indoc!( From b349fca5216f0faed8e1d97111ef77862bee355e Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 21 Jun 2023 17:21:41 +0200 Subject: [PATCH 046/140] make NQueens more tail recursive --- crates/cli_testing_examples/benchmarks/NQueens.roc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/cli_testing_examples/benchmarks/NQueens.roc b/crates/cli_testing_examples/benchmarks/NQueens.roc index e1a94144282..62b931fb3e6 100644 --- a/crates/cli_testing_examples/benchmarks/NQueens.roc +++ b/crates/cli_testing_examples/benchmarks/NQueens.roc @@ -46,7 +46,10 @@ safe = \queen, diagonal, xs -> when xs is Nil -> Bool.true Cons q t -> - queen != q && queen != q + diagonal && queen != q - diagonal && safe queen (diagonal + 1) t + if queen != q && queen != q + diagonal && queen != q - diagonal then + safe queen (diagonal + 1) t + else + Bool.false length : ConsList a -> I64 From c87519c209cbce162c8e4b1bb79365125f077c3e Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 21 Jun 2023 20:56:36 +0200 Subject: [PATCH 047/140] search for multiple TRMC opportunities --- .../cli_testing_examples/benchmarks/CFold.roc | 2 +- .../cli_testing_examples/benchmarks/Deriv.roc | 1 - .../benchmarks/NQueens.roc | 9 +- .../benchmarks/QuicksortApp.roc | 1 - .../benchmarks/RBTreeCk.roc | 10 +- .../benchmarks/RBTreeDel.roc | 1 - crates/compiler/collections/src/vec_set.rs | 16 ++ crates/compiler/mono/src/tail_recursion.rs | 216 +++++++++--------- 8 files changed, 139 insertions(+), 117 deletions(-) diff --git a/crates/cli_testing_examples/benchmarks/CFold.roc b/crates/cli_testing_examples/benchmarks/CFold.roc index 8c496c6f9c4..e4b1e2423dd 100644 --- a/crates/cli_testing_examples/benchmarks/CFold.roc +++ b/crates/cli_testing_examples/benchmarks/CFold.roc @@ -21,7 +21,7 @@ main = |> Task.putLine Err GetIntError -> - Task.putLine "Error: Failed to get Integer from stdin." + Task.putLine "Error: Failed to get Integer from stdin." Expr : [ Add Expr Expr, diff --git a/crates/cli_testing_examples/benchmarks/Deriv.roc b/crates/cli_testing_examples/benchmarks/Deriv.roc index 5ad3f3b9d0c..974c1ada668 100644 --- a/crates/cli_testing_examples/benchmarks/Deriv.roc +++ b/crates/cli_testing_examples/benchmarks/Deriv.roc @@ -23,7 +23,6 @@ main = Err GetIntError -> Task.putLine "Error: Failed to get Integer from stdin." - nest : (I64, Expr -> IO Expr), I64, Expr -> IO Expr nest = \f, n, e -> Task.loop { s: n, f, m: n, x: e } nestHelp diff --git a/crates/cli_testing_examples/benchmarks/NQueens.roc b/crates/cli_testing_examples/benchmarks/NQueens.roc index 62b931fb3e6..15593e37216 100644 --- a/crates/cli_testing_examples/benchmarks/NQueens.roc +++ b/crates/cli_testing_examples/benchmarks/NQueens.roc @@ -10,8 +10,8 @@ main = when inputResult is Ok n -> queens n # original koka 13 - |> Num.toStr - |> Task.putLine + |> Num.toStr + |> Task.putLine Err GetIntError -> Task.putLine "Error: Failed to get Integer from stdin." @@ -21,7 +21,8 @@ ConsList a : [Nil, Cons a (ConsList a)] queens = \n -> length (findSolutions n n) findSolutions = \n, k -> - if k <= 0 then # should we use U64 as input type here instead? + if k <= 0 then + # should we use U64 as input type here instead? Cons Nil Nil else extend n Nil (findSolutions n (k - 1)) @@ -40,7 +41,6 @@ appendSafe = \k, soln, solns -> else appendSafe (k - 1) soln solns - safe : I64, I64, ConsList I64 -> Bool safe = \queen, diagonal, xs -> when xs is @@ -51,7 +51,6 @@ safe = \queen, diagonal, xs -> else Bool.false - length : ConsList a -> I64 length = \xs -> lengthHelp xs 0 diff --git a/crates/cli_testing_examples/benchmarks/QuicksortApp.roc b/crates/cli_testing_examples/benchmarks/QuicksortApp.roc index cc38026216c..67766bc9820 100644 --- a/crates/cli_testing_examples/benchmarks/QuicksortApp.roc +++ b/crates/cli_testing_examples/benchmarks/QuicksortApp.roc @@ -23,7 +23,6 @@ main = Err GetIntError -> Task.putLine "Error: Failed to get Integer from stdin." - sort : List I64 -> List I64 sort = \list -> diff --git a/crates/cli_testing_examples/benchmarks/RBTreeCk.roc b/crates/cli_testing_examples/benchmarks/RBTreeCk.roc index 254be6d0ebf..5c685b195e6 100644 --- a/crates/cli_testing_examples/benchmarks/RBTreeCk.roc +++ b/crates/cli_testing_examples/benchmarks/RBTreeCk.roc @@ -93,9 +93,15 @@ ins = \tree, kx, vx -> Node Black a ky vy b -> if lt kx ky then - (if isRed a then balance1 (Node Black Leaf ky vy b) (ins a kx vx) else Node Black (ins a kx vx) ky vy b) + if isRed a then + balance1 (Node Black Leaf ky vy b) (ins a kx vx) + else + Node Black (ins a kx vx) ky vy b else if lt ky kx then - (if isRed b then balance2 (Node Black a ky vy Leaf) (ins b kx vx) else Node Black a ky vy (ins b kx vx)) + if isRed b then + balance2 (Node Black a ky vy Leaf) (ins b kx vx) + else + Node Black a ky vy (ins b kx vx) else Node Black a kx vx b diff --git a/crates/cli_testing_examples/benchmarks/RBTreeDel.roc b/crates/cli_testing_examples/benchmarks/RBTreeDel.roc index 37f0523ecac..7f5e940b73d 100644 --- a/crates/cli_testing_examples/benchmarks/RBTreeDel.roc +++ b/crates/cli_testing_examples/benchmarks/RBTreeDel.roc @@ -26,7 +26,6 @@ main = Err GetIntError -> Task.putLine "Error: Failed to get Integer from stdin." - boom : Str -> a boom = \_ -> boom "" diff --git a/crates/compiler/collections/src/vec_set.rs b/crates/compiler/collections/src/vec_set.rs index 52be9862497..c45a8169248 100644 --- a/crates/compiler/collections/src/vec_set.rs +++ b/crates/compiler/collections/src/vec_set.rs @@ -34,6 +34,12 @@ impl VecSet { self.elements.is_empty() } + pub fn singleton(value: T) -> Self { + Self { + elements: vec![value], + } + } + pub fn swap_remove(&mut self, index: usize) -> T { self.elements.swap_remove(index) } @@ -96,6 +102,16 @@ impl VecSet { { self.elements.retain(f) } + + pub fn keep_if_in_both(&mut self, other: &Self) { + self.elements.retain(|e| other.contains(e)); + } + + pub fn keep_if_in_either(&mut self, other: Self) { + for e in other.elements { + self.insert(e); + } + } } impl Extend for VecSet { diff --git a/crates/compiler/mono/src/tail_recursion.rs b/crates/compiler/mono/src/tail_recursion.rs index f2afbc9c7ee..0a7ab187d1b 100644 --- a/crates/compiler/mono/src/tail_recursion.rs +++ b/crates/compiler/mono/src/tail_recursion.rs @@ -10,7 +10,7 @@ use crate::layout::{ }; use bumpalo::collections::Vec; use bumpalo::Bump; -use roc_collections::MutMap; +use roc_collections::{MutMap, VecSet}; use roc_module::low_level::LowLevel; use roc_module::symbol::{IdentIds, ModuleId, Symbol}; @@ -53,8 +53,11 @@ pub fn apply_trmc<'a, 'i>( for proc in procs.values_mut() { use self::SelfRecursive::*; if let SelfRecursive(id) = proc.is_self_recursive { - if crate::tail_recursion::is_trmc_candidate(env.interner, proc) { - let new_proc = crate::tail_recursion::TrmcEnv::init(env, proc); + let trmc_candidate_symbols = trmc_candidates(env.interner, proc); + + if !trmc_candidate_symbols.is_empty() { + let new_proc = + crate::tail_recursion::TrmcEnv::init(env, proc, trmc_candidate_symbols); *proc = new_proc; } else { let mut args = Vec::with_capacity_in(proc.args.len(), arena); @@ -402,7 +405,49 @@ fn insert_jumps<'a>( } } -pub(crate) fn is_trmc_candidate<'a, I>(interner: &'_ I, proc: &'_ Proc<'a>) -> bool +#[derive(Debug, Clone, Default)] +struct TrmcCandidateSet { + /// Recursive calls for which we have found a TRMC opportunity + confirmed: VecSet, + /// Recursive calls that are (still) considered for TRMC + active: VecSet, + /// Recursive calls that are used in such a way that makes TRMC impossible + invalid: VecSet, +} + +impl TrmcCandidateSet { + fn insert(&mut self, call: Symbol) { + // there really is no way it could have been inserted already + debug_assert!(!self.invalid.contains(&call)); + + self.active.insert(call); + } + + fn extend(&mut self, other: Self) { + self.confirmed.keep_if_in_either(other.confirmed); + self.invalid.keep_if_in_either(other.invalid); + self.active.keep_if_in_either(other.active); + + self.active.retain(|k| !self.invalid.contains(k)); + self.confirmed.retain(|k| !self.invalid.contains(k)); + } + + fn retain(&mut self, keep: F) + where + F: Fn(&Symbol) -> bool, + { + for c in self.active.iter() { + if !keep(c) { + self.invalid.insert(*c); + } + } + + self.active.retain(|k| !self.invalid.contains(k)); + self.confirmed.retain(|k| !self.invalid.contains(k)); + } +} + +fn trmc_candidates<'a, I>(interner: &'_ I, proc: &'_ Proc<'a>) -> VecSet where I: LayoutInterner<'a>, { @@ -411,87 +456,50 @@ where proc.is_self_recursive, crate::ir::SelfRecursive::SelfRecursive(_) ) { - return false; + return VecSet::default(); } // and return a recursive tag union if !matches!(interner.get_repr(proc.ret_layout), LayoutRepr::Union(union_layout) if union_layout.is_recursive()) { - return false; + return VecSet::default(); } - match has_cons_in_tail_position(&proc.body, proc.name, None) { - SymbolUse::NotUsed | SymbolUse::Used => false, - SymbolUse::TrmcOppotunity => true, - } + trmc_candidates_help(proc.name, &proc.body, TrmcCandidateSet::default()).confirmed } -#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)] -#[repr(C)] -enum SymbolUse { - #[default] - NotUsed = 0, - TrmcOppotunity = 1, - Used = 2, -} - -impl SymbolUse { - #[must_use] - fn mappend(self, y: Self) -> Self { - debug_assert_eq!(self.mappend_slow(y), Ord::max(self, y)); - - Ord::max(self, y) - } - - fn mappend_slow(self, y: Self) -> Self { - use SymbolUse::*; - - match (self, y) { - (Used, _) | (_, Used) => Used, - (TrmcOppotunity, _) | (_, TrmcOppotunity) => TrmcOppotunity, - (NotUsed, NotUsed) => NotUsed, - } - } -} - -fn has_cons_in_tail_position( - stmt: &Stmt<'_>, +fn trmc_candidates_help<'a>( function_name: LambdaName, - recursive_call: Option, -) -> SymbolUse { - // we are looking for code of the form - // - // let x = Tag a b c - // ret x - + stmt: &'_ Stmt<'a>, + mut candidates: TrmcCandidateSet, +) -> TrmcCandidateSet { // if this stmt is the literal tail tag application and return, then this is a TRMC opportunity if let Some(cons_info) = TrmcEnv::is_terminal_constructor(stmt) { // must use the result of a recursive call directly as an argument - if let Some(recursive_call) = recursive_call { - if cons_info.arguments.contains(&recursive_call) { - return SymbolUse::TrmcOppotunity; + // we pick the (syntactically) first one + for recursive_call in candidates.active.iter() { + if cons_info.arguments.contains(recursive_call) { + return TrmcCandidateSet { + confirmed: VecSet::singleton(*recursive_call), + active: VecSet::default(), + invalid: candidates.invalid, + }; } } } // if the stmt uses the active recursive call, that invalidates the recursive call for this branch - if let Some(recursive_call) = recursive_call { - if stmt_contains_symbol_nonrec(stmt, recursive_call) { - // this means we really only check for the first recursive call (in each branch) - // whether it presents a TRMC opportunity. In theory we can look at all recursive calls - // this is future work. - return SymbolUse::Used; - } - } + candidates.retain(|recursive_call| !stmt_contains_symbol_nonrec(stmt, *recursive_call)); match stmt { Stmt::Let(symbol, expr, _, next) => { // find a new recursive call if we currently have none // that means we generally pick the first recursive call we find - let recursive_call = recursive_call - .or_else(|| TrmcEnv::is_recursive_expr(expr, function_name).map(|_| *symbol)); + if TrmcEnv::is_recursive_expr(expr, function_name).is_some() { + candidates.insert(*symbol); + } - has_cons_in_tail_position(next, function_name, recursive_call) + trmc_candidates_help(function_name, next, candidates) } Stmt::Switch { branches, @@ -503,54 +511,43 @@ fn has_cons_in_tail_position( .map(|(_, _, stmt)| stmt) .chain([default_branch.1]); - let mut accum = SymbolUse::NotUsed; + let mut accum = candidates.clone(); for next in it { - let x = has_cons_in_tail_position(next, function_name, recursive_call); - accum = accum.mappend(x); + let x = trmc_candidates_help(function_name, next, candidates.clone()); - if let SymbolUse::Used = accum { - return SymbolUse::Used; - } + accum.extend(x); } accum } - Stmt::Refcounting(_, next) => { - has_cons_in_tail_position(next, function_name, recursive_call) - } + Stmt::Refcounting(_, next) => trmc_candidates_help(function_name, next, candidates), Stmt::Expect { remainder, .. } | Stmt::ExpectFx { remainder, .. } - | Stmt::Dbg { remainder, .. } => { - has_cons_in_tail_position(remainder, function_name, recursive_call) - } + | Stmt::Dbg { remainder, .. } => trmc_candidates_help(function_name, remainder, candidates), Stmt::Join { body, remainder, .. } => { - let x = has_cons_in_tail_position(body, function_name, recursive_call); + let mut x = trmc_candidates_help(function_name, body, candidates.clone()); + let y = trmc_candidates_help(function_name, remainder, candidates.clone()); - if let SymbolUse::Used = x { - SymbolUse::Used - } else { - let y = has_cons_in_tail_position(remainder, function_name, recursive_call); - x.mappend(y) - } + x.extend(y); + + x } - Stmt::Ret(_) | Stmt::Jump(_, _) | Stmt::Crash(_, _) => SymbolUse::NotUsed, + Stmt::Ret(_) | Stmt::Jump(_, _) | Stmt::Crash(_, _) => candidates, } } #[derive(Clone)] pub(crate) struct TrmcEnv<'a> { - function_name: LambdaName<'a>, hole_symbol: Symbol, initial_ptr_symbol: Symbol, joinpoint_id: JoinPointId, return_layout: InLayout<'a>, ptr_return_layout: InLayout<'a>, - // the call we are performing TRMC on - recursive_call: Option<(Symbol, Call<'a>)>, + trmc_calls: MutMap>>, } #[derive(Debug)] @@ -634,7 +631,11 @@ impl<'a> TrmcEnv<'a> { ) } - pub fn init<'i>(env: &mut Env<'a, 'i>, proc: &Proc<'a>) -> Proc<'a> { + pub fn init<'i>( + env: &mut Env<'a, 'i>, + proc: &Proc<'a>, + trmc_calls: VecSet, + ) -> Proc<'a> { let arena = env.arena; let return_layout = proc.ret_layout; @@ -682,14 +683,15 @@ impl<'a> TrmcEnv<'a> { let jump_stmt = Stmt::Jump(joinpoint_id, jump_arguments.into_bump_slice()); + let trmc_calls = trmc_calls.iter().map(|s| (*s, None)).collect(); + let mut this = Self { - function_name: proc.name, hole_symbol, initial_ptr_symbol, joinpoint_id, return_layout, ptr_return_layout, - recursive_call: None, + trmc_calls, }; let param = Param { @@ -733,24 +735,30 @@ impl<'a> TrmcEnv<'a> { match stmt { Stmt::Let(symbol, expr, layout, next) => { - if self.recursive_call.is_none() { - if let Some(call) = Self::is_recursive_expr(expr, self.function_name) { - let can_trmc = - has_cons_in_tail_position(next, self.function_name, Some(*symbol)); - - match can_trmc { - SymbolUse::NotUsed => { /* the variable is dead */ } - SymbolUse::TrmcOppotunity => { - self.recursive_call = Some((*symbol, call)); - return self.walk_stmt(env, next); - } - SymbolUse::Used => { /* the variable is used making TRMC invaid */ } - } - } + // if this is a TRMC call, + if let Some(opt_call) = self.trmc_calls.get_mut(symbol) { + debug_assert!(opt_call.is_none()); + + let call = match expr { + Expr::Call(call) => call, + _ => unreachable!(), + }; + + *opt_call = Some(call.clone()); + + return self.walk_stmt(env, next); } if let Some(cons_info) = Self::is_terminal_constructor(stmt) { - match &self.recursive_call { + // figure out which TRMC call to use here. We pick the first one that works + let opt_recursive_call = cons_info.arguments.iter().find_map(|arg| { + self.trmc_calls + .get(arg) + .and_then(|x| x.as_ref()) + .map(|x| (arg, x)) + }); + + match opt_recursive_call { None => { // this control flow path did not encounter a recursive call. Just // write the end result into the hole and we're done. @@ -863,16 +871,12 @@ impl<'a> TrmcEnv<'a> { } => { let mut new_branches = Vec::with_capacity_in(branches.len(), arena); - let opt_recursive_call = self.recursive_call.clone(); - for (id, info, stmt) in branches.iter() { - self.recursive_call = opt_recursive_call.clone(); let new_stmt = self.walk_stmt(env, stmt); new_branches.push((*id, info.clone(), new_stmt)); } - self.recursive_call = opt_recursive_call; let new_default_branch = &*arena.alloc(self.walk_stmt(env, default_branch.1)); Stmt::Switch { From e19f0ae6d6b42dc31ed41317ea09adde27f44b93 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 21 Jun 2023 21:43:16 +0200 Subject: [PATCH 048/140] don't capture from outside join point for the dev backend --- crates/compiler/mono/src/tail_recursion.rs | 16 +++++++++++++--- crates/compiler/test_gen/src/gen_primitives.rs | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/crates/compiler/mono/src/tail_recursion.rs b/crates/compiler/mono/src/tail_recursion.rs index 0a7ab187d1b..0ae595579be 100644 --- a/crates/compiler/mono/src/tail_recursion.rs +++ b/crates/compiler/mono/src/tail_recursion.rs @@ -542,7 +542,7 @@ fn trmc_candidates_help<'a>( #[derive(Clone)] pub(crate) struct TrmcEnv<'a> { hole_symbol: Symbol, - initial_ptr_symbol: Symbol, + head_symbol: Symbol, joinpoint_id: JoinPointId, return_layout: InLayout<'a>, ptr_return_layout: InLayout<'a>, @@ -659,6 +659,7 @@ impl<'a> TrmcEnv<'a> { // the root of the recursive structure that we'll be building let initial_ptr_symbol = env.named_unique_symbol("initial"); jump_arguments.push(initial_ptr_symbol); + jump_arguments.push(initial_ptr_symbol); let null_symbol = env.named_unique_symbol("null"); let let_null = |next| Stmt::Let(null_symbol, Expr::NullPointer, return_layout, next); @@ -680,6 +681,7 @@ impl<'a> TrmcEnv<'a> { let joinpoint_id = JoinPointId(env.named_unique_symbol("trmc")); let hole_symbol = env.named_unique_symbol("hole"); + let head_symbol = env.named_unique_symbol("head"); let jump_stmt = Stmt::Jump(joinpoint_id, jump_arguments.into_bump_slice()); @@ -687,7 +689,7 @@ impl<'a> TrmcEnv<'a> { let mut this = Self { hole_symbol, - initial_ptr_symbol, + head_symbol, joinpoint_id, return_layout, ptr_return_layout, @@ -701,6 +703,13 @@ impl<'a> TrmcEnv<'a> { }; joinpoint_parameters.push(param); + let param = Param { + symbol: head_symbol, + ownership: Ownership::Owned, + layout: ptr_return_layout, + }; + joinpoint_parameters.push(param); + let joinpoint = Stmt::Join { id: joinpoint_id, parameters: joinpoint_parameters.into_bump_slice(), @@ -834,6 +843,7 @@ impl<'a> TrmcEnv<'a> { let mut jump_arguments = Vec::from_iter_in(call.arguments.iter().copied(), env.arena); jump_arguments.push(new_hole_symbol); + jump_arguments.push(self.head_symbol); let jump = Stmt::Jump(self.joinpoint_id, jump_arguments.into_bump_slice()); @@ -963,7 +973,7 @@ impl<'a> TrmcEnv<'a> { op: LowLevel::PtrLoad, update_mode: UpdateModeId::BACKEND_DUMMY, }, - arguments: &*arena.alloc([self.initial_ptr_symbol]), + arguments: &*arena.alloc([self.head_symbol]), }; let ptr_load = |next| Stmt::Let(final_symbol, Expr::Call(call), layout, next); diff --git a/crates/compiler/test_gen/src/gen_primitives.rs b/crates/compiler/test_gen/src/gen_primitives.rs index 568a893dead..952a4a61d78 100644 --- a/crates/compiler/test_gen/src/gen_primitives.rs +++ b/crates/compiler/test_gen/src/gen_primitives.rs @@ -795,7 +795,7 @@ fn linked_list_sum_int() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn linked_list_map() { assert_evals_to!( indoc!( From f7104bfe54265d21ba4d9dd2b5fc92504d09995f Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 22 Jun 2023 18:34:30 +0200 Subject: [PATCH 049/140] update mono tests --- .../test_mono/generated/linked_list_map.txt | 34 +- .../test_mono/generated/rb_tree_fbip.txt | 793 +++++++++--------- 2 files changed, 431 insertions(+), 396 deletions(-) diff --git a/crates/compiler/test_mono/generated/linked_list_map.txt b/crates/compiler/test_mono/generated/linked_list_map.txt index f10aaf4b9bd..8519c182987 100644 --- a/crates/compiler/test_mono/generated/linked_list_map.txt +++ b/crates/compiler/test_mono/generated/linked_list_map.txt @@ -10,37 +10,37 @@ procedure Test.10 (Test.11): procedure Test.2 (#Derived_gen.0, #Derived_gen.1): let #Derived_gen.3 : [, C I64 *self] = NullPointer; let #Derived_gen.2 : Ptr([, C I64 *self]) = lowlevel PtrToStackValue #Derived_gen.3; - joinpoint #Derived_gen.4 Test.4 Test.5 #Derived_gen.5: + joinpoint #Derived_gen.4 Test.4 Test.5 #Derived_gen.5 #Derived_gen.6: let Test.22 : U8 = 1i64; let Test.23 : U8 = GetTagId Test.5; let Test.24 : Int1 = lowlevel Eq Test.22 Test.23; if Test.24 then let Test.18 : [, C I64 *self] = TagId(1) ; - let #Derived_gen.7 : {} = lowlevel PtrStore #Derived_gen.5 Test.18; - let #Derived_gen.6 : [, C I64 *self] = lowlevel PtrLoad #Derived_gen.2; - ret #Derived_gen.6; + let #Derived_gen.8 : {} = lowlevel PtrStore #Derived_gen.5 Test.18; + let #Derived_gen.7 : [, C I64 *self] = lowlevel PtrLoad #Derived_gen.6; + ret #Derived_gen.7; else let Test.7 : I64 = UnionAtIndex (Id 0) (Index 0) Test.5; let Test.8 : [, C I64 *self] = UnionAtIndex (Id 0) (Index 1) Test.5; - joinpoint #Derived_gen.11 #Derived_gen.14: + joinpoint #Derived_gen.12 #Derived_gen.15: let Test.20 : I64 = CallByName Test.10 Test.7; - let #Derived_gen.8 : [, C I64 *self] = NullPointer; - let Test.19 : [, C I64 *self] = Reuse #Derived_gen.14 UpdateModeId { id: 1 } TagId(0) Test.20 #Derived_gen.8; - let #Derived_gen.9 : Ptr([, C I64 *self]) = UnionFieldPtrAtIndex (Id 0) (Index 1) Test.19; - let #Derived_gen.10 : {} = lowlevel PtrStore #Derived_gen.5 Test.19; - jump #Derived_gen.4 Test.4 Test.8 #Derived_gen.9; + let #Derived_gen.9 : [, C I64 *self] = NullPointer; + let Test.19 : [, C I64 *self] = Reuse #Derived_gen.15 UpdateModeId { id: 1 } TagId(0) Test.20 #Derived_gen.9; + let #Derived_gen.10 : Ptr([, C I64 *self]) = UnionFieldPtrAtIndex (Id 0) (Index 1) Test.19; + let #Derived_gen.11 : {} = lowlevel PtrStore #Derived_gen.5 Test.19; + jump #Derived_gen.4 Test.4 Test.8 #Derived_gen.10 #Derived_gen.6; in - let #Derived_gen.12 : Int1 = lowlevel RefCountIsUnique Test.5; - if #Derived_gen.12 then - let #Derived_gen.15 : [, C I64 *self] = ResetRef { symbol: Test.5, id: UpdateModeId { id: 2 } }; - jump #Derived_gen.11 #Derived_gen.15; + let #Derived_gen.13 : Int1 = lowlevel RefCountIsUnique Test.5; + if #Derived_gen.13 then + let #Derived_gen.16 : [, C I64 *self] = ResetRef { symbol: Test.5, id: UpdateModeId { id: 2 } }; + jump #Derived_gen.12 #Derived_gen.16; else inc Test.8; decref Test.5; - let #Derived_gen.16 : [, C I64 *self] = NullPointer; - jump #Derived_gen.11 #Derived_gen.16; + let #Derived_gen.17 : [, C I64 *self] = NullPointer; + jump #Derived_gen.12 #Derived_gen.17; in - jump #Derived_gen.4 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2; + jump #Derived_gen.4 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.2; procedure Test.0 (): let Test.15 : {} = Struct {}; diff --git a/crates/compiler/test_mono/generated/rb_tree_fbip.txt b/crates/compiler/test_mono/generated/rb_tree_fbip.txt index a56c6fd2faa..e6cb057d392 100644 --- a/crates/compiler/test_mono/generated/rb_tree_fbip.txt +++ b/crates/compiler/test_mono/generated/rb_tree_fbip.txt @@ -6,415 +6,450 @@ procedure Num.24 (#Attr.2, #Attr.3): let Num.293 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; ret Num.293; -procedure Test.3 (Test.9, Test.10, Test.11): - let Test.254 : U8 = 0i64; - let Test.255 : U8 = GetTagId Test.9; - let Test.256 : Int1 = lowlevel Eq Test.254 Test.255; - if Test.256 then - let Test.113 : [C *self I64 *self I32 Int1, ] = TagId(0) ; - let Test.114 : [C *self I64 *self I32 Int1, ] = TagId(0) ; - let Test.112 : Int1 = true; - let Test.111 : [C *self I64 *self I32 Int1, ] = TagId(1) Test.113 Test.11 Test.114 Test.10 Test.112; - ret Test.111; - else - let Test.251 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.9; - let Test.252 : Int1 = false; - let Test.253 : Int1 = lowlevel Eq Test.252 Test.251; - if Test.253 then - let Test.16 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.9; - let Test.18 : I64 = UnionAtIndex (Id 1) (Index 1) Test.9; - let Test.19 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.9; - let Test.17 : I32 = UnionAtIndex (Id 1) (Index 3) Test.9; - joinpoint #Derived_gen.75 #Derived_gen.80: - let Test.179 : Int1 = CallByName Num.22 Test.10 Test.17; - if Test.179 then - joinpoint Test.238 #Derived_gen.142: - let Test.233 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.16 Test.10 Test.11; - let Test.232 : Int1 = false; - let Test.231 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.142 UpdateModeId { id: 56 } TagId(1) Test.233 Test.18 Test.19 Test.17 Test.232; - ret Test.231; - in - let Test.236 : U8 = 1i64; - let Test.237 : U8 = GetTagId Test.16; - let Test.240 : Int1 = lowlevel Eq Test.236 Test.237; - if Test.240 then - let Test.234 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.16; - let Test.235 : Int1 = true; - let Test.239 : Int1 = lowlevel Eq Test.235 Test.234; - if Test.239 then - let Test.180 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.16 Test.10 Test.11; - joinpoint Test.199 #Derived_gen.169: - let Test.198 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.20 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.198; - inc Test.20; - let Test.22 : I64 = UnionAtIndex (Id 1) (Index 1) Test.198; - let Test.23 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.198; - inc Test.23; - let Test.21 : I32 = UnionAtIndex (Id 1) (Index 3) Test.198; - let Test.25 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; - let Test.26 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; - let Test.24 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; - joinpoint #Derived_gen.33 #Derived_gen.172 #Derived_gen.173 #Derived_gen.174: - let Test.186 : Int1 = false; - let Test.183 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.174 UpdateModeId { id: 85 } TagId(1) Test.20 Test.22 Test.23 Test.21 Test.186; - let Test.185 : Int1 = false; - let Test.184 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.173 UpdateModeId { id: 84 } TagId(1) Test.26 Test.18 Test.19 Test.17 Test.185; - let Test.182 : Int1 = true; - let Test.181 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.172 UpdateModeId { id: 83 } TagId(1) Test.183 Test.25 Test.184 Test.24 Test.182; - ret Test.181; - in - let #Derived_gen.34 : Int1 = lowlevel RefCountIsUnique Test.180; - if #Derived_gen.34 then - let #Derived_gen.175 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.198, id: UpdateModeId { id: 86 } }; - let #Derived_gen.176 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 87 } }; - jump #Derived_gen.33 #Derived_gen.169 #Derived_gen.175 #Derived_gen.176; - else - inc Test.26; - decref Test.180; - let #Derived_gen.177 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.33 #Derived_gen.177 #Derived_gen.177 #Derived_gen.169; - in - let Test.228 : U8 = 1i64; - let Test.229 : U8 = GetTagId Test.180; - let Test.230 : Int1 = lowlevel Eq Test.228 Test.229; - if Test.230 then - joinpoint Test.225 #Derived_gen.187: - joinpoint Test.216 #Derived_gen.188: - let Test.46 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.48 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; - let Test.49 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; - let Test.47 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; - joinpoint #Derived_gen.27 #Derived_gen.190 #Derived_gen.191: - let Test.196 : Int1 = true; - let Test.195 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.191 UpdateModeId { id: 100 } TagId(1) Test.46 Test.48 Test.49 Test.47 Test.196; - let Test.194 : Int1 = false; - let Test.193 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.190 UpdateModeId { id: 99 } TagId(1) Test.195 Test.18 Test.19 Test.17 Test.194; - ret Test.193; - in - let #Derived_gen.28 : Int1 = lowlevel RefCountIsUnique Test.180; - if #Derived_gen.28 then - let #Derived_gen.192 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 101 } }; - jump #Derived_gen.27 #Derived_gen.188 #Derived_gen.192; - else - inc Test.46; - inc Test.49; - decref Test.180; - let #Derived_gen.193 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.27 #Derived_gen.193 #Derived_gen.188; +procedure Test.3 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): + let #Derived_gen.4 : [C *self I64 *self I32 Int1, ] = NullPointer; + let #Derived_gen.3 : Ptr([C *self I64 *self I32 Int1, ]) = lowlevel PtrToStackValue #Derived_gen.4; + joinpoint #Derived_gen.5 Test.9 Test.10 Test.11 #Derived_gen.6 #Derived_gen.7: + let Test.254 : U8 = 0i64; + let Test.255 : U8 = GetTagId Test.9; + let Test.256 : Int1 = lowlevel Eq Test.254 Test.255; + if Test.256 then + let Test.113 : [C *self I64 *self I32 Int1, ] = TagId(0) ; + let Test.114 : [C *self I64 *self I32 Int1, ] = TagId(0) ; + let Test.112 : Int1 = true; + let Test.111 : [C *self I64 *self I32 Int1, ] = TagId(1) Test.113 Test.11 Test.114 Test.10 Test.112; + let #Derived_gen.9 : {} = lowlevel PtrStore #Derived_gen.6 Test.111; + let #Derived_gen.8 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; + ret #Derived_gen.8; + else + let Test.251 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.9; + let Test.252 : Int1 = false; + let Test.253 : Int1 = lowlevel Eq Test.252 Test.251; + if Test.253 then + let Test.16 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.9; + let Test.18 : I64 = UnionAtIndex (Id 1) (Index 1) Test.9; + let Test.19 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.9; + let Test.17 : I32 = UnionAtIndex (Id 1) (Index 3) Test.9; + joinpoint #Derived_gen.114 #Derived_gen.119: + let Test.179 : Int1 = CallByName Num.22 Test.10 Test.17; + if Test.179 then + joinpoint Test.238 #Derived_gen.181: + let Test.232 : Int1 = false; + let #Derived_gen.10 : [C *self I64 *self I32 Int1, ] = NullPointer; + let Test.231 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.181 UpdateModeId { id: 56 } TagId(1) #Derived_gen.10 Test.18 Test.19 Test.17 Test.232; + let #Derived_gen.11 : Ptr([C *self I64 *self I32 Int1, ]) = UnionFieldPtrAtIndex (Id 1) (Index 0) Test.231; + let #Derived_gen.12 : {} = lowlevel PtrStore #Derived_gen.6 Test.231; + jump #Derived_gen.5 Test.16 Test.10 Test.11 #Derived_gen.11 #Derived_gen.7; + in + let Test.236 : U8 = 1i64; + let Test.237 : U8 = GetTagId Test.16; + let Test.240 : Int1 = lowlevel Eq Test.236 Test.237; + if Test.240 then + let Test.234 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.16; + let Test.235 : Int1 = true; + let Test.239 : Int1 = lowlevel Eq Test.235 Test.234; + if Test.239 then + let Test.180 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.16 Test.10 Test.11; + joinpoint Test.199 #Derived_gen.208: + let Test.198 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.20 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.198; + inc Test.20; + let Test.22 : I64 = UnionAtIndex (Id 1) (Index 1) Test.198; + let Test.23 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.198; + inc Test.23; + let Test.21 : I32 = UnionAtIndex (Id 1) (Index 3) Test.198; + let Test.25 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; + let Test.26 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; + let Test.24 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; + joinpoint #Derived_gen.72 #Derived_gen.211 #Derived_gen.212 #Derived_gen.213: + let Test.186 : Int1 = false; + let Test.183 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.213 UpdateModeId { id: 85 } TagId(1) Test.20 Test.22 Test.23 Test.21 Test.186; + let Test.185 : Int1 = false; + let Test.184 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.212 UpdateModeId { id: 84 } TagId(1) Test.26 Test.18 Test.19 Test.17 Test.185; + let Test.182 : Int1 = true; + let Test.181 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.211 UpdateModeId { id: 83 } TagId(1) Test.183 Test.25 Test.184 Test.24 Test.182; + let #Derived_gen.14 : {} = lowlevel PtrStore #Derived_gen.6 Test.181; + let #Derived_gen.13 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; + ret #Derived_gen.13; in - let Test.213 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.214 : U8 = 1i64; - let Test.215 : U8 = GetTagId Test.213; - let Test.218 : Int1 = lowlevel Eq Test.214 Test.215; - if Test.218 then - let Test.210 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.211 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.210; - let Test.212 : Int1 = true; - let Test.217 : Int1 = lowlevel Eq Test.212 Test.211; - if Test.217 then - jump Test.199 #Derived_gen.187; - else - jump Test.216 #Derived_gen.187; + let #Derived_gen.73 : Int1 = lowlevel RefCountIsUnique Test.180; + if #Derived_gen.73 then + let #Derived_gen.214 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.198, id: UpdateModeId { id: 86 } }; + let #Derived_gen.215 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 87 } }; + jump #Derived_gen.72 #Derived_gen.208 #Derived_gen.214 #Derived_gen.215; else - jump Test.216 #Derived_gen.187; + inc Test.26; + decref Test.180; + let #Derived_gen.216 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.72 #Derived_gen.216 #Derived_gen.216 #Derived_gen.208; in - let Test.222 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; - let Test.223 : U8 = 1i64; - let Test.224 : U8 = GetTagId Test.222; - let Test.227 : Int1 = lowlevel Eq Test.223 Test.224; - if Test.227 then - let Test.219 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; - let Test.220 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.219; - let Test.221 : Int1 = true; - let Test.226 : Int1 = lowlevel Eq Test.221 Test.220; - if Test.226 then - joinpoint Test.207 #Derived_gen.194: - let Test.33 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.35 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; - let Test.200 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; - let Test.36 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.200; - inc Test.36; - let Test.38 : I64 = UnionAtIndex (Id 1) (Index 1) Test.200; - let Test.39 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.200; - inc Test.39; - let Test.37 : I32 = UnionAtIndex (Id 1) (Index 3) Test.200; - let Test.34 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; - joinpoint #Derived_gen.31 #Derived_gen.197 #Derived_gen.198 #Derived_gen.199: - let Test.192 : Int1 = false; - let Test.189 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.199 UpdateModeId { id: 107 } TagId(1) Test.33 Test.35 Test.36 Test.34 Test.192; - let Test.191 : Int1 = false; - let Test.190 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.198 UpdateModeId { id: 106 } TagId(1) Test.39 Test.18 Test.19 Test.17 Test.191; - let Test.188 : Int1 = true; - let Test.187 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.197 UpdateModeId { id: 105 } TagId(1) Test.189 Test.38 Test.190 Test.37 Test.188; - ret Test.187; + let Test.228 : U8 = 1i64; + let Test.229 : U8 = GetTagId Test.180; + let Test.230 : Int1 = lowlevel Eq Test.228 Test.229; + if Test.230 then + joinpoint Test.225 #Derived_gen.226: + joinpoint Test.216 #Derived_gen.227: + let Test.46 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.48 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; + let Test.49 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; + let Test.47 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; + joinpoint #Derived_gen.66 #Derived_gen.229 #Derived_gen.230: + let Test.196 : Int1 = true; + let Test.195 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.230 UpdateModeId { id: 100 } TagId(1) Test.46 Test.48 Test.49 Test.47 Test.196; + let Test.194 : Int1 = false; + let Test.193 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.229 UpdateModeId { id: 99 } TagId(1) Test.195 Test.18 Test.19 Test.17 Test.194; + let #Derived_gen.16 : {} = lowlevel PtrStore #Derived_gen.6 Test.193; + let #Derived_gen.15 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; + ret #Derived_gen.15; in - let #Derived_gen.32 : Int1 = lowlevel RefCountIsUnique Test.180; - if #Derived_gen.32 then - let #Derived_gen.200 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.200, id: UpdateModeId { id: 108 } }; - let #Derived_gen.201 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 109 } }; - jump #Derived_gen.31 #Derived_gen.194 #Derived_gen.200 #Derived_gen.201; + let #Derived_gen.67 : Int1 = lowlevel RefCountIsUnique Test.180; + if #Derived_gen.67 then + let #Derived_gen.231 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 101 } }; + jump #Derived_gen.66 #Derived_gen.227 #Derived_gen.231; else - inc Test.33; + inc Test.46; + inc Test.49; decref Test.180; - let #Derived_gen.202 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.31 #Derived_gen.202 #Derived_gen.202 #Derived_gen.194; + let #Derived_gen.232 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.66 #Derived_gen.232 #Derived_gen.227; in - let Test.204 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.205 : U8 = 1i64; - let Test.206 : U8 = GetTagId Test.204; - let Test.209 : Int1 = lowlevel Eq Test.205 Test.206; - if Test.209 then - let Test.201 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; - let Test.202 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.201; - let Test.203 : Int1 = true; - let Test.208 : Int1 = lowlevel Eq Test.203 Test.202; - if Test.208 then - jump Test.199 #Derived_gen.80; + let Test.213 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.214 : U8 = 1i64; + let Test.215 : U8 = GetTagId Test.213; + let Test.218 : Int1 = lowlevel Eq Test.214 Test.215; + if Test.218 then + let Test.210 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.211 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.210; + let Test.212 : Int1 = true; + let Test.217 : Int1 = lowlevel Eq Test.212 Test.211; + if Test.217 then + jump Test.199 #Derived_gen.226; + else + jump Test.216 #Derived_gen.226; + else + jump Test.216 #Derived_gen.226; + in + let Test.222 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; + let Test.223 : U8 = 1i64; + let Test.224 : U8 = GetTagId Test.222; + let Test.227 : Int1 = lowlevel Eq Test.223 Test.224; + if Test.227 then + let Test.219 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; + let Test.220 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.219; + let Test.221 : Int1 = true; + let Test.226 : Int1 = lowlevel Eq Test.221 Test.220; + if Test.226 then + joinpoint Test.207 #Derived_gen.233: + let Test.33 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.35 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; + let Test.200 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; + let Test.36 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.200; + inc Test.36; + let Test.38 : I64 = UnionAtIndex (Id 1) (Index 1) Test.200; + let Test.39 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.200; + inc Test.39; + let Test.37 : I32 = UnionAtIndex (Id 1) (Index 3) Test.200; + let Test.34 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; + joinpoint #Derived_gen.70 #Derived_gen.236 #Derived_gen.237 #Derived_gen.238: + let Test.192 : Int1 = false; + let Test.189 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.238 UpdateModeId { id: 107 } TagId(1) Test.33 Test.35 Test.36 Test.34 Test.192; + let Test.191 : Int1 = false; + let Test.190 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.237 UpdateModeId { id: 106 } TagId(1) Test.39 Test.18 Test.19 Test.17 Test.191; + let Test.188 : Int1 = true; + let Test.187 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.236 UpdateModeId { id: 105 } TagId(1) Test.189 Test.38 Test.190 Test.37 Test.188; + let #Derived_gen.18 : {} = lowlevel PtrStore #Derived_gen.6 Test.187; + let #Derived_gen.17 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; + ret #Derived_gen.17; + in + let #Derived_gen.71 : Int1 = lowlevel RefCountIsUnique Test.180; + if #Derived_gen.71 then + let #Derived_gen.239 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.200, id: UpdateModeId { id: 108 } }; + let #Derived_gen.240 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 109 } }; + jump #Derived_gen.70 #Derived_gen.233 #Derived_gen.239 #Derived_gen.240; + else + inc Test.33; + decref Test.180; + let #Derived_gen.241 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.70 #Derived_gen.241 #Derived_gen.241 #Derived_gen.233; + in + let Test.204 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.205 : U8 = 1i64; + let Test.206 : U8 = GetTagId Test.204; + let Test.209 : Int1 = lowlevel Eq Test.205 Test.206; + if Test.209 then + let Test.201 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; + let Test.202 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.201; + let Test.203 : Int1 = true; + let Test.208 : Int1 = lowlevel Eq Test.203 Test.202; + if Test.208 then + jump Test.199 #Derived_gen.119; + else + jump Test.207 #Derived_gen.119; else - jump Test.207 #Derived_gen.80; + jump Test.207 #Derived_gen.119; else - jump Test.207 #Derived_gen.80; + jump Test.225 #Derived_gen.119; else - jump Test.225 #Derived_gen.80; + jump Test.225 #Derived_gen.119; else - jump Test.225 #Derived_gen.80; + decref #Derived_gen.119; + dec Test.19; + let Test.197 : [C *self I64 *self I32 Int1, ] = TagId(0) ; + let #Derived_gen.20 : {} = lowlevel PtrStore #Derived_gen.6 Test.197; + let #Derived_gen.19 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; + ret #Derived_gen.19; else - decref #Derived_gen.80; - dec Test.19; - let Test.197 : [C *self I64 *self I32 Int1, ] = TagId(0) ; - ret Test.197; + jump Test.238 #Derived_gen.119; else - jump Test.238 #Derived_gen.80; + jump Test.238 #Derived_gen.119; else - jump Test.238 #Derived_gen.80; - else - let Test.117 : Int1 = CallByName Num.24 Test.10 Test.17; - if Test.117 then - joinpoint Test.176 #Derived_gen.294: - let Test.171 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.19 Test.10 Test.11; - let Test.170 : Int1 = false; - let Test.169 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.294 UpdateModeId { id: 196 } TagId(1) Test.16 Test.18 Test.171 Test.17 Test.170; - ret Test.169; - in - let Test.174 : U8 = 1i64; - let Test.175 : U8 = GetTagId Test.19; - let Test.178 : Int1 = lowlevel Eq Test.174 Test.175; - if Test.178 then - let Test.172 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.19; - let Test.173 : Int1 = true; - let Test.177 : Int1 = lowlevel Eq Test.173 Test.172; - if Test.177 then - inc Test.19; - let #Derived_gen.295 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.16, id: UpdateModeId { id: 197 } }; - let Test.118 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.19 Test.10 Test.11; - joinpoint Test.137 #Derived_gen.335 #Derived_gen.336: - let Test.136 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.57 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.136; - inc Test.57; - let Test.59 : I64 = UnionAtIndex (Id 1) (Index 1) Test.136; - let Test.60 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.136; - inc Test.60; - let Test.58 : I32 = UnionAtIndex (Id 1) (Index 3) Test.136; - let Test.62 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; - let Test.63 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; - let Test.61 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; - joinpoint #Derived_gen.73 #Derived_gen.340 #Derived_gen.341 #Derived_gen.342: - let Test.124 : Int1 = false; - let Test.121 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.342 UpdateModeId { id: 242 } TagId(1) Test.57 Test.59 Test.60 Test.58 Test.124; - let Test.123 : Int1 = false; - let Test.122 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.341 UpdateModeId { id: 241 } TagId(1) Test.63 Test.18 Test.19 Test.17 Test.123; - let Test.120 : Int1 = true; - let Test.119 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.340 UpdateModeId { id: 240 } TagId(1) Test.121 Test.62 Test.122 Test.61 Test.120; - ret Test.119; - in - let #Derived_gen.74 : Int1 = lowlevel RefCountIsUnique Test.118; - if #Derived_gen.74 then - decref #Derived_gen.335; - let #Derived_gen.343 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.136, id: UpdateModeId { id: 243 } }; - let #Derived_gen.344 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 244 } }; - jump #Derived_gen.73 #Derived_gen.336 #Derived_gen.343 #Derived_gen.344; - else - inc Test.63; - decref Test.118; - let #Derived_gen.345 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.73 #Derived_gen.345 #Derived_gen.335 #Derived_gen.336; - in - let Test.166 : U8 = 1i64; - let Test.167 : U8 = GetTagId Test.118; - let Test.168 : Int1 = lowlevel Eq Test.166 Test.167; - if Test.168 then - joinpoint Test.163 #Derived_gen.357 #Derived_gen.358: - joinpoint Test.154 #Derived_gen.359 #Derived_gen.360: - let Test.83 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.85 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; - let Test.86 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; - let Test.84 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; - joinpoint #Derived_gen.63 #Derived_gen.363 #Derived_gen.364: - let Test.134 : Int1 = true; - let Test.133 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.364 UpdateModeId { id: 262 } TagId(1) Test.83 Test.85 Test.86 Test.84 Test.134; - let Test.132 : Int1 = false; - let Test.131 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.363 UpdateModeId { id: 261 } TagId(1) Test.133 Test.18 Test.19 Test.17 Test.132; - ret Test.131; - in - let #Derived_gen.64 : Int1 = lowlevel RefCountIsUnique Test.118; - if #Derived_gen.64 then - decref #Derived_gen.359; - let #Derived_gen.365 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 263 } }; - jump #Derived_gen.63 #Derived_gen.360 #Derived_gen.365; - else - inc Test.83; - inc Test.86; - decref Test.118; - jump #Derived_gen.63 #Derived_gen.359 #Derived_gen.360; + let Test.117 : Int1 = CallByName Num.24 Test.10 Test.17; + if Test.117 then + joinpoint Test.176 #Derived_gen.333: + let Test.170 : Int1 = false; + let #Derived_gen.21 : [C *self I64 *self I32 Int1, ] = NullPointer; + let Test.169 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.333 UpdateModeId { id: 196 } TagId(1) Test.16 Test.18 #Derived_gen.21 Test.17 Test.170; + let #Derived_gen.22 : Ptr([C *self I64 *self I32 Int1, ]) = UnionFieldPtrAtIndex (Id 1) (Index 2) Test.169; + let #Derived_gen.23 : {} = lowlevel PtrStore #Derived_gen.6 Test.169; + jump #Derived_gen.5 Test.19 Test.10 Test.11 #Derived_gen.22 #Derived_gen.7; + in + let Test.174 : U8 = 1i64; + let Test.175 : U8 = GetTagId Test.19; + let Test.178 : Int1 = lowlevel Eq Test.174 Test.175; + if Test.178 then + let Test.172 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.19; + let Test.173 : Int1 = true; + let Test.177 : Int1 = lowlevel Eq Test.173 Test.172; + if Test.177 then + inc Test.19; + let #Derived_gen.334 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.16, id: UpdateModeId { id: 197 } }; + let Test.118 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.19 Test.10 Test.11; + joinpoint Test.137 #Derived_gen.374 #Derived_gen.375: + let Test.136 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.57 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.136; + inc Test.57; + let Test.59 : I64 = UnionAtIndex (Id 1) (Index 1) Test.136; + let Test.60 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.136; + inc Test.60; + let Test.58 : I32 = UnionAtIndex (Id 1) (Index 3) Test.136; + let Test.62 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; + let Test.63 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; + let Test.61 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; + joinpoint #Derived_gen.112 #Derived_gen.379 #Derived_gen.380 #Derived_gen.381: + let Test.124 : Int1 = false; + let Test.121 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.381 UpdateModeId { id: 242 } TagId(1) Test.57 Test.59 Test.60 Test.58 Test.124; + let Test.123 : Int1 = false; + let Test.122 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.380 UpdateModeId { id: 241 } TagId(1) Test.63 Test.18 Test.19 Test.17 Test.123; + let Test.120 : Int1 = true; + let Test.119 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.379 UpdateModeId { id: 240 } TagId(1) Test.121 Test.62 Test.122 Test.61 Test.120; + let #Derived_gen.25 : {} = lowlevel PtrStore #Derived_gen.6 Test.119; + let #Derived_gen.24 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; + ret #Derived_gen.24; in - let Test.151 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.152 : U8 = 1i64; - let Test.153 : U8 = GetTagId Test.151; - let Test.156 : Int1 = lowlevel Eq Test.152 Test.153; - if Test.156 then - let Test.148 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.149 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.148; - let Test.150 : Int1 = true; - let Test.155 : Int1 = lowlevel Eq Test.150 Test.149; - if Test.155 then - jump Test.137 #Derived_gen.357 #Derived_gen.358; - else - jump Test.154 #Derived_gen.357 #Derived_gen.358; + let #Derived_gen.113 : Int1 = lowlevel RefCountIsUnique Test.118; + if #Derived_gen.113 then + decref #Derived_gen.374; + let #Derived_gen.382 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.136, id: UpdateModeId { id: 243 } }; + let #Derived_gen.383 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 244 } }; + jump #Derived_gen.112 #Derived_gen.375 #Derived_gen.382 #Derived_gen.383; else - jump Test.154 #Derived_gen.357 #Derived_gen.358; + inc Test.63; + decref Test.118; + let #Derived_gen.384 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.112 #Derived_gen.384 #Derived_gen.374 #Derived_gen.375; in - let Test.160 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; - let Test.161 : U8 = 1i64; - let Test.162 : U8 = GetTagId Test.160; - let Test.165 : Int1 = lowlevel Eq Test.161 Test.162; - if Test.165 then - let Test.157 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; - let Test.158 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.157; - let Test.159 : Int1 = true; - let Test.164 : Int1 = lowlevel Eq Test.159 Test.158; - if Test.164 then - joinpoint Test.145 #Derived_gen.366 #Derived_gen.367: - let Test.70 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.72 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; - let Test.138 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; - let Test.73 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.138; - inc Test.73; - let Test.75 : I64 = UnionAtIndex (Id 1) (Index 1) Test.138; - let Test.76 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.138; - inc Test.76; - let Test.74 : I32 = UnionAtIndex (Id 1) (Index 3) Test.138; - let Test.71 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; - joinpoint #Derived_gen.67 #Derived_gen.371 #Derived_gen.372 #Derived_gen.373: - let Test.130 : Int1 = false; - let Test.127 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.373 UpdateModeId { id: 271 } TagId(1) Test.70 Test.72 Test.73 Test.71 Test.130; - let Test.129 : Int1 = false; - let Test.128 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.372 UpdateModeId { id: 270 } TagId(1) Test.76 Test.18 Test.19 Test.17 Test.129; - let Test.126 : Int1 = true; - let Test.125 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.371 UpdateModeId { id: 269 } TagId(1) Test.127 Test.75 Test.128 Test.74 Test.126; - ret Test.125; + let Test.166 : U8 = 1i64; + let Test.167 : U8 = GetTagId Test.118; + let Test.168 : Int1 = lowlevel Eq Test.166 Test.167; + if Test.168 then + joinpoint Test.163 #Derived_gen.396 #Derived_gen.397: + joinpoint Test.154 #Derived_gen.398 #Derived_gen.399: + let Test.83 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.85 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; + let Test.86 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; + let Test.84 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; + joinpoint #Derived_gen.102 #Derived_gen.402 #Derived_gen.403: + let Test.134 : Int1 = true; + let Test.133 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.403 UpdateModeId { id: 262 } TagId(1) Test.83 Test.85 Test.86 Test.84 Test.134; + let Test.132 : Int1 = false; + let Test.131 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.402 UpdateModeId { id: 261 } TagId(1) Test.133 Test.18 Test.19 Test.17 Test.132; + let #Derived_gen.27 : {} = lowlevel PtrStore #Derived_gen.6 Test.131; + let #Derived_gen.26 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; + ret #Derived_gen.26; in - let #Derived_gen.68 : Int1 = lowlevel RefCountIsUnique Test.118; - if #Derived_gen.68 then - decref #Derived_gen.366; - let #Derived_gen.374 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.138, id: UpdateModeId { id: 272 } }; - let #Derived_gen.375 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 273 } }; - jump #Derived_gen.67 #Derived_gen.367 #Derived_gen.374 #Derived_gen.375; + let #Derived_gen.103 : Int1 = lowlevel RefCountIsUnique Test.118; + if #Derived_gen.103 then + decref #Derived_gen.398; + let #Derived_gen.404 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 263 } }; + jump #Derived_gen.102 #Derived_gen.399 #Derived_gen.404; else - inc Test.70; + inc Test.83; + inc Test.86; decref Test.118; - let #Derived_gen.376 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.67 #Derived_gen.376 #Derived_gen.366 #Derived_gen.367; + jump #Derived_gen.102 #Derived_gen.398 #Derived_gen.399; in - let Test.142 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.143 : U8 = 1i64; - let Test.144 : U8 = GetTagId Test.142; - let Test.147 : Int1 = lowlevel Eq Test.143 Test.144; - if Test.147 then - let Test.139 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; - let Test.140 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.139; - let Test.141 : Int1 = true; - let Test.146 : Int1 = lowlevel Eq Test.141 Test.140; - if Test.146 then - jump Test.137 #Derived_gen.80 #Derived_gen.295; + let Test.151 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.152 : U8 = 1i64; + let Test.153 : U8 = GetTagId Test.151; + let Test.156 : Int1 = lowlevel Eq Test.152 Test.153; + if Test.156 then + let Test.148 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.149 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.148; + let Test.150 : Int1 = true; + let Test.155 : Int1 = lowlevel Eq Test.150 Test.149; + if Test.155 then + jump Test.137 #Derived_gen.396 #Derived_gen.397; + else + jump Test.154 #Derived_gen.396 #Derived_gen.397; + else + jump Test.154 #Derived_gen.396 #Derived_gen.397; + in + let Test.160 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; + let Test.161 : U8 = 1i64; + let Test.162 : U8 = GetTagId Test.160; + let Test.165 : Int1 = lowlevel Eq Test.161 Test.162; + if Test.165 then + let Test.157 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; + let Test.158 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.157; + let Test.159 : Int1 = true; + let Test.164 : Int1 = lowlevel Eq Test.159 Test.158; + if Test.164 then + joinpoint Test.145 #Derived_gen.405 #Derived_gen.406: + let Test.70 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.72 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; + let Test.138 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; + let Test.73 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.138; + inc Test.73; + let Test.75 : I64 = UnionAtIndex (Id 1) (Index 1) Test.138; + let Test.76 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.138; + inc Test.76; + let Test.74 : I32 = UnionAtIndex (Id 1) (Index 3) Test.138; + let Test.71 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; + joinpoint #Derived_gen.106 #Derived_gen.410 #Derived_gen.411 #Derived_gen.412: + let Test.130 : Int1 = false; + let Test.127 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.412 UpdateModeId { id: 271 } TagId(1) Test.70 Test.72 Test.73 Test.71 Test.130; + let Test.129 : Int1 = false; + let Test.128 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.411 UpdateModeId { id: 270 } TagId(1) Test.76 Test.18 Test.19 Test.17 Test.129; + let Test.126 : Int1 = true; + let Test.125 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.410 UpdateModeId { id: 269 } TagId(1) Test.127 Test.75 Test.128 Test.74 Test.126; + let #Derived_gen.29 : {} = lowlevel PtrStore #Derived_gen.6 Test.125; + let #Derived_gen.28 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; + ret #Derived_gen.28; + in + let #Derived_gen.107 : Int1 = lowlevel RefCountIsUnique Test.118; + if #Derived_gen.107 then + decref #Derived_gen.405; + let #Derived_gen.413 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.138, id: UpdateModeId { id: 272 } }; + let #Derived_gen.414 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 273 } }; + jump #Derived_gen.106 #Derived_gen.406 #Derived_gen.413 #Derived_gen.414; + else + inc Test.70; + decref Test.118; + let #Derived_gen.415 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.106 #Derived_gen.415 #Derived_gen.405 #Derived_gen.406; + in + let Test.142 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.143 : U8 = 1i64; + let Test.144 : U8 = GetTagId Test.142; + let Test.147 : Int1 = lowlevel Eq Test.143 Test.144; + if Test.147 then + let Test.139 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; + let Test.140 : Int1 = UnionAtIndex (Id 1) (Index 4) Test.139; + let Test.141 : Int1 = true; + let Test.146 : Int1 = lowlevel Eq Test.141 Test.140; + if Test.146 then + jump Test.137 #Derived_gen.119 #Derived_gen.334; + else + jump Test.145 #Derived_gen.119 #Derived_gen.334; else - jump Test.145 #Derived_gen.80 #Derived_gen.295; + jump Test.145 #Derived_gen.119 #Derived_gen.334; else - jump Test.145 #Derived_gen.80 #Derived_gen.295; + jump Test.163 #Derived_gen.119 #Derived_gen.334; else - jump Test.163 #Derived_gen.80 #Derived_gen.295; + jump Test.163 #Derived_gen.119 #Derived_gen.334; else - jump Test.163 #Derived_gen.80 #Derived_gen.295; + decref #Derived_gen.334; + decref #Derived_gen.119; + joinpoint #Derived_gen.108: + let Test.135 : [C *self I64 *self I32 Int1, ] = TagId(0) ; + let #Derived_gen.31 : {} = lowlevel PtrStore #Derived_gen.6 Test.135; + let #Derived_gen.30 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; + ret #Derived_gen.30; + in + let #Derived_gen.111 : Int1 = lowlevel RefCountIsUnique Test.19; + if #Derived_gen.111 then + let #Derived_gen.110 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.19; + dec #Derived_gen.110; + let #Derived_gen.109 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.19; + dec #Derived_gen.109; + decref Test.19; + jump #Derived_gen.108; + else + decref Test.19; + jump #Derived_gen.108; else - decref #Derived_gen.295; - decref #Derived_gen.80; - joinpoint #Derived_gen.69: - let Test.135 : [C *self I64 *self I32 Int1, ] = TagId(0) ; - ret Test.135; - in - let #Derived_gen.72 : Int1 = lowlevel RefCountIsUnique Test.19; - if #Derived_gen.72 then - let #Derived_gen.71 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.19; - dec #Derived_gen.71; - let #Derived_gen.70 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.19; - dec #Derived_gen.70; - decref Test.19; - jump #Derived_gen.69; - else - decref Test.19; - jump #Derived_gen.69; + jump Test.176 #Derived_gen.119; else - jump Test.176 #Derived_gen.80; + jump Test.176 #Derived_gen.119; else - jump Test.176 #Derived_gen.80; - else - let Test.116 : Int1 = false; - let Test.115 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.80 UpdateModeId { id: 1 } TagId(1) Test.16 Test.11 Test.19 Test.10 Test.116; - ret Test.115; - in - let #Derived_gen.76 : Int1 = lowlevel RefCountIsUnique Test.9; - if #Derived_gen.76 then - let #Derived_gen.385 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.9, id: UpdateModeId { id: 282 } }; - jump #Derived_gen.75 #Derived_gen.385; - else - inc Test.16; - inc Test.19; - decref Test.9; - let #Derived_gen.386 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.75 #Derived_gen.386; - else - let Test.96 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.9; - let Test.98 : I64 = UnionAtIndex (Id 1) (Index 1) Test.9; - let Test.99 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.9; - let Test.97 : I32 = UnionAtIndex (Id 1) (Index 3) Test.9; - joinpoint #Derived_gen.77 #Derived_gen.388: - let Test.247 : Int1 = CallByName Num.22 Test.10 Test.97; - if Test.247 then - let Test.250 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.96 Test.10 Test.11; - let Test.249 : Int1 = true; - let Test.248 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.388 UpdateModeId { id: 284 } TagId(1) Test.250 Test.98 Test.99 Test.97 Test.249; - ret Test.248; + let Test.116 : Int1 = false; + let Test.115 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.119 UpdateModeId { id: 1 } TagId(1) Test.16 Test.11 Test.19 Test.10 Test.116; + let #Derived_gen.33 : {} = lowlevel PtrStore #Derived_gen.6 Test.115; + let #Derived_gen.32 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; + ret #Derived_gen.32; + in + let #Derived_gen.115 : Int1 = lowlevel RefCountIsUnique Test.9; + if #Derived_gen.115 then + let #Derived_gen.424 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.9, id: UpdateModeId { id: 282 } }; + jump #Derived_gen.114 #Derived_gen.424; else - let Test.243 : Int1 = CallByName Num.24 Test.10 Test.97; - if Test.243 then - let Test.246 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.99 Test.10 Test.11; - let Test.245 : Int1 = true; - let Test.244 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.388 UpdateModeId { id: 284 } TagId(1) Test.96 Test.98 Test.246 Test.97 Test.245; - ret Test.244; - else - let Test.242 : Int1 = true; - let Test.241 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.388 UpdateModeId { id: 284 } TagId(1) Test.96 Test.11 Test.99 Test.10 Test.242; - ret Test.241; - in - let #Derived_gen.78 : Int1 = lowlevel RefCountIsUnique Test.9; - if #Derived_gen.78 then - let #Derived_gen.389 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.9, id: UpdateModeId { id: 285 } }; - jump #Derived_gen.77 #Derived_gen.389; + inc Test.16; + inc Test.19; + decref Test.9; + let #Derived_gen.425 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.114 #Derived_gen.425; else - inc Test.96; - inc Test.99; - decref Test.9; - let #Derived_gen.390 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.77 #Derived_gen.390; + let Test.96 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.9; + let Test.98 : I64 = UnionAtIndex (Id 1) (Index 1) Test.9; + let Test.99 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.9; + let Test.97 : I32 = UnionAtIndex (Id 1) (Index 3) Test.9; + joinpoint #Derived_gen.116 #Derived_gen.427: + let Test.247 : Int1 = CallByName Num.22 Test.10 Test.97; + if Test.247 then + let Test.249 : Int1 = true; + let #Derived_gen.34 : [C *self I64 *self I32 Int1, ] = NullPointer; + let Test.248 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.427 UpdateModeId { id: 284 } TagId(1) #Derived_gen.34 Test.98 Test.99 Test.97 Test.249; + let #Derived_gen.35 : Ptr([C *self I64 *self I32 Int1, ]) = UnionFieldPtrAtIndex (Id 1) (Index 0) Test.248; + let #Derived_gen.36 : {} = lowlevel PtrStore #Derived_gen.6 Test.248; + jump #Derived_gen.5 Test.96 Test.10 Test.11 #Derived_gen.35 #Derived_gen.7; + else + let Test.243 : Int1 = CallByName Num.24 Test.10 Test.97; + if Test.243 then + let Test.245 : Int1 = true; + let #Derived_gen.37 : [C *self I64 *self I32 Int1, ] = NullPointer; + let Test.244 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.427 UpdateModeId { id: 284 } TagId(1) Test.96 Test.98 #Derived_gen.37 Test.97 Test.245; + let #Derived_gen.38 : Ptr([C *self I64 *self I32 Int1, ]) = UnionFieldPtrAtIndex (Id 1) (Index 2) Test.244; + let #Derived_gen.39 : {} = lowlevel PtrStore #Derived_gen.6 Test.244; + jump #Derived_gen.5 Test.99 Test.10 Test.11 #Derived_gen.38 #Derived_gen.7; + else + let Test.242 : Int1 = true; + let Test.241 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.427 UpdateModeId { id: 284 } TagId(1) Test.96 Test.11 Test.99 Test.10 Test.242; + let #Derived_gen.41 : {} = lowlevel PtrStore #Derived_gen.6 Test.241; + let #Derived_gen.40 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; + ret #Derived_gen.40; + in + let #Derived_gen.117 : Int1 = lowlevel RefCountIsUnique Test.9; + if #Derived_gen.117 then + let #Derived_gen.428 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.9, id: UpdateModeId { id: 285 } }; + jump #Derived_gen.116 #Derived_gen.428; + else + inc Test.96; + inc Test.99; + decref Test.9; + let #Derived_gen.429 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.116 #Derived_gen.429; + in + jump #Derived_gen.5 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.3; procedure Test.0 (): let Test.281 : [C *self I64 *self I32 Int1, ] = TagId(0) ; From c38f8bec759a766f3ed48ef48101e6b49f4e9437 Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 22 Jun 2023 18:42:21 +0200 Subject: [PATCH 050/140] fix llvm gen tests --- crates/compiler/gen_llvm/src/llvm/compare.rs | 8 +-- .../compiler/test_gen/src/gen_primitives.rs | 67 ++++++++++--------- 2 files changed, 35 insertions(+), 40 deletions(-) diff --git a/crates/compiler/gen_llvm/src/llvm/compare.rs b/crates/compiler/gen_llvm/src/llvm/compare.rs index 804e8db8120..02dcbea26bf 100644 --- a/crates/compiler/gen_llvm/src/llvm/compare.rs +++ b/crates/compiler/gen_llvm/src/llvm/compare.rs @@ -144,14 +144,8 @@ fn build_eq<'a, 'ctx>( lhs_val: BasicValueEnum<'ctx>, rhs_val: BasicValueEnum<'ctx>, lhs_layout: LayoutRepr<'a>, - rhs_layout: LayoutRepr<'a>, + _rhs_layout: LayoutRepr<'a>, ) -> BasicValueEnum<'ctx> { - debug_assert_eq!( - lhs_layout, rhs_layout, - "Equality of different layouts; did you have a type mismatch?\n{:?} == {:?}", - lhs_layout, rhs_layout - ); - match lhs_layout { LayoutRepr::Builtin(builtin) => build_eq_builtin( env, diff --git a/crates/compiler/test_gen/src/gen_primitives.rs b/crates/compiler/test_gen/src/gen_primitives.rs index 952a4a61d78..dc1078011c5 100644 --- a/crates/compiler/test_gen/src/gen_primitives.rs +++ b/crates/compiler/test_gen/src/gen_primitives.rs @@ -2211,45 +2211,46 @@ fn nullable_eval_cfold() { #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn nested_switch() { - // exposed bug with passing the right symbol/layout down into switch branch generation - // This is also the only test_gen test that exercises Reset/Reuse (as of Aug 2022) - assert_evals_to!( - indoc!( - r#" - app "test" provides [main] to "./platform" + crate::helpers::with_larger_debug_stack(|| + // exposed bug with passing the right symbol/layout down into switch branch generation + // This is also the only test_gen test that exercises Reset/Reuse (as of Aug 2022) + assert_evals_to!( + indoc!( + r#" + app "test" provides [main] to "./platform" - Expr : [ZAdd Expr Expr, Val I64, Var I64] + Expr : [ZAdd Expr Expr, Val I64, Var I64] - eval : Expr -> I64 - eval = \e -> - when e is - Var _ -> 0 - Val v -> v - ZAdd l r -> eval l + eval r + eval : Expr -> I64 + eval = \e -> + when e is + Var _ -> 0 + Val v -> v + ZAdd l r -> eval l + eval r - constFolding : Expr -> Expr - constFolding = \e -> - when e is - ZAdd e1 e2 -> - when Pair e1 e2 is - Pair (Val a) (Val b) -> Val (a+b) - Pair (Val a) (ZAdd x (Val b)) -> ZAdd (Val (a+b)) x - Pair _ _ -> ZAdd e1 e2 + constFolding : Expr -> Expr + constFolding = \e -> + when e is + ZAdd e1 e2 -> + when Pair e1 e2 is + Pair (Val a) (Val b) -> Val (a+b) + Pair (Val a) (ZAdd x (Val b)) -> ZAdd (Val (a+b)) x + Pair _ _ -> ZAdd e1 e2 - _ -> e + _ -> e - expr : Expr - expr = ZAdd (Val 3) (ZAdd (Val 4) (Val 5)) + expr : Expr + expr = ZAdd (Val 3) (ZAdd (Val 4) (Val 5)) - main : I64 - main = eval (constFolding expr) - "# - ), - 12, - i64 - ); + main : I64 + main = eval (constFolding expr) + "# + ), + 12, + i64 + )); } #[test] @@ -4522,8 +4523,8 @@ fn linked_list_trmc() { Nil -> 0 Cons _ rest -> 1 + length rest - main : I64 - main = + main : I64 + main = repeat "foo" 5 |> length "# From 41af8ff9693f9bbcf62b25d1092fb8d3453b78a0 Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 22 Jun 2023 21:14:22 +0200 Subject: [PATCH 051/140] fix invalid register write --- crates/compiler/gen_dev/src/generic64/mod.rs | 54 ++++++++++++-------- examples/platform-switching/rocLovesZig.roc | 17 +++++- 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/crates/compiler/gen_dev/src/generic64/mod.rs b/crates/compiler/gen_dev/src/generic64/mod.rs index b933ca70dc5..76aa3e3f9bb 100644 --- a/crates/compiler/gen_dev/src/generic64/mod.rs +++ b/crates/compiler/gen_dev/src/generic64/mod.rs @@ -2798,7 +2798,7 @@ impl< ASM::mov_reg64_imm64(&mut self.buf, mask_reg, (!0b111) as _); // mask out the tag id bits - ASM::and_reg64_reg64_reg64(&mut self.buf, ptr_reg, ptr_reg, mask_reg); + ASM::and_reg64_reg64_reg64(&mut self.buf, mask_reg, ptr_reg, mask_reg); let mut offset = 0; for field in &other_fields[..index as usize] { @@ -2809,7 +2809,7 @@ impl< &mut self.buf, &mut self.storage_manager, self.layout_interner, - ptr_reg, + mask_reg, offset as i32, element_layout, *sym, @@ -2824,15 +2824,22 @@ impl< .load_to_general_reg(&mut self.buf, structure); // mask out the tag id bits - if !union_layout.stores_tag_id_as_data(self.storage_manager.target_info) { - let mask_symbol = self.debug_symbol("tag_id_mask"); - let mask_reg = self + let unmasked_reg = if union_layout + .stores_tag_id_as_data(self.storage_manager.target_info) + { + ptr_reg + } else { + let umasked_symbol = self.debug_symbol("unmasked"); + let unmasked_reg = self .storage_manager - .claim_general_reg(&mut self.buf, &mask_symbol); - ASM::mov_reg64_imm64(&mut self.buf, mask_reg, (!0b111) as _); + .claim_general_reg(&mut self.buf, &umasked_symbol); - ASM::and_reg64_reg64_reg64(&mut self.buf, ptr_reg, ptr_reg, mask_reg); - } + ASM::mov_reg64_imm64(&mut self.buf, unmasked_reg, (!0b111) as _); + + ASM::and_reg64_reg64_reg64(&mut self.buf, unmasked_reg, ptr_reg, unmasked_reg); + + unmasked_reg + }; let mut offset = 0; for field in &other_fields[..index as usize] { @@ -2843,7 +2850,7 @@ impl< &mut self.buf, &mut self.storage_manager, self.layout_interner, - ptr_reg, + unmasked_reg, offset as i32, element_layout, *sym, @@ -2911,14 +2918,14 @@ impl< ASM::mov_reg64_imm64(&mut self.buf, mask_reg, (!0b111) as _); // mask out the tag id bits - ASM::and_reg64_reg64_reg64(&mut self.buf, ptr_reg, ptr_reg, mask_reg); + ASM::and_reg64_reg64_reg64(&mut self.buf, mask_reg, ptr_reg, mask_reg); let mut offset = 0; for field in &other_fields[..index as usize] { offset += self.layout_interner.stack_size(*field); } - ASM::add_reg64_reg64_imm32(&mut self.buf, sym_reg, ptr_reg, offset as i32); + ASM::add_reg64_reg64_imm32(&mut self.buf, sym_reg, mask_reg, offset as i32); } UnionLayout::Recursive(tag_layouts) => { let other_fields = tag_layouts[tag_id as usize]; @@ -2928,22 +2935,29 @@ impl< .load_to_general_reg(&mut self.buf, structure); // mask out the tag id bits - if !union_layout.stores_tag_id_as_data(self.storage_manager.target_info) { - let mask_symbol = self.debug_symbol("tag_id_mask"); - let mask_reg = self + let unmasked_reg = if union_layout + .stores_tag_id_as_data(self.storage_manager.target_info) + { + ptr_reg + } else { + let umasked_symbol = self.debug_symbol("unmasked"); + let unmasked_reg = self .storage_manager - .claim_general_reg(&mut self.buf, &mask_symbol); - ASM::mov_reg64_imm64(&mut self.buf, mask_reg, (!0b111) as _); + .claim_general_reg(&mut self.buf, &umasked_symbol); - ASM::and_reg64_reg64_reg64(&mut self.buf, ptr_reg, ptr_reg, mask_reg); - } + ASM::mov_reg64_imm64(&mut self.buf, unmasked_reg, (!0b111) as _); + + ASM::and_reg64_reg64_reg64(&mut self.buf, unmasked_reg, ptr_reg, unmasked_reg); + + unmasked_reg + }; let mut offset = 0; for field in &other_fields[..index as usize] { offset += self.layout_interner.stack_size(*field); } - ASM::add_reg64_reg64_imm32(&mut self.buf, sym_reg, ptr_reg, offset as i32); + ASM::add_reg64_reg64_imm32(&mut self.buf, sym_reg, unmasked_reg, offset as i32); } } } diff --git a/examples/platform-switching/rocLovesZig.roc b/examples/platform-switching/rocLovesZig.roc index fe838c5396c..df8b079d18e 100644 --- a/examples/platform-switching/rocLovesZig.roc +++ b/examples/platform-switching/rocLovesZig.roc @@ -3,4 +3,19 @@ app "rocLovesZig" imports [] provides [main] to pf -main = "Roc <3 Zig!\n" +Expr : [Var, Val I64, Add Expr Expr, Mul Expr Expr] + +mkExpr : I64 -> Expr +mkExpr = \n -> + when n is + 0 -> Var + _ -> Add (mkExpr (n-1)) Var + +main : Str +main = + when mkExpr 1 is + Var -> "var" + Add _ _ -> "add" + _ -> "other" + + From 26308f1dae15ce6358b69b430f6b46e3bc2a81ad Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 22 Jun 2023 21:14:39 +0200 Subject: [PATCH 052/140] reformat test --- .../compiler/test_gen/src/gen_primitives.rs | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/crates/compiler/test_gen/src/gen_primitives.rs b/crates/compiler/test_gen/src/gen_primitives.rs index dc1078011c5..7c51ad5c8f8 100644 --- a/crates/compiler/test_gen/src/gen_primitives.rs +++ b/crates/compiler/test_gen/src/gen_primitives.rs @@ -2215,42 +2215,42 @@ fn nested_switch() { // exposed bug with passing the right symbol/layout down into switch branch generation // This is also the only test_gen test that exercises Reset/Reuse (as of Aug 2022) assert_evals_to!( - indoc!( - r#" - app "test" provides [main] to "./platform" + indoc!( + r#" + app "test" provides [main] to "./platform" - Expr : [ZAdd Expr Expr, Val I64, Var I64] + Expr : [ZAdd Expr Expr, Val I64, Var I64] - eval : Expr -> I64 - eval = \e -> - when e is - Var _ -> 0 - Val v -> v - ZAdd l r -> eval l + eval r + eval : Expr -> I64 + eval = \e -> + when e is + Var _ -> 0 + Val v -> v + ZAdd l r -> eval l + eval r - constFolding : Expr -> Expr - constFolding = \e -> - when e is - ZAdd e1 e2 -> - when Pair e1 e2 is - Pair (Val a) (Val b) -> Val (a+b) - Pair (Val a) (ZAdd x (Val b)) -> ZAdd (Val (a+b)) x - Pair _ _ -> ZAdd e1 e2 + constFolding : Expr -> Expr + constFolding = \e -> + when e is + ZAdd e1 e2 -> + when Pair e1 e2 is + Pair (Val a) (Val b) -> Val (a+b) + Pair (Val a) (ZAdd x (Val b)) -> ZAdd (Val (a+b)) x + Pair _ _ -> ZAdd e1 e2 - _ -> e + _ -> e - expr : Expr - expr = ZAdd (Val 3) (ZAdd (Val 4) (Val 5)) + expr : Expr + expr = ZAdd (Val 3) (ZAdd (Val 4) (Val 5)) - main : I64 - main = eval (constFolding expr) - "# - ), - 12, - i64 - )); + main : I64 + main = eval (constFolding expr) + "# + ), + 12, + i64 + )); } #[test] From 0b03a0bc2651ce739fef5e7755db71da34426700 Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 22 Jun 2023 21:26:58 +0200 Subject: [PATCH 053/140] revert rocLovesZig.roc --- examples/platform-switching/rocLovesZig.roc | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/examples/platform-switching/rocLovesZig.roc b/examples/platform-switching/rocLovesZig.roc index df8b079d18e..fe838c5396c 100644 --- a/examples/platform-switching/rocLovesZig.roc +++ b/examples/platform-switching/rocLovesZig.roc @@ -3,19 +3,4 @@ app "rocLovesZig" imports [] provides [main] to pf -Expr : [Var, Val I64, Add Expr Expr, Mul Expr Expr] - -mkExpr : I64 -> Expr -mkExpr = \n -> - when n is - 0 -> Var - _ -> Add (mkExpr (n-1)) Var - -main : Str -main = - when mkExpr 1 is - Var -> "var" - Add _ _ -> "add" - _ -> "other" - - +main = "Roc <3 Zig!\n" From 654cf7b861017a1649663e317fec2c8736da6ced Mon Sep 17 00:00:00 2001 From: Folkert Date: Fri, 23 Jun 2023 22:36:21 +0200 Subject: [PATCH 054/140] changes after review --- Cargo.lock | 1 + crates/compiler/can/src/builtins.rs | 2 +- crates/compiler/collections/src/vec_set.rs | 10 -- crates/compiler/gen_dev/src/generic64/mod.rs | 89 ++++++------- crates/compiler/gen_dev/src/lib.rs | 2 +- crates/compiler/gen_llvm/src/llvm/build.rs | 16 +-- crates/compiler/gen_llvm/src/llvm/lowlevel.rs | 2 +- crates/compiler/gen_wasm/src/low_level.rs | 4 +- crates/compiler/module/src/low_level.rs | 4 +- crates/compiler/mono/Cargo.toml | 1 + crates/compiler/mono/src/borrow.rs | 2 +- .../compiler/mono/src/drop_specialization.rs | 2 +- crates/compiler/mono/src/ir.rs | 1 + crates/compiler/mono/src/layout.rs | 3 + crates/compiler/mono/src/tail_recursion.rs | 122 +++++++++++------- .../test_mono/generated/linked_list_map.txt | 2 +- .../test_mono/generated/rb_tree_fbip.txt | 2 +- 17 files changed, 142 insertions(+), 123 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 256cbe02628..904d6d5066b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3669,6 +3669,7 @@ dependencies = [ name = "roc_mono" version = "0.0.1" dependencies = [ + "arrayvec 0.7.2", "bitvec", "bumpalo", "hashbrown 0.13.2", diff --git a/crates/compiler/can/src/builtins.rs b/crates/compiler/can/src/builtins.rs index cf8ca72ee94..656f9cd1b42 100644 --- a/crates/compiler/can/src/builtins.rs +++ b/crates/compiler/can/src/builtins.rs @@ -87,7 +87,7 @@ macro_rules! map_symbol_to_lowlevel_and_arity { LowLevel::PtrCast => unimplemented!(), LowLevel::PtrStore => unimplemented!(), LowLevel::PtrLoad => unimplemented!(), - LowLevel::PtrToStackValue => unimplemented!(), + LowLevel::Alloca => unimplemented!(), LowLevel::RefCountIncRcPtr => unimplemented!(), LowLevel::RefCountDecRcPtr=> unimplemented!(), LowLevel::RefCountIncDataPtr => unimplemented!(), diff --git a/crates/compiler/collections/src/vec_set.rs b/crates/compiler/collections/src/vec_set.rs index c45a8169248..2a19bf2b9c7 100644 --- a/crates/compiler/collections/src/vec_set.rs +++ b/crates/compiler/collections/src/vec_set.rs @@ -102,16 +102,6 @@ impl VecSet { { self.elements.retain(f) } - - pub fn keep_if_in_both(&mut self, other: &Self) { - self.elements.retain(|e| other.contains(e)); - } - - pub fn keep_if_in_either(&mut self, other: Self) { - for e in other.elements { - self.insert(e); - } - } } impl Extend for VecSet { diff --git a/crates/compiler/gen_dev/src/generic64/mod.rs b/crates/compiler/gen_dev/src/generic64/mod.rs index 76aa3e3f9bb..90804dbc0f8 100644 --- a/crates/compiler/gen_dev/src/generic64/mod.rs +++ b/crates/compiler/gen_dev/src/generic64/mod.rs @@ -2791,14 +2791,7 @@ impl< .storage_manager .load_to_general_reg(&mut self.buf, structure); - let mask_symbol = self.debug_symbol("tag_id_mask"); - let mask_reg = self - .storage_manager - .claim_general_reg(&mut self.buf, &mask_symbol); - ASM::mov_reg64_imm64(&mut self.buf, mask_reg, (!0b111) as _); - - // mask out the tag id bits - ASM::and_reg64_reg64_reg64(&mut self.buf, mask_reg, ptr_reg, mask_reg); + let (mask_symbol, mask_reg) = self.clear_tag_id(ptr_reg); let mut offset = 0; for field in &other_fields[..index as usize] { @@ -2814,6 +2807,8 @@ impl< element_layout, *sym, ); + + self.free_symbol(&mask_symbol) } UnionLayout::Recursive(tag_layouts) => { let other_fields = tag_layouts[tag_id as usize]; @@ -2824,22 +2819,13 @@ impl< .load_to_general_reg(&mut self.buf, structure); // mask out the tag id bits - let unmasked_reg = if union_layout - .stores_tag_id_as_data(self.storage_manager.target_info) - { - ptr_reg - } else { - let umasked_symbol = self.debug_symbol("unmasked"); - let unmasked_reg = self - .storage_manager - .claim_general_reg(&mut self.buf, &umasked_symbol); - - ASM::mov_reg64_imm64(&mut self.buf, unmasked_reg, (!0b111) as _); - - ASM::and_reg64_reg64_reg64(&mut self.buf, unmasked_reg, ptr_reg, unmasked_reg); - - unmasked_reg - }; + let (unmasked_symbol, unmasked_reg) = + if union_layout.stores_tag_id_as_data(self.storage_manager.target_info) { + (None, ptr_reg) + } else { + let (mask_symbol, mask_reg) = self.clear_tag_id(ptr_reg); + (Some(mask_symbol), mask_reg) + }; let mut offset = 0; for field in &other_fields[..index as usize] { @@ -2855,6 +2841,10 @@ impl< element_layout, *sym, ); + + if let Some(unmasked_symbol) = unmasked_symbol { + self.free_symbol(&unmasked_symbol); + } } } } @@ -2911,14 +2901,7 @@ impl< other_tags[tag_id as usize - 1] }; - let mask_symbol = self.debug_symbol("tag_id_mask"); - let mask_reg = self - .storage_manager - .claim_general_reg(&mut self.buf, &mask_symbol); - ASM::mov_reg64_imm64(&mut self.buf, mask_reg, (!0b111) as _); - - // mask out the tag id bits - ASM::and_reg64_reg64_reg64(&mut self.buf, mask_reg, ptr_reg, mask_reg); + let (mask_symbol, mask_reg) = self.clear_tag_id(ptr_reg); let mut offset = 0; for field in &other_fields[..index as usize] { @@ -2926,6 +2909,8 @@ impl< } ASM::add_reg64_reg64_imm32(&mut self.buf, sym_reg, mask_reg, offset as i32); + + self.free_symbol(&mask_symbol); } UnionLayout::Recursive(tag_layouts) => { let other_fields = tag_layouts[tag_id as usize]; @@ -2935,22 +2920,13 @@ impl< .load_to_general_reg(&mut self.buf, structure); // mask out the tag id bits - let unmasked_reg = if union_layout - .stores_tag_id_as_data(self.storage_manager.target_info) - { - ptr_reg - } else { - let umasked_symbol = self.debug_symbol("unmasked"); - let unmasked_reg = self - .storage_manager - .claim_general_reg(&mut self.buf, &umasked_symbol); - - ASM::mov_reg64_imm64(&mut self.buf, unmasked_reg, (!0b111) as _); - - ASM::and_reg64_reg64_reg64(&mut self.buf, unmasked_reg, ptr_reg, unmasked_reg); - - unmasked_reg - }; + let (unmasked_symbol, unmasked_reg) = + if union_layout.stores_tag_id_as_data(self.storage_manager.target_info) { + (None, ptr_reg) + } else { + let (mask_symbol, mask_reg) = self.clear_tag_id(ptr_reg); + (Some(mask_symbol), mask_reg) + }; let mut offset = 0; for field in &other_fields[..index as usize] { @@ -2958,6 +2934,10 @@ impl< } ASM::add_reg64_reg64_imm32(&mut self.buf, sym_reg, unmasked_reg, offset as i32); + + if let Some(unmasked_symbol) = unmasked_symbol { + self.free_symbol(&unmasked_symbol); + } } } } @@ -3986,6 +3966,19 @@ impl< CC: CallConv, > Backend64Bit<'a, 'r, GeneralReg, FloatReg, ASM, CC> { + fn clear_tag_id(&mut self, ptr_reg: GeneralReg) -> (Symbol, GeneralReg) { + let unmasked_symbol = self.debug_symbol("unmasked"); + let unmasked_reg = self + .storage_manager + .claim_general_reg(&mut self.buf, &unmasked_symbol); + + ASM::mov_reg64_imm64(&mut self.buf, unmasked_reg, (!0b111) as _); + + ASM::and_reg64_reg64_reg64(&mut self.buf, unmasked_reg, ptr_reg, unmasked_reg); + + (unmasked_symbol, unmasked_reg) + } + fn compare( &mut self, op: CompareOperation, diff --git a/crates/compiler/gen_dev/src/lib.rs b/crates/compiler/gen_dev/src/lib.rs index dab8eb6b93a..25bd620e95e 100644 --- a/crates/compiler/gen_dev/src/lib.rs +++ b/crates/compiler/gen_dev/src/lib.rs @@ -1605,7 +1605,7 @@ trait Backend<'a> { self.build_ptr_load(*sym, args[0], *ret_layout); } - LowLevel::PtrToStackValue => { + LowLevel::Alloca => { self.build_ptr_to_stack_value(*sym, args[0], arg_layouts[0]); } diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 9718c8863ce..38a06b4dac7 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -1502,7 +1502,7 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( let ptr = tag_pointer_clear_tag_id(env, argument.into_pointer_value()); let target_loaded_type = basic_type_from_layout(env, layout_interner, ret_repr); - union_field_at_index( + union_field_ptr_at_index( env, layout_interner, field_layouts, @@ -1518,7 +1518,7 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( let struct_type = basic_type_from_layout(env, layout_interner, struct_layout); let target_loaded_type = basic_type_from_layout(env, layout_interner, ret_repr); - union_field_at_index( + union_field_ptr_at_index( env, layout_interner, field_layouts, @@ -1546,7 +1546,7 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( let ptr = tag_pointer_clear_tag_id(env, argument.into_pointer_value()); let target_loaded_type = basic_type_from_layout(env, layout_interner, ret_repr); - union_field_at_index( + union_field_ptr_at_index( env, layout_interner, field_layouts, @@ -1569,7 +1569,7 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( let struct_type = basic_type_from_layout(env, layout_interner, struct_layout); let target_loaded_type = basic_type_from_layout(env, layout_interner, ret_repr); - union_field_at_index( + union_field_ptr_at_index( env, layout_interner, field_layouts, @@ -2156,7 +2156,7 @@ fn lookup_at_index_ptr<'a, 'ctx>( struct_type: Option>, target_loaded_type: BasicTypeEnum<'ctx>, ) -> BasicValueEnum<'ctx> { - let elem_ptr = union_field_at_index_help( + let elem_ptr = union_field_ptr_at_index_help( env, layout_interner, field_layouts, @@ -2179,7 +2179,7 @@ fn lookup_at_index_ptr<'a, 'ctx>( cast_if_necessary_for_opaque_recursive_pointers(env.builder, result, target_loaded_type) } -fn union_field_at_index_help<'a, 'ctx>( +fn union_field_ptr_at_index_help<'a, 'ctx>( env: &Env<'a, 'ctx, '_>, layout_interner: &STLayoutInterner<'a>, field_layouts: &'a [InLayout<'a>], @@ -2213,7 +2213,7 @@ fn union_field_at_index_help<'a, 'ctx>( .unwrap() } -fn union_field_at_index<'a, 'ctx>( +fn union_field_ptr_at_index<'a, 'ctx>( env: &Env<'a, 'ctx, '_>, layout_interner: &STLayoutInterner<'a>, field_layouts: &'a [InLayout<'a>], @@ -2222,7 +2222,7 @@ fn union_field_at_index<'a, 'ctx>( value: PointerValue<'ctx>, target_loaded_type: BasicTypeEnum<'ctx>, ) -> PointerValue<'ctx> { - let result = union_field_at_index_help( + let result = union_field_ptr_at_index_help( env, layout_interner, field_layouts, diff --git a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs index 241d0e7a537..63a9a15e740 100644 --- a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs +++ b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs @@ -1325,7 +1325,7 @@ pub(crate) fn run_low_level<'a, 'ctx>( .new_build_load(element_type, ptr.into_pointer_value(), "ptr_load") } - PtrToStackValue => { + Alloca => { arguments!(initial_value); let ptr = entry_block_alloca_zerofill(env, initial_value.get_type(), "stack_value"); diff --git a/crates/compiler/gen_wasm/src/low_level.rs b/crates/compiler/gen_wasm/src/low_level.rs index 8e76474d6dd..f87807a6da6 100644 --- a/crates/compiler/gen_wasm/src/low_level.rs +++ b/crates/compiler/gen_wasm/src/low_level.rs @@ -1979,8 +1979,8 @@ impl<'a> LowLevelCall<'a> { ); } PtrLoad => backend.expr_unbox(self.ret_symbol, self.arguments[0]), - PtrToStackValue => { - // PtrToStackValue : a -> Ptr a + Alloca => { + // Alloca : a -> Ptr a let arg = self.arguments[0]; let arg_layout = backend.storage.symbol_layouts.get(&arg).unwrap(); diff --git a/crates/compiler/module/src/low_level.rs b/crates/compiler/module/src/low_level.rs index a8b68cd4f34..bbb30d075cd 100644 --- a/crates/compiler/module/src/low_level.rs +++ b/crates/compiler/module/src/low_level.rs @@ -120,7 +120,7 @@ pub enum LowLevel { PtrCast, PtrStore, PtrLoad, - PtrToStackValue, + Alloca, RefCountIncRcPtr, RefCountDecRcPtr, RefCountIncDataPtr, @@ -232,7 +232,7 @@ macro_rules! map_symbol_to_lowlevel { LowLevel::PtrCast => unimplemented!(), LowLevel::PtrStore => unimplemented!(), LowLevel::PtrLoad => unimplemented!(), - LowLevel::PtrToStackValue => unimplemented!(), + LowLevel::Alloca => unimplemented!(), LowLevel::RefCountIncRcPtr => unimplemented!(), LowLevel::RefCountDecRcPtr=> unimplemented!(), LowLevel::RefCountIncDataPtr => unimplemented!(), diff --git a/crates/compiler/mono/Cargo.toml b/crates/compiler/mono/Cargo.toml index 44887a5b8f6..2fd6db34d93 100644 --- a/crates/compiler/mono/Cargo.toml +++ b/crates/compiler/mono/Cargo.toml @@ -27,6 +27,7 @@ roc_types = { path = "../types" } ven_pretty = { path = "../../vendor/pretty" } bitvec.workspace = true +arrayvec.workspace = true bumpalo.workspace = true hashbrown.workspace = true parking_lot.workspace = true diff --git a/crates/compiler/mono/src/borrow.rs b/crates/compiler/mono/src/borrow.rs index cb2b9aeb5bf..bd03651ecc2 100644 --- a/crates/compiler/mono/src/borrow.rs +++ b/crates/compiler/mono/src/borrow.rs @@ -1045,7 +1045,7 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[Ownership] { PtrStore => arena.alloc_slice_copy(&[owned, owned]), PtrLoad => arena.alloc_slice_copy(&[owned]), - PtrToStackValue => arena.alloc_slice_copy(&[owned]), + Alloca => arena.alloc_slice_copy(&[owned]), PtrCast | RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr | RefCountDecDataPtr | RefCountIsUnique => { diff --git a/crates/compiler/mono/src/drop_specialization.rs b/crates/compiler/mono/src/drop_specialization.rs index 2be4cfb76e6..6639440583c 100644 --- a/crates/compiler/mono/src/drop_specialization.rs +++ b/crates/compiler/mono/src/drop_specialization.rs @@ -1680,7 +1680,7 @@ fn low_level_no_rc(lowlevel: &LowLevel) -> RC { // only inserted for internal purposes. RC should not touch it PtrStore => RC::NoRc, PtrLoad => RC::NoRc, - PtrToStackValue => RC::NoRc, + Alloca => RC::NoRc, PtrCast | RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr | RefCountDecDataPtr | RefCountIsUnique => { diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index 5c6ba99250c..4e417b3cdaf 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -7659,6 +7659,7 @@ fn substitute_in_expr<'a>( None => None, }, + // currently only used for tail recursion modulo cons (TRMC) UnionFieldPtrAtIndex { structure, tag_id, diff --git a/crates/compiler/mono/src/layout.rs b/crates/compiler/mono/src/layout.rs index 905b1cbb280..afa9abaa646 100644 --- a/crates/compiler/mono/src/layout.rs +++ b/crates/compiler/mono/src/layout.rs @@ -674,7 +674,10 @@ pub(crate) enum LayoutWrapper<'a> { pub enum LayoutRepr<'a> { Builtin(Builtin<'a>), Struct(&'a [InLayout<'a>]), + // A (heap allocated) reference-counted value Boxed(InLayout<'a>), + // A pointer (heap or stack) without any reference counting + // Ptr is not user-facing. The compiler author must make sure that invariants are upheld Ptr(InLayout<'a>), Union(UnionLayout<'a>), LambdaSet(LambdaSet<'a>), diff --git a/crates/compiler/mono/src/tail_recursion.rs b/crates/compiler/mono/src/tail_recursion.rs index 0ae595579be..829b4d157f6 100644 --- a/crates/compiler/mono/src/tail_recursion.rs +++ b/crates/compiler/mono/src/tail_recursion.rs @@ -10,7 +10,7 @@ use crate::layout::{ }; use bumpalo::collections::Vec; use bumpalo::Bump; -use roc_collections::{MutMap, VecSet}; +use roc_collections::{MutMap, VecMap, VecSet}; use roc_module::low_level::LowLevel; use roc_module::symbol::{IdentIds, ModuleId, Symbol}; @@ -423,15 +423,6 @@ impl TrmcCandidateSet { self.active.insert(call); } - fn extend(&mut self, other: Self) { - self.confirmed.keep_if_in_either(other.confirmed); - self.invalid.keep_if_in_either(other.invalid); - self.active.keep_if_in_either(other.active); - - self.active.retain(|k| !self.invalid.contains(k)); - self.confirmed.retain(|k| !self.invalid.contains(k)); - } - fn retain(&mut self, keep: F) where F: Fn(&Symbol) -> bool, @@ -443,7 +434,7 @@ impl TrmcCandidateSet { } self.active.retain(|k| !self.invalid.contains(k)); - self.confirmed.retain(|k| !self.invalid.contains(k)); + debug_assert!(!self.confirmed.iter().any(|x| self.invalid.contains(x))); } } @@ -465,26 +456,31 @@ where return VecSet::default(); } - trmc_candidates_help(proc.name, &proc.body, TrmcCandidateSet::default()).confirmed + let mut candidate_set = TrmcCandidateSet::default(); + trmc_candidates_help(proc.name, &proc.body, &mut candidate_set); + candidate_set.confirmed } fn trmc_candidates_help<'a>( function_name: LambdaName, stmt: &'_ Stmt<'a>, - mut candidates: TrmcCandidateSet, -) -> TrmcCandidateSet { + candidates: &mut TrmcCandidateSet, +) { // if this stmt is the literal tail tag application and return, then this is a TRMC opportunity if let Some(cons_info) = TrmcEnv::is_terminal_constructor(stmt) { - // must use the result of a recursive call directly as an argument - // we pick the (syntactically) first one - for recursive_call in candidates.active.iter() { - if cons_info.arguments.contains(recursive_call) { - return TrmcCandidateSet { - confirmed: VecSet::singleton(*recursive_call), - active: VecSet::default(), - invalid: candidates.invalid, - }; - } + // the tag application must directly use the result of the recursive call + let recursive_call = candidates + .active + .iter() + .copied() + .find(|call| cons_info.arguments.contains(call)); + + // if we find a usage, this is a confirmed TRMC call + if let Some(recursive_call) = recursive_call { + candidates.active.remove(&recursive_call); + candidates.confirmed.insert(recursive_call); + + return; } } @@ -511,15 +507,9 @@ fn trmc_candidates_help<'a>( .map(|(_, _, stmt)| stmt) .chain([default_branch.1]); - let mut accum = candidates.clone(); - for next in it { - let x = trmc_candidates_help(function_name, next, candidates.clone()); - - accum.extend(x); + trmc_candidates_help(function_name, next, candidates); } - - accum } Stmt::Refcounting(_, next) => trmc_candidates_help(function_name, next, candidates), Stmt::Expect { remainder, .. } @@ -528,26 +518,63 @@ fn trmc_candidates_help<'a>( Stmt::Join { body, remainder, .. } => { - let mut x = trmc_candidates_help(function_name, body, candidates.clone()); - let y = trmc_candidates_help(function_name, remainder, candidates.clone()); - - x.extend(y); - - x + trmc_candidates_help(function_name, body, candidates); + trmc_candidates_help(function_name, remainder, candidates); } - Stmt::Ret(_) | Stmt::Jump(_, _) | Stmt::Crash(_, _) => candidates, + Stmt::Ret(_) | Stmt::Jump(_, _) | Stmt::Crash(_, _) => { /* terminal */ } } } +// TRMC (tail recursion modulo constructor) is an optimization for some recursive functions that return a recursive data type. The most basic example is a repeat function on linked lists: +// +// ```roc +// LinkedList a : [ Nil, Cons a (LinkedList a) ] +// +// repeat : a, Nat -> LinkedList a +// repeat = \element, n -> +// when n is +// 0 -> Nil +// _ -> Cons element (repeat element (n - 1)) +// ``` +// +// This function is recursive, but cannot use standard tail-call elimintation, because the recursive call is not in tail position (i.e. the last thing happening before a return). Rather the recursive call is an argument to a constructor of the recursive output type. This means that `repeat n` will creat `n` stack frames. For big inputs, a stack overflow is inevitable. +// +// But there is a trick: TRMC. Using TRMC and join points, we are able to convert this function into a loop, which uses only one stack frame for the whole process. +// +// ```pseudo-roc +// repeat : a, Nat -> LinkedList a +// repeat = \initialElement, initialN -> +// joinpoint trmc = \element, n, hole, head -> +// when n is +// 0 -> +// # write the value `Nil` into the hole +// *hole = Nil +// # dereference (load from) the pointer to the first element +// *head +// +// _ -> +// *hole = Cons element NULL +// newHole = &hole.Cons.1 +// jump trmc element (n - 1) newHole head +// in +// # creates a stack allocation, gives a pointer to that stack allocation +// initial : Ptr (LinkedList a) = #alloca NULL +// jump trmc initialElement initialN initial initial +// ``` +// +// The functionality here figures out whether this transformation can be applied in valid way, and then performs the transformation. + #[derive(Clone)] pub(crate) struct TrmcEnv<'a> { + /// Current hole to fill hole_symbol: Symbol, + /// Pointer to the first constructor ("the head of the list") head_symbol: Symbol, joinpoint_id: JoinPointId, return_layout: InLayout<'a>, ptr_return_layout: InLayout<'a>, - trmc_calls: MutMap>>, + trmc_calls: VecMap>>, } #[derive(Debug)] @@ -599,7 +626,7 @@ impl<'a> TrmcEnv<'a> { fn is_recursive_call(call: &Call<'a>, lambda_name: LambdaName<'_>) -> bool { match call.call_type { CallType::ByName { name, .. } => { - // TODO are there other restrictions? + // because we do not allow polymorphic recursion, this is the only constraint name == lambda_name } CallType::Foreign { .. } | CallType::LowLevel { .. } | CallType::HigherOrder(_) => { @@ -617,7 +644,6 @@ impl<'a> TrmcEnv<'a> { let ptr_write = Call { call_type: crate::ir::CallType::LowLevel { op: LowLevel::PtrStore, - // update_mode: env.next_update_mode_id(), update_mode: UpdateModeId::BACKEND_DUMMY, }, arguments: env.arena.alloc([ptr, value]), @@ -639,9 +665,9 @@ impl<'a> TrmcEnv<'a> { let arena = env.arena; let return_layout = proc.ret_layout; - let mut joinpoint_parameters = Vec::with_capacity_in(proc.args.len() + 1, env.arena); + let mut joinpoint_parameters = Vec::with_capacity_in(proc.args.len() + 2, env.arena); let mut new_proc_arguments = Vec::with_capacity_in(proc.args.len(), env.arena); - let mut jump_arguments = Vec::with_capacity_in(proc.args.len() + 1, env.arena); + let mut jump_arguments = Vec::with_capacity_in(proc.args.len() + 2, env.arena); for (i, (layout, old_symbol)) in proc.args.iter().enumerate() { let symbol = env.named_unique_symbol(&format!("arg_{i}")); @@ -670,7 +696,7 @@ impl<'a> TrmcEnv<'a> { let call = Call { call_type: CallType::LowLevel { - op: LowLevel::PtrToStackValue, + op: LowLevel::Alloca, update_mode: UpdateModeId::BACKEND_DUMMY, }, arguments: arena.alloc([null_symbol]), @@ -744,9 +770,13 @@ impl<'a> TrmcEnv<'a> { match stmt { Stmt::Let(symbol, expr, layout, next) => { - // if this is a TRMC call, + // if this is a TRMC call, remember what the call looks like, so we can turn it + // into a jump later. The call is then removed from the Stmt if let Some(opt_call) = self.trmc_calls.get_mut(symbol) { - debug_assert!(opt_call.is_none()); + debug_assert!( + opt_call.is_none(), + "didn't expect to visit call again since symbols are unique" + ); let call = match expr { Expr::Call(call) => call, diff --git a/crates/compiler/test_mono/generated/linked_list_map.txt b/crates/compiler/test_mono/generated/linked_list_map.txt index 8519c182987..9626e531966 100644 --- a/crates/compiler/test_mono/generated/linked_list_map.txt +++ b/crates/compiler/test_mono/generated/linked_list_map.txt @@ -9,7 +9,7 @@ procedure Test.10 (Test.11): procedure Test.2 (#Derived_gen.0, #Derived_gen.1): let #Derived_gen.3 : [, C I64 *self] = NullPointer; - let #Derived_gen.2 : Ptr([, C I64 *self]) = lowlevel PtrToStackValue #Derived_gen.3; + let #Derived_gen.2 : Ptr([, C I64 *self]) = lowlevel Alloca #Derived_gen.3; joinpoint #Derived_gen.4 Test.4 Test.5 #Derived_gen.5 #Derived_gen.6: let Test.22 : U8 = 1i64; let Test.23 : U8 = GetTagId Test.5; diff --git a/crates/compiler/test_mono/generated/rb_tree_fbip.txt b/crates/compiler/test_mono/generated/rb_tree_fbip.txt index e6cb057d392..e2db544d2d9 100644 --- a/crates/compiler/test_mono/generated/rb_tree_fbip.txt +++ b/crates/compiler/test_mono/generated/rb_tree_fbip.txt @@ -8,7 +8,7 @@ procedure Num.24 (#Attr.2, #Attr.3): procedure Test.3 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): let #Derived_gen.4 : [C *self I64 *self I32 Int1, ] = NullPointer; - let #Derived_gen.3 : Ptr([C *self I64 *self I32 Int1, ]) = lowlevel PtrToStackValue #Derived_gen.4; + let #Derived_gen.3 : Ptr([C *self I64 *self I32 Int1, ]) = lowlevel Alloca #Derived_gen.4; joinpoint #Derived_gen.5 Test.9 Test.10 Test.11 #Derived_gen.6 #Derived_gen.7: let Test.254 : U8 = 0i64; let Test.255 : U8 = GetTagId Test.9; From 9d10389c2ba43c99adc192c0f2e3d7450d2bdc61 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sat, 24 Jun 2023 14:49:31 +0200 Subject: [PATCH 055/140] make trmc candidate set cheaper to clone --- crates/compiler/mono/src/tail_recursion.rs | 95 +++++++++++++++------- 1 file changed, 64 insertions(+), 31 deletions(-) diff --git a/crates/compiler/mono/src/tail_recursion.rs b/crates/compiler/mono/src/tail_recursion.rs index 829b4d157f6..7b2690bcd51 100644 --- a/crates/compiler/mono/src/tail_recursion.rs +++ b/crates/compiler/mono/src/tail_recursion.rs @@ -10,7 +10,7 @@ use crate::layout::{ }; use bumpalo::collections::Vec; use bumpalo::Bump; -use roc_collections::{MutMap, VecMap, VecSet}; +use roc_collections::{MutMap, VecMap}; use roc_module::low_level::LowLevel; use roc_module::symbol::{IdentIds, ModuleId, Symbol}; @@ -405,40 +405,80 @@ fn insert_jumps<'a>( } } -#[derive(Debug, Clone, Default)] +#[derive(Debug, Default)] struct TrmcCandidateSet { - /// Recursive calls for which we have found a TRMC opportunity - confirmed: VecSet, - /// Recursive calls that are (still) considered for TRMC - active: VecSet, - /// Recursive calls that are used in such a way that makes TRMC impossible - invalid: VecSet, + interner: arrayvec::ArrayVec, + confirmed: u64, + active: u64, + invalid: u64, } impl TrmcCandidateSet { - fn insert(&mut self, call: Symbol) { + fn confirmed(&self) -> impl Iterator + '_ { + self.interner + .iter() + .enumerate() + .filter_map(|(i, s)| (self.confirmed & (1 << i) != 0).then_some(*s)) + } + + fn active(&self) -> impl Iterator + '_ { + self.interner + .iter() + .enumerate() + .filter_map(|(i, s)| (self.active & (1 << i) != 0).then_some(*s)) + } + + fn position(&self, symbol: Symbol) -> Option { + self.interner.iter().position(|s| *s == symbol) + } + + fn insert(&mut self, symbol: Symbol) { // there really is no way it could have been inserted already - debug_assert!(!self.invalid.contains(&call)); + debug_assert!(self.position(symbol).is_none()); - self.active.insert(call); + let index = self.interner.len(); + self.interner.push(symbol); + + self.active |= 1 << index; } fn retain(&mut self, keep: F) where F: Fn(&Symbol) -> bool, { - for c in self.active.iter() { - if !keep(c) { - self.invalid.insert(*c); + for (i, s) in self.interner.iter().enumerate() { + if !keep(s) { + let mask = 1 << i; + + self.active &= !mask; + self.confirmed &= !mask; + + self.invalid |= mask; } } + } + + fn confirm(&mut self, symbol: Symbol) { + match self.position(symbol) { + None => debug_assert_eq!(0, 1, "confirm of invalid symbol"), + Some(index) => { + let mask = 1 << index; - self.active.retain(|k| !self.invalid.contains(k)); - debug_assert!(!self.confirmed.iter().any(|x| self.invalid.contains(x))); + debug_assert_eq!(self.invalid & mask, 0); + debug_assert_ne!(self.active & mask, 0); + + self.active &= !mask; + self.confirmed |= mask; + } + } + } + + fn is_empty(&self) -> bool { + self.confirmed == 0 } } -fn trmc_candidates<'a, I>(interner: &'_ I, proc: &'_ Proc<'a>) -> VecSet +fn trmc_candidates<'a, I>(interner: &'_ I, proc: &'_ Proc<'a>) -> TrmcCandidateSet where I: LayoutInterner<'a>, { @@ -447,18 +487,18 @@ where proc.is_self_recursive, crate::ir::SelfRecursive::SelfRecursive(_) ) { - return VecSet::default(); + return TrmcCandidateSet::default(); } // and return a recursive tag union if !matches!(interner.get_repr(proc.ret_layout), LayoutRepr::Union(union_layout) if union_layout.is_recursive()) { - return VecSet::default(); + return TrmcCandidateSet::default(); } let mut candidate_set = TrmcCandidateSet::default(); trmc_candidates_help(proc.name, &proc.body, &mut candidate_set); - candidate_set.confirmed + candidate_set } fn trmc_candidates_help<'a>( @@ -470,15 +510,12 @@ fn trmc_candidates_help<'a>( if let Some(cons_info) = TrmcEnv::is_terminal_constructor(stmt) { // the tag application must directly use the result of the recursive call let recursive_call = candidates - .active - .iter() - .copied() + .active() .find(|call| cons_info.arguments.contains(call)); // if we find a usage, this is a confirmed TRMC call if let Some(recursive_call) = recursive_call { - candidates.active.remove(&recursive_call); - candidates.confirmed.insert(recursive_call); + candidates.confirm(recursive_call); return; } @@ -657,11 +694,7 @@ impl<'a> TrmcEnv<'a> { ) } - pub fn init<'i>( - env: &mut Env<'a, 'i>, - proc: &Proc<'a>, - trmc_calls: VecSet, - ) -> Proc<'a> { + fn init<'i>(env: &mut Env<'a, 'i>, proc: &Proc<'a>, trmc_calls: TrmcCandidateSet) -> Proc<'a> { let arena = env.arena; let return_layout = proc.ret_layout; @@ -711,7 +744,7 @@ impl<'a> TrmcEnv<'a> { let jump_stmt = Stmt::Jump(joinpoint_id, jump_arguments.into_bump_slice()); - let trmc_calls = trmc_calls.iter().map(|s| (*s, None)).collect(); + let trmc_calls = trmc_calls.confirmed().map(|s| (s, None)).collect(); let mut this = Self { hole_symbol, From ae47cc51713ed4444d031007d72bfe8531e35039 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sat, 24 Jun 2023 19:45:44 +0200 Subject: [PATCH 056/140] in TRMC, still apply normal TCE --- crates/compiler/mono/src/tail_recursion.rs | 28 +++++++++ .../generated/linked_list_filter.txt | 57 +++++++++++++++++++ crates/compiler/test_mono/src/tests.rs | 45 ++++++++++++--- 3 files changed, 121 insertions(+), 9 deletions(-) create mode 100644 crates/compiler/test_mono/generated/linked_list_filter.txt diff --git a/crates/compiler/mono/src/tail_recursion.rs b/crates/compiler/mono/src/tail_recursion.rs index 7b2690bcd51..46b0684ce2e 100644 --- a/crates/compiler/mono/src/tail_recursion.rs +++ b/crates/compiler/mono/src/tail_recursion.rs @@ -603,6 +603,7 @@ fn trmc_candidates_help<'a>( #[derive(Clone)] pub(crate) struct TrmcEnv<'a> { + lambda_name: LambdaName<'a>, /// Current hole to fill hole_symbol: Symbol, /// Pointer to the first constructor ("the head of the list") @@ -672,6 +673,18 @@ impl<'a> TrmcEnv<'a> { } } + fn is_tail_recursive_call( + lambda_name: LambdaName, + symbol: Symbol, + expr: &Expr<'a>, + next: &Stmt<'a>, + ) -> Option> { + match next { + Stmt::Ret(s) if *s == symbol => Self::is_recursive_expr(expr, lambda_name), + _ => None, + } + } + fn ptr_write( env: &mut Env<'a, '_>, ptr: Symbol, @@ -747,6 +760,7 @@ impl<'a> TrmcEnv<'a> { let trmc_calls = trmc_calls.confirmed().map(|s| (s, None)).collect(); let mut this = Self { + lambda_name: proc.name, hole_symbol, head_symbol, joinpoint_id, @@ -821,6 +835,20 @@ impl<'a> TrmcEnv<'a> { return self.walk_stmt(env, next); } + if let Some(call) = + Self::is_tail_recursive_call(self.lambda_name, *symbol, expr, next) + { + // turn the call into a jump. Just re-use the existing hole + let mut arguments = Vec::new_in(arena); + arguments.extend(call.arguments); + arguments.push(self.hole_symbol); + arguments.push(self.head_symbol); + + let jump = Stmt::Jump(self.joinpoint_id, arguments.into_bump_slice()); + + return jump; + } + if let Some(cons_info) = Self::is_terminal_constructor(stmt) { // figure out which TRMC call to use here. We pick the first one that works let opt_recursive_call = cons_info.arguments.iter().find_map(|arg| { diff --git a/crates/compiler/test_mono/generated/linked_list_filter.txt b/crates/compiler/test_mono/generated/linked_list_filter.txt new file mode 100644 index 00000000000..e7120f4e91c --- /dev/null +++ b/crates/compiler/test_mono/generated/linked_list_filter.txt @@ -0,0 +1,57 @@ +procedure Num.31 (Num.234): + let Num.293 : I64 = 2i64; + let Num.292 : Int1 = CallByName Num.86 Num.234 Num.293; + ret Num.292; + +procedure Num.86 (#Attr.2, #Attr.3): + let Num.294 : Int1 = lowlevel NumIsMultipleOf #Attr.2 #Attr.3; + ret Num.294; + +procedure Test.2 (#Derived_gen.0, #Derived_gen.1): + let #Derived_gen.3 : [, C I64 *self] = NullPointer; + let #Derived_gen.2 : Ptr([, C I64 *self]) = lowlevel Alloca #Derived_gen.3; + joinpoint #Derived_gen.4 Test.4 Test.5 #Derived_gen.5 #Derived_gen.6: + let Test.22 : U8 = 1i64; + let Test.23 : U8 = GetTagId Test.4; + let Test.24 : Int1 = lowlevel Eq Test.22 Test.23; + if Test.24 then + let Test.17 : [, C I64 *self] = TagId(1) ; + let #Derived_gen.8 : {} = lowlevel PtrStore #Derived_gen.5 Test.17; + let #Derived_gen.7 : [, C I64 *self] = lowlevel PtrLoad #Derived_gen.6; + ret #Derived_gen.7; + else + let Test.7 : I64 = UnionAtIndex (Id 0) (Index 0) Test.4; + let Test.8 : [, C I64 *self] = UnionAtIndex (Id 0) (Index 1) Test.4; + joinpoint #Derived_gen.12 #Derived_gen.15: + let Test.19 : Int1 = CallByName Num.31 Test.7; + if Test.19 then + let #Derived_gen.9 : [, C I64 *self] = NullPointer; + let Test.20 : [, C I64 *self] = Reuse #Derived_gen.15 UpdateModeId { id: 1 } TagId(0) Test.7 #Derived_gen.9; + let #Derived_gen.10 : Ptr([, C I64 *self]) = UnionFieldPtrAtIndex (Id 0) (Index 1) Test.20; + let #Derived_gen.11 : {} = lowlevel PtrStore #Derived_gen.5 Test.20; + jump #Derived_gen.4 Test.8 Test.5 #Derived_gen.10 #Derived_gen.6; + else + decref #Derived_gen.15; + jump #Derived_gen.4 Test.8 Test.5 #Derived_gen.5 #Derived_gen.6; + in + let #Derived_gen.13 : Int1 = lowlevel RefCountIsUnique Test.4; + if #Derived_gen.13 then + let #Derived_gen.16 : [, C I64 *self] = ResetRef { symbol: Test.4, id: UpdateModeId { id: 2 } }; + jump #Derived_gen.12 #Derived_gen.16; + else + inc Test.8; + decref Test.4; + let #Derived_gen.17 : [, C I64 *self] = NullPointer; + jump #Derived_gen.12 #Derived_gen.17; + in + jump #Derived_gen.4 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.2; + +procedure Test.0 (): + let Test.25 : I64 = 1i64; + let Test.27 : I64 = 2i64; + let Test.28 : [, C I64 *self] = TagId(1) ; + let Test.26 : [, C I64 *self] = TagId(0) Test.27 Test.28; + let Test.14 : [, C I64 *self] = TagId(0) Test.25 Test.26; + let Test.15 : {} = Struct {}; + let Test.13 : [, C I64 *self] = CallByName Test.2 Test.14 Test.15; + ret Test.13; diff --git a/crates/compiler/test_mono/src/tests.rs b/crates/compiler/test_mono/src/tests.rs index 88a1109b6d5..71064f8baf3 100644 --- a/crates/compiler/test_mono/src/tests.rs +++ b/crates/compiler/test_mono/src/tests.rs @@ -146,7 +146,9 @@ fn compiles_to_ir(test_name: &str, src: &str, mode: &str, allow_type_errors: boo println!("Ignoring {} canonicalization problems", can_problems.len()); } - assert!(allow_type_errors || type_problems.is_empty()); + if !(allow_type_errors || type_problems.is_empty()) { + panic!("mono test has type problems:\n\n{:#?}", type_problems); + } let main_fn_symbol = exposed_to_host.top_level_values.keys().copied().next(); @@ -2873,11 +2875,11 @@ fn layout_cache_structure_with_multiple_recursive_structures() { LinkedList : [Nil, Cons { first : Chain, rest : LinkedList }] main = - base : LinkedList + base : LinkedList base = Nil walker : LinkedList, Chain -> LinkedList - walker = \rest, first -> Cons { first, rest } + walker = \rest, first -> Cons { first, rest } list : List Chain list = [] @@ -3004,7 +3006,7 @@ fn rb_tree_fbip() { if k < kx then Node Red (ins l k v) kx vx r else - if k > kx + if k > kx then Node Red l kx vx (ins r k v) else Node Red l k v r "# @@ -3017,10 +3019,10 @@ fn specialize_after_match() { r#" app "test" provides [main] to "./platform" - main = + main = listA : LinkedList Str listA = Nil - + listB : LinkedList Str listB = Nil @@ -3033,13 +3035,13 @@ fn specialize_after_match() { Nil -> linkedListLength listB Cons a aa -> when listB is Nil -> linkedListLength listA - Cons b bb -> + Cons b bb -> lengthA = (linkedListLength aa) + 1 lengthB = linkedListLength listB if lengthA > lengthB then lengthA else lengthB - + linkedListLength : LinkedList a -> Nat linkedListLength = \list -> when list is Nil -> 0 @@ -3088,7 +3090,7 @@ fn drop_specialize_after_jump() { v = "value" t = { left: { left: v, right: v }, right: v } tupleItem t - + tupleItem = \t -> true = Bool.true l = t.left @@ -3189,3 +3191,28 @@ fn linked_list_map() { "# ) } + +#[mono_test] +fn linked_list_filter() { + indoc!( + r#" + app "test" provides [main] to "./platform" + + LinkedList a : [Nil, Cons a (LinkedList a)] + + filter : LinkedList a, (a -> Bool) -> LinkedList a + filter = \list, predicate -> + when list is + Nil -> Nil + Cons x xs -> + if predicate x then + Cons x (filter xs predicate) + else + filter xs predicate + + + main : LinkedList I64 + main = filter (Cons 1 (Cons 2 Nil)) Num.isEven + "# + ) +} From 4f97ab29656d2d0f184a66d893971224b93dbf76 Mon Sep 17 00:00:00 2001 From: Brendan Hansknecht Date: Sat, 24 Jun 2023 10:22:23 -0700 Subject: [PATCH 057/140] remove old compiler-rt workarounds for macos --- .../fixtures/multi-dep-str/platform/host.zig | 14 --- .../multi-dep-thunk/platform/host.zig | 14 --- .../tests/fixtures/packages/platform/host.zig | 14 --- .../algorithms/fibonacci-platform/host.zig | 14 --- .../algorithms/quicksort-platform/host.zig | 14 --- .../benchmarks/platform/host.zig | 14 --- .../expects/zig-platform/host.zig | 14 --- crates/compiler/build/src/link.rs | 95 +------------------ crates/compiler/build/src/target.rs | 4 +- .../builtins/bitcode/src/compiler_rt.zig | 45 +++++++++ crates/linker/src/pe.rs | 1 + crates/valgrind/zig-platform/host.zig | 14 --- examples/cli/effects-platform/host.zig | 14 --- examples/cli/tui-platform/host.zig | 14 --- .../platform-switching/zig-platform/host.zig | 14 --- 15 files changed, 49 insertions(+), 250 deletions(-) diff --git a/crates/cli/tests/fixtures/multi-dep-str/platform/host.zig b/crates/cli/tests/fixtures/multi-dep-str/platform/host.zig index 4248e171a8c..2a4fb112849 100644 --- a/crates/cli/tests/fixtures/multi-dep-str/platform/host.zig +++ b/crates/cli/tests/fixtures/multi-dep-str/platform/host.zig @@ -6,20 +6,6 @@ const testing = std.testing; const expectEqual = testing.expectEqual; const expect = testing.expect; -comptime { - // This is a workaround for https://github.com/ziglang/zig/issues/8218 - // which is only necessary on macOS. - // - // Once that issue is fixed, we can undo the changes in - // 177cf12e0555147faa4d436e52fc15175c2c4ff0 and go back to passing - // -fcompiler-rt in link.rs instead of doing this. Note that this - // workaround is present in many host.zig files, so make sure to undo - // it everywhere! - if (builtin.os.tag == .macos) { - _ = @import("compiler_rt"); - } -} - const mem = std.mem; const Allocator = mem.Allocator; diff --git a/crates/cli/tests/fixtures/multi-dep-thunk/platform/host.zig b/crates/cli/tests/fixtures/multi-dep-thunk/platform/host.zig index 18bb5d00749..a7cff59a0b1 100644 --- a/crates/cli/tests/fixtures/multi-dep-thunk/platform/host.zig +++ b/crates/cli/tests/fixtures/multi-dep-thunk/platform/host.zig @@ -6,20 +6,6 @@ const testing = std.testing; const expectEqual = testing.expectEqual; const expect = testing.expect; -comptime { - // This is a workaround for https://github.com/ziglang/zig/issues/8218 - // which is only necessary on macOS. - // - // Once that issue is fixed, we can undo the changes in - // 177cf12e0555147faa4d436e52fc15175c2c4ff0 and go back to passing - // -fcompiler-rt in link.rs instead of doing this. Note that this - // workaround is present in many host.zig files, so make sure to undo - // it everywhere! - if (builtin.os.tag == .macos) { - _ = @import("compiler_rt"); - } -} - const mem = std.mem; const Allocator = mem.Allocator; diff --git a/crates/cli/tests/fixtures/packages/platform/host.zig b/crates/cli/tests/fixtures/packages/platform/host.zig index 4248e171a8c..2a4fb112849 100644 --- a/crates/cli/tests/fixtures/packages/platform/host.zig +++ b/crates/cli/tests/fixtures/packages/platform/host.zig @@ -6,20 +6,6 @@ const testing = std.testing; const expectEqual = testing.expectEqual; const expect = testing.expect; -comptime { - // This is a workaround for https://github.com/ziglang/zig/issues/8218 - // which is only necessary on macOS. - // - // Once that issue is fixed, we can undo the changes in - // 177cf12e0555147faa4d436e52fc15175c2c4ff0 and go back to passing - // -fcompiler-rt in link.rs instead of doing this. Note that this - // workaround is present in many host.zig files, so make sure to undo - // it everywhere! - if (builtin.os.tag == .macos) { - _ = @import("compiler_rt"); - } -} - const mem = std.mem; const Allocator = mem.Allocator; diff --git a/crates/cli_testing_examples/algorithms/fibonacci-platform/host.zig b/crates/cli_testing_examples/algorithms/fibonacci-platform/host.zig index c27916c26f2..6e2d2e6b393 100644 --- a/crates/cli_testing_examples/algorithms/fibonacci-platform/host.zig +++ b/crates/cli_testing_examples/algorithms/fibonacci-platform/host.zig @@ -5,20 +5,6 @@ const expectEqual = testing.expectEqual; const expect = testing.expect; const maxInt = std.math.maxInt; -comptime { - // This is a workaround for https://github.com/ziglang/zig/issues/8218 - // which is only necessary on macOS. - // - // Once that issue is fixed, we can undo the changes in - // 177cf12e0555147faa4d436e52fc15175c2c4ff0 and go back to passing - // -fcompiler-rt in link.rs instead of doing this. Note that this - // workaround is present in many host.zig files, so make sure to undo - // it everywhere! - if (builtin.os.tag == .macos) { - _ = @import("compiler_rt"); - } -} - const mem = std.mem; const Allocator = mem.Allocator; diff --git a/crates/cli_testing_examples/algorithms/quicksort-platform/host.zig b/crates/cli_testing_examples/algorithms/quicksort-platform/host.zig index c402674a231..1ae4b1cc0e6 100644 --- a/crates/cli_testing_examples/algorithms/quicksort-platform/host.zig +++ b/crates/cli_testing_examples/algorithms/quicksort-platform/host.zig @@ -6,20 +6,6 @@ const testing = std.testing; const expectEqual = testing.expectEqual; const expect = testing.expect; -comptime { - // This is a workaround for https://github.com/ziglang/zig/issues/8218 - // which is only necessary on macOS. - // - // Once that issue is fixed, we can undo the changes in - // 177cf12e0555147faa4d436e52fc15175c2c4ff0 and go back to passing - // -fcompiler-rt in link.rs instead of doing this. Note that this - // workaround is present in many host.zig files, so make sure to undo - // it everywhere! - if (builtin.os.tag == .macos) { - _ = @import("compiler_rt"); - } -} - const mem = std.mem; const Allocator = mem.Allocator; diff --git a/crates/cli_testing_examples/benchmarks/platform/host.zig b/crates/cli_testing_examples/benchmarks/platform/host.zig index 85f343c061b..7902302f451 100644 --- a/crates/cli_testing_examples/benchmarks/platform/host.zig +++ b/crates/cli_testing_examples/benchmarks/platform/host.zig @@ -7,20 +7,6 @@ const expectEqual = testing.expectEqual; const expect = testing.expect; const maxInt = std.math.maxInt; -comptime { - // This is a workaround for https://github.com/ziglang/zig/issues/8218 - // which is only necessary on macOS. - // - // Once that issue is fixed, we can undo the changes in - // 177cf12e0555147faa4d436e52fc15175c2c4ff0 and go back to passing - // -fcompiler-rt in link.rs instead of doing this. Note that this - // workaround is present in many host.zig files, so make sure to undo - // it everywhere! - if (builtin.os.tag == .macos) { - _ = @import("compiler_rt"); - } -} - const mem = std.mem; const Allocator = mem.Allocator; diff --git a/crates/cli_testing_examples/expects/zig-platform/host.zig b/crates/cli_testing_examples/expects/zig-platform/host.zig index 20c09320d90..33c1995d8df 100644 --- a/crates/cli_testing_examples/expects/zig-platform/host.zig +++ b/crates/cli_testing_examples/expects/zig-platform/host.zig @@ -6,20 +6,6 @@ const testing = std.testing; const expectEqual = testing.expectEqual; const expect = testing.expect; -comptime { - // This is a workaround for https://github.com/ziglang/zig/issues/8218 - // which is only necessary on macOS. - // - // Once that issue is fixed, we can undo the changes in - // 177cf12e0555147faa4d436e52fc15175c2c4ff0 and go back to passing - // -fcompiler-rt in link.rs instead of doing this. Note that this - // workaround is present in many host.zig files, so make sure to undo - // it everywhere! - if (builtin.os.tag == .macos) { - _ = @import("compiler_rt"); - } -} - const Align = 2 * @alignOf(usize); extern fn malloc(size: usize) callconv(.C) ?*align(Align) anyopaque; extern fn realloc(c_ptr: [*]align(Align) u8, size: usize) callconv(.C) ?*anyopaque; diff --git a/crates/compiler/build/src/link.rs b/crates/compiler/build/src/link.rs index 2c69ced034f..a48e57c1732 100644 --- a/crates/compiler/build/src/link.rs +++ b/crates/compiler/build/src/link.rs @@ -126,7 +126,7 @@ fn find_wasi_libc_path() -> PathBuf { internal_error!("cannot find `wasi-libc.a`") } -#[cfg(all(unix, not(target_os = "macos")))] +#[cfg(unix)] #[allow(clippy::too_many_arguments)] pub fn build_zig_host_native( env_path: &str, @@ -257,99 +257,6 @@ pub fn build_zig_host_native( zig_cmd } -#[cfg(target_os = "macos")] -#[allow(clippy::too_many_arguments)] -pub fn build_zig_host_native( - env_path: &str, - env_home: &str, - emit_bin: &str, - zig_host_src: &str, - _target: &str, - opt_level: OptLevel, - shared_lib_path: Option<&Path>, - builtins_host_path: &Path, - // For compatibility with the non-macOS def above. Keep these in sync. -) -> Command { - use serde_json::Value; - - // Run `zig env` to find the location of zig's std/ directory - let zig_env_output = zig().args(["env"]).output().unwrap(); - - let zig_env_json = if zig_env_output.status.success() { - std::str::from_utf8(&zig_env_output.stdout).unwrap_or_else(|utf8_err| { - internal_error!( - "`zig env` failed; its stderr output was invalid utf8 ({:?})", - utf8_err - ); - }) - } else { - match std::str::from_utf8(&zig_env_output.stderr) { - Ok(stderr) => internal_error!("`zig env` failed - stderr output was: {:?}", stderr), - Err(utf8_err) => internal_error!( - "`zig env` failed; its stderr output was invalid utf8 ({:?})", - utf8_err - ), - } - }; - - let mut zig_compiler_rt_path = match serde_json::from_str(zig_env_json) { - Ok(Value::Object(map)) => match map.get("std_dir") { - Some(Value::String(std_dir)) => PathBuf::from(Path::new(std_dir)), - _ => { - internal_error!("Expected JSON containing a `std_dir` String field from `zig env`, but got: {:?}", zig_env_json); - } - }, - _ => { - internal_error!( - "Expected JSON containing a `std_dir` field from `zig env`, but got: {:?}", - zig_env_json - ); - } - }; - - zig_compiler_rt_path.push("special"); - zig_compiler_rt_path.push("compiler_rt.zig"); - - let mut zig_cmd = zig(); - zig_cmd - .env_clear() - .env("PATH", env_path) - .env("HOME", env_home); - if let Some(shared_lib_path) = shared_lib_path { - zig_cmd.args([ - "build-exe", - "-fPIE", - shared_lib_path.to_str().unwrap(), - builtins_host_path.to_str().unwrap(), - ]); - } else { - zig_cmd.args(["build-obj"]); - } - zig_cmd.args([ - zig_host_src, - &format!("-femit-bin={}", emit_bin), - "--pkg-begin", - "glue", - find_zig_glue_path().to_str().unwrap(), - "--pkg-end", - // include the zig runtime - "--pkg-begin", - "compiler_rt", - zig_compiler_rt_path.to_str().unwrap(), - "--pkg-end", - // include libc - "--library", - "c", - ]); - if matches!(opt_level, OptLevel::Optimize) { - zig_cmd.args(["-O", "ReleaseSafe"]); - } else if matches!(opt_level, OptLevel::Size) { - zig_cmd.args(["-O", "ReleaseSmall"]); - } - - zig_cmd -} - pub fn build_zig_host_wasm32( env_path: &str, env_home: &str, diff --git a/crates/compiler/build/src/target.rs b/crates/compiler/build/src/target.rs index 6abe50cb349..4acd2ce8c4a 100644 --- a/crates/compiler/build/src/target.rs +++ b/crates/compiler/build/src/target.rs @@ -87,12 +87,12 @@ pub fn target_zig_str(target: &Triple) -> &'static str { architecture: Architecture::X86_64, operating_system: OperatingSystem::Darwin, .. - } => "x86_64-apple-darwin", + } => "x86_64-macos-gnu", Triple { architecture: Architecture::Aarch64(_), operating_system: OperatingSystem::Darwin, .. - } => "aarch64-apple-darwin", + } => "aarch64-macos-gnu", _ => internal_error!("TODO gracefully handle unsupported target: {:?}", target), } } diff --git a/crates/compiler/builtins/bitcode/src/compiler_rt.zig b/crates/compiler/builtins/bitcode/src/compiler_rt.zig index b00961fa218..e4bc02da9bf 100644 --- a/crates/compiler/builtins/bitcode/src/compiler_rt.zig +++ b/crates/compiler/builtins/bitcode/src/compiler_rt.zig @@ -18,6 +18,7 @@ const v2u64 = @Vector(2, u64); // Export it as weak incase it is already linked in by something else. comptime { @export(__muloti4, .{ .name = "__muloti4", .linkage = .Weak }); + @export(__lshrti3, .{ .name = "__lshrti3", .linkage = .Weak }); if (want_windows_v2u64_abi) { @export(__divti3_windows_x86_64, .{ .name = "__divti3", .linkage = .Weak }); @export(__modti3_windows_x86_64, .{ .name = "__modti3", .linkage = .Weak }); @@ -440,3 +441,47 @@ pub inline fn floatFractionalBits(comptime T: type) comptime_int { else => @compileError("unknown floating point type " ++ @typeName(T)), }; } + +pub fn __lshrti3(a: i128, b: i32) callconv(.C) i128 { + return lshrXi3(i128, a, b); +} + +// Logical shift right: shift in 0 from left to right +// Precondition: 0 <= b < T.bit_count +inline fn lshrXi3(comptime T: type, a: T, b: i32) T { + const word_t = HalveInt(T, false); + const S = std.math.Log2Int(word_t.HalfT); + + const input = word_t{ .all = a }; + var output: word_t = undefined; + + if (b >= word_t.bits) { + output.s.high = 0; + output.s.low = input.s.high >> @intCast(S, b - word_t.bits); + } else if (b == 0) { + return a; + } else { + output.s.high = input.s.high >> @intCast(S, b); + output.s.low = input.s.high << @intCast(S, word_t.bits - b); + output.s.low |= input.s.low >> @intCast(S, b); + } + + return output.all; +} + +/// Allows to access underlying bits as two equally sized lower and higher +/// signed or unsigned integers. +fn HalveInt(comptime T: type, comptime signed_half: bool) type { + return extern union { + pub const bits = @divExact(@typeInfo(T).Int.bits, 2); + pub const HalfTU = std.meta.Int(.unsigned, bits); + pub const HalfTS = std.meta.Int(.signed, bits); + pub const HalfT = if (signed_half) HalfTS else HalfTU; + + all: T, + s: if (native_endian == .Little) + extern struct { low: HalfT, high: HalfT } + else + extern struct { high: HalfT, low: HalfT }, + }; +} diff --git a/crates/linker/src/pe.rs b/crates/linker/src/pe.rs index 0332aaf7144..8848172e1d9 100644 --- a/crates/linker/src/pe.rs +++ b/crates/linker/src/pe.rs @@ -444,6 +444,7 @@ pub(crate) fn surgery_pe(executable_path: &Path, metadata_path: &Path, roc_app_b "__fixsfti", "__fixunsdfti", "__fixunssfti", + "__lshrti3", "memcpy_decision", ] .contains(&name.as_str()); diff --git a/crates/valgrind/zig-platform/host.zig b/crates/valgrind/zig-platform/host.zig index 6025d07d157..8ba1179e4ff 100644 --- a/crates/valgrind/zig-platform/host.zig +++ b/crates/valgrind/zig-platform/host.zig @@ -6,20 +6,6 @@ const testing = std.testing; const expectEqual = testing.expectEqual; const expect = testing.expect; -comptime { - // This is a workaround for https://github.com/ziglang/zig/issues/8218 - // which is only necessary on macOS. - // - // Once that issue is fixed, we can undo the changes in - // 177cf12e0555147faa4d436e52fc15175c2c4ff0 and go back to passing - // -fcompiler-rt in link.rs instead of doing this. Note that this - // workaround is present in many host.zig files, so make sure to undo - // it everywhere! - if (builtin.os.tag == .macos) { - _ = @import("compiler_rt"); - } -} - const Align = 2 * @alignOf(usize); extern fn malloc(size: usize) callconv(.C) ?*align(Align) anyopaque; extern fn realloc(c_ptr: [*]align(Align) u8, size: usize) callconv(.C) ?*anyopaque; diff --git a/examples/cli/effects-platform/host.zig b/examples/cli/effects-platform/host.zig index a0780797b31..e0e100278ff 100644 --- a/examples/cli/effects-platform/host.zig +++ b/examples/cli/effects-platform/host.zig @@ -7,20 +7,6 @@ const expectEqual = testing.expectEqual; const expect = testing.expect; const maxInt = std.math.maxInt; -comptime { - // This is a workaround for https://github.com/ziglang/zig/issues/8218 - // which is only necessary on macOS. - // - // Once that issue is fixed, we can undo the changes in - // 177cf12e0555147faa4d436e52fc15175c2c4ff0 and go back to passing - // -fcompiler-rt in link.rs instead of doing this. Note that this - // workaround is present in many host.zig files, so make sure to undo - // it everywhere! - if (builtin.os.tag == .macos) { - _ = @import("compiler_rt"); - } -} - const mem = std.mem; const Allocator = mem.Allocator; diff --git a/examples/cli/tui-platform/host.zig b/examples/cli/tui-platform/host.zig index 0eb4717d8c7..6e1c1869e93 100644 --- a/examples/cli/tui-platform/host.zig +++ b/examples/cli/tui-platform/host.zig @@ -7,20 +7,6 @@ const expectEqual = testing.expectEqual; const expect = testing.expect; const maxInt = std.math.maxInt; -comptime { - // This is a workaround for https://github.com/ziglang/zig/issues/8218 - // which is only necessary on macOS. - // - // Once that issue is fixed, we can undo the changes in - // 177cf12e0555147faa4d436e52fc15175c2c4ff0 and go back to passing - // -fcompiler-rt in link.rs instead of doing this. Note that this - // workaround is present in many host.zig files, so make sure to undo - // it everywhere! - if (builtin.os.tag == .macos) { - _ = @import("compiler_rt"); - } -} - const mem = std.mem; const Allocator = mem.Allocator; diff --git a/examples/platform-switching/zig-platform/host.zig b/examples/platform-switching/zig-platform/host.zig index 6025d07d157..8ba1179e4ff 100644 --- a/examples/platform-switching/zig-platform/host.zig +++ b/examples/platform-switching/zig-platform/host.zig @@ -6,20 +6,6 @@ const testing = std.testing; const expectEqual = testing.expectEqual; const expect = testing.expect; -comptime { - // This is a workaround for https://github.com/ziglang/zig/issues/8218 - // which is only necessary on macOS. - // - // Once that issue is fixed, we can undo the changes in - // 177cf12e0555147faa4d436e52fc15175c2c4ff0 and go back to passing - // -fcompiler-rt in link.rs instead of doing this. Note that this - // workaround is present in many host.zig files, so make sure to undo - // it everywhere! - if (builtin.os.tag == .macos) { - _ = @import("compiler_rt"); - } -} - const Align = 2 * @alignOf(usize); extern fn malloc(size: usize) callconv(.C) ?*align(Align) anyopaque; extern fn realloc(c_ptr: [*]align(Align) u8, size: usize) callconv(.C) ?*anyopaque; From d22d5a1202281e1aa3cae8b5a3af4a42ee2b6b98 Mon Sep 17 00:00:00 2001 From: Luke Boswell Date: Sun, 25 Jun 2023 14:20:00 +1000 Subject: [PATCH 058/140] more content for WIP website --- .../content/design_goals_page.md | 112 +++++++++++++++++- www/wip_new_website/content/home_page.md | 69 +++++++---- www/wip_new_website/content/install_page.md | 4 +- www/wip_new_website/main.roc | 14 ++- 4 files changed, 163 insertions(+), 36 deletions(-) diff --git a/www/wip_new_website/content/design_goals_page.md b/www/wip_new_website/content/design_goals_page.md index 2148b5e12fc..5168538080d 100644 --- a/www/wip_new_website/content/design_goals_page.md +++ b/www/wip_new_website/content/design_goals_page.md @@ -9,12 +9,23 @@ The three goals are Fast, Friendly, and Functional - communicate the key selling points of Roc - essence that sets the language apart -TODO move content from current home page, update for current progress +TODO update below for current progress --> -# Fast +Roc's goal is to be a fast, friendly, functional language. It's very much a work in progress; below, you can see the current progress towards this goal. This website is intentionally unstyled as a way to emphasize the language's current level of incompleteness. The website will become more polished after the language itself becomes more polished! + +Roc compiles to machine code or to [WebAssembly](https://webassembly.org). Eventually you'll be able to use Roc to build high-quality servers, command-line applications, graphical native desktop user interfaces, among other classes of applications. Today, only command-line interfaces have support beyond the proof-of-concept stage; the other use cases will mature over time. + +Like [Lua](https://www.lua.org/), Roc's automatic memory management doesn't require a virtual machine, and it's possible to call Roc functions directly from any language that can call [C](https://en.wikipedia.org/wiki/C_(programming_language)) functions. This makes Roc additionally useful as a language for implementing plugins, and gives you a way to incrementally transition a legacy code base from another language to Roc. + +So far, the Roc compiler has progressed past the "proof of concept" stage, but there are currently lots of known bugs and unimplemented features, and the documentation for both the language and the standard library is incomplete. The overall ecosystem is in its infancy, and the compiler is neither battle-tested nor fuzz-tested yet, so we don't recommend relying on Roc for critical projects until its development is further along. + +# Fast{#fast} -# Friendly +## Goal + +We want Roc to run faster than any non-systems language (like C, C++, Rust, or Zig) that sees mainstream use in industry. The goal is that nobody should find themselves thinking "I should rewrite my Roc program in \[some mainstream garbage-collected language\] because that will make it run significantly faster." + +When benchmarking Roc code against similarly-optimized programs written in [Go](https://go.dev), [Swift](https://www.swift.org/), [Java](https://www.java.com), [C#](https://learn.microsoft.com/en-us/dotnet/csharp), or [JavaScript](https://www.ecma-international.org/publications-and-standards/standards/ecma-262), we generally aim for Roc to outperform all of those languages. Outperforming systems languages like Rust, Zig, C, D, and C++ is a non-goal, as is outperforming research languages that see little or no use in industry. (Realistically, there will always be certain specific benchmarks where some popular non-systems-level languages outperform Roc, but the goal is to usually be at the front of that pack.) + +## Current progress + +Progress towards this performance goal is already quite far along. + +Roc already uses unboxed data structures and unboxed closures, monomorphizes polymorphic code, and uses LLVM as a compiler backend. These optimizations, especially unboxed closures and monomorphization, can be found in several systems-level languages (like C++ and Rust), but not in any mainstream garbage-collected languages. Roc closures in particular have the distinction of being as ergonomic as the closures found in garbage-collected languages (where they are typically boxed), but have the performance of systems language closures (which are typically unboxed, but have more complicated types). + +Because of these optimizations, in many cases Roc code already compiles to the same machine instructions that the equivalent code written in one of these systems languages would. Something we do regularly is to compare the LLVM instructions generated by Roc's compiler and by these systems languages' compilers, to check whether we're generating equivalent instructions. + +That said, there are also cases where Roc has strictly more runtime overhead than languages like C, C++, Zig, and Rust do. The most costly is automatic memory management, which Roc implements using automatic reference counting. Static reference count optimizations like elision and reuse (thanks to Morphic and [Perceus](https://www.microsoft.com/en-us/research/publication/perceus-garbage-free-reference-counting-with-reuse/)) improve things, but significant runtime overhead remains. + +Eliminating this overhead altogether would require sacrificing other design goals (e.g. it would require introducing memory-unsafe operations, or compile-time lifetime errors), and there isn't much overhead left to remove outside of automatic memory management. For example, smaller sources of overhead include mandatory array bounds checks, disallowing cyclic references (which rules out a certain niche of efficient graph data structures), and automatic opportunistic in-place mutation instead of direct mutation. Even if all of these sources of overhead were completely eliminated, it seems unlikely that typical Roc programs would see a particularly big performance boost. + +Overall, we expect Roc's performance in the use cases mentioned above (servers, CLIs, GUIs, etc.) to be about the same as the equivalent C++ code would be, if all that C++ code (including its dependencies) were written in a restricted subset of C++ which always did array bounds checks and used shared pointers for all heap allocations. The Roc code might even run somewhat faster, because its reference counts are non-atomic by default, and can be statically optimized away in some cases—but then again, Roc also has a bit of overhead to perform opportunistic in-place mutation instead of direct mutation. + +To be clear, we don't expect this because we've benchmarked a bunch of programs written in Roc and in this restricted C++ subset, and found that the numbers were about the same (although if you know C++ well enough and want to do such experiments, we'd happy to help and would be interested to see the results!) but rather because Roc's compiler and [clang](https://clang.llvm.org/) should both be generating essentially the same LLVM instructions when the C++ is restricted to that subset. + +Of course, _unrestricted_ C++ code can certainly run faster than unrestricted Roc code. The same is true when comparing other such minimal-overhead systems languages to Roc, including Rust, Zig, C, and D. The point of the comparison is to give you a general idea of what Roc compiles to, since it is quite different from the VMs and JITted bytecode interpreters found in today's most popular garbage-collected languages! + +The talk [Outperforming Imperative with Pure Functional Languages](https://youtu.be/vzfy4EKwG_Y) discusses some early results from Roc's optimizations, and [Roc at Handmade Seattle](https://media.handmade-seattle.com/roc-lang) gets into low-level details of how Roc's compiler generates programs similarly to how clang does. + +# Friendly{#friendly} -# Functional +## Goals + +Roc aims to be a user-friendly language with a friendly community of users. + +A programming language can be much more than a tool for writing software, it can also be a way for people to come together through shared experiences, to teach and to learn from one another, and to make new friends. + +No community is perfect, but a community where people show kindness to each another by default can be a true joy to participate in. That all starts with friendliness, especially towards beginners, and including towards people who prefer other programming languages. After all, languages are tools people use to create software, and there's no need for us to create artificial divisions between ourselves based on the tools we use! + +On a technical level, Roc aims to ship a toolset where user-friendliness is a major priority. This includes everything from helpful error messages (aiming to meet the bar set by [Elm](https://elm-lang.org)) to quality-of-life improvements inspired by dynamic languages (always being able to run your program even if there are compile errors, automatic serialization and deserialization using schemas determined by type inference, reliable hot code loading that's always enabled and requires no configuration to set up, etc.) to accessibility features in the included editor. + +Roc also aims to ship a single binary that includes not only a compiler, but also a [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop), package manager, test runner, debugger, static analyzer, code formatter, and a full-featured editor, all of which are designed to work seamlessly together. + +## Current Progress + +Work has not yet started on the package manager, static analyzer, debugger, or hot code loading system, and although work has started on the editor, it's not yet far enough along to be usable for practical purposes. The standard library is perhaps 80 percent complete in terms of functionality, but a lot of operations do not yet have documentation. + +The REPL fully supports entering arbitrary expressions, and will evaluate them and print the results. It remembers recent expressions entered in the current session (if you press the up arrow), but it can't yet execute effects. You can try out the REPL in a browser at [roc-lang.org/repl](https://roc-lang.org/repl) - it uses a WebAssembly build of Roc's compiler, and compiles the code you write to WebAssembly on the fly, which it then executes in the browser to display the answer. + +The compiler works well enough on a basic level to build things with it, but some error messages could use significant improvement, and it has a lot of known bugs and missing features. You can currently use it on macOS (either Intel or Apple Silicon), Linux (only x86-64 machines at the moment), and Windows (only recently supported; debugging and testing features don't work on it yet, and there are likely bugs we haven't encountered yet due to lack of battle testing). Support for other operating systems has not yet been discussed. + +The compiler doesn't yet support incremental compilation or hot code loading, and build times vary based on what machine you're building for. + +For example, suppose you run \`roc check\`, which reports errors it finds (type mismatches, naming errors, and so on) but doesn't actually build an executable, on a code base that's under a thousand lines of code. On an M1 MacBook Pro, this typically takes about 10 milliseconds. + +In contrast, if you do \`roc build\` (or \`roc run\`) on that same machine, it will take closer to 500 milliseconds instead. Almost all that extra time is spent waiting for LLVM to generate (unoptimized) machine code, and then for the system linker to assemble an executable from it. + +Fortunately, we can eliminate almost all of those extra 490 millisconds of build time by using Roc's (work in progress) development backend instead of LLVM. This compiles directly from Roc's internal representation to machine code, like most compilers did before LLVM. (LLVM can optimize code into running very fast, but even when it performs no optimization at all, LLVM itself takes a lot longer to run than generating unoptimized machine code directly.) + +The LLVM backend is currently the most feature-complete, followed closely by the WebAssembly backend (which the online REPL uses exclusively, instead of LLVM). The x86 and ARM backends still have a ways to go, but improving them can be done by anyone with the patience to read some documentation; we have issues split up for them, and are happy to help new contributors get up and running! + +Builds on Linux and Windows also use Roc's surgical linker instead of the system linker, which runs so fast that linking essentially disappears from the performance profile altogether. The surgical linker currently only works on Linux and Windows, and it currently supports building executables but not (yet) dynamic libraries, which is relevant if you're using Roc to create plugins or want to call Roc functions from existing code bases in other languages. Work has started on macOS surgical linking, but it isn't usable yet. If you're interested in working on that, please get in touch on [Roc Zulip](https://roc.zulipchat.com/)! + +The test runner currently has first-class support for running standard non-effectful tests. It does not yet have first-class support for effectful tests, property-based tests, snapshot tests, or "simulation tests" (where effects are replaced by hardcoded values during the test - similar to "mocking" in other languages), although these are all planned for the future. + +The code formatter is nearly feature-complete, although occasionally it will report an error - usually due to a comment being placed somewhere it doesn't yet know how to handle. Unlike most of the rest of the compiler, the formatter is one place where the number of known bugs is so small that fuzzing would be very helpful as a way to surface bugs we don't yet know about. (If you're interested in working on setting up fuzzing for the formatter, please let us know in the [`#contributing` channel](https://roc.zulipchat.com/#narrow/stream/316715-contributing) on Zulip! Separately, we're also very interested in fuzzing the compiler, even though we already have a sizable list of known bugs there.) + +On the community side, so far the community is a friendly bunch, and we want to keep it that way as it grows! We hope to do that by encouraging a culture of kindness and helping one another out, especially by being welcoming towards beginners. + +If you'd like to join in, the best place to do that is in our Zulip chat. Feel free to drop by the [`introductions` topic](https://roc.zulipchat.com/#narrow/stream/231634-beginners/topic/introductions) and introduce yourself! + +# Functional{#functional} \ No newline at end of file +--> + +## Goals + +Roc aims to be a purely functional programming language. This means all Roc functions are [pure functions](https://en.wikipedia.org/wiki/Pure_function), and all effects are [managed effects](https://medium.com/@kaw2k/managed-effects-and-elm-36b7fcd246a9) instead of side effects. + +A major motivating reason for this is to facilitate tooling. For example, in the future the goal is that Roc's test runner won't bother re-running tests whose outcomes could not possibly have changed (because they were pure functions whose inputs did not change). Tests that contain only pure functions can be trivially run in parallel, and they will never [flake](https://www.smashingmagazine.com/2021/04/flaky-tests-living-nightmare/). Additionally, having the guarantee that the application contains only pure functions can also make certain debugging tools more reliable, such as time travel and retroactive tracing. + +Roc also takes a novel approach to managed effects. In most programming languages, the standard library contains both data structures and I/O primitives (e.g. for using the file system or the network), and then you might decide to use a [framework](https://en.wikipedia.org/wiki/Application_framework) on top of that standard library. + +In Roc, every application is built on a _platform_. A platform is like a framework except that it also provides I/O primitives and behind-the-scenes memory management. (Roc's standard library only contains data structures.) In practice, this means that using Roc feels similar to using any other programming language where you've chosen to use a framework, except that the documentation for your I/O primitives comes from the framework instead of the standard library. + +This might sound like a minor distinction, but it turns out there are a lot of surprising benefits to organizing things this way, which would be impossible to achieve without having platforms as a first-class language concept. [The Edges of Cutting-Edge Languages](https://youtu.be/cpQwtwVKAfU) goes into more detail about some of these benefits. + +## Current Progress + +Today, platforms as a concept already exist, and there are a few different ones implemented. You can find them in the [`examples/`](https://github.com/roc-lang/roc/tree/main/examples) directory in the source code repository. The platform for building command-line interfaces is the most fully featured; the others are mostly in the proof-of-concept stage. + +Roc's built-in tooling is not yet far enough along to take advantage of pure functions. For example, there is a built-in test runner, but it does not yet run tests in parallel or skip running tests whose outcomes could not possibly have changed. + +Roc is already a purely functional programming language, though, so all of these benefits are ready to be unlocked as the tooling implementations progress! diff --git a/www/wip_new_website/content/home_page.md b/www/wip_new_website/content/home_page.md index b45b1fbf443..d99a586d701 100644 --- a/www/wip_new_website/content/home_page.md +++ b/www/wip_new_website/content/home_page.md @@ -1,46 +1,63 @@ - -# Roc lang{#page-title} +# Roc lang -- fast -- friendly -- functional +A systems programming language that is fast, friendly, and functional. - +
+ +
+

a friendly language

+

Roc aims to be a user-friendly language with a friendly community of users. Learn more

+
+
+

a functional language

+

Roc aims to be a purely functional programming language. Learn more

+
## Try Roc - + -## Use cases (Roc applications) +```roc +app "hello-world" + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.3.2/tE4xS_zLdmmxmHwHih9kHWQ7fsXtJr7W7h3425-eZFk.tar.br" } + imports [pf.Stdout] + provides [main] to pf - +main = Stdout.line "Hello, World!" +``` -- Tools & Scripts -- Web (coming soon) -- Networking & Servers (coming soon) -- Graphical (coming soon) -- Scientific (coming soon) -- Embedded (coming soon) +## Use cases + +- Tools & Scripts +- Web (coming soon) +- Networking & Servers (coming soon) +- Graphical (coming soon) +- Scientific (coming soon) +- Embedded (coming soon) ## Roc Platforms/Applications (vs libraries) - +TODO ## Talks and Publications - +If you'd like to learn more about Roc check out one of these videos: -- Roc at Handmade Seattle - November 12, 2021 (very low-level explanation of how Roc's compiler makes programs run fast) -- Outperforming Imperative with Pure Functional Languages - October 1, 2021 (about Roc's runtime performance and optimizer) -- A taste of Roc - September 23, 2021 (syntax, application examples) -- Roc at the Philly ETE conference - May 6, 2021 (platforms and applications) -- Roc on Zig Showtime - April 24, 2021 (making a platform) -- Roc at the Berlin FP Meetup - September 1, 2020 (overall vision for the language) \ No newline at end of file +* [Roc at Handmade Seattle](https://media.handmade-seattle.com/roc-lang) - November 12, 2021 (very low-level explanation of how Roc's compiler makes programs run fast) +* [Outperforming Imperative with Pure Functional Languages](https://youtu.be/vzfy4EKwG_Y) - October 1, 2021 (about Roc's runtime performance and optimizer) +* [A taste of Roc](https://youtu.be/6qzWm_eoUXM) - September 23, 2021 (syntax, application examples) +* [Roc at the Philly ETE conference](https://youtu.be/cpQwtwVKAfU?t=75) - May 6, 2021 (platforms and applications) +* [Roc on Zig Showtime](https://youtu.be/FMyyYdFSOHA) - April 24, 2021 (making a platform) +* [Roc at the Berlin FP Meetup](https://youtu.be/ZnYa99QoznE?t=4790) - September 1, 2020 (overall vision for the language) diff --git a/www/wip_new_website/content/install_page.md b/www/wip_new_website/content/install_page.md index b4f08562df4..3ede7d1a857 100644 --- a/www/wip_new_website/content/install_page.md +++ b/www/wip_new_website/content/install_page.md @@ -10,7 +10,9 @@ ## Nightly Builds - + + +[nightly builds](https://github.com/roc-lang/roc/releases) ## Roc CLI diff --git a/www/wip_new_website/main.roc b/www/wip_new_website/main.roc index d43c61856f7..27e863291bd 100644 --- a/www/wip_new_website/main.roc +++ b/www/wip_new_website/main.roc @@ -1,8 +1,8 @@ app "roc-website" packages { pf: "../../examples/static-site-gen/platform/main.roc" } imports [ - pf.Html.{ html, head, body, footer, script, div, main, text, nav, a, link, meta }, - pf.Html.Attributes.{ content, name, id, href, rel, lang, class, title, charset, src }, + pf.Html.{ html, head, body, footer, p, div, main, text, nav, a, link, meta }, + pf.Html.Attributes.{ content, name, id, href, rel, lang, class, title, charset }, ] provides [transformFileContent] to pf @@ -49,14 +49,20 @@ view = \page, htmlContent -> main [] [ text htmlContent, ], - footer [] [ + footer [ + id "footer" + ] [ + p [] [ + a [href "https://github.com/roc-lang/roc"] [text "source code repository"], + ], # text "This site is powered by ", a [href "https://www.netlify.com"] [ text "Netlify"], text ". Made by people who like to make nice things. © Roc 2023", ] ], - script [src "/site.js"] [], + # TODO - add site.js if needed + # script [src "/site.js"] [], ] viewNavbar : Html.Node From fd18840bda54dfe80649536df5ae59c6568f1d39 Mon Sep 17 00:00:00 2001 From: Luke Boswell Date: Sun, 25 Jun 2023 14:20:32 +1000 Subject: [PATCH 059/140] update css --- www/wip_new_website/static/site.css | 46 +++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/www/wip_new_website/static/site.css b/www/wip_new_website/static/site.css index 76d4f743b15..66781081d07 100644 --- a/www/wip_new_website/static/site.css +++ b/www/wip_new_website/static/site.css @@ -27,7 +27,7 @@ html { line-height: 1.5rem; - background: var(--body-bg); + background: var(--body-bg-color); color: var(--text-color); font-family: "Lato", sans-serif; } @@ -67,7 +67,7 @@ li { } #top-bar { - background-color: var(--top-bar-bg); + background-color: var(--violet-bg); width: 100%; height: 50px; } @@ -277,7 +277,7 @@ footer { margin: 0; } } - + @font-face { font-family: "Permanent Marker"; font-style: normal; @@ -545,3 +545,43 @@ code .dim { height: 40px; margin: 0 auto; } + +.home-goals-container { + display: flex; + justify-content: space-between; +} + +.home-goals-column { + flex-basis: 30%; + padding: 20px; + background-color: var(--violet-bg); + margin-right: 20px; +} + +.home-goals-column:last-child { + margin-right: 0; +} + +.home-goals-title { + font-size: 18px; + font-weight: bold; + margin-bottom: 10px; +} + +.home-goals-description { + font-size: 14px; + line-height: 1.5; + margin-bottom: 10px; +} + +.home-goals-learn-more { + color: var(--violet); + text-decoration: none; +} + +#footer { + background-color: var(--violet-bg); + color: var(--text-color); + padding: 20px; + text-align: center; + } \ No newline at end of file From f43e3468976acb31b6951a88a97f8e2041bd45da Mon Sep 17 00:00:00 2001 From: eiei114 Date: Sun, 25 Jun 2023 17:14:02 +0900 Subject: [PATCH 060/140] replace --- Cargo.lock | 1174 +++++++++++++++++--------------- crates/repl_cli/Cargo.toml | 1 + crates/repl_cli/src/cli_gen.rs | 8 +- crates/repl_expect/src/lib.rs | 5 +- crates/repl_expect/src/run.rs | 10 +- 5 files changed, 650 insertions(+), 548 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fec98114852..6abfd2f068c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "ab_glyph" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe21446ad43aa56417a767f3e2f3d7c4ca522904de1dd640529a76e9c5c3b33c" +checksum = "5110f1c78cf582855d895ecd0746b653db010cec6d9f5575293f27934d980a39" dependencies = [ "ab_glyph_rasterizer", "owned_ttf_parser", @@ -57,9 +57,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" dependencies = [ "memchr", ] @@ -88,6 +88,55 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "anstream" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" + +[[package]] +name = "anstyle-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "anstyle-wincon" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +dependencies = [ + "anstyle", + "windows-sys 0.48.0", +] + [[package]] name = "approx" version = "0.4.0" @@ -115,9 +164,9 @@ dependencies = [ [[package]] name = "arrayref" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" [[package]] name = "arrayvec" @@ -127,9 +176,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "arrayvec" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "as-slice" @@ -146,7 +195,7 @@ version = "0.34.0+1.2.203" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0f780da53d0063880d45554306489f09dd8d1bda47688b4a57bc579119356df" dependencies = [ - "libloading", + "libloading 0.7.4", ] [[package]] @@ -176,7 +225,7 @@ dependencies = [ "cc", "cfg-if 1.0.0", "libc", - "miniz_oxide", + "miniz_oxide 0.6.2", "object", "rustc-demangle", ] @@ -189,9 +238,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.0" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" [[package]] name = "base64-url" @@ -232,12 +281,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bitflags" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487f1e0fcbe47deb8b0574e646def1c903389d95241dd1bbcc6ce4a715dfc0c1" - [[package]] name = "bitmaps" version = "2.1.0" @@ -261,12 +304,12 @@ dependencies = [ [[package]] name = "blake3" -version = "1.3.3" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef" +checksum = "729b71f35bd3fa1a4c86b85d32c8b9069ea7fe14f7a53cfabb65f62d4265b888" dependencies = [ "arrayref", - "arrayvec 0.7.2", + "arrayvec 0.7.4", "cc", "cfg-if 1.0.0", "constant_time_eq", @@ -281,9 +324,9 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] name = "block-buffer" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] @@ -311,9 +354,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "bytemuck" @@ -326,13 +369,13 @@ dependencies = [ [[package]] name = "bytemuck_derive" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aca418a974d83d40a0c1f0c5cba6ff4bc28d8df099109ca459a2118d40b6322" +checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.22", ] [[package]] @@ -426,21 +469,21 @@ version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "bitflags 1.3.2", + "bitflags", "textwrap 0.11.0", "unicode-width", ] [[package]] name = "clap" -version = "3.2.23" +version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "atty", - "bitflags 1.3.2", + "bitflags", "clap_lex 0.2.4", - "indexmap", + "indexmap 1.9.3", "strsim", "termcolor", "textwrap 0.16.0", @@ -448,30 +491,38 @@ dependencies = [ [[package]] name = "clap" -version = "4.1.11" +version = "4.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42dfd32784433290c51d92c438bb72ea5063797fc3cc9a21a8c4346bebbb2098" +checksum = "d9394150f5b4273a1763355bd1c2ec54cc5a2593f790587bcd6b2c947cfa9211" dependencies = [ - "bitflags 2.0.2", + "clap_builder", "clap_derive", - "clap_lex 0.3.3", - "is-terminal", "once_cell", +] + +[[package]] +name = "clap_builder" +version = "4.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a78fbdd3cc2914ddf37ba444114bc7765bbdcb55ec9cbe6fa054f0137400717" +dependencies = [ + "anstream", + "anstyle", + "bitflags", + "clap_lex 0.5.0", "strsim", - "termcolor", ] [[package]] name = "clap_derive" -version = "4.1.9" +version = "4.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fddf67631444a3a3e3e5ac51c36a5e01335302de677bd78759eaa90ab1f46644" +checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" dependencies = [ "heck", - "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 2.0.22", ] [[package]] @@ -485,12 +536,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.3.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "033f6b7a4acb1f358c742aaca805c939ee73b4c6209ae4318ec7aca81c42e646" -dependencies = [ - "os_str_bytes", -] +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" [[package]] name = "cli_utils" @@ -536,7 +584,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" dependencies = [ - "bitflags 1.3.2", + "bitflags", "block", "cocoa-foundation", "core-foundation 0.9.3", @@ -548,11 +596,11 @@ dependencies = [ [[package]] name = "cocoa-foundation" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" +checksum = "931d3837c286f56e3c58423ce4eba12d08db2374461a785c86f672b08b5650d6" dependencies = [ - "bitflags 1.3.2", + "bitflags", "block", "core-foundation 0.9.3", "core-graphics-types", @@ -571,6 +619,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "colored" version = "2.0.0" @@ -585,7 +639,7 @@ dependencies = [ [[package]] name = "confy" version = "0.5.1" -source = "git+https://github.com/rust-cli/confy#700337e5a3fbc12f4f49fc9b7ce449b1b71040ee" +source = "git+https://github.com/rust-cli/confy#d5abd6cce9b936130832cfb4e1ed8afd7e1c488b" dependencies = [ "directories", "serde", @@ -595,14 +649,14 @@ dependencies = [ [[package]] name = "console" -version = "0.15.5" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" dependencies = [ "encode_unicode 0.3.6", "lazy_static", "libc", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -617,18 +671,18 @@ dependencies = [ [[package]] name = "const_format" -version = "0.2.30" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7309d9b4d3d2c0641e018d449232f2e28f1b22933c137f157d3dbc14228b8c0e" +checksum = "c990efc7a285731f9a4378d81aff2f0e85a2c8781a05ef0f8baa8dac54d0ff48" dependencies = [ "const_format_proc_macros", ] [[package]] name = "const_format_proc_macros" -version = "0.2.29" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f47bf7270cf70d370f8f98c1abb6d2d4cf60a6845d30e05bfb90c6568650" +checksum = "e026b6ce194a874cb9cf32cd5772d1ef9767cc8fcb5765948d74f37a9d8b2bf6" dependencies = [ "proc-macro2", "quote", @@ -637,9 +691,9 @@ dependencies = [ [[package]] name = "constant_time_eq" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279" +checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" [[package]] name = "copyless" @@ -677,7 +731,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ - "core-foundation-sys 0.8.3", + "core-foundation-sys 0.8.4", "libc", ] @@ -689,9 +743,9 @@ checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "core-graphics" @@ -699,7 +753,7 @@ version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" dependencies = [ - "bitflags 1.3.2", + "bitflags", "core-foundation 0.7.0", "foreign-types", "libc", @@ -711,7 +765,7 @@ version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" dependencies = [ - "bitflags 1.3.2", + "bitflags", "core-foundation 0.9.3", "core-graphics-types", "foreign-types", @@ -720,13 +774,12 @@ dependencies = [ [[package]] name = "core-graphics-types" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" +checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" dependencies = [ - "bitflags 1.3.2", + "bitflags", "core-foundation 0.9.3", - "foreign-types", "libc", ] @@ -745,9 +798,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.5" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" dependencies = [ "libc", ] @@ -811,9 +864,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -832,14 +885,14 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.14" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ "autocfg", "cfg-if 1.0.0", "crossbeam-utils", - "memoffset 0.8.0", + "memoffset 0.9.0", "scopeguard", ] @@ -855,9 +908,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if 1.0.0", ] @@ -874,9 +927,9 @@ dependencies = [ [[package]] name = "csv" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b015497079b9a9d69c02ad25de6c0a6edef051ea6360a327d0bd05802ef64ad" +checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086" dependencies = [ "csv-core", "itoa", @@ -900,7 +953,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -911,11 +964,11 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" [[package]] name = "cvt" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ac344c7efccb80cd25bc61b2170aec26f2f693fd40e765a539a1243db48c71" +checksum = "d2ae9bf77fbf2d39ef573205d554d87e86c12f1994e9ea335b0651b9b278bcf1" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", ] [[package]] @@ -924,8 +977,8 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2daefd788d1e96e0a9d66dee4b828b883509bc3ea9ce30665f04c3246372690c" dependencies = [ - "bitflags 1.3.2", - "libloading", + "bitflags", + "libloading 0.7.4", "winapi", ] @@ -950,7 +1003,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn", + "syn 1.0.109", ] [[package]] @@ -961,7 +1014,7 @@ checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -974,7 +1027,7 @@ dependencies = [ "hashbrown 0.12.3", "lock_api", "once_cell", - "parking_lot_core 0.9.7", + "parking_lot_core 0.9.8", ] [[package]] @@ -985,9 +1038,9 @@ checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", @@ -1060,11 +1113,11 @@ checksum = "6d9d8664cf849d7d0f3114a3a387d2f5e4303176d746d5a951aaddc66dfe9240" [[package]] name = "dlib" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading", + "libloading 0.8.0", ] [[package]] @@ -1081,9 +1134,9 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" [[package]] name = "dunce" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "either" @@ -1129,25 +1182,20 @@ dependencies = [ ] [[package]] -name = "errno" -version = "0.2.8" +name = "equivalent" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" -dependencies = [ - "errno-dragonfly", - "libc", - "winapi", -] +checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" [[package]] name = "errno" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -1172,25 +1220,25 @@ dependencies = [ [[package]] name = "fd-lock" -version = "3.0.10" +version = "3.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ef1a30ae415c3a691a4f41afddc2dbcd6d70baf338368d85ebc1e8ed92cedb9" +checksum = "39ae6b3d9530211fb3b12a95374b8b0823be812f53d09e18c5675c0146b09642" dependencies = [ "cfg-if 1.0.0", - "rustix 0.36.9", - "windows-sys 0.45.0", + "rustix", + "windows-sys 0.48.0", ] [[package]] name = "filetime" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" +checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall", - "windows-sys 0.45.0", + "redox_syscall 0.2.16", + "windows-sys 0.48.0", ] [[package]] @@ -1204,12 +1252,12 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.7.1", ] [[package]] @@ -1235,26 +1283,25 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] [[package]] name = "fs_at" -version = "0.1.1" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab60b097d8208fe02d24ae954c3248a9436f96edefa8f4b9fcb0f26d60d003a9" +checksum = "15550ecca96ea332ec143fb450701074143b70d358e50b32b1f847ccff2e1cf7" dependencies = [ "aligned", "cfg-if 1.0.0", "cvt", "libc", "nix 0.26.2", - "smart-default", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -1271,9 +1318,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" dependencies = [ "futures-channel", "futures-core", @@ -1286,9 +1333,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", "futures-sink", @@ -1296,15 +1343,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" [[package]] name = "futures-executor" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" dependencies = [ "futures-core", "futures-task", @@ -1313,38 +1360,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" [[package]] name = "futures-macro" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.22", ] [[package]] name = "futures-sink" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" [[package]] name = "futures-task" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" [[package]] name = "futures-util" -version = "0.3.26" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ "futures-channel", "futures-core", @@ -1369,9 +1416,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.6" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -1389,9 +1436,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -1402,9 +1449,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" [[package]] name = "glow" @@ -1458,11 +1505,11 @@ dependencies = [ [[package]] name = "gpu-alloc" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc59e5f710e310e76e6707f86c561dd646f69a8876da9131703b2f717de818d" +checksum = "22beaafc29b38204457ea030f6fb7a84c9e4dd1b86e311ba0542533453d87f62" dependencies = [ - "bitflags 1.3.2", + "bitflags", "gpu-alloc-types", ] @@ -1472,7 +1519,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" dependencies = [ - "bitflags 1.3.2", + "bitflags", ] [[package]] @@ -1481,7 +1528,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b0c02e1ba0bdb14e965058ca34e09c020f8e507a760df1121728e0aef68d57a" dependencies = [ - "bitflags 1.3.2", + "bitflags", "gpu-descriptor-types", "hashbrown 0.12.3", ] @@ -1492,14 +1539,14 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "363e3677e55ad168fef68cf9de3a4a310b53124c5e784c53a1d70e92d23f2126" dependencies = [ - "bitflags 1.3.2", + "bitflags", ] [[package]] name = "h2" -version = "0.3.16" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d" +checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" dependencies = [ "bytes", "fnv", @@ -1507,7 +1554,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 1.9.3", "slab", "tokio", "tokio-util", @@ -1539,6 +1586,12 @@ dependencies = [ "bumpalo", ] +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + [[package]] name = "heck" version = "0.4.1" @@ -1620,9 +1673,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.14.24" +version = "0.14.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" +checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" dependencies = [ "bytes", "futures-channel", @@ -1644,9 +1697,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.23.2" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" +checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7" dependencies = [ "http", "hyper", @@ -1657,9 +1710,9 @@ dependencies = [ [[package]] name = "iced-x86" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd04b950d75b3498320253b17fb92745b2cc79ead8814aede2f7c1bab858bec" +checksum = "b7cc8d38244d84278262c8ebe6930cc44283d194cbabae2651f6112103802fb5" dependencies = [ "lazy_static", ] @@ -1672,9 +1725,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -1710,14 +1763,24 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.2" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", ] +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown 0.14.0", +] + [[package]] name = "indoc" version = "1.0.9" @@ -1744,7 +1807,7 @@ source = "git+https://github.com/roc-lang/inkwell?branch=inkwell-llvm-15#95a3a13 dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1755,9 +1818,9 @@ checksum = "e567468c50f3d4bc7397702e09b380139f9b9288b4e909b070571007f8b5bf78" [[package]] name = "insta" -version = "1.28.0" +version = "1.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea5b3894afe466b4bcf0388630fc15e11938a6074af0cd637c825ba2ec8a099" +checksum = "28491f7753051e5704d4d0ae7860d45fae3238d7d235bc4289dcd45c48d3cec3" dependencies = [ "console", "lazy_static", @@ -1780,30 +1843,31 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.6" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfa919a82ea574332e2de6e74b4c36e74d41982b335080fa59d4ef31be20fdf3" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ + "hermit-abi 0.3.1", "libc", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] name = "ipnet" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" +checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" [[package]] name = "is-terminal" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "256017f749ab3117e93acb91063009e1f1bb56d03965b14c2c8df4eb02c524d8" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ "hermit-abi 0.3.1", "io-lifetimes", - "rustix 0.37.3", - "windows-sys 0.45.0", + "rustix", + "windows-sys 0.48.0", ] [[package]] @@ -1838,9 +1902,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "js-sys" -version = "0.3.61" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] @@ -1862,7 +1926,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" dependencies = [ "libc", - "libloading", + "libloading 0.7.4", ] [[package]] @@ -1879,9 +1943,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.139" +version = "0.2.146" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" [[package]] name = "libloading" @@ -1893,17 +1957,27 @@ dependencies = [ "winapi", ] +[[package]] +name = "libloading" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb" +dependencies = [ + "cfg-if 1.0.0", + "windows-sys 0.48.0", +] + [[package]] name = "libm" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" +checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" [[package]] name = "libmimalloc-sys" -version = "0.1.30" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8c7cbf8b89019683667e347572e6d55a7df7ea36b0c4ce69961b0cde67b174" +checksum = "f4ac0e912c8ef1b735e92369695618dc5b1819f5a7bf3f167301a3ba1cea515e" dependencies = [ "cc", "libc", @@ -1911,11 +1985,11 @@ dependencies = [ [[package]] name = "libtest-mimic" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7b603516767d1ab23d0de09d023e62966c3322f7148297c35cf3d97aa8b37fa" +checksum = "6d8de370f98a6cb8a4606618e53e802f93b094ddec0f96988eaec2c27e6e9ce7" dependencies = [ - "clap 4.1.11", + "clap 4.3.8", "termcolor", "threadpool", ] @@ -1928,21 +2002,15 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" - -[[package]] -name = "linux-raw-sys" -version = "0.3.1" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "llvm-sys" -version = "130.0.7" +version = "130.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b54ec4a457c4b55ffb2bd56ed44841161ae933fd4fe3dc379748fcd4193661d4" +checksum = "e7d0f52cdf734a48a85e8de93ea3c8664264ed534dd519d4a64b19483e0fe709" dependencies = [ "cc", "lazy_static", @@ -1953,9 +2021,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", @@ -1963,12 +2031,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "mach_object" @@ -1976,7 +2041,7 @@ version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6f2d7176b94027af58085a2c9d27c4e416586caba409c314569213901d6068" dependencies = [ - "bitflags 1.3.2", + "bitflags", "byteorder", "lazy_static", "libc", @@ -2045,9 +2110,9 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] @@ -2058,7 +2123,7 @@ version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0514f491f4cc03632ab399ee01e2c1c1b12d3e1cf2d667c1ff5f87d6dcd2084" dependencies = [ - "bitflags 1.3.2", + "bitflags", "block", "core-graphics-types", "foreign-types", @@ -2068,18 +2133,18 @@ dependencies = [ [[package]] name = "mimalloc" -version = "0.1.34" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dcb174b18635f7561a0c6c9fc2ce57218ac7523cf72c50af80e2d79ab8f3ba1" +checksum = "4e2894987a3459f3ffb755608bd82188f8ed00d0ae077f1edea29c068d639d98" dependencies = [ "libmimalloc-sys", ] [[package]] name = "mime" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "minimal-lexical" @@ -2096,16 +2161,25 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + [[package]] name = "mio" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "log", "wasi", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -2126,10 +2200,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3012f2dbcc79e8e0b5825a4836a7106a75dd9b2fe42c528163be0f572538c705" dependencies = [ "bit-set", - "bitflags 1.3.2", + "bitflags", "codespan-reporting", "hexf-parse", - "indexmap", + "indexmap 1.9.3", "log", "num-traits", "rustc-hash", @@ -2143,7 +2217,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d868f654c72e75f8687572699cdabe755f03effbb62542768e995d5b8d699d" dependencies = [ - "bitflags 1.3.2", + "bitflags", "jni-sys", "ndk-sys", "num_enum", @@ -2181,7 +2255,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2205,7 +2279,7 @@ version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf" dependencies = [ - "bitflags 1.3.2", + "bitflags", "cc", "cfg-if 1.0.0", "libc", @@ -2218,7 +2292,7 @@ version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" dependencies = [ - "bitflags 1.3.2", + "bitflags", "cc", "cfg-if 1.0.0", "libc", @@ -2231,7 +2305,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ - "bitflags 1.3.2", + "bitflags", "cfg-if 1.0.0", "libc", "memoffset 0.6.5", @@ -2243,7 +2317,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" dependencies = [ - "bitflags 1.3.2", + "bitflags", "cfg-if 1.0.0", "libc", "static_assertions", @@ -2267,11 +2341,11 @@ checksum = "aeaf4ad7403de93e699c191202f017118df734d3850b01e13a3a8b2e6953d3c9" [[package]] name = "normpath" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "972dec05f98e7c787ede35d7a9ea4735eb7788c299287352757b3def6cc1f7b5" +checksum = "ec60c60a693226186f5d6edf073232bfb6464ed97eb22cf3b01c1e8198fd97f5" dependencies = [ - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -2322,7 +2396,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2366,22 +2440,22 @@ dependencies = [ [[package]] name = "object" -version = "0.30.3" +version = "0.30.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" dependencies = [ "crc32fast", "flate2", "hashbrown 0.13.2", - "indexmap", + "indexmap 1.9.3", "memchr", ] [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "oorandom" @@ -2391,18 +2465,18 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "ordered-float" -version = "3.4.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d84eb1409416d254e4a9c8fa56cc24701755025b458f0fcd8e59e1f5f40c23bf" +checksum = "2fc2dbde8f8a79f2102cc474ceb0ad68e3b80b85289ea62389b60e66777e4213" dependencies = [ "num-traits", ] [[package]] name = "os_str_bytes" -version = "6.4.1" +version = "6.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" +checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" [[package]] name = "output_vt100" @@ -2421,9 +2495,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "owned_ttf_parser" -version = "0.18.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e25e9fb15717794fae58ab55c26e044103aad13186fbb625893f9a3bbcc24228" +checksum = "706de7e2214113d63a8238d1910463cfce781129a6f263d13fdb09ff64355ba4" dependencies = [ "ttf-parser", ] @@ -2447,7 +2521,7 @@ checksum = "9cd6706dfe50d53e0f6aa09e12c034c44faacd23e966ae5a209e8bdb8f179f98" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2481,7 +2555,7 @@ dependencies = [ "find-crate", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2502,7 +2576,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.7", + "parking_lot_core 0.9.8", ] [[package]] @@ -2514,22 +2588,22 @@ dependencies = [ "cfg-if 1.0.0", "instant", "libc", - "redox_syscall", + "redox_syscall 0.2.16", "smallvec", "winapi", ] [[package]] name = "parking_lot_core" -version = "0.9.7" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall", + "redox_syscall 0.3.5", "smallvec", - "windows-sys 0.45.0", + "windows-targets 0.48.0", ] [[package]] @@ -2561,15 +2635,15 @@ checksum = "9fa00462b37ead6d11a82c9d568b26682d78e0477dc02d1966c013af80969739" [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" -version = "2.5.6" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cbd939b234e95d72bc393d51788aec68aeeb5d51e748ca08ff3aad58cb722f7" +checksum = "f73935e4d55e2abf7f130186537b19e7a4abc886a0252380b59248af473a3fc9" dependencies = [ "thiserror", "ucd-trie", @@ -2577,9 +2651,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.5.6" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a81186863f3d0a27340815be8f2078dd8050b14cd71913db9fbda795e5f707d7" +checksum = "aef623c9bbfa0eedf5a0efba11a5ee83209c326653ca31ff019bec3a95bfff2b" dependencies = [ "pest", "pest_generator", @@ -2587,22 +2661,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.5.6" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75a1ef20bf3193c15ac345acb32e26b3dc3223aff4d77ae4fc5359567683796b" +checksum = "b3e8cba4ec22bada7fc55ffe51e2deb6a0e0db2d0b7ab0b103acc80d2510c190" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn", + "syn 2.0.22", ] [[package]] name = "pest_meta" -version = "2.5.6" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e3b284b1f13a20dc5ebc90aff59a51b8d7137c221131b52a7260c08cbc1cc80" +checksum = "a01f71cb40bd8bb94232df14b946909e14660e33fc05db3e50ae2a82d7ea0ca0" dependencies = [ "once_cell", "pest", @@ -2611,9 +2685,9 @@ dependencies = [ [[package]] name = "phf" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ "phf_macros", "phf_shared", @@ -2621,9 +2695,9 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" dependencies = [ "phf_shared", "rand", @@ -2631,22 +2705,22 @@ dependencies = [ [[package]] name = "phf_macros" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92aacdc5f16768709a569e913f7451034034178b05bdc8acda226659a3dccc66" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" dependencies = [ "phf_generator", "phf_shared", "proc-macro2", "quote", - "syn", + "syn 2.0.22", ] [[package]] name = "phf_shared" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" dependencies = [ "siphasher", ] @@ -2665,9 +2739,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "plotters" @@ -2683,15 +2757,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" +checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" [[package]] name = "plotters-svg" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" +checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" dependencies = [ "plotters-backend", ] @@ -2724,61 +2798,36 @@ dependencies = [ "toml_edit", ] -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro2" -version = "1.0.51" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" dependencies = [ "unicode-ident", ] [[package]] name = "profiling" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74605f360ce573babfe43964cbe520294dcb081afbf8c108fc6e23036b4da2df" +checksum = "332cd62e95873ea4f41f3dfd6bbbfc5b52aec892d7e8d534197c4720a0bbbab2" [[package]] name = "proptest" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29f1b898011ce9595050a68e60f90bad083ff2987a695a42357134c8381fba70" +checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" dependencies = [ "bit-set", - "bitflags 1.3.2", + "bitflags", "byteorder", "lazy_static", "num-traits", - "quick-error 2.0.1", "rand", "rand_chacha", "rand_xorshift", - "regex-syntax", + "regex-syntax 0.6.29", "rusty-fork", "tempfile", "unarray", @@ -2786,11 +2835,11 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63" +checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" dependencies = [ - "bitflags 1.3.2", + "bitflags", "memchr", "unicase", ] @@ -2801,12 +2850,6 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" -[[package]] -name = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" - [[package]] name = "quickcheck" version = "1.0.3" @@ -2826,14 +2869,14 @@ checksum = "b22a693222d716a9587786f37ac3f6b4faedb5b80c23914e7303ff5a1d8016e9" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "quote" -version = "1.0.23" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" dependencies = [ "proc-macro2", ] @@ -2945,7 +2988,16 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags 1.3.2", + "bitflags", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", ] [[package]] @@ -2955,19 +3007,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ "getrandom", - "redox_syscall", + "redox_syscall 0.2.16", "thiserror", ] [[package]] name = "regex" -version = "1.7.1" +version = "1.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.7.2", ] [[package]] @@ -2976,14 +3028,20 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ - "regex-syntax", + "regex-syntax 0.6.29", ] [[package]] name = "regex-syntax" -version = "0.6.28" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" [[package]] name = "remove_dir_all" @@ -2996,9 +3054,9 @@ dependencies = [ [[package]] name = "remove_dir_all" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7174320e07c29945955cedd70b865995b286847111c8308d349a1f3a9e3af555" +checksum = "23895cfadc1917fed9c6ed76a8c2903615fa3704f7493ff82b364c6540acc02b" dependencies = [ "aligned", "cfg-if 1.0.0", @@ -3032,11 +3090,11 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.14" +version = "0.11.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" +checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" dependencies = [ - "base64 0.21.0", + "base64 0.21.2", "bytes", "encoding_rs", "futures-core", @@ -3110,7 +3168,7 @@ dependencies = [ name = "roc_ast" version = "0.0.1" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "bumpalo", "indoc", "libc", @@ -3162,7 +3220,7 @@ dependencies = [ "bumpalo", "indoc", "inkwell", - "libloading", + "libloading 0.7.4", "roc_bitcode", "roc_can", "roc_collections", @@ -3230,15 +3288,15 @@ name = "roc_cli" version = "0.0.1" dependencies = [ "bumpalo", - "clap 3.2.23", + "clap 3.2.25", "cli_utils", "const_format", "criterion", - "errno 0.3.0", + "errno", "indoc", "inkwell", "libc", - "libloading", + "libloading 0.7.4", "mimalloc", "parking_lot 0.12.1", "pretty_assertions", @@ -3311,7 +3369,7 @@ version = "0.0.1" name = "roc_constrain" version = "0.0.1" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "roc_can", "roc_collections", "roc_error_macros", @@ -3381,7 +3439,7 @@ dependencies = [ name = "roc_docs_cli" version = "0.0.1" dependencies = [ - "clap 3.2.23", + "clap 3.2.25", "libc", "roc_docs", ] @@ -3390,7 +3448,7 @@ dependencies = [ name = "roc_editor" version = "0.0.1" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "bumpalo", "bytemuck", "cgmath", @@ -3539,10 +3597,10 @@ dependencies = [ "cli_utils", "dircpy", "fnv", - "indexmap", + "indexmap 1.9.3", "indoc", "libc", - "libloading", + "libloading 0.7.4", "pretty_assertions", "roc_build", "roc_builtins", @@ -3776,10 +3834,11 @@ dependencies = [ "bumpalo", "const_format", "inkwell", - "libloading", + "libloading 0.7.4", "roc_build", "roc_builtins", "roc_collections", + "roc_error_macros", "roc_gen_llvm", "roc_load", "roc_module", @@ -3827,7 +3886,7 @@ dependencies = [ "indoc", "inkwell", "libc", - "libloading", + "libloading 0.7.4", "pretty_assertions", "roc_build", "roc_builtins", @@ -3921,7 +3980,7 @@ dependencies = [ name = "roc_solve" version = "0.0.1" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "bumpalo", "indoc", "insta", @@ -3970,7 +4029,7 @@ dependencies = [ name = "roc_std" version = "0.0.1" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "libc", "pretty_assertions", "quickcheck", @@ -3994,7 +4053,7 @@ name = "roc_test_utils" version = "0.0.1" dependencies = [ "pretty_assertions", - "remove_dir_all 0.8.1", + "remove_dir_all 0.8.2", ] [[package]] @@ -4025,7 +4084,7 @@ dependencies = [ name = "roc_unify" version = "0.0.1" dependencies = [ - "bitflags 1.3.2", + "bitflags", "roc_collections", "roc_debug_flags", "roc_error_macros", @@ -4040,7 +4099,7 @@ version = "0.0.1" dependencies = [ "bitvec", "bumpalo", - "clap 3.2.23", + "clap 3.2.25", "rand", "roc_wasm_module", ] @@ -4056,9 +4115,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.21" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustc-hash" @@ -4072,47 +4131,33 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.16", -] - -[[package]] -name = "rustix" -version = "0.36.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd5c6ff11fecd55b40746d1995a02f2eb375bf8c00d192d521ee09f42bef37bc" -dependencies = [ - "bitflags 1.3.2", - "errno 0.2.8", - "io-lifetimes", - "libc", - "linux-raw-sys 0.1.4", - "windows-sys 0.45.0", + "semver 1.0.17", ] [[package]] name = "rustix" -version = "0.37.3" +version = "0.37.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b24138615de35e32031d041a09032ef3487a616d901ca4db224e7d557efae2" +checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0" dependencies = [ - "bitflags 1.3.2", - "errno 0.3.0", + "bitflags", + "errno", "io-lifetimes", "libc", - "linux-raw-sys 0.3.1", - "windows-sys 0.45.0", + "linux-raw-sys", + "windows-sys 0.48.0", ] [[package]] name = "rustls" -version = "0.20.8" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +checksum = "e32ca28af694bc1bbf399c33a516dbdf1c90090b8ab23c2bc24f834aa2247f5f" dependencies = [ "log", "ring", + "rustls-webpki", "sct", - "webpki", ] [[package]] @@ -4121,7 +4166,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" dependencies = [ - "base64 0.21.0", + "base64 0.21.2", +] + +[[package]] +name = "rustls-webpki" +version = "0.100.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +dependencies = [ + "ring", + "untrusted", ] [[package]] @@ -4137,7 +4192,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" dependencies = [ "fnv", - "quick-error 1.2.3", + "quick-error", "tempfile", "wait-timeout", ] @@ -4147,7 +4202,7 @@ name = "rustyline" version = "9.1.1" source = "git+https://github.com/roc-lang/rustyline?rev=e74333c#e74333c0d618896b88175bf06645108f996fe6d0" dependencies = [ - "bitflags 1.3.2", + "bitflags", "cfg-if 1.0.0", "clipboard-win 4.5.0", "dirs-next", @@ -4171,7 +4226,7 @@ version = "0.6.0" source = "git+https://github.com/roc-lang/rustyline?rev=e74333c#e74333c0d618896b88175bf06645108f996fe6d0" dependencies = [ "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -4222,9 +4277,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" [[package]] name = "semver-parser" @@ -4237,9 +4292,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.153" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a382c72b4ba118526e187430bb4963cd6d55051ebf13d9b25574d379cc98d20" +checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" dependencies = [ "serde_derive", ] @@ -4268,20 +4323,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.153" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ef476a5790f0f6decbc66726b6e5d63680ed518283e64c7df415989d880954f" +checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.22", ] [[package]] name = "serde_json" -version = "1.0.94" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" +checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" dependencies = [ "itoa", "ryu", @@ -4306,7 +4361,7 @@ version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ - "indexmap", + "indexmap 1.9.3", "ryu", "serde", "yaml-rust", @@ -4334,14 +4389,14 @@ checksum = "079a83df15f85d89a68d64ae1238f142f172b1fa915d0d76b26a7cba1b659a69" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -4422,24 +4477,13 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" -[[package]] -name = "smart-default" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "smithay-client-toolkit" version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a28f16a97fa0e8ce563b2774d1e732dd5d4025d2772c5dba0a41a0f90a29da3" dependencies = [ - "bitflags 1.3.2", + "bitflags", "calloop", "dlib", "lazy_static", @@ -4458,7 +4502,7 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f307c47d32d2715eb2e0ece5589057820e0e5e70d07c247d1063e844e107f454" dependencies = [ - "bitflags 1.3.2", + "bitflags", "dlib", "lazy_static", "log", @@ -4500,7 +4544,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -4525,7 +4569,7 @@ version = "0.2.0+1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" dependencies = [ - "bitflags 1.3.2", + "bitflags", "num-traits", ] @@ -4581,14 +4625,14 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn", + "syn 1.0.109", ] [[package]] name = "subtle" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" @@ -4601,6 +4645,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "tap" version = "1.0.1" @@ -4620,9 +4675,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.6" +version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae9980cab1db3fceee2f6c6f643d5d8de2997c58ee8d25fb0cc8a9e9e7348e5" +checksum = "1b1c7f239eb94671427157bd93b3694320f3668d4e1eff08c7285366fd777fac" [[package]] name = "tempfile" @@ -4633,7 +4688,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "rand", - "redox_syscall", + "redox_syscall 0.2.16", "remove_dir_all 0.5.3", "winapi", ] @@ -4681,7 +4736,7 @@ dependencies = [ "inkwell", "lazy_static", "libc", - "libloading", + "libloading 0.7.4", "roc_bitcode", "roc_build", "roc_builtins", @@ -4739,7 +4794,7 @@ version = "0.0.1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -4801,22 +4856,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.22", ] [[package]] @@ -4840,9 +4895,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.20" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" +checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" dependencies = [ "itoa", "serde", @@ -4852,15 +4907,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" +checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" dependencies = [ "time-core", ] @@ -4892,37 +4947,35 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.26.0" +version = "1.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64" +checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" dependencies = [ "autocfg", "bytes", "libc", - "memchr", "mio", "num_cpus", "pin-project-lite", "socket2", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] name = "tokio-rustls" -version = "0.23.4" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ "rustls", "tokio", - "webpki", ] [[package]] name = "tokio-util" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" dependencies = [ "bytes", "futures-core", @@ -4943,17 +4996,17 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" [[package]] name = "toml_edit" -version = "0.19.4" +version = "0.19.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825" +checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7" dependencies = [ - "indexmap", + "indexmap 2.0.0", "toml_datetime", "winnow", ] @@ -4989,20 +5042,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.23" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.22", ] [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" dependencies = [ "once_cell", "valuable", @@ -5021,9 +5074,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" +checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" dependencies = [ "matchers", "nu-ansi-term", @@ -5045,9 +5098,9 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "ttf-parser" -version = "0.18.1" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0609f771ad9c6155384897e1df4d948e692667cc0588548b68eb44d052b27633" +checksum = "a464a4b34948a5f67fddd2b823c62d9d92e44be75058b99939eae6c5b6960b33" [[package]] name = "twox-hash" @@ -5122,15 +5175,15 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.10" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" [[package]] name = "unicode-normalization" @@ -5167,9 +5220,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" dependencies = [ "form_urlencoded", "idna", @@ -5184,15 +5237,15 @@ checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" [[package]] name = "utf8parse" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.3.0" +version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" +checksum = "0fa2982af2eec27de306107c027578ff7f423d65f7250e40ce0fea8f45248b81" dependencies = [ "getrandom", ] @@ -5232,7 +5285,7 @@ dependencies = [ name = "ven_pretty" version = "0.9.1-alpha.0" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "termcolor", "typed-arena", ] @@ -5275,22 +5328,20 @@ dependencies = [ [[package]] name = "walkdir" -version = "2.3.2" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" dependencies = [ "same-file", - "winapi", "winapi-util", ] [[package]] name = "want" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "log", "try-lock", ] @@ -5309,9 +5360,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -5319,24 +5370,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn", + "syn 2.0.22", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.34" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -5346,9 +5397,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5356,22 +5407,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.22", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wayland-client" @@ -5379,7 +5430,7 @@ version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715" dependencies = [ - "bitflags 1.3.2", + "bitflags", "downcast-rs", "libc", "nix 0.24.3", @@ -5418,7 +5469,7 @@ version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" dependencies = [ - "bitflags 1.3.2", + "bitflags", "wayland-client", "wayland-commons", "wayland-scanner", @@ -5481,7 +5532,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b97cd781ff044d6d697b632a2e212032c2e957d1afaa21dbf58069cbb8f78567" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "js-sys", "log", "naga", @@ -5502,8 +5553,8 @@ version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4688c000eb841ca55f7b35db659b78d6e1cd77d7caf8fb929f4e181f754047d" dependencies = [ - "arrayvec 0.7.2", - "bitflags 1.3.2", + "arrayvec 0.7.4", + "bitflags", "cfg_aliases", "codespan-reporting", "copyless", @@ -5525,10 +5576,10 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d684ea6a34974a2fc19f1dfd183d11a62e22d75c4f187a574bb1224df8e056c2" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "ash", "bit-set", - "bitflags 1.3.2", + "bitflags", "block", "core-graphics-types", "d3d12", @@ -5540,7 +5591,7 @@ dependencies = [ "inplace_it", "js-sys", "khronos-egl", - "libloading", + "libloading 0.7.4", "log", "metal", "naga", @@ -5563,7 +5614,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "549533d9e1cdd4b4cda7718d33ff500fc4c34b5467b71d76b547ae0324f3b2a2" dependencies = [ - "bitflags 1.3.2", + "bitflags", ] [[package]] @@ -5620,84 +5671,135 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows-targets 0.42.2", ] [[package]] name = "windows-sys" -version = "0.45.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" dependencies = [ - "windows-targets", + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", ] [[package]] name = "windows-targets" -version = "0.42.1" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.1" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.42.1" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" [[package]] name = "windows_i686_gnu" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" [[package]] name = "windows_i686_msvc" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.42.1" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.42.1" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winit" @@ -5705,7 +5807,7 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b43cc931d58b99461188607efd7acb2a093e65fc621f54cad78517a6063e73a" dependencies = [ - "bitflags 1.3.2", + "bitflags", "cocoa", "core-foundation 0.9.3", "core-graphics 0.22.3", @@ -5734,9 +5836,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.3.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee7b2c67f962bf5042bfd8b6a916178df33a26eec343ae064cb8e069f638fa6f" +checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" dependencies = [ "memchr", ] @@ -5770,9 +5872,9 @@ dependencies = [ [[package]] name = "x11-clipboard" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0827f86aa910c4e73329a4f619deabe88ebb4b042370bf023c2d5d8b4eb54695" +checksum = "980b9aa9226c3b7de8e2adb11bf20124327c054e0e5812d2aac0b5b5a87e7464" dependencies = [ "x11rb", ] @@ -5836,9 +5938,9 @@ checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" [[package]] name = "xml-rs" -version = "0.8.4" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" +checksum = "52839dc911083a8ef63efa4d039d1f58b5e409f923e44c80828f206f66e5541c" [[package]] name = "yaml-rust" diff --git a/crates/repl_cli/Cargo.toml b/crates/repl_cli/Cargo.toml index 34db9dc2238..147b887b705 100644 --- a/crates/repl_cli/Cargo.toml +++ b/crates/repl_cli/Cargo.toml @@ -30,6 +30,7 @@ roc_reporting = { path = "../reporting" } roc_std = { path = "../roc_std" } roc_target = { path = "../compiler/roc_target" } roc_types = { path = "../compiler/types" } +roc_error_macros = { path = "../error_macros" } bumpalo.workspace = true const_format.workspace = true diff --git a/crates/repl_cli/src/cli_gen.rs b/crates/repl_cli/src/cli_gen.rs index 8009f12cf7a..61beafb4ea3 100644 --- a/crates/repl_cli/src/cli_gen.rs +++ b/crates/repl_cli/src/cli_gen.rs @@ -3,6 +3,7 @@ use inkwell::context::Context; use libloading::Library; use roc_build::link::llvm_module_to_dylib; use roc_collections::all::MutSet; +use roc_error_macros::internal_error; use roc_gen_llvm::llvm::build::LlvmBackendMode; use roc_gen_llvm::llvm::externs::add_default_roc_externs; use roc_gen_llvm::{run_jit_function, run_jit_function_dynamic_type}; @@ -263,7 +264,7 @@ fn mono_module_to_dylib<'a>( if main_fn.verify(true) { function_pass.run_on(&main_fn); } else { - panic!("Main function {} failed LLVM verification in build. Uncomment things nearby to see more details.", main_fn_name); + internal_error!("Main function {} failed LLVM verification in build. Uncomment things nearby to see more details.", main_fn_name); } module_pass.run_on(env.module); @@ -273,10 +274,7 @@ fn mono_module_to_dylib<'a>( // Verify the module if let Err(errors) = env.module.verify() { - panic!( - "Errors defining module:\n{}\n\nUncomment things nearby to see more details.", - errors.to_string() - ); + internal_error!("Errors defining module:\n{}", errors.to_string()); } llvm_module_to_dylib(env.module, &target, opt_level) diff --git a/crates/repl_expect/src/lib.rs b/crates/repl_expect/src/lib.rs index 1d399b7efec..9332a2a3913 100644 --- a/crates/repl_expect/src/lib.rs +++ b/crates/repl_expect/src/lib.rs @@ -93,6 +93,7 @@ pub fn get_values<'a>( mod test { use indoc::indoc; use pretty_assertions::assert_eq; + use roc_error_macros::internal_error; use roc_gen_llvm::{llvm::build::LlvmBackendMode, run_roc::RocCallResult, run_roc_dylib}; use roc_load::{ExecutionMode, LoadConfig, LoadMonomorphizedError, Threading}; use roc_packaging::cache::RocCacheDir; @@ -136,9 +137,9 @@ mod test { ) { Ok(m) => m, Err(LoadMonomorphizedError::ErrorModule(m)) => { - panic!("{:?}", (m.can_problems, m.type_problems)) + internal_error!("{:?}", (m.can_problems, m.type_problems)) } - Err(e) => panic!("{e:?}"), + Err(e) => internal_error!("{e:?}"), }; let mut loaded = loaded; diff --git a/crates/repl_expect/src/run.rs b/crates/repl_expect/src/run.rs index 0c8846906ea..385a6f6df06 100644 --- a/crates/repl_expect/src/run.rs +++ b/crates/repl_expect/src/run.rs @@ -327,7 +327,7 @@ fn run_expect_fx<'a, W: std::io::Write>( try_run_jit_function!(lib, expect.name, (), |v: ()| v); if let Err((msg, _)) = result { - panic!("roc panic {}", msg); + internal_error!("roc panic {}", msg); } if sequence.count_failures() > 0 { @@ -518,7 +518,7 @@ fn render_dbg_failure<'a>( let data = expectations.get_mut(&module_id).unwrap(); let current = match data.dbgs.get(&dbg_symbol) { - None => panic!("region {failure_region:?} not in list of dbgs"), + None => internal_error!("region {failure_region:?} not in list of dbgs"), Some(current) => current, }; let failure_region = current.region; @@ -565,7 +565,7 @@ fn render_expect_failure<'a>( let data = expectations.get_mut(&module_id).unwrap(); let current = match data.expectations.get(&failure_region) { - None => panic!("region {failure_region:?} not in list of expects"), + None => internal_error!("region {failure_region:?} not in list of expects"), Some(current) => current, }; @@ -638,7 +638,7 @@ impl ExpectSequence { 0 => std::hint::spin_loop(), 1 => break ChildProcessMsg::Expect, 2 => break ChildProcessMsg::Dbg, - n => panic!("invalid atomic value set by the child: {:#x}", n), + n => internal_error!("invalid atomic value set by the child: {:#x}", n), } } } @@ -815,7 +815,7 @@ pub fn expect_mono_module_to_dylib<'a>( if let Err(errors) = env.module.verify() { let path = std::env::temp_dir().join("test.ll"); env.module.print_to_file(&path).unwrap(); - panic!( + internal_error!( "Errors defining module:\n{}\n\nUncomment things nearby to see more details. IR written to `{:?}`", errors.to_string(), path, ); From c1d4a18c004c541f7424cbf51f179227b5c58368 Mon Sep 17 00:00:00 2001 From: eiei114 Date: Sun, 25 Jun 2023 17:50:05 +0900 Subject: [PATCH 061/140] Revert "replace" This reverts commit f43e3468976acb31b6951a88a97f8e2041bd45da. --- Cargo.lock | 1174 +++++++++++++++----------------- crates/repl_cli/Cargo.toml | 1 - crates/repl_cli/src/cli_gen.rs | 8 +- crates/repl_expect/src/lib.rs | 5 +- crates/repl_expect/src/run.rs | 10 +- 5 files changed, 548 insertions(+), 650 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6abfd2f068c..fec98114852 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "ab_glyph" -version = "0.2.21" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5110f1c78cf582855d895ecd0746b653db010cec6d9f5575293f27934d980a39" +checksum = "fe21446ad43aa56417a767f3e2f3d7c4ca522904de1dd640529a76e9c5c3b33c" dependencies = [ "ab_glyph_rasterizer", "owned_ttf_parser", @@ -57,9 +57,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.2" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] @@ -88,55 +88,6 @@ dependencies = [ "alloc-no-stdlib", ] -[[package]] -name = "anstream" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is-terminal", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" - -[[package]] -name = "anstyle-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" -dependencies = [ - "windows-sys 0.48.0", -] - -[[package]] -name = "anstyle-wincon" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" -dependencies = [ - "anstyle", - "windows-sys 0.48.0", -] - [[package]] name = "approx" version = "0.4.0" @@ -164,9 +115,9 @@ dependencies = [ [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" [[package]] name = "arrayvec" @@ -176,9 +127,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" [[package]] name = "as-slice" @@ -195,7 +146,7 @@ version = "0.34.0+1.2.203" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0f780da53d0063880d45554306489f09dd8d1bda47688b4a57bc579119356df" dependencies = [ - "libloading 0.7.4", + "libloading", ] [[package]] @@ -225,7 +176,7 @@ dependencies = [ "cc", "cfg-if 1.0.0", "libc", - "miniz_oxide 0.6.2", + "miniz_oxide", "object", "rustc-demangle", ] @@ -238,9 +189,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.2" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" [[package]] name = "base64-url" @@ -281,6 +232,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487f1e0fcbe47deb8b0574e646def1c903389d95241dd1bbcc6ce4a715dfc0c1" + [[package]] name = "bitmaps" version = "2.1.0" @@ -304,12 +261,12 @@ dependencies = [ [[package]] name = "blake3" -version = "1.4.0" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729b71f35bd3fa1a4c86b85d32c8b9069ea7fe14f7a53cfabb65f62d4265b888" +checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef" dependencies = [ "arrayref", - "arrayvec 0.7.4", + "arrayvec 0.7.2", "cc", "cfg-if 1.0.0", "constant_time_eq", @@ -324,9 +281,9 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] name = "block-buffer" -version = "0.10.4" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ "generic-array", ] @@ -354,9 +311,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "bytemuck" @@ -369,13 +326,13 @@ dependencies = [ [[package]] name = "bytemuck_derive" -version = "1.4.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192" +checksum = "1aca418a974d83d40a0c1f0c5cba6ff4bc28d8df099109ca459a2118d40b6322" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] @@ -469,21 +426,21 @@ version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "bitflags", + "bitflags 1.3.2", "textwrap 0.11.0", "unicode-width", ] [[package]] name = "clap" -version = "3.2.25" +version = "3.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" dependencies = [ "atty", - "bitflags", + "bitflags 1.3.2", "clap_lex 0.2.4", - "indexmap 1.9.3", + "indexmap", "strsim", "termcolor", "textwrap 0.16.0", @@ -491,38 +448,30 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.8" +version = "4.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9394150f5b4273a1763355bd1c2ec54cc5a2593f790587bcd6b2c947cfa9211" +checksum = "42dfd32784433290c51d92c438bb72ea5063797fc3cc9a21a8c4346bebbb2098" dependencies = [ - "clap_builder", + "bitflags 2.0.2", "clap_derive", + "clap_lex 0.3.3", + "is-terminal", "once_cell", -] - -[[package]] -name = "clap_builder" -version = "4.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a78fbdd3cc2914ddf37ba444114bc7765bbdcb55ec9cbe6fa054f0137400717" -dependencies = [ - "anstream", - "anstyle", - "bitflags", - "clap_lex 0.5.0", "strsim", + "termcolor", ] [[package]] name = "clap_derive" -version = "4.3.2" +version = "4.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" +checksum = "fddf67631444a3a3e3e5ac51c36a5e01335302de677bd78759eaa90ab1f46644" dependencies = [ "heck", + "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] @@ -536,9 +485,12 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +checksum = "033f6b7a4acb1f358c742aaca805c939ee73b4c6209ae4318ec7aca81c42e646" +dependencies = [ + "os_str_bytes", +] [[package]] name = "cli_utils" @@ -584,7 +536,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "block", "cocoa-foundation", "core-foundation 0.9.3", @@ -596,11 +548,11 @@ dependencies = [ [[package]] name = "cocoa-foundation" -version = "0.1.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "931d3837c286f56e3c58423ce4eba12d08db2374461a785c86f672b08b5650d6" +checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" dependencies = [ - "bitflags", + "bitflags 1.3.2", "block", "core-foundation 0.9.3", "core-graphics-types", @@ -619,12 +571,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "colorchoice" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" - [[package]] name = "colored" version = "2.0.0" @@ -639,7 +585,7 @@ dependencies = [ [[package]] name = "confy" version = "0.5.1" -source = "git+https://github.com/rust-cli/confy#d5abd6cce9b936130832cfb4e1ed8afd7e1c488b" +source = "git+https://github.com/rust-cli/confy#700337e5a3fbc12f4f49fc9b7ce449b1b71040ee" dependencies = [ "directories", "serde", @@ -649,14 +595,14 @@ dependencies = [ [[package]] name = "console" -version = "0.15.7" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" dependencies = [ "encode_unicode 0.3.6", "lazy_static", "libc", - "windows-sys 0.45.0", + "windows-sys 0.42.0", ] [[package]] @@ -671,18 +617,18 @@ dependencies = [ [[package]] name = "const_format" -version = "0.2.31" +version = "0.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c990efc7a285731f9a4378d81aff2f0e85a2c8781a05ef0f8baa8dac54d0ff48" +checksum = "7309d9b4d3d2c0641e018d449232f2e28f1b22933c137f157d3dbc14228b8c0e" dependencies = [ "const_format_proc_macros", ] [[package]] name = "const_format_proc_macros" -version = "0.2.31" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e026b6ce194a874cb9cf32cd5772d1ef9767cc8fcb5765948d74f37a9d8b2bf6" +checksum = "d897f47bf7270cf70d370f8f98c1abb6d2d4cf60a6845d30e05bfb90c6568650" dependencies = [ "proc-macro2", "quote", @@ -691,9 +637,9 @@ dependencies = [ [[package]] name = "constant_time_eq" -version = "0.2.6" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" +checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279" [[package]] name = "copyless" @@ -731,7 +677,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ - "core-foundation-sys 0.8.4", + "core-foundation-sys 0.8.3", "libc", ] @@ -743,9 +689,9 @@ checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "core-graphics" @@ -753,7 +699,7 @@ version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation 0.7.0", "foreign-types", "libc", @@ -765,7 +711,7 @@ version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation 0.9.3", "core-graphics-types", "foreign-types", @@ -774,12 +720,13 @@ dependencies = [ [[package]] name = "core-graphics-types" -version = "0.1.2" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" +checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation 0.9.3", + "foreign-types", "libc", ] @@ -798,9 +745,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.8" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" dependencies = [ "libc", ] @@ -864,9 +811,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -885,14 +832,14 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" dependencies = [ "autocfg", "cfg-if 1.0.0", "crossbeam-utils", - "memoffset 0.9.0", + "memoffset 0.8.0", "scopeguard", ] @@ -908,9 +855,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" dependencies = [ "cfg-if 1.0.0", ] @@ -927,9 +874,9 @@ dependencies = [ [[package]] name = "csv" -version = "1.2.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086" +checksum = "0b015497079b9a9d69c02ad25de6c0a6edef051ea6360a327d0bd05802ef64ad" dependencies = [ "csv-core", "itoa", @@ -953,7 +900,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -964,11 +911,11 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" [[package]] name = "cvt" -version = "0.1.2" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ae9bf77fbf2d39ef573205d554d87e86c12f1994e9ea335b0651b9b278bcf1" +checksum = "34ac344c7efccb80cd25bc61b2170aec26f2f693fd40e765a539a1243db48c71" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 0.1.10", ] [[package]] @@ -977,8 +924,8 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2daefd788d1e96e0a9d66dee4b828b883509bc3ea9ce30665f04c3246372690c" dependencies = [ - "bitflags", - "libloading 0.7.4", + "bitflags 1.3.2", + "libloading", "winapi", ] @@ -1003,7 +950,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 1.0.109", + "syn", ] [[package]] @@ -1014,7 +961,7 @@ checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -1027,7 +974,7 @@ dependencies = [ "hashbrown 0.12.3", "lock_api", "once_cell", - "parking_lot_core 0.9.8", + "parking_lot_core 0.9.7", ] [[package]] @@ -1038,9 +985,9 @@ checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "digest" -version = "0.10.7" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer", "crypto-common", @@ -1113,11 +1060,11 @@ checksum = "6d9d8664cf849d7d0f3114a3a387d2f5e4303176d746d5a951aaddc66dfe9240" [[package]] name = "dlib" -version = "0.5.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" dependencies = [ - "libloading 0.8.0", + "libloading", ] [[package]] @@ -1134,9 +1081,9 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" [[package]] name = "dunce" -version = "1.0.4" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c" [[package]] name = "either" @@ -1182,20 +1129,25 @@ dependencies = [ ] [[package]] -name = "equivalent" -version = "1.0.0" +name = "errno" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] [[package]] name = "errno" -version = "0.3.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" dependencies = [ "errno-dragonfly", "libc", - "windows-sys 0.48.0", + "windows-sys 0.45.0", ] [[package]] @@ -1220,25 +1172,25 @@ dependencies = [ [[package]] name = "fd-lock" -version = "3.0.12" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ae6b3d9530211fb3b12a95374b8b0823be812f53d09e18c5675c0146b09642" +checksum = "8ef1a30ae415c3a691a4f41afddc2dbcd6d70baf338368d85ebc1e8ed92cedb9" dependencies = [ "cfg-if 1.0.0", - "rustix", - "windows-sys 0.48.0", + "rustix 0.36.9", + "windows-sys 0.45.0", ] [[package]] name = "filetime" -version = "0.2.21" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.2.16", - "windows-sys 0.48.0", + "redox_syscall", + "windows-sys 0.45.0", ] [[package]] @@ -1252,12 +1204,12 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.26" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ "crc32fast", - "miniz_oxide 0.7.1", + "miniz_oxide", ] [[package]] @@ -1283,25 +1235,26 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ "percent-encoding", ] [[package]] name = "fs_at" -version = "0.1.8" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15550ecca96ea332ec143fb450701074143b70d358e50b32b1f847ccff2e1cf7" +checksum = "ab60b097d8208fe02d24ae954c3248a9436f96edefa8f4b9fcb0f26d60d003a9" dependencies = [ "aligned", "cfg-if 1.0.0", "cvt", "libc", "nix 0.26.2", - "windows-sys 0.48.0", + "smart-default", + "windows-sys 0.45.0", ] [[package]] @@ -1318,9 +1271,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.28" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" dependencies = [ "futures-channel", "futures-core", @@ -1333,9 +1286,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -1343,15 +1296,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" dependencies = [ "futures-core", "futures-task", @@ -1360,38 +1313,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures-channel", "futures-core", @@ -1416,9 +1369,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", @@ -1436,9 +1389,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -1449,9 +1402,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.3" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" [[package]] name = "glow" @@ -1505,11 +1458,11 @@ dependencies = [ [[package]] name = "gpu-alloc" -version = "0.5.4" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22beaafc29b38204457ea030f6fb7a84c9e4dd1b86e311ba0542533453d87f62" +checksum = "7fc59e5f710e310e76e6707f86c561dd646f69a8876da9131703b2f717de818d" dependencies = [ - "bitflags", + "bitflags 1.3.2", "gpu-alloc-types", ] @@ -1519,7 +1472,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1528,7 +1481,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b0c02e1ba0bdb14e965058ca34e09c020f8e507a760df1121728e0aef68d57a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "gpu-descriptor-types", "hashbrown 0.12.3", ] @@ -1539,14 +1492,14 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "363e3677e55ad168fef68cf9de3a4a310b53124c5e784c53a1d70e92d23f2126" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] name = "h2" -version = "0.3.19" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" +checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d" dependencies = [ "bytes", "fnv", @@ -1554,7 +1507,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap", "slab", "tokio", "tokio-util", @@ -1586,12 +1539,6 @@ dependencies = [ "bumpalo", ] -[[package]] -name = "hashbrown" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" - [[package]] name = "heck" version = "0.4.1" @@ -1673,9 +1620,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.14.26" +version = "0.14.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" +checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" dependencies = [ "bytes", "futures-channel", @@ -1697,9 +1644,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.0" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7" +checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" dependencies = [ "http", "hyper", @@ -1710,9 +1657,9 @@ dependencies = [ [[package]] name = "iced-x86" -version = "1.19.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cc8d38244d84278262c8ebe6930cc44283d194cbabae2651f6112103802fb5" +checksum = "1dd04b950d75b3498320253b17fb92745b2cc79ead8814aede2f7c1bab858bec" dependencies = [ "lazy_static", ] @@ -1725,9 +1672,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.4.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -1763,24 +1710,14 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.3" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown 0.12.3", ] -[[package]] -name = "indexmap" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" -dependencies = [ - "equivalent", - "hashbrown 0.14.0", -] - [[package]] name = "indoc" version = "1.0.9" @@ -1807,7 +1744,7 @@ source = "git+https://github.com/roc-lang/inkwell?branch=inkwell-llvm-15#95a3a13 dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -1818,9 +1755,9 @@ checksum = "e567468c50f3d4bc7397702e09b380139f9b9288b4e909b070571007f8b5bf78" [[package]] name = "insta" -version = "1.30.0" +version = "1.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28491f7753051e5704d4d0ae7860d45fae3238d7d235bc4289dcd45c48d3cec3" +checksum = "fea5b3894afe466b4bcf0388630fc15e11938a6074af0cd637c825ba2ec8a099" dependencies = [ "console", "lazy_static", @@ -1843,31 +1780,30 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.11" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +checksum = "cfa919a82ea574332e2de6e74b4c36e74d41982b335080fa59d4ef31be20fdf3" dependencies = [ - "hermit-abi 0.3.1", "libc", - "windows-sys 0.48.0", + "windows-sys 0.45.0", ] [[package]] name = "ipnet" -version = "2.7.2" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" +checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" [[package]] name = "is-terminal" -version = "0.4.7" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +checksum = "256017f749ab3117e93acb91063009e1f1bb56d03965b14c2c8df4eb02c524d8" dependencies = [ "hermit-abi 0.3.1", "io-lifetimes", - "rustix", - "windows-sys 0.48.0", + "rustix 0.37.3", + "windows-sys 0.45.0", ] [[package]] @@ -1902,9 +1838,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] @@ -1926,7 +1862,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" dependencies = [ "libc", - "libloading 0.7.4", + "libloading", ] [[package]] @@ -1943,9 +1879,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.146" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libloading" @@ -1957,27 +1893,17 @@ dependencies = [ "winapi", ] -[[package]] -name = "libloading" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb" -dependencies = [ - "cfg-if 1.0.0", - "windows-sys 0.48.0", -] - [[package]] name = "libm" -version = "0.2.7" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] name = "libmimalloc-sys" -version = "0.1.33" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4ac0e912c8ef1b735e92369695618dc5b1819f5a7bf3f167301a3ba1cea515e" +checksum = "dd8c7cbf8b89019683667e347572e6d55a7df7ea36b0c4ce69961b0cde67b174" dependencies = [ "cc", "libc", @@ -1985,11 +1911,11 @@ dependencies = [ [[package]] name = "libtest-mimic" -version = "0.6.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d8de370f98a6cb8a4606618e53e802f93b094ddec0f96988eaec2c27e6e9ce7" +checksum = "d7b603516767d1ab23d0de09d023e62966c3322f7148297c35cf3d97aa8b37fa" dependencies = [ - "clap 4.3.8", + "clap 4.1.11", "termcolor", "threadpool", ] @@ -2002,15 +1928,21 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] +name = "linux-raw-sys" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" [[package]] name = "llvm-sys" -version = "130.1.1" +version = "130.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7d0f52cdf734a48a85e8de93ea3c8664264ed534dd519d4a64b19483e0fe709" +checksum = "b54ec4a457c4b55ffb2bd56ed44841161ae933fd4fe3dc379748fcd4193661d4" dependencies = [ "cc", "lazy_static", @@ -2021,9 +1953,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", @@ -2031,9 +1963,12 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if 1.0.0", +] [[package]] name = "mach_object" @@ -2041,7 +1976,7 @@ version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6f2d7176b94027af58085a2c9d27c4e416586caba409c314569213901d6068" dependencies = [ - "bitflags", + "bitflags 1.3.2", "byteorder", "lazy_static", "libc", @@ -2110,9 +2045,9 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.9.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" dependencies = [ "autocfg", ] @@ -2123,7 +2058,7 @@ version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0514f491f4cc03632ab399ee01e2c1c1b12d3e1cf2d667c1ff5f87d6dcd2084" dependencies = [ - "bitflags", + "bitflags 1.3.2", "block", "core-graphics-types", "foreign-types", @@ -2133,18 +2068,18 @@ dependencies = [ [[package]] name = "mimalloc" -version = "0.1.37" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e2894987a3459f3ffb755608bd82188f8ed00d0ae077f1edea29c068d639d98" +checksum = "9dcb174b18635f7561a0c6c9fc2ce57218ac7523cf72c50af80e2d79ab8f3ba1" dependencies = [ "libmimalloc-sys", ] [[package]] name = "mime" -version = "0.3.17" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "minimal-lexical" @@ -2161,25 +2096,16 @@ dependencies = [ "adler", ] -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - [[package]] name = "mio" -version = "0.8.8" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ "libc", "log", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.45.0", ] [[package]] @@ -2200,10 +2126,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3012f2dbcc79e8e0b5825a4836a7106a75dd9b2fe42c528163be0f572538c705" dependencies = [ "bit-set", - "bitflags", + "bitflags 1.3.2", "codespan-reporting", "hexf-parse", - "indexmap 1.9.3", + "indexmap", "log", "num-traits", "rustc-hash", @@ -2217,7 +2143,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d868f654c72e75f8687572699cdabe755f03effbb62542768e995d5b8d699d" dependencies = [ - "bitflags", + "bitflags 1.3.2", "jni-sys", "ndk-sys", "num_enum", @@ -2255,7 +2181,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -2279,7 +2205,7 @@ version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cc", "cfg-if 1.0.0", "libc", @@ -2292,7 +2218,7 @@ version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cc", "cfg-if 1.0.0", "libc", @@ -2305,7 +2231,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if 1.0.0", "libc", "memoffset 0.6.5", @@ -2317,7 +2243,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if 1.0.0", "libc", "static_assertions", @@ -2341,11 +2267,11 @@ checksum = "aeaf4ad7403de93e699c191202f017118df734d3850b01e13a3a8b2e6953d3c9" [[package]] name = "normpath" -version = "1.1.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec60c60a693226186f5d6edf073232bfb6464ed97eb22cf3b01c1e8198fd97f5" +checksum = "972dec05f98e7c787ede35d7a9ea4735eb7788c299287352757b3def6cc1f7b5" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.45.0", ] [[package]] @@ -2396,7 +2322,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -2440,22 +2366,22 @@ dependencies = [ [[package]] name = "object" -version = "0.30.4" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" dependencies = [ "crc32fast", "flate2", "hashbrown 0.13.2", - "indexmap 1.9.3", + "indexmap", "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "oorandom" @@ -2465,18 +2391,18 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "ordered-float" -version = "3.7.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fc2dbde8f8a79f2102cc474ceb0ad68e3b80b85289ea62389b60e66777e4213" +checksum = "d84eb1409416d254e4a9c8fa56cc24701755025b458f0fcd8e59e1f5f40c23bf" dependencies = [ "num-traits", ] [[package]] name = "os_str_bytes" -version = "6.5.1" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" [[package]] name = "output_vt100" @@ -2495,9 +2421,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "owned_ttf_parser" -version = "0.19.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "706de7e2214113d63a8238d1910463cfce781129a6f263d13fdb09ff64355ba4" +checksum = "e25e9fb15717794fae58ab55c26e044103aad13186fbb625893f9a3bbcc24228" dependencies = [ "ttf-parser", ] @@ -2521,7 +2447,7 @@ checksum = "9cd6706dfe50d53e0f6aa09e12c034c44faacd23e966ae5a209e8bdb8f179f98" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -2555,7 +2481,7 @@ dependencies = [ "find-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -2576,7 +2502,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.8", + "parking_lot_core 0.9.7", ] [[package]] @@ -2588,22 +2514,22 @@ dependencies = [ "cfg-if 1.0.0", "instant", "libc", - "redox_syscall 0.2.16", + "redox_syscall", "smallvec", "winapi", ] [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.3.5", + "redox_syscall", "smallvec", - "windows-targets 0.48.0", + "windows-sys 0.45.0", ] [[package]] @@ -2635,15 +2561,15 @@ checksum = "9fa00462b37ead6d11a82c9d568b26682d78e0477dc02d1966c013af80969739" [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.7.0" +version = "2.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73935e4d55e2abf7f130186537b19e7a4abc886a0252380b59248af473a3fc9" +checksum = "8cbd939b234e95d72bc393d51788aec68aeeb5d51e748ca08ff3aad58cb722f7" dependencies = [ "thiserror", "ucd-trie", @@ -2651,9 +2577,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.0" +version = "2.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef623c9bbfa0eedf5a0efba11a5ee83209c326653ca31ff019bec3a95bfff2b" +checksum = "a81186863f3d0a27340815be8f2078dd8050b14cd71913db9fbda795e5f707d7" dependencies = [ "pest", "pest_generator", @@ -2661,22 +2587,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.0" +version = "2.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e8cba4ec22bada7fc55ffe51e2deb6a0e0db2d0b7ab0b103acc80d2510c190" +checksum = "75a1ef20bf3193c15ac345acb32e26b3dc3223aff4d77ae4fc5359567683796b" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] name = "pest_meta" -version = "2.7.0" +version = "2.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01f71cb40bd8bb94232df14b946909e14660e33fc05db3e50ae2a82d7ea0ca0" +checksum = "5e3b284b1f13a20dc5ebc90aff59a51b8d7137c221131b52a7260c08cbc1cc80" dependencies = [ "once_cell", "pest", @@ -2685,9 +2611,9 @@ dependencies = [ [[package]] name = "phf" -version = "0.11.2" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" dependencies = [ "phf_macros", "phf_shared", @@ -2695,9 +2621,9 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.11.2" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" dependencies = [ "phf_shared", "rand", @@ -2705,22 +2631,22 @@ dependencies = [ [[package]] name = "phf_macros" -version = "0.11.2" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +checksum = "92aacdc5f16768709a569e913f7451034034178b05bdc8acda226659a3dccc66" dependencies = [ "phf_generator", "phf_shared", "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] name = "phf_shared" -version = "0.11.2" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" dependencies = [ "siphasher", ] @@ -2739,9 +2665,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "plotters" @@ -2757,15 +2683,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" dependencies = [ "plotters-backend", ] @@ -2798,36 +2724,61 @@ dependencies = [ "toml_edit", ] +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" -version = "1.0.63" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] [[package]] name = "profiling" -version = "1.0.8" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332cd62e95873ea4f41f3dfd6bbbfc5b52aec892d7e8d534197c4720a0bbbab2" +checksum = "74605f360ce573babfe43964cbe520294dcb081afbf8c108fc6e23036b4da2df" [[package]] name = "proptest" -version = "1.2.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" +checksum = "29f1b898011ce9595050a68e60f90bad083ff2987a695a42357134c8381fba70" dependencies = [ "bit-set", - "bitflags", + "bitflags 1.3.2", "byteorder", "lazy_static", "num-traits", + "quick-error 2.0.1", "rand", "rand_chacha", "rand_xorshift", - "regex-syntax 0.6.29", + "regex-syntax", "rusty-fork", "tempfile", "unarray", @@ -2835,11 +2786,11 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.9.3" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" +checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63" dependencies = [ - "bitflags", + "bitflags 1.3.2", "memchr", "unicase", ] @@ -2850,6 +2801,12 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quickcheck" version = "1.0.3" @@ -2869,14 +2826,14 @@ checksum = "b22a693222d716a9587786f37ac3f6b4faedb5b80c23914e7303ff5a1d8016e9" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] name = "quote" -version = "1.0.28" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] @@ -2988,16 +2945,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -3007,19 +2955,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ "getrandom", - "redox_syscall 0.2.16", + "redox_syscall", "thiserror", ] [[package]] name = "regex" -version = "1.8.4" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.2", + "regex-syntax", ] [[package]] @@ -3028,20 +2976,14 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ - "regex-syntax 0.6.29", + "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.7.2" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" @@ -3054,9 +2996,9 @@ dependencies = [ [[package]] name = "remove_dir_all" -version = "0.8.2" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23895cfadc1917fed9c6ed76a8c2903615fa3704f7493ff82b364c6540acc02b" +checksum = "7174320e07c29945955cedd70b865995b286847111c8308d349a1f3a9e3af555" dependencies = [ "aligned", "cfg-if 1.0.0", @@ -3090,11 +3032,11 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.18" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" dependencies = [ - "base64 0.21.2", + "base64 0.21.0", "bytes", "encoding_rs", "futures-core", @@ -3168,7 +3110,7 @@ dependencies = [ name = "roc_ast" version = "0.0.1" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.2", "bumpalo", "indoc", "libc", @@ -3220,7 +3162,7 @@ dependencies = [ "bumpalo", "indoc", "inkwell", - "libloading 0.7.4", + "libloading", "roc_bitcode", "roc_can", "roc_collections", @@ -3288,15 +3230,15 @@ name = "roc_cli" version = "0.0.1" dependencies = [ "bumpalo", - "clap 3.2.25", + "clap 3.2.23", "cli_utils", "const_format", "criterion", - "errno", + "errno 0.3.0", "indoc", "inkwell", "libc", - "libloading 0.7.4", + "libloading", "mimalloc", "parking_lot 0.12.1", "pretty_assertions", @@ -3369,7 +3311,7 @@ version = "0.0.1" name = "roc_constrain" version = "0.0.1" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.2", "roc_can", "roc_collections", "roc_error_macros", @@ -3439,7 +3381,7 @@ dependencies = [ name = "roc_docs_cli" version = "0.0.1" dependencies = [ - "clap 3.2.25", + "clap 3.2.23", "libc", "roc_docs", ] @@ -3448,7 +3390,7 @@ dependencies = [ name = "roc_editor" version = "0.0.1" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.2", "bumpalo", "bytemuck", "cgmath", @@ -3597,10 +3539,10 @@ dependencies = [ "cli_utils", "dircpy", "fnv", - "indexmap 1.9.3", + "indexmap", "indoc", "libc", - "libloading 0.7.4", + "libloading", "pretty_assertions", "roc_build", "roc_builtins", @@ -3834,11 +3776,10 @@ dependencies = [ "bumpalo", "const_format", "inkwell", - "libloading 0.7.4", + "libloading", "roc_build", "roc_builtins", "roc_collections", - "roc_error_macros", "roc_gen_llvm", "roc_load", "roc_module", @@ -3886,7 +3827,7 @@ dependencies = [ "indoc", "inkwell", "libc", - "libloading 0.7.4", + "libloading", "pretty_assertions", "roc_build", "roc_builtins", @@ -3980,7 +3921,7 @@ dependencies = [ name = "roc_solve" version = "0.0.1" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.2", "bumpalo", "indoc", "insta", @@ -4029,7 +3970,7 @@ dependencies = [ name = "roc_std" version = "0.0.1" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.2", "libc", "pretty_assertions", "quickcheck", @@ -4053,7 +3994,7 @@ name = "roc_test_utils" version = "0.0.1" dependencies = [ "pretty_assertions", - "remove_dir_all 0.8.2", + "remove_dir_all 0.8.1", ] [[package]] @@ -4084,7 +4025,7 @@ dependencies = [ name = "roc_unify" version = "0.0.1" dependencies = [ - "bitflags", + "bitflags 1.3.2", "roc_collections", "roc_debug_flags", "roc_error_macros", @@ -4099,7 +4040,7 @@ version = "0.0.1" dependencies = [ "bitvec", "bumpalo", - "clap 3.2.25", + "clap 3.2.23", "rand", "roc_wasm_module", ] @@ -4115,9 +4056,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" [[package]] name = "rustc-hash" @@ -4131,33 +4072,47 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.17", + "semver 1.0.16", +] + +[[package]] +name = "rustix" +version = "0.36.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd5c6ff11fecd55b40746d1995a02f2eb375bf8c00d192d521ee09f42bef37bc" +dependencies = [ + "bitflags 1.3.2", + "errno 0.2.8", + "io-lifetimes", + "libc", + "linux-raw-sys 0.1.4", + "windows-sys 0.45.0", ] [[package]] name = "rustix" -version = "0.37.20" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0" +checksum = "62b24138615de35e32031d041a09032ef3487a616d901ca4db224e7d557efae2" dependencies = [ - "bitflags", - "errno", + "bitflags 1.3.2", + "errno 0.3.0", "io-lifetimes", "libc", - "linux-raw-sys", - "windows-sys 0.48.0", + "linux-raw-sys 0.3.1", + "windows-sys 0.45.0", ] [[package]] name = "rustls" -version = "0.21.2" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e32ca28af694bc1bbf399c33a516dbdf1c90090b8ab23c2bc24f834aa2247f5f" +checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" dependencies = [ "log", "ring", - "rustls-webpki", "sct", + "webpki", ] [[package]] @@ -4166,17 +4121,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" dependencies = [ - "base64 0.21.2", -] - -[[package]] -name = "rustls-webpki" -version = "0.100.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" -dependencies = [ - "ring", - "untrusted", + "base64 0.21.0", ] [[package]] @@ -4192,7 +4137,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" dependencies = [ "fnv", - "quick-error", + "quick-error 1.2.3", "tempfile", "wait-timeout", ] @@ -4202,7 +4147,7 @@ name = "rustyline" version = "9.1.1" source = "git+https://github.com/roc-lang/rustyline?rev=e74333c#e74333c0d618896b88175bf06645108f996fe6d0" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if 1.0.0", "clipboard-win 4.5.0", "dirs-next", @@ -4226,7 +4171,7 @@ version = "0.6.0" source = "git+https://github.com/roc-lang/rustyline?rev=e74333c#e74333c0d618896b88175bf06645108f996fe6d0" dependencies = [ "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -4277,9 +4222,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" [[package]] name = "semver-parser" @@ -4292,9 +4237,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.164" +version = "1.0.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +checksum = "3a382c72b4ba118526e187430bb4963cd6d55051ebf13d9b25574d379cc98d20" dependencies = [ "serde_derive", ] @@ -4323,20 +4268,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.164" +version = "1.0.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +checksum = "1ef476a5790f0f6decbc66726b6e5d63680ed518283e64c7df415989d880954f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] name = "serde_json" -version = "1.0.99" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" +checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" dependencies = [ "itoa", "ryu", @@ -4361,7 +4306,7 @@ version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ - "indexmap 1.9.3", + "indexmap", "ryu", "serde", "yaml-rust", @@ -4389,14 +4334,14 @@ checksum = "079a83df15f85d89a68d64ae1238f142f172b1fa915d0d76b26a7cba1b659a69" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -4477,13 +4422,24 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "smart-default" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "smithay-client-toolkit" version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a28f16a97fa0e8ce563b2774d1e732dd5d4025d2772c5dba0a41a0f90a29da3" dependencies = [ - "bitflags", + "bitflags 1.3.2", "calloop", "dlib", "lazy_static", @@ -4502,7 +4458,7 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f307c47d32d2715eb2e0ece5589057820e0e5e70d07c247d1063e844e107f454" dependencies = [ - "bitflags", + "bitflags 1.3.2", "dlib", "lazy_static", "log", @@ -4544,7 +4500,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -4569,7 +4525,7 @@ version = "0.2.0+1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" dependencies = [ - "bitflags", + "bitflags 1.3.2", "num-traits", ] @@ -4625,14 +4581,14 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 1.0.109", + "syn", ] [[package]] name = "subtle" -version = "2.5.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" @@ -4645,17 +4601,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "syn" -version = "2.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "tap" version = "1.0.1" @@ -4675,9 +4620,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.8" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1c7f239eb94671427157bd93b3694320f3668d4e1eff08c7285366fd777fac" +checksum = "8ae9980cab1db3fceee2f6c6f643d5d8de2997c58ee8d25fb0cc8a9e9e7348e5" [[package]] name = "tempfile" @@ -4688,7 +4633,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "rand", - "redox_syscall 0.2.16", + "redox_syscall", "remove_dir_all 0.5.3", "winapi", ] @@ -4736,7 +4681,7 @@ dependencies = [ "inkwell", "lazy_static", "libc", - "libloading 0.7.4", + "libloading", "roc_bitcode", "roc_build", "roc_builtins", @@ -4794,7 +4739,7 @@ version = "0.0.1" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -4856,22 +4801,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] @@ -4895,9 +4840,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.22" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" +checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" dependencies = [ "itoa", "serde", @@ -4907,15 +4852,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" [[package]] name = "time-macros" -version = "0.2.9" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" dependencies = [ "time-core", ] @@ -4947,35 +4892,37 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.28.2" +version = "1.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" +checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64" dependencies = [ "autocfg", "bytes", "libc", + "memchr", "mio", "num_cpus", "pin-project-lite", "socket2", - "windows-sys 0.48.0", + "windows-sys 0.45.0", ] [[package]] name = "tokio-rustls" -version = "0.24.1" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" dependencies = [ "rustls", "tokio", + "webpki", ] [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" dependencies = [ "bytes", "futures-core", @@ -4996,17 +4943,17 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" [[package]] name = "toml_edit" -version = "0.19.11" +version = "0.19.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7" +checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825" dependencies = [ - "indexmap 2.0.0", + "indexmap", "toml_datetime", "winnow", ] @@ -5042,20 +4989,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", "valuable", @@ -5074,9 +5021,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" dependencies = [ "matchers", "nu-ansi-term", @@ -5098,9 +5045,9 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "ttf-parser" -version = "0.19.1" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a464a4b34948a5f67fddd2b823c62d9d92e44be75058b99939eae6c5b6960b33" +checksum = "0609f771ad9c6155384897e1df4d948e692667cc0588548b68eb44d052b27633" [[package]] name = "twox-hash" @@ -5175,15 +5122,15 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" [[package]] name = "unicode-normalization" @@ -5220,9 +5167,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.4.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", "idna", @@ -5237,15 +5184,15 @@ checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372" [[package]] name = "uuid" -version = "1.3.4" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa2982af2eec27de306107c027578ff7f423d65f7250e40ce0fea8f45248b81" +checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" dependencies = [ "getrandom", ] @@ -5285,7 +5232,7 @@ dependencies = [ name = "ven_pretty" version = "0.9.1-alpha.0" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.2", "termcolor", "typed-arena", ] @@ -5328,20 +5275,22 @@ dependencies = [ [[package]] name = "walkdir" -version = "2.3.3" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" dependencies = [ "same-file", + "winapi", "winapi-util", ] [[package]] name = "want" -version = "0.3.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" dependencies = [ + "log", "try-lock", ] @@ -5360,9 +5309,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -5370,24 +5319,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.22", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -5397,9 +5346,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5407,22 +5356,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "wayland-client" @@ -5430,7 +5379,7 @@ version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715" dependencies = [ - "bitflags", + "bitflags 1.3.2", "downcast-rs", "libc", "nix 0.24.3", @@ -5469,7 +5418,7 @@ version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" dependencies = [ - "bitflags", + "bitflags 1.3.2", "wayland-client", "wayland-commons", "wayland-scanner", @@ -5532,7 +5481,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b97cd781ff044d6d697b632a2e212032c2e957d1afaa21dbf58069cbb8f78567" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.2", "js-sys", "log", "naga", @@ -5553,8 +5502,8 @@ version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4688c000eb841ca55f7b35db659b78d6e1cd77d7caf8fb929f4e181f754047d" dependencies = [ - "arrayvec 0.7.4", - "bitflags", + "arrayvec 0.7.2", + "bitflags 1.3.2", "cfg_aliases", "codespan-reporting", "copyless", @@ -5576,10 +5525,10 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d684ea6a34974a2fc19f1dfd183d11a62e22d75c4f187a574bb1224df8e056c2" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.2", "ash", "bit-set", - "bitflags", + "bitflags 1.3.2", "block", "core-graphics-types", "d3d12", @@ -5591,7 +5540,7 @@ dependencies = [ "inplace_it", "js-sys", "khronos-egl", - "libloading 0.7.4", + "libloading", "log", "metal", "naga", @@ -5614,7 +5563,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "549533d9e1cdd4b4cda7718d33ff500fc4c34b5467b71d76b547ae0324f3b2a2" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -5671,135 +5620,84 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.45.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows-targets 0.42.2", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] name = "winit" @@ -5807,7 +5705,7 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b43cc931d58b99461188607efd7acb2a093e65fc621f54cad78517a6063e73a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cocoa", "core-foundation 0.9.3", "core-graphics 0.22.3", @@ -5836,9 +5734,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.4.7" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" +checksum = "ee7b2c67f962bf5042bfd8b6a916178df33a26eec343ae064cb8e069f638fa6f" dependencies = [ "memchr", ] @@ -5872,9 +5770,9 @@ dependencies = [ [[package]] name = "x11-clipboard" -version = "0.7.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "980b9aa9226c3b7de8e2adb11bf20124327c054e0e5812d2aac0b5b5a87e7464" +checksum = "0827f86aa910c4e73329a4f619deabe88ebb4b042370bf023c2d5d8b4eb54695" dependencies = [ "x11rb", ] @@ -5938,9 +5836,9 @@ checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" [[package]] name = "xml-rs" -version = "0.8.14" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52839dc911083a8ef63efa4d039d1f58b5e409f923e44c80828f206f66e5541c" +checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" [[package]] name = "yaml-rust" diff --git a/crates/repl_cli/Cargo.toml b/crates/repl_cli/Cargo.toml index 147b887b705..34db9dc2238 100644 --- a/crates/repl_cli/Cargo.toml +++ b/crates/repl_cli/Cargo.toml @@ -30,7 +30,6 @@ roc_reporting = { path = "../reporting" } roc_std = { path = "../roc_std" } roc_target = { path = "../compiler/roc_target" } roc_types = { path = "../compiler/types" } -roc_error_macros = { path = "../error_macros" } bumpalo.workspace = true const_format.workspace = true diff --git a/crates/repl_cli/src/cli_gen.rs b/crates/repl_cli/src/cli_gen.rs index 61beafb4ea3..8009f12cf7a 100644 --- a/crates/repl_cli/src/cli_gen.rs +++ b/crates/repl_cli/src/cli_gen.rs @@ -3,7 +3,6 @@ use inkwell::context::Context; use libloading::Library; use roc_build::link::llvm_module_to_dylib; use roc_collections::all::MutSet; -use roc_error_macros::internal_error; use roc_gen_llvm::llvm::build::LlvmBackendMode; use roc_gen_llvm::llvm::externs::add_default_roc_externs; use roc_gen_llvm::{run_jit_function, run_jit_function_dynamic_type}; @@ -264,7 +263,7 @@ fn mono_module_to_dylib<'a>( if main_fn.verify(true) { function_pass.run_on(&main_fn); } else { - internal_error!("Main function {} failed LLVM verification in build. Uncomment things nearby to see more details.", main_fn_name); + panic!("Main function {} failed LLVM verification in build. Uncomment things nearby to see more details.", main_fn_name); } module_pass.run_on(env.module); @@ -274,7 +273,10 @@ fn mono_module_to_dylib<'a>( // Verify the module if let Err(errors) = env.module.verify() { - internal_error!("Errors defining module:\n{}", errors.to_string()); + panic!( + "Errors defining module:\n{}\n\nUncomment things nearby to see more details.", + errors.to_string() + ); } llvm_module_to_dylib(env.module, &target, opt_level) diff --git a/crates/repl_expect/src/lib.rs b/crates/repl_expect/src/lib.rs index 9332a2a3913..1d399b7efec 100644 --- a/crates/repl_expect/src/lib.rs +++ b/crates/repl_expect/src/lib.rs @@ -93,7 +93,6 @@ pub fn get_values<'a>( mod test { use indoc::indoc; use pretty_assertions::assert_eq; - use roc_error_macros::internal_error; use roc_gen_llvm::{llvm::build::LlvmBackendMode, run_roc::RocCallResult, run_roc_dylib}; use roc_load::{ExecutionMode, LoadConfig, LoadMonomorphizedError, Threading}; use roc_packaging::cache::RocCacheDir; @@ -137,9 +136,9 @@ mod test { ) { Ok(m) => m, Err(LoadMonomorphizedError::ErrorModule(m)) => { - internal_error!("{:?}", (m.can_problems, m.type_problems)) + panic!("{:?}", (m.can_problems, m.type_problems)) } - Err(e) => internal_error!("{e:?}"), + Err(e) => panic!("{e:?}"), }; let mut loaded = loaded; diff --git a/crates/repl_expect/src/run.rs b/crates/repl_expect/src/run.rs index 385a6f6df06..0c8846906ea 100644 --- a/crates/repl_expect/src/run.rs +++ b/crates/repl_expect/src/run.rs @@ -327,7 +327,7 @@ fn run_expect_fx<'a, W: std::io::Write>( try_run_jit_function!(lib, expect.name, (), |v: ()| v); if let Err((msg, _)) = result { - internal_error!("roc panic {}", msg); + panic!("roc panic {}", msg); } if sequence.count_failures() > 0 { @@ -518,7 +518,7 @@ fn render_dbg_failure<'a>( let data = expectations.get_mut(&module_id).unwrap(); let current = match data.dbgs.get(&dbg_symbol) { - None => internal_error!("region {failure_region:?} not in list of dbgs"), + None => panic!("region {failure_region:?} not in list of dbgs"), Some(current) => current, }; let failure_region = current.region; @@ -565,7 +565,7 @@ fn render_expect_failure<'a>( let data = expectations.get_mut(&module_id).unwrap(); let current = match data.expectations.get(&failure_region) { - None => internal_error!("region {failure_region:?} not in list of expects"), + None => panic!("region {failure_region:?} not in list of expects"), Some(current) => current, }; @@ -638,7 +638,7 @@ impl ExpectSequence { 0 => std::hint::spin_loop(), 1 => break ChildProcessMsg::Expect, 2 => break ChildProcessMsg::Dbg, - n => internal_error!("invalid atomic value set by the child: {:#x}", n), + n => panic!("invalid atomic value set by the child: {:#x}", n), } } } @@ -815,7 +815,7 @@ pub fn expect_mono_module_to_dylib<'a>( if let Err(errors) = env.module.verify() { let path = std::env::temp_dir().join("test.ll"); env.module.print_to_file(&path).unwrap(); - internal_error!( + panic!( "Errors defining module:\n{}\n\nUncomment things nearby to see more details. IR written to `{:?}`", errors.to_string(), path, ); From 486558396f9730799b08517e57b757143fe8d6df Mon Sep 17 00:00:00 2001 From: eiei114 Date: Sun, 25 Jun 2023 18:13:44 +0900 Subject: [PATCH 062/140] replace panic --- crates/repl_cli/Cargo.toml | 1 + crates/repl_cli/src/cli_gen.rs | 8 +++----- crates/repl_expect/src/lib.rs | 5 +++-- crates/repl_expect/src/run.rs | 10 +++++----- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/crates/repl_cli/Cargo.toml b/crates/repl_cli/Cargo.toml index 34db9dc2238..147b887b705 100644 --- a/crates/repl_cli/Cargo.toml +++ b/crates/repl_cli/Cargo.toml @@ -30,6 +30,7 @@ roc_reporting = { path = "../reporting" } roc_std = { path = "../roc_std" } roc_target = { path = "../compiler/roc_target" } roc_types = { path = "../compiler/types" } +roc_error_macros = { path = "../error_macros" } bumpalo.workspace = true const_format.workspace = true diff --git a/crates/repl_cli/src/cli_gen.rs b/crates/repl_cli/src/cli_gen.rs index 8009f12cf7a..61beafb4ea3 100644 --- a/crates/repl_cli/src/cli_gen.rs +++ b/crates/repl_cli/src/cli_gen.rs @@ -3,6 +3,7 @@ use inkwell::context::Context; use libloading::Library; use roc_build::link::llvm_module_to_dylib; use roc_collections::all::MutSet; +use roc_error_macros::internal_error; use roc_gen_llvm::llvm::build::LlvmBackendMode; use roc_gen_llvm::llvm::externs::add_default_roc_externs; use roc_gen_llvm::{run_jit_function, run_jit_function_dynamic_type}; @@ -263,7 +264,7 @@ fn mono_module_to_dylib<'a>( if main_fn.verify(true) { function_pass.run_on(&main_fn); } else { - panic!("Main function {} failed LLVM verification in build. Uncomment things nearby to see more details.", main_fn_name); + internal_error!("Main function {} failed LLVM verification in build. Uncomment things nearby to see more details.", main_fn_name); } module_pass.run_on(env.module); @@ -273,10 +274,7 @@ fn mono_module_to_dylib<'a>( // Verify the module if let Err(errors) = env.module.verify() { - panic!( - "Errors defining module:\n{}\n\nUncomment things nearby to see more details.", - errors.to_string() - ); + internal_error!("Errors defining module:\n{}", errors.to_string()); } llvm_module_to_dylib(env.module, &target, opt_level) diff --git a/crates/repl_expect/src/lib.rs b/crates/repl_expect/src/lib.rs index 1d399b7efec..9332a2a3913 100644 --- a/crates/repl_expect/src/lib.rs +++ b/crates/repl_expect/src/lib.rs @@ -93,6 +93,7 @@ pub fn get_values<'a>( mod test { use indoc::indoc; use pretty_assertions::assert_eq; + use roc_error_macros::internal_error; use roc_gen_llvm::{llvm::build::LlvmBackendMode, run_roc::RocCallResult, run_roc_dylib}; use roc_load::{ExecutionMode, LoadConfig, LoadMonomorphizedError, Threading}; use roc_packaging::cache::RocCacheDir; @@ -136,9 +137,9 @@ mod test { ) { Ok(m) => m, Err(LoadMonomorphizedError::ErrorModule(m)) => { - panic!("{:?}", (m.can_problems, m.type_problems)) + internal_error!("{:?}", (m.can_problems, m.type_problems)) } - Err(e) => panic!("{e:?}"), + Err(e) => internal_error!("{e:?}"), }; let mut loaded = loaded; diff --git a/crates/repl_expect/src/run.rs b/crates/repl_expect/src/run.rs index 0c8846906ea..385a6f6df06 100644 --- a/crates/repl_expect/src/run.rs +++ b/crates/repl_expect/src/run.rs @@ -327,7 +327,7 @@ fn run_expect_fx<'a, W: std::io::Write>( try_run_jit_function!(lib, expect.name, (), |v: ()| v); if let Err((msg, _)) = result { - panic!("roc panic {}", msg); + internal_error!("roc panic {}", msg); } if sequence.count_failures() > 0 { @@ -518,7 +518,7 @@ fn render_dbg_failure<'a>( let data = expectations.get_mut(&module_id).unwrap(); let current = match data.dbgs.get(&dbg_symbol) { - None => panic!("region {failure_region:?} not in list of dbgs"), + None => internal_error!("region {failure_region:?} not in list of dbgs"), Some(current) => current, }; let failure_region = current.region; @@ -565,7 +565,7 @@ fn render_expect_failure<'a>( let data = expectations.get_mut(&module_id).unwrap(); let current = match data.expectations.get(&failure_region) { - None => panic!("region {failure_region:?} not in list of expects"), + None => internal_error!("region {failure_region:?} not in list of expects"), Some(current) => current, }; @@ -638,7 +638,7 @@ impl ExpectSequence { 0 => std::hint::spin_loop(), 1 => break ChildProcessMsg::Expect, 2 => break ChildProcessMsg::Dbg, - n => panic!("invalid atomic value set by the child: {:#x}", n), + n => internal_error!("invalid atomic value set by the child: {:#x}", n), } } } @@ -815,7 +815,7 @@ pub fn expect_mono_module_to_dylib<'a>( if let Err(errors) = env.module.verify() { let path = std::env::temp_dir().join("test.ll"); env.module.print_to_file(&path).unwrap(); - panic!( + internal_error!( "Errors defining module:\n{}\n\nUncomment things nearby to see more details. IR written to `{:?}`", errors.to_string(), path, ); From 69a67aca36affb9d1fe299fff46a3729680d031d Mon Sep 17 00:00:00 2001 From: KekmaTime <136650032+KekmaTime@users.noreply.github.com> Date: Sun, 25 Jun 2023 19:24:09 +0530 Subject: [PATCH 063/140] added-paragraph --- www/public/repl/index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/www/public/repl/index.html b/www/public/repl/index.html index b71fc2c87b7..b09591ec860 100644 --- a/www/public/repl/index.html +++ b/www/public/repl/index.html @@ -33,6 +33,7 @@

The rockin' Roc REPL

> +

This web REPL misses some features that are available in the CLI (roc repl) like defining variables without a final expression, which will result in the "Missing Final Expression" error.

From 4c77358b3630bf01926f2f6b292b65c9cbd49a8b Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Sun, 25 Jun 2023 17:27:02 +0200 Subject: [PATCH 064/140] link docs to overview it used to be necessary to link to a specific module page but a module overview page was recently added Signed-off-by: Anton-4 <17049058+Anton-4@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1887ea37ec7..d701a872935 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Roc is not ready for a 0.1 release yet, but we do have: - [**installation** guide](https://github.com/roc-lang/roc/tree/main/getting_started) - [**tutorial**](https://roc-lang.org/tutorial) -- [**docs** for the standard library](https://www.roc-lang.org/builtins/Str) +- [**docs** for the standard library](https://www.roc-lang.org/builtins) - [**examples**](https://github.com/roc-lang/examples/tree/main/examples) - [frequently asked questions](https://github.com/roc-lang/roc/blob/main/FAQ.md) - [Group chat](https://roc.zulipchat.com) for help, questions and discussions From 419f5a4f6a1211c154d03a63943073aff5c3550c Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Sun, 25 Jun 2023 19:39:52 +0200 Subject: [PATCH 065/140] add warning icon This helps grab the attention. Signed-off-by: Anton-4 <17049058+Anton-4@users.noreply.github.com> --- www/public/repl/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/public/repl/index.html b/www/public/repl/index.html index b09591ec860..fdb8c971a65 100644 --- a/www/public/repl/index.html +++ b/www/public/repl/index.html @@ -33,7 +33,7 @@

The rockin' Roc REPL

> -

This web REPL misses some features that are available in the CLI (roc repl) like defining variables without a final expression, which will result in the "Missing Final Expression" error.

+

⚠️ This web REPL misses some features that are available in the CLI (roc repl) like defining variables without a final expression, which will result in the "Missing Final Expression" error.

From 74ed31c5a98bcc67358e182b3d00afa30db1c55d Mon Sep 17 00:00:00 2001 From: NoaVidovic Date: Sun, 25 Jun 2023 22:09:56 +0200 Subject: [PATCH 066/140] Fix typo in tutorial.md The first example of an app module header included `provides main to pf` instead of the correct `provides [main] to pf` Signed-off-by: NoaVidovic --- www/generate_tutorial/src/input/tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/generate_tutorial/src/input/tutorial.md b/www/generate_tutorial/src/input/tutorial.md index 90e43fad064..42b8ed547f9 100644 --- a/www/generate_tutorial/src/input/tutorial.md +++ b/www/generate_tutorial/src/input/tutorial.md @@ -1373,7 +1373,7 @@ Let's take a closer look at the part of `main.roc` above the `main` def: app "hello" packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.3.2/tE4xS_zLdmmxmHwHih9kHWQ7fsXtJr7W7h3425-eZFk.tar.br" } imports [pf.Stdout] - provides main to pf + provides [main] to pf ``` This is known as a _module header_. Every `.roc` file is a _module_, and there are different types of modules. We know this particular one is an _application module_ because it begins with the `app` keyword. From 416d8e21b07a060e869f66fb72ba9d746d259a5e Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 26 Jun 2023 09:45:33 -0400 Subject: [PATCH 067/140] Have RustGlue bundle roc_std --- crates/glue/src/RustGlue.roc | 33 ++++++++++++++++++++++++++++++--- crates/glue/static/Cargo.toml | 8 ++++++++ crates/roc_std/Cargo.toml | 3 +-- 3 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 crates/glue/static/Cargo.toml diff --git a/crates/glue/src/RustGlue.roc b/crates/glue/src/RustGlue.roc index 5e3fcc71089..2e6dc6c91dd 100644 --- a/crates/glue/src/RustGlue.roc +++ b/crates/glue/src/RustGlue.roc @@ -1,6 +1,17 @@ app "rust-glue" packages { pf: "../platform/main.roc" } - imports [pf.Types.{ Types }, pf.Shape.{ Shape, RocFn }, pf.File.{ File }, pf.TypeId.{ TypeId }] + imports [ + pf.Types.{ Types }, pf.Shape.{ Shape, RocFn }, pf.File.{ File }, pf.TypeId.{ TypeId }, + "../static/Cargo.toml" as rocAppCargoToml : Str, + "../../roc_std/Cargo.toml" as rocStdCargoToml : Str, + "../../roc_std/src/lib.rs" as rocStdLib : Str, + "../../roc_std/src/roc_box.rs" as rocStdBox : Str, + "../../roc_std/src/roc_list.rs" as rocStdList : Str, + "../../roc_std/src/roc_dict.rs" as rocStdDict : Str, + "../../roc_std/src/roc_set.rs" as rocStdSet : Str, + "../../roc_std/src/roc_str.rs" as rocStdStr : Str, + "../../roc_std/src/storage.rs" as rocStdStorage : Str, + ] provides [makeGlue] to pf makeGlue : List Types -> Result (List File) Str @@ -22,9 +33,25 @@ makeGlue = \typesByArch -> typesByArch |> List.map convertTypesToFile - |> List.append { name: "mod.rs", content: modFileContent } + |> List.append { name: "roc_app/src/lib.rs", content: modFileContent } + |> List.concat staticFiles |> Ok +## These are always included, and don't depend on the specifices of the app. +staticFiles : List File +staticFiles = + [ + { name: "roc_app/Cargo.toml", content: rocAppCargoToml }, + { name: "roc_std/Cargo.toml", content: rocStdCargoToml }, + { name: "roc_std/src/lib.rs", content: rocStdLib }, + { name: "roc_std/src/roc_box.rs", content: rocStdBox }, + { name: "roc_std/src/roc_list.rs", content: rocStdList }, + { name: "roc_std/src/roc_dict.rs", content: rocStdDict }, + { name: "roc_std/src/roc_set.rs", content: rocStdSet }, + { name: "roc_std/src/roc_str.rs", content: rocStdStr }, + { name: "roc_std/src/storage.rs", content: rocStdStorage }, + ] + convertTypesToFile : Types -> File convertTypesToFile = \types -> content = @@ -94,7 +121,7 @@ convertTypesToFile = \types -> archStr = archName arch { - name: "\(archStr).rs", + name: "roc_app/src/\(archStr).rs", content: content |> generateEntryPoints types, } diff --git a/crates/glue/static/Cargo.toml b/crates/glue/static/Cargo.toml new file mode 100644 index 00000000000..ff900959690 --- /dev/null +++ b/crates/glue/static/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "roc_app" +description = "This was generated by `roc glue`. It provides glue between a specific Roc platform and a Rust host." +version = "1.0.0" +edition = "2021" + +[dependencies] +roc_std = { path = "../roc_std" } diff --git a/crates/roc_std/Cargo.toml b/crates/roc_std/Cargo.toml index 8c7b41cb9df..8318bdad415 100644 --- a/crates/roc_std/Cargo.toml +++ b/crates/roc_std/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "roc_std" description = "Rust representations of Roc data structures" -readme = "README.md" authors = ["The Roc Contributors"] edition = "2021" @@ -26,4 +25,4 @@ serde = ["dep:serde"] std = [] [package.metadata.cargo-udeps.ignore] -development = ["quickcheck_macros", "serde_json"] \ No newline at end of file +development = ["quickcheck_macros", "serde_json"] From ff4d47f2934ef2c6ae90522735b94f57ea0d4f7e Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 26 Jun 2023 14:49:46 -0400 Subject: [PATCH 068/140] Fix typo --- crates/glue/src/RustGlue.roc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/glue/src/RustGlue.roc b/crates/glue/src/RustGlue.roc index 2e6dc6c91dd..0a862eb7ab8 100644 --- a/crates/glue/src/RustGlue.roc +++ b/crates/glue/src/RustGlue.roc @@ -37,7 +37,7 @@ makeGlue = \typesByArch -> |> List.concat staticFiles |> Ok -## These are always included, and don't depend on the specifices of the app. +## These are always included, and don't depend on the specifics of the app. staticFiles : List File staticFiles = [ From abaed603261673b820e62df4bc83f83c6de71ff9 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 26 Jun 2023 15:54:26 -0400 Subject: [PATCH 069/140] Improve debug_assert message --- crates/glue/src/types.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/glue/src/types.rs b/crates/glue/src/types.rs index d5b6b79fd84..1f7fde4239b 100644 --- a/crates/glue/src/types.rs +++ b/crates/glue/src/types.rs @@ -2229,7 +2229,13 @@ fn single_tag_payload_fields<'a, 'b>( env.glue_procs_by_layout.get(&layout).is_some(), env.layout_cache .interner - .has_varying_stack_size(in_layout, env.arena) + .has_varying_stack_size(in_layout, env.arena), + "glue_procs_by_layout for {:?} was {:?}, but the layout cache said its has_varying_stack_size was {}", + &layout, + env.glue_procs_by_layout.get(&layout), + env.layout_cache + .interner + .has_varying_stack_size(in_layout, env.arena) ); let (tag_name, payload_vars) = single_tag_payload(union_tags, subs); From 28591da79ad6618d02e36bcbf03268d39e0655e3 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 26 Jun 2023 16:28:10 -0400 Subject: [PATCH 070/140] Update glue tests --- .../tests/fixture-templates/rust/Cargo.toml | 3 ++- .../advanced-recursive-union/src/lib.rs | 5 ++--- crates/glue/tests/fixtures/arguments/src/lib.rs | 4 ++-- .../glue/tests/fixtures/basic-record/src/lib.rs | 4 ++-- .../fixtures/basic-recursive-union/src/lib.rs | 11 ++--------- .../glue/tests/fixtures/enumeration/src/lib.rs | 8 ++++---- .../fixtures/list-recursive-union/src/lib.rs | 17 +++-------------- .../tests/fixtures/multiple-modules/src/lib.rs | 5 ++--- .../tests/fixtures/nested-record/src/lib.rs | 4 ++-- .../fixtures/nonnullable-unwrapped/src/lib.rs | 4 ++-- .../fixtures/nullable-unwrapped/src/lib.rs | 11 +++-------- .../tests/fixtures/nullable-wrapped/src/lib.rs | 6 +++--- crates/glue/tests/fixtures/option/src/lib.rs | 6 +++--- .../tests/fixtures/return-function/src/lib.rs | 4 ++-- crates/glue/tests/fixtures/rocresult/src/lib.rs | 6 +++--- .../tests/fixtures/single-tag-union/src/lib.rs | 6 +++--- .../fixtures/union-with-padding/src/lib.rs | 6 +++--- .../fixtures/union-without-padding/src/lib.rs | 14 +++++++------- crates/glue/tests/test_glue_cli.rs | 2 +- 19 files changed, 51 insertions(+), 75 deletions(-) diff --git a/crates/glue/tests/fixture-templates/rust/Cargo.toml b/crates/glue/tests/fixture-templates/rust/Cargo.toml index 9697079aa5a..56f73f42ff6 100644 --- a/crates/glue/tests/fixture-templates/rust/Cargo.toml +++ b/crates/glue/tests/fixture-templates/rust/Cargo.toml @@ -27,7 +27,8 @@ name = "host" path = "src/main.rs" [dependencies] -roc_std = { path = "../../../../roc_std" } +roc_std = { path = "test_glue/roc_std" } +roc_app = { path = "test_glue/roc_app" } libc = "0.2" indoc = "1.0.6" diff --git a/crates/glue/tests/fixtures/advanced-recursive-union/src/lib.rs b/crates/glue/tests/fixtures/advanced-recursive-union/src/lib.rs index e5c6e0c71f8..85af141dcbd 100644 --- a/crates/glue/tests/fixtures/advanced-recursive-union/src/lib.rs +++ b/crates/glue/tests/fixtures/advanced-recursive-union/src/lib.rs @@ -1,14 +1,13 @@ -mod test_glue; +use roc_app; use indoc::indoc; -// use test_glue::Rbt; #[no_mangle] pub extern "C" fn rust_main() -> i32 { use std::cmp::Ordering; use std::collections::hash_set::HashSet; - let tag_union = test_glue::mainForHost(()); + let tag_union = roc_app::mainForHost(()); // Verify that it has all the expected traits. diff --git a/crates/glue/tests/fixtures/arguments/src/lib.rs b/crates/glue/tests/fixtures/arguments/src/lib.rs index e20cb959598..9b5d52ac9b3 100644 --- a/crates/glue/tests/fixtures/arguments/src/lib.rs +++ b/crates/glue/tests/fixtures/arguments/src/lib.rs @@ -1,8 +1,8 @@ -mod test_glue; +use roc_app; #[no_mangle] pub extern "C" fn rust_main() -> i32 { - let answer = test_glue::mainForHost(42i64); + let answer = roc_app::mainForHost(42i64); println!("Answer was: {:?}", answer); // Debug diff --git a/crates/glue/tests/fixtures/basic-record/src/lib.rs b/crates/glue/tests/fixtures/basic-record/src/lib.rs index 4adf2de4c6f..d5cc2ea1e0b 100644 --- a/crates/glue/tests/fixtures/basic-record/src/lib.rs +++ b/crates/glue/tests/fixtures/basic-record/src/lib.rs @@ -1,11 +1,11 @@ -mod test_glue; +use roc_app; #[no_mangle] pub extern "C" fn rust_main() -> i32 { use std::cmp::Ordering; use std::collections::hash_set::HashSet; - let record = test_glue::mainForHost(); + let record = roc_app::mainForHost(); // Verify that the record has all the expected traits. diff --git a/crates/glue/tests/fixtures/basic-recursive-union/src/lib.rs b/crates/glue/tests/fixtures/basic-recursive-union/src/lib.rs index 299f9c802c6..ff0293bf68d 100644 --- a/crates/glue/tests/fixtures/basic-recursive-union/src/lib.rs +++ b/crates/glue/tests/fixtures/basic-recursive-union/src/lib.rs @@ -1,19 +1,12 @@ -mod test_glue; - use indoc::indoc; -use test_glue::Expr; - -extern "C" { - #[link_name = "roc__mainForHost_1_exposed_generic"] - fn roc_main(_: *mut Expr); -} +use roc_app::{self, Expr}; #[no_mangle] pub extern "C" fn rust_main() -> i32 { use std::cmp::Ordering; use std::collections::hash_set::HashSet; - let tag_union = test_glue::mainForHost(()); + let tag_union = roc_app::mainForHost(()); // Verify that it has all the expected traits. diff --git a/crates/glue/tests/fixtures/enumeration/src/lib.rs b/crates/glue/tests/fixtures/enumeration/src/lib.rs index 395b1296433..59704b6be9c 100644 --- a/crates/glue/tests/fixtures/enumeration/src/lib.rs +++ b/crates/glue/tests/fixtures/enumeration/src/lib.rs @@ -1,11 +1,11 @@ -mod test_glue; +use roc_app; #[no_mangle] pub extern "C" fn rust_main() -> i32 { use std::cmp::Ordering; use std::collections::hash_set::HashSet; - let tag_union = test_glue::mainForHost(); + let tag_union = roc_app::mainForHost(); // Verify that it has all the expected traits. @@ -28,8 +28,8 @@ pub extern "C" fn rust_main() -> i32 { println!( "tag_union was: {:?}, Bar is: {:?}, Baz is: {:?}", tag_union, - test_glue::MyEnum::Bar, - test_glue::MyEnum::Baz, + roc_app::MyEnum::Bar, + roc_app::MyEnum::Baz, ); // Debug // Exit code diff --git a/crates/glue/tests/fixtures/list-recursive-union/src/lib.rs b/crates/glue/tests/fixtures/list-recursive-union/src/lib.rs index e494b94e25b..0b598c19d93 100644 --- a/crates/glue/tests/fixtures/list-recursive-union/src/lib.rs +++ b/crates/glue/tests/fixtures/list-recursive-union/src/lib.rs @@ -1,25 +1,14 @@ -mod test_glue; +use roc_app; use indoc::indoc; -use test_glue::Rbt; - -extern "C" { - #[link_name = "roc__mainForHost_1_exposed_generic"] - fn roc_main(_: *mut Rbt); -} +use roc_app::Rbt; #[no_mangle] pub extern "C" fn rust_main() -> i32 { use std::cmp::Ordering; use std::collections::hash_set::HashSet; - let tag_union = unsafe { - let mut ret: core::mem::MaybeUninit = core::mem::MaybeUninit::uninit(); - - roc_main(ret.as_mut_ptr()); - - ret.assume_init() - }; + let tag_union = roc_app::mainForHost(); // Verify that it has all the expected traits. diff --git a/crates/glue/tests/fixtures/multiple-modules/src/lib.rs b/crates/glue/tests/fixtures/multiple-modules/src/lib.rs index 74c44d6f528..e26415e7101 100644 --- a/crates/glue/tests/fixtures/multiple-modules/src/lib.rs +++ b/crates/glue/tests/fixtures/multiple-modules/src/lib.rs @@ -1,13 +1,12 @@ -mod test_glue; - use indoc::indoc; +use roc_app; #[no_mangle] pub extern "C" fn rust_main() -> i32 { use std::cmp::Ordering; use std::collections::hash_set::HashSet; - let tag_union = test_glue::mainForHost(); + let tag_union = roc_app::mainForHost(); // Verify that it has all the expected traits. diff --git a/crates/glue/tests/fixtures/nested-record/src/lib.rs b/crates/glue/tests/fixtures/nested-record/src/lib.rs index 161b103780b..92deb035b25 100644 --- a/crates/glue/tests/fixtures/nested-record/src/lib.rs +++ b/crates/glue/tests/fixtures/nested-record/src/lib.rs @@ -1,10 +1,10 @@ -mod test_glue; +use roc_app; #[no_mangle] pub extern "C" fn rust_main() -> i32 { use std::cmp::Ordering; - let outer = test_glue::mainForHost(); + let outer = roc_app::mainForHost(); // Verify that `inner` has all the expected traits. { diff --git a/crates/glue/tests/fixtures/nonnullable-unwrapped/src/lib.rs b/crates/glue/tests/fixtures/nonnullable-unwrapped/src/lib.rs index ed7286e47ae..fcae9742c22 100644 --- a/crates/glue/tests/fixtures/nonnullable-unwrapped/src/lib.rs +++ b/crates/glue/tests/fixtures/nonnullable-unwrapped/src/lib.rs @@ -1,8 +1,8 @@ -mod test_glue; +use roc_app; use indoc::indoc; +use roc_app::StrRoseTree; use roc_std::{RocList, RocStr}; -use test_glue::StrRoseTree; extern "C" { #[link_name = "roc__mainForHost_1_exposed_generic"] diff --git a/crates/glue/tests/fixtures/nullable-unwrapped/src/lib.rs b/crates/glue/tests/fixtures/nullable-unwrapped/src/lib.rs index 22ece28b599..db461e6339f 100644 --- a/crates/glue/tests/fixtures/nullable-unwrapped/src/lib.rs +++ b/crates/glue/tests/fixtures/nullable-unwrapped/src/lib.rs @@ -1,19 +1,14 @@ -mod test_glue; +use roc_app; use indoc::indoc; -use test_glue::StrConsList; - -extern "C" { - #[link_name = "roc__mainForHost_1_exposed_generic"] - fn roc_main(_: *mut StrConsList); -} +use roc_app::StrConsList; #[no_mangle] pub extern "C" fn rust_main() -> i32 { use std::cmp::Ordering; use std::collections::hash_set::HashSet; - let tag_union = test_glue::mainForHost(()); + let tag_union = roc_app::mainForHost(()); // Verify that it has all the expected traits. diff --git a/crates/glue/tests/fixtures/nullable-wrapped/src/lib.rs b/crates/glue/tests/fixtures/nullable-wrapped/src/lib.rs index 8a288f4d304..7cb25db13be 100644 --- a/crates/glue/tests/fixtures/nullable-wrapped/src/lib.rs +++ b/crates/glue/tests/fixtures/nullable-wrapped/src/lib.rs @@ -1,8 +1,8 @@ -mod test_glue; +use roc_app; use indoc::indoc; +use roc_app::StrFingerTree; use roc_std::RocStr; -use test_glue::StrFingerTree; extern "C" { #[link_name = "roc__mainForHost_1_exposed_generic"] @@ -14,7 +14,7 @@ pub extern "C" fn rust_main() -> i32 { use std::cmp::Ordering; use std::collections::hash_set::HashSet; - let tag_union = test_glue::mainForHost(()); + let tag_union = roc_app::mainForHost(()); // Eq assert!(StrFingerTree::Empty() == StrFingerTree::Empty()); diff --git a/crates/glue/tests/fixtures/option/src/lib.rs b/crates/glue/tests/fixtures/option/src/lib.rs index 697013032c6..3f7ee45b88e 100644 --- a/crates/glue/tests/fixtures/option/src/lib.rs +++ b/crates/glue/tests/fixtures/option/src/lib.rs @@ -1,11 +1,11 @@ -mod test_glue; +use roc_app; #[no_mangle] pub extern "C" fn rust_main() -> i32 { - let string = test_glue::mainForHost(true); + let string = roc_app::mainForHost(true); println!("Answer was: {:?}", string.unwrap_Some()); // Debug // - let integer = test_glue::mainForHost(false); + let integer = roc_app::mainForHost(false); println!("Answer was: {:?}", integer.discriminant()); // Debug // Exit code diff --git a/crates/glue/tests/fixtures/return-function/src/lib.rs b/crates/glue/tests/fixtures/return-function/src/lib.rs index fad8f088059..396bed19b2e 100644 --- a/crates/glue/tests/fixtures/return-function/src/lib.rs +++ b/crates/glue/tests/fixtures/return-function/src/lib.rs @@ -1,8 +1,8 @@ -mod test_glue; +use roc_app; #[no_mangle] pub extern "C" fn rust_main() -> i32 { - let record = test_glue::mainForHost(); + let record = roc_app::mainForHost(); let answer1 = record.f.force_thunk(42i64, 1); let answer2 = record.g.force_thunk(42i64, 1); diff --git a/crates/glue/tests/fixtures/rocresult/src/lib.rs b/crates/glue/tests/fixtures/rocresult/src/lib.rs index dad518783b5..e07fbee768e 100644 --- a/crates/glue/tests/fixtures/rocresult/src/lib.rs +++ b/crates/glue/tests/fixtures/rocresult/src/lib.rs @@ -1,11 +1,11 @@ -mod test_glue; +use roc_app; #[no_mangle] pub extern "C" fn rust_main() -> i32 { - let string = test_glue::mainForHost(true); + let string = roc_app::mainForHost(true); println!("Answer was: {:?}", string); // Debug // - let integer = test_glue::mainForHost(false); + let integer = roc_app::mainForHost(false); println!("Answer was: {:?}", integer); // Debug // Exit code diff --git a/crates/glue/tests/fixtures/single-tag-union/src/lib.rs b/crates/glue/tests/fixtures/single-tag-union/src/lib.rs index a5b8aa1e3e9..cc2e1ae01da 100644 --- a/crates/glue/tests/fixtures/single-tag-union/src/lib.rs +++ b/crates/glue/tests/fixtures/single-tag-union/src/lib.rs @@ -1,14 +1,14 @@ -mod test_glue; +use roc_app; use indoc::indoc; -use test_glue::SingleTagUnion; +use roc_app::SingleTagUnion; #[no_mangle] pub extern "C" fn rust_main() -> i32 { use std::cmp::Ordering; use std::collections::hash_set::HashSet; - let tag_union = test_glue::mainForHost(); + let tag_union = roc_app::mainForHost(); // Verify that it has all the expected traits. diff --git a/crates/glue/tests/fixtures/union-with-padding/src/lib.rs b/crates/glue/tests/fixtures/union-with-padding/src/lib.rs index 31f209efa99..0c22b185fbe 100644 --- a/crates/glue/tests/fixtures/union-with-padding/src/lib.rs +++ b/crates/glue/tests/fixtures/union-with-padding/src/lib.rs @@ -1,6 +1,6 @@ -mod test_glue; +use roc_app; -use test_glue::NonRecursive; +use roc_app::NonRecursive; extern "C" { #[link_name = "roc__mainForHost_1_exposed_generic"] @@ -12,7 +12,7 @@ pub extern "C" fn rust_main() -> i32 { use std::cmp::Ordering; use std::collections::hash_set::HashSet; - let tag_union = test_glue::mainForHost(()); + let tag_union = roc_app::mainForHost(()); // Verify that it has all the expected traits. diff --git a/crates/glue/tests/fixtures/union-without-padding/src/lib.rs b/crates/glue/tests/fixtures/union-without-padding/src/lib.rs index 6e5bbb2a2f1..e4fb9a53047 100644 --- a/crates/glue/tests/fixtures/union-without-padding/src/lib.rs +++ b/crates/glue/tests/fixtures/union-without-padding/src/lib.rs @@ -1,8 +1,8 @@ -mod test_glue; +use roc_app; extern "C" { #[link_name = "roc__mainForHost_1_exposed_generic"] - fn roc_main(_: *mut test_glue::NonRecursive); + fn roc_main(_: *mut roc_app::NonRecursive); } #[no_mangle] @@ -10,7 +10,7 @@ pub extern "C" fn rust_main() -> i32 { use std::cmp::Ordering; use std::collections::hash_set::HashSet; - let tag_union = test_glue::mainForHost(()); + let tag_union = roc_app::mainForHost(()); // Verify that it has all the expected traits. @@ -23,10 +23,10 @@ pub extern "C" fn rust_main() -> i32 { println!( "tag_union was: {:?}\n`Foo \"small str\"` is: {:?}\n`Bar 123` is: {:?}\n`Baz` is: {:?}\n`Blah 456` is: {:?}", tag_union, - test_glue::NonRecursive::Foo("small str".into()), - test_glue::NonRecursive::Bar(123), - test_glue::NonRecursive::Baz(), - test_glue::NonRecursive::Blah(456), + roc_app::NonRecursive::Foo("small str".into()), + roc_app::NonRecursive::Bar(123), + roc_app::NonRecursive::Baz(), + roc_app::NonRecursive::Blah(456), ); // Debug let mut set = HashSet::new(); diff --git a/crates/glue/tests/test_glue_cli.rs b/crates/glue/tests/test_glue_cli.rs index f61189f033e..c1f54d1aa93 100644 --- a/crates/glue/tests/test_glue_cli.rs +++ b/crates/glue/tests/test_glue_cli.rs @@ -173,7 +173,7 @@ mod glue_cli_run { args: I, ) -> Out { let platform_module_path = platform_dir.join("platform.roc"); - let glue_dir = platform_dir.join("src").join("test_glue"); + let glue_dir = platform_dir.join("test_glue"); let fixture_templates_dir = platform_dir .parent() .unwrap() From fb17e57f7c87de9fb8d9ffc0a50705276809e000 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 26 Jun 2023 16:30:19 -0400 Subject: [PATCH 071/140] Mark disciminant enums as pub in RustGlue --- crates/glue/src/RustGlue.roc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/glue/src/RustGlue.roc b/crates/glue/src/RustGlue.roc index 0a862eb7ab8..66ef96d1db4 100644 --- a/crates/glue/src/RustGlue.roc +++ b/crates/glue/src/RustGlue.roc @@ -1315,7 +1315,7 @@ generateNullableUnwrapped = \buf, types, tagUnionid, name, nullTag, nonNullTag, FirstTagIsNull -> """ #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] - enum discriminant_\(name) { + pub enum discriminant_\(name) { \(nullTag) = 0, \(nonNullTag) = 1, } @@ -1324,7 +1324,7 @@ generateNullableUnwrapped = \buf, types, tagUnionid, name, nullTag, nonNullTag, SecondTagIsNull -> """ #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] - enum discriminant_\(name) { + pub enum discriminant_\(name) { \(nonNullTag) = 0, \(nullTag) = 1, } From 0af548a66f73a20962cb2badf8c24d324f666375 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 26 Jun 2023 16:30:33 -0400 Subject: [PATCH 072/140] Drop unnecessary thunk (plus it's not FFI-safe) --- crates/glue/tests/fixtures/nullable-unwrapped/platform.roc | 4 ++-- crates/glue/tests/fixtures/nullable-unwrapped/src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/glue/tests/fixtures/nullable-unwrapped/platform.roc b/crates/glue/tests/fixtures/nullable-unwrapped/platform.roc index c5e54d6f594..13992876507 100644 --- a/crates/glue/tests/fixtures/nullable-unwrapped/platform.roc +++ b/crates/glue/tests/fixtures/nullable-unwrapped/platform.roc @@ -7,5 +7,5 @@ platform "test-platform" StrConsList : [Nil, Cons Str StrConsList] -mainForHost : {} -> StrConsList -mainForHost = \{} -> main +mainForHost : StrConsList +mainForHost = main diff --git a/crates/glue/tests/fixtures/nullable-unwrapped/src/lib.rs b/crates/glue/tests/fixtures/nullable-unwrapped/src/lib.rs index db461e6339f..f2bf716c7fd 100644 --- a/crates/glue/tests/fixtures/nullable-unwrapped/src/lib.rs +++ b/crates/glue/tests/fixtures/nullable-unwrapped/src/lib.rs @@ -8,7 +8,7 @@ pub extern "C" fn rust_main() -> i32 { use std::cmp::Ordering; use std::collections::hash_set::HashSet; - let tag_union = roc_app::mainForHost(()); + let tag_union = roc_app::mainForHost(); // Verify that it has all the expected traits. From 8738c95d6f80115f17cd9551a4c6534141c19039 Mon Sep 17 00:00:00 2001 From: Folkert Date: Mon, 26 Jun 2023 23:51:26 +0200 Subject: [PATCH 073/140] give `0` as a value to our enum attributes --- crates/compiler/build/src/program.rs | 2 +- crates/compiler/gen_llvm/src/llvm/bitcode.rs | 8 ++++---- crates/compiler/gen_llvm/src/llvm/build.rs | 4 ++-- crates/compiler/gen_llvm/src/llvm/lowlevel.rs | 6 +++--- crates/compiler/test_gen/src/helpers/llvm.rs | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/compiler/build/src/program.rs b/crates/compiler/build/src/program.rs index 09f8123f261..6b183d093f6 100644 --- a/crates/compiler/build/src/program.rs +++ b/crates/compiler/build/src/program.rs @@ -166,7 +166,7 @@ fn gen_from_mono_module_llvm<'a>( let kind_id = Attribute::get_named_enum_kind_id("alwaysinline"); debug_assert!(kind_id > 0); - let enum_attr = context.create_enum_attribute(kind_id, 1); + let enum_attr = context.create_enum_attribute(kind_id, 0); for function in module.get_functions() { let name = function.get_name().to_str().unwrap(); diff --git a/crates/compiler/gen_llvm/src/llvm/bitcode.rs b/crates/compiler/gen_llvm/src/llvm/bitcode.rs index 4762076da89..64dac3814e0 100644 --- a/crates/compiler/gen_llvm/src/llvm/bitcode.rs +++ b/crates/compiler/gen_llvm/src/llvm/bitcode.rs @@ -225,7 +225,7 @@ fn build_transform_caller_help<'a, 'ctx>( let kind_id = Attribute::get_named_enum_kind_id("alwaysinline"); debug_assert!(kind_id > 0); - let attr = env.context.create_enum_attribute(kind_id, 1); + let attr = env.context.create_enum_attribute(kind_id, 0); function_value.add_attribute(AttributeLoc::Function, attr); let entry = env.context.append_basic_block(function_value, "entry"); @@ -408,7 +408,7 @@ fn build_rc_wrapper<'a, 'ctx>( let kind_id = Attribute::get_named_enum_kind_id("alwaysinline"); debug_assert!(kind_id > 0); - let attr = env.context.create_enum_attribute(kind_id, 1); + let attr = env.context.create_enum_attribute(kind_id, 0); function_value.add_attribute(AttributeLoc::Function, attr); let entry = env.context.append_basic_block(function_value, "entry"); @@ -497,7 +497,7 @@ pub fn build_eq_wrapper<'a, 'ctx>( let kind_id = Attribute::get_named_enum_kind_id("alwaysinline"); debug_assert!(kind_id > 0); - let attr = env.context.create_enum_attribute(kind_id, 1); + let attr = env.context.create_enum_attribute(kind_id, 0); function_value.add_attribute(AttributeLoc::Function, attr); let entry = env.context.append_basic_block(function_value, "entry"); @@ -598,7 +598,7 @@ pub fn build_compare_wrapper<'a, 'ctx>( let kind_id = Attribute::get_named_enum_kind_id("alwaysinline"); debug_assert!(kind_id > 0); - let attr = env.context.create_enum_attribute(kind_id, 1); + let attr = env.context.create_enum_attribute(kind_id, 0); function_value.add_attribute(AttributeLoc::Function, attr); let entry = env.context.append_basic_block(function_value, "entry"); diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 38a06b4dac7..4d9cf61b795 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -5207,14 +5207,14 @@ fn build_proc_header<'a, 'ctx>( if false { let kind_id = Attribute::get_named_enum_kind_id("alwaysinline"); debug_assert!(kind_id > 0); - let enum_attr = env.context.create_enum_attribute(kind_id, 1); + let enum_attr = env.context.create_enum_attribute(kind_id, 0); fn_val.add_attribute(AttributeLoc::Function, enum_attr); } if false { let kind_id = Attribute::get_named_enum_kind_id("noinline"); debug_assert!(kind_id > 0); - let enum_attr = env.context.create_enum_attribute(kind_id, 1); + let enum_attr = env.context.create_enum_attribute(kind_id, 0); fn_val.add_attribute(AttributeLoc::Function, enum_attr); } diff --git a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs index 63a9a15e740..285f4b929a8 100644 --- a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs +++ b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs @@ -1844,19 +1844,19 @@ fn throw_because_overflow<'ctx>(env: &Env<'_, 'ctx, '_>, message: &str) { // prevent inlining of this function let kind_id = Attribute::get_named_enum_kind_id("noinline"); debug_assert!(kind_id > 0); - let enum_attr = env.context.create_enum_attribute(kind_id, 1); + let enum_attr = env.context.create_enum_attribute(kind_id, 0); function_value.add_attribute(AttributeLoc::Function, enum_attr); // calling this function is unlikely let kind_id = Attribute::get_named_enum_kind_id("cold"); debug_assert!(kind_id > 0); - let enum_attr = env.context.create_enum_attribute(kind_id, 1); + let enum_attr = env.context.create_enum_attribute(kind_id, 0); function_value.add_attribute(AttributeLoc::Function, enum_attr); // this function never returns let kind_id = Attribute::get_named_enum_kind_id("noreturn"); debug_assert!(kind_id > 0); - let enum_attr = env.context.create_enum_attribute(kind_id, 1); + let enum_attr = env.context.create_enum_attribute(kind_id, 0); function_value.add_attribute(AttributeLoc::Function, enum_attr); // Add a basic block for the entry point diff --git a/crates/compiler/test_gen/src/helpers/llvm.rs b/crates/compiler/test_gen/src/helpers/llvm.rs index 2ec40d96245..6ad7cc29a37 100644 --- a/crates/compiler/test_gen/src/helpers/llvm.rs +++ b/crates/compiler/test_gen/src/helpers/llvm.rs @@ -192,7 +192,7 @@ fn create_llvm_module<'a>( let kind_id = Attribute::get_named_enum_kind_id("alwaysinline"); debug_assert!(kind_id > 0); - let attr = context.create_enum_attribute(kind_id, 1); + let attr = context.create_enum_attribute(kind_id, 0); for function in module.get_functions() { let name = function.get_name().to_str().unwrap(); From 7311c565f17c98c92cd03b4a4fa40ac17391e7cb Mon Sep 17 00:00:00 2001 From: Folkert Date: Mon, 26 Jun 2023 23:54:03 +0200 Subject: [PATCH 074/140] use updated llvm type signatures --- crates/compiler/gen_llvm/src/llvm/build.rs | 25 ++++++++----- crates/compiler/gen_llvm/src/llvm/struct_.rs | 37 ++++++++++---------- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 4d9cf61b795..3870d5ba388 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -1941,8 +1941,12 @@ fn tag_pointer_set_tag_id<'ctx>( // NOTE: assumes the lower bits of `cast_pointer` are all 0 let indexed_pointer = unsafe { - env.builder - .build_in_bounds_gep(cast_pointer, &[tag_id_intval], "indexed_pointer") + env.builder.new_build_in_bounds_gep( + env.context.i8_type(), + cast_pointer, + &[tag_id_intval], + "indexed_pointer", + ) }; env.builder @@ -1994,7 +1998,14 @@ pub fn tag_pointer_clear_tag_id<'ctx>( "cast_to_i8_ptr", ); - let indexed_pointer = unsafe { env.builder.build_gep(cast_pointer, &[index], "new_ptr") }; + let indexed_pointer = unsafe { + env.builder.new_build_in_bounds_gep( + env.context.i8_type(), + cast_pointer, + &[index], + "new_ptr", + ) + }; env.builder .build_pointer_cast(indexed_pointer, pointer.get_type(), "cast_from_i8_ptr") @@ -3954,11 +3965,9 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx>( arguments_for_call.push(*arg); } else { match layout_interner.get_repr(*layout) { - LayoutRepr::Builtin(Builtin::List(_)) => { - let list_type = arg_type - .into_pointer_type() - .get_element_type() - .into_struct_type(); + repr @ LayoutRepr::Builtin(Builtin::List(_)) => { + let list_type = basic_type_from_layout(env, layout_interner, repr); + let loaded = env.builder.new_build_load( list_type, arg.into_pointer_value(), diff --git a/crates/compiler/gen_llvm/src/llvm/struct_.rs b/crates/compiler/gen_llvm/src/llvm/struct_.rs index 30da7eb55e0..64226445868 100644 --- a/crates/compiler/gen_llvm/src/llvm/struct_.rs +++ b/crates/compiler/gen_llvm/src/llvm/struct_.rs @@ -92,7 +92,15 @@ impl<'ctx> RocStruct<'ctx> { index_struct_value(env, layout_interner, field_layouts, *argument, index) } (Self::ByReference(ptr), LayoutRepr::Struct(field_layouts)) => { - index_struct_ptr(env, layout_interner, field_layouts, *ptr, index) + let struct_type = basic_type_from_layout(env, layout_interner, struct_layout); + index_struct_ptr( + env, + layout_interner, + struct_type.into_struct_type(), + field_layouts, + *ptr, + index, + ) } (other, layout) => { unreachable!( @@ -135,26 +143,26 @@ fn index_struct_value<'a, 'ctx>( fn index_struct_ptr<'a, 'ctx>( env: &Env<'a, 'ctx, '_>, layout_interner: &STLayoutInterner<'a>, + struct_type: StructType<'ctx>, field_layouts: &[InLayout<'a>], ptr: PointerValue<'ctx>, index: u64, ) -> BasicValueEnum<'ctx> { debug_assert!(!field_layouts.is_empty()); - let field_value = get_field_from_ptr( - env, - ptr, - index as _, - env.arena - .alloc(format!("struct_field_access_record_{}", index)), - ); - let field_layout = field_layouts[index as usize]; + let field_repr = layout_interner.get_repr(field_layout); + + let name = format!("struct_field_access_record_{}", index); + let field_value = env + .builder + .new_build_struct_gep(struct_type, ptr, index as u32, &name) + .unwrap(); load_roc_value( env, layout_interner, - layout_interner.get_repr(field_layout), + field_repr, field_value, "struct_field", ) @@ -171,15 +179,6 @@ fn get_field_from_value<'ctx>( .unwrap() } -fn get_field_from_ptr<'ctx>( - env: &Env<'_, 'ctx, '_>, - ptr: PointerValue<'ctx>, - index: u32, - name: &str, -) -> PointerValue<'ctx> { - env.builder.build_struct_gep(ptr, index, name).unwrap() -} - struct BuildStruct<'ctx> { struct_type: StructType<'ctx>, struct_val: StructValue<'ctx>, From 7c9c3d829cf10ad02ee90527809f7bb435dfc330 Mon Sep 17 00:00:00 2001 From: Folkert Date: Tue, 27 Jun 2023 00:37:09 +0200 Subject: [PATCH 075/140] use 32-bit GEP indices where easily possible --- crates/compiler/gen_llvm/src/llvm/build.rs | 17 +++++++++++------ .../compiler/gen_llvm/src/llvm/refcounting.rs | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 3870d5ba388..6bcae600c44 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -1931,7 +1931,7 @@ fn tag_pointer_set_tag_id<'ctx>( // we only have 3 bits, so can encode only 0..7 (or on 32-bit targets, 2 bits to encode 0..3) debug_assert!((tag_id as u32) < env.target_info.ptr_width() as u32); - let tag_id_intval = env.ptr_int().const_int(tag_id as u64, false); + let tag_id_intval = env.context.i32_type().const_int(tag_id as u64, false); let cast_pointer = env.builder.build_pointer_cast( pointer, @@ -1991,6 +1991,9 @@ pub fn tag_pointer_clear_tag_id<'ctx>( let current_tag_id = env.builder.build_and(as_int, mask, "masked"); let index = env.builder.build_int_neg(current_tag_id, "index"); + let index = env + .builder + .build_int_cast(index, env.context.i32_type(), "to_i32"); let cast_pointer = env.builder.build_pointer_cast( pointer, @@ -2444,8 +2447,9 @@ fn list_literal<'a, 'ctx>( // all elements are constants, so we can use the memory in the constants section directly // here we make a pointer to the first actual element (skipping the 0 bytes that // represent the refcount) - let zero = env.ptr_int().const_zero(); - let offset = env.ptr_int().const_int(zero_elements as _, false); + let i32_type = env.context.i32_type(); + let zero = i32_type.const_zero(); + let offset = i32_type.const_int(zero_elements as _, false); let ptr = unsafe { env.builder.new_build_in_bounds_gep( @@ -2474,7 +2478,7 @@ fn list_literal<'a, 'ctx>( // then replace the `undef`s with the values that we evaluate at runtime for (index, val) in runtime_evaluated_elements { - let index_val = ctx.i64_type().const_int(index as u64, false); + let index_val = ctx.i32_type().const_int(index as u64, false); let elem_ptr = unsafe { builder.new_build_in_bounds_gep(element_type, ptr, &[index_val], "index") }; @@ -2495,7 +2499,7 @@ fn list_literal<'a, 'ctx>( } ListLiteralElement::Symbol(symbol) => scope.load_symbol(symbol), }; - let index_val = ctx.i64_type().const_int(index as u64, false); + let index_val = ctx.i32_type().const_int(index as u64, false); let elem_ptr = unsafe { builder.new_build_in_bounds_gep(element_type, ptr, &[index_val], "index") }; @@ -6259,7 +6263,8 @@ fn define_global_str_literal_ptr<'ctx>( env.context.i8_type(), ptr, &[env - .ptr_int() + .context + .i32_type() .const_int(env.target_info.ptr_width() as u64, false)], "get_rc_ptr", ) diff --git a/crates/compiler/gen_llvm/src/llvm/refcounting.rs b/crates/compiler/gen_llvm/src/llvm/refcounting.rs index 06f9e73bf1e..6d03fa54c29 100644 --- a/crates/compiler/gen_llvm/src/llvm/refcounting.rs +++ b/crates/compiler/gen_llvm/src/llvm/refcounting.rs @@ -61,7 +61,7 @@ impl<'ctx> PointerToRefcount<'ctx> { builder.build_pointer_cast(data_ptr, refcount_ptr_type, "as_usize_ptr"); // get a pointer to index -1 - let index_intvalue = refcount_type.const_int(-1_i64 as u64, false); + let index_intvalue = env.context.i32_type().const_int(-1_i64 as u64, false); let refcount_ptr = unsafe { builder.new_build_in_bounds_gep( env.ptr_int(), From ca0de5241d7aff7e0ec173bd1b8166315dff5ceb Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 26 Jun 2023 19:35:40 -0400 Subject: [PATCH 076/140] Remove some unnecessary dbg! uses --- crates/ast/src/solve_type.rs | 5 ++++- examples/glue/rust-platform/src/lib.rs | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/ast/src/solve_type.rs b/crates/ast/src/solve_type.rs index 90e562ad2a0..96873f37f9a 100644 --- a/crates/ast/src/solve_type.rs +++ b/crates/ast/src/solve_type.rs @@ -606,7 +606,10 @@ fn solve<'a>( let result = offenders.len(); if result > 0 { - dbg!(&subs, &offenders, &let_con.def_types); + eprintln!( + "subs: {:?}\n\noffenders: {:?}\n\nlet_con.def_types: {:?}\n", + &subs, &offenders, &let_con.def_types + ); } result diff --git a/examples/glue/rust-platform/src/lib.rs b/examples/glue/rust-platform/src/lib.rs index a91550458b1..fe5398b6475 100644 --- a/examples/glue/rust-platform/src/lib.rs +++ b/examples/glue/rust-platform/src/lib.rs @@ -87,7 +87,7 @@ pub extern "C" fn rust_main() -> i32 { let mut op: Op = roc_main(); loop { - match dbg!(op.discriminant()) { + match op.discriminant() { StdoutWrite => { let stdout_write = op.get_StdoutWrite(); let output: RocStr = stdout_write.f0; From b26ef289b62d2c4ca4896997d8cecf51ce57237b Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 26 Jun 2023 19:38:58 -0400 Subject: [PATCH 077/140] Add basic webserver platform --- examples/webserver/.gitignore | 2 + examples/webserver/Http.roc | 4 + examples/webserver/HttpInternal.roc | 4 + examples/webserver/build.sh | 2 + examples/webserver/main.roc | 6 ++ examples/webserver/platform/Cargo.toml | 38 +++++++ examples/webserver/platform/build.rs | 9 ++ examples/webserver/platform/host.c | 14 +++ examples/webserver/platform/main.roc | 9 ++ examples/webserver/platform/src/lib.rs | 128 ++++++++++++++++++++++++ examples/webserver/platform/src/main.rs | 3 + 11 files changed, 219 insertions(+) create mode 100644 examples/webserver/.gitignore create mode 100644 examples/webserver/Http.roc create mode 100644 examples/webserver/HttpInternal.roc create mode 100755 examples/webserver/build.sh create mode 100644 examples/webserver/main.roc create mode 100644 examples/webserver/platform/Cargo.toml create mode 100644 examples/webserver/platform/build.rs create mode 100644 examples/webserver/platform/host.c create mode 100644 examples/webserver/platform/main.roc create mode 100644 examples/webserver/platform/src/lib.rs create mode 100644 examples/webserver/platform/src/main.rs diff --git a/examples/webserver/.gitignore b/examples/webserver/.gitignore new file mode 100644 index 00000000000..d0e2c82835f --- /dev/null +++ b/examples/webserver/.gitignore @@ -0,0 +1,2 @@ +platform/glue +app diff --git a/examples/webserver/Http.roc b/examples/webserver/Http.roc new file mode 100644 index 00000000000..bdb8a14eba3 --- /dev/null +++ b/examples/webserver/Http.roc @@ -0,0 +1,4 @@ +interface Http exposes [request] imports [HttpInternal] + +request : Str -> Str +request = \req -> HttpInternal.request req diff --git a/examples/webserver/HttpInternal.roc b/examples/webserver/HttpInternal.roc new file mode 100644 index 00000000000..0201a2d2723 --- /dev/null +++ b/examples/webserver/HttpInternal.roc @@ -0,0 +1,4 @@ +interface HttpInternal exposes [request] imports [] + +request : Str -> Str +request = \req -> req diff --git a/examples/webserver/build.sh b/examples/webserver/build.sh new file mode 100755 index 00000000000..46790466f83 --- /dev/null +++ b/examples/webserver/build.sh @@ -0,0 +1,2 @@ +roc glue ../../crates/glue/src/RustGlue.roc platform/glue platform/main.roc +roc build diff --git a/examples/webserver/main.roc b/examples/webserver/main.roc new file mode 100644 index 00000000000..d5660386553 --- /dev/null +++ b/examples/webserver/main.roc @@ -0,0 +1,6 @@ +app "app" + packages { pf: "platform/main.roc" } + imports [] + provides [main] to pf + +main = \str -> "hi, \(str)!!" diff --git a/examples/webserver/platform/Cargo.toml b/examples/webserver/platform/Cargo.toml new file mode 100644 index 00000000000..29062b4c73f --- /dev/null +++ b/examples/webserver/platform/Cargo.toml @@ -0,0 +1,38 @@ +# ⚠️ READ THIS BEFORE MODIFYING THIS FILE! ⚠️ +# +# This file is a fixture template. If the file you're looking at is +# in the fixture-templates/ directory, then you're all set - go ahead +# and modify it, and it will modify all the fixture tests. +# +# If this file is in the fixtures/ directory, on the other hand, then +# it is gitignored and will be overwritten the next time tests run. +# So you probably don't want to modify it by hand! Instead, modify the +# file with the same name in the fixture-templates/ directory. + +[package] +name = "host" +version = "0.0.1" +authors = ["The Roc Contributors"] +license = "UPL-1.0" +edition = "2018" +links = "app" + +[lib] +name = "host" +path = "src/lib.rs" +crate-type = ["staticlib", "rlib"] + +[[bin]] +name = "host" +path = "src/main.rs" + +[dependencies] +roc_std = { path = "glue/roc_std" } +roc_app = { path = "glue/roc_app" } +libc = "0.2" +hyper = { version = "0.14", features= ["http1", "http2", "client", "server", "runtime", "backports", "deprecated"] } +tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] } +futures = "0.3" +bytes = "1.0" + +[workspace] diff --git a/examples/webserver/platform/build.rs b/examples/webserver/platform/build.rs new file mode 100644 index 00000000000..47763b34c39 --- /dev/null +++ b/examples/webserver/platform/build.rs @@ -0,0 +1,9 @@ +fn main() { + #[cfg(not(windows))] + println!("cargo:rustc-link-lib=dylib=app"); + + #[cfg(windows)] + println!("cargo:rustc-link-lib=dylib=libapp"); + + println!("cargo:rustc-link-search=."); +} diff --git a/examples/webserver/platform/host.c b/examples/webserver/platform/host.c new file mode 100644 index 00000000000..3914d3f6eed --- /dev/null +++ b/examples/webserver/platform/host.c @@ -0,0 +1,14 @@ +// ⚠️ READ THIS BEFORE MODIFYING THIS FILE! ⚠️ +// +// This file is a fixture template. If the file you're looking at is +// in the fixture-templates/ directory, then you're all set - go ahead +// and modify it, and it will modify all the fixture tests. +// +// If this file is in the fixtures/ directory, on the other hand, then +// it is gitignored and will be overwritten the next time tests run. +// So you probably don't want to modify it by hand! Instead, modify the +// file with the same name in the fixture-templates/ directory. + +extern int rust_main(); + +int main() { return rust_main(); } diff --git a/examples/webserver/platform/main.roc b/examples/webserver/platform/main.roc new file mode 100644 index 00000000000..c01047b7575 --- /dev/null +++ b/examples/webserver/platform/main.roc @@ -0,0 +1,9 @@ +platform "webserver-platform" + requires {} { main : _ } + exposes [] + packages {} + imports [] + provides [mainForHost] + +mainForHost : Str -> Str +mainForHost = \str -> main str diff --git a/examples/webserver/platform/src/lib.rs b/examples/webserver/platform/src/lib.rs new file mode 100644 index 00000000000..6cbdb4f27fe --- /dev/null +++ b/examples/webserver/platform/src/lib.rs @@ -0,0 +1,128 @@ +use futures::{Future, FutureExt}; +use hyper::{Body, Request, Response, Server, StatusCode}; +use std::convert::Infallible; +use std::net::SocketAddr; +use std::panic::AssertUnwindSafe; +use tokio::task::spawn_blocking; +use roc_app; +use std::time::Instant; + +const LISTEN_ON_PORT: u16 = 8000; + +fn call_roc(req_bytes: &[u8]) -> (StatusCode, Vec) { + // TODO setjmp (both for signal handlers and for roc_panic, bc calling Rust panics from FFI code is UB) + // TODO install signal handlers + // TODO convert roc_bytes to RocList, call roc_mainForHost, and convert from its RocList response + let req_str: &str = std::str::from_utf8(req_bytes).unwrap(); // TODO don't unwrap + + (StatusCode::OK, roc_app::mainForHost(req_str.into()).as_str().into()) +} + +async fn handle(req: Request) -> Response { + match hyper::body::to_bytes(req.into_body()).await { + Ok(req_body) => { + spawn_blocking(move || { + let (status_code, resp_bytes) = call_roc(&req_body); + + Response::builder() + .status(status_code) // TODO get status code from Roc too + .body(Body::from(resp_bytes)) + .unwrap() // TODO don't unwrap() here + }) + .then(|resp| async { + resp.unwrap() // TODO don't unwrap here + }) + .await + } + Err(_) => todo!(), // TODO + } +} + +/// Translate Rust panics in the given Future into 500 errors +async fn handle_panics( + fut: impl Future>, +) -> Result, Infallible> { + match AssertUnwindSafe(fut).catch_unwind().await { + Ok(response) => Ok(response), + Err(_panic) => { + let error = Response::builder() + .status(StatusCode::INTERNAL_SERVER_ERROR) + .body("Panic detected!".into()) + .unwrap(); // TODO don't unwrap here + + Ok(error) + } + } +} + +#[no_mangle] +pub extern "C" fn rust_main() -> i32 { + let start_time = Instant::now(); + let addr = SocketAddr::from(([127, 0, 0, 1], LISTEN_ON_PORT)); + + tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + .unwrap() // TODO print and error and return nonzero + .block_on(async { + let server = Server::bind(&addr).serve(hyper::service::make_service_fn(|_conn| async { + Ok::<_, Infallible>(hyper::service::service_fn(|req| handle_panics(handle(req)))) + })); + + let elapsed_time = start_time.elapsed(); + + println!("Server started up and listening on {:?} in {} ms", addr, elapsed_time.as_millis()); + + match server.await { + Ok(_) => 0, + Err(err) => { + eprintln!("Error initializing Rust `hyper` server: {}", err); // TODO improve this + 1 + } + } + }) +} + +// Externs required by roc_std and by the Roc app + +use core::ffi::c_void; +use std::ffi::CStr; +use std::os::raw::c_char; + +#[no_mangle] +pub unsafe extern "C" fn roc_alloc(size: usize, _alignment: u32) -> *mut c_void { + return libc::malloc(size); +} + +#[no_mangle] +pub unsafe extern "C" fn roc_realloc( + c_ptr: *mut c_void, + new_size: usize, + _old_size: usize, + _alignment: u32, +) -> *mut c_void { + return libc::realloc(c_ptr, new_size); +} + +#[no_mangle] +pub unsafe extern "C" fn roc_dealloc(c_ptr: *mut c_void, _alignment: u32) { + return libc::free(c_ptr); +} + +#[no_mangle] +pub unsafe extern "C" fn roc_panic(c_ptr: *mut c_void, tag_id: u32) { + match tag_id { + 0 => { + let slice = CStr::from_ptr(c_ptr as *const c_char); + let string = slice.to_str().unwrap(); + eprintln!("Roc hit a panic: {}", string); + std::process::exit(1); + } + _ => todo!(), + } +} + +#[no_mangle] +pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { + libc::memset(dst, c, n) +} diff --git a/examples/webserver/platform/src/main.rs b/examples/webserver/platform/src/main.rs new file mode 100644 index 00000000000..0765384f29f --- /dev/null +++ b/examples/webserver/platform/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + std::process::exit(host::rust_main() as _); +} From 1fff1cd2a132d1f1cfffd1c12a1ade8354bd53e6 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 26 Jun 2023 19:35:52 -0400 Subject: [PATCH 078/140] Fix some glue fixtures --- crates/glue/tests/fixture-templates/rust/build.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/glue/tests/fixture-templates/rust/build.rs b/crates/glue/tests/fixture-templates/rust/build.rs index 7dcf8da4e95..6c70d142f01 100644 --- a/crates/glue/tests/fixture-templates/rust/build.rs +++ b/crates/glue/tests/fixture-templates/rust/build.rs @@ -10,6 +10,11 @@ // file with the same name in the fixture-templates/ directory. fn main() { + #[cfg(not(windows))] println!("cargo:rustc-link-lib=dylib=app"); + + #[cfg(windows)] + println!("cargo:rustc-link-lib=dylib=libapp"); + println!("cargo:rustc-link-search=."); } From db8d222c52f6f15093e01965dd2d4d09adb85b09 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 26 Jun 2023 21:12:49 -0400 Subject: [PATCH 079/140] Refactor some webserver example init stuff --- examples/webserver/platform/src/lib.rs | 55 ++++++++++++++------------ 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/examples/webserver/platform/src/lib.rs b/examples/webserver/platform/src/lib.rs index 6cbdb4f27fe..09d5b6de134 100644 --- a/examples/webserver/platform/src/lib.rs +++ b/examples/webserver/platform/src/lib.rs @@ -5,9 +5,8 @@ use std::net::SocketAddr; use std::panic::AssertUnwindSafe; use tokio::task::spawn_blocking; use roc_app; -use std::time::Instant; -const LISTEN_ON_PORT: u16 = 8000; +const DEFAULT_PORT: u16 = 8000; fn call_roc(req_bytes: &[u8]) -> (StatusCode, Vec) { // TODO setjmp (both for signal handlers and for roc_panic, bc calling Rust panics from FFI code is UB) @@ -55,32 +54,36 @@ async fn handle_panics( } } +const LOCALHOST: [u8; 4] = [127, 0, 0, 1]; + +async fn run_server(port: u16) -> i32 { + let addr = SocketAddr::from((LOCALHOST, port)); + let server = Server::bind(&addr).serve(hyper::service::make_service_fn(|_conn| async { + Ok::<_, Infallible>(hyper::service::service_fn(|req| handle_panics(handle(req)))) + })); + + println!("Listening on "); + + match server.await { + Ok(_) => 0, + Err(err) => { + eprintln!("Error initializing Rust `hyper` server: {}", err); // TODO improve this + + 1 + } + } +} + #[no_mangle] pub extern "C" fn rust_main() -> i32 { - let start_time = Instant::now(); - let addr = SocketAddr::from(([127, 0, 0, 1], LISTEN_ON_PORT)); - - tokio::runtime::Builder::new_multi_thread() - .enable_all() - .build() - .unwrap() // TODO print and error and return nonzero - .block_on(async { - let server = Server::bind(&addr).serve(hyper::service::make_service_fn(|_conn| async { - Ok::<_, Infallible>(hyper::service::service_fn(|req| handle_panics(handle(req)))) - })); - - let elapsed_time = start_time.elapsed(); - - println!("Server started up and listening on {:?} in {} ms", addr, elapsed_time.as_millis()); - - match server.await { - Ok(_) => 0, - Err(err) => { - eprintln!("Error initializing Rust `hyper` server: {}", err); // TODO improve this - 1 - } - } - }) + match tokio::runtime::Builder::new_multi_thread().enable_all().build() { + Ok(runtime) => runtime.block_on(async { run_server(DEFAULT_PORT).await }), + Err(err) => { + eprintln!("Error initializing tokio multithreaded runtime: {}", err); // TODO improve this + + 1 + } + } } // Externs required by roc_std and by the Roc app From 7df7d5100627b85973093fd15a80d08e67186b1f Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 26 Jun 2023 22:13:59 -0400 Subject: [PATCH 080/140] webserver example setjmp/longjmp error handling --- examples/webserver/platform/Cargo.toml | 4 +- examples/webserver/platform/src/lib.rs | 151 +++++++++++++++++++------ 2 files changed, 117 insertions(+), 38 deletions(-) diff --git a/examples/webserver/platform/Cargo.toml b/examples/webserver/platform/Cargo.toml index 29062b4c73f..867603fafc2 100644 --- a/examples/webserver/platform/Cargo.toml +++ b/examples/webserver/platform/Cargo.toml @@ -27,10 +27,10 @@ name = "host" path = "src/main.rs" [dependencies] -roc_std = { path = "glue/roc_std" } +roc_std = { path = "glue/roc_std", features = ["std"] } roc_app = { path = "glue/roc_app" } libc = "0.2" -hyper = { version = "0.14", features= ["http1", "http2", "client", "server", "runtime", "backports", "deprecated"] } +hyper = { version = "0.14", features = ["http1", "http2", "client", "server", "runtime", "backports", "deprecated"] } tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] } futures = "0.3" bytes = "1.0" diff --git a/examples/webserver/platform/src/lib.rs b/examples/webserver/platform/src/lib.rs index 09d5b6de134..ad54ace3592 100644 --- a/examples/webserver/platform/src/lib.rs +++ b/examples/webserver/platform/src/lib.rs @@ -1,37 +1,114 @@ use futures::{Future, FutureExt}; use hyper::{Body, Request, Response, Server, StatusCode}; +use roc_app; +use roc_std::RocStr; +use std::cell::RefCell; use std::convert::Infallible; use std::net::SocketAddr; +use std::os::raw::{c_int, c_long, c_void}; use std::panic::AssertUnwindSafe; use tokio::task::spawn_blocking; -use roc_app; +use libc::{sigaction, siginfo_t, sigemptyset, SIGBUS, SIGFPE, SIGILL, SIGSEGV, sighandler_t, sigset_t, SA_SIGINFO, SIG_DFL}; const DEFAULT_PORT: u16 = 8000; -fn call_roc(req_bytes: &[u8]) -> (StatusCode, Vec) { - // TODO setjmp (both for signal handlers and for roc_panic, bc calling Rust panics from FFI code is UB) - // TODO install signal handlers - // TODO convert roc_bytes to RocList, call roc_mainForHost, and convert from its RocList response - let req_str: &str = std::str::from_utf8(req_bytes).unwrap(); // TODO don't unwrap +// If we have a roc_panic or a segfault, these will be used to record where to jump back to +// (a point at which we can return a different response). +thread_local! { + // 64 is the biggest jmp_buf in setjmp.h + static SETJMP_ENV: RefCell<[c_long; 64]> = RefCell::new([0 as c_long; 64]); + static ROC_CRASH_MSG: RefCell = RefCell::new(RocStr::empty()); + static SIGNAL_CAUGHT: RefCell = RefCell::new(0); +} + +extern "C" { + #[link_name = "setjmp"] + pub fn setjmp(env: *mut c_void) -> c_int; + + #[link_name = "longjmp"] + pub fn longjmp(env: *mut c_void, val: c_int); +} + +unsafe extern "C" fn signal_handler(sig: c_int, _: *mut siginfo_t, _: *mut libc::c_void) { + SIGNAL_CAUGHT.with(|val| { + *val.borrow_mut() = sig; + }); + + SETJMP_ENV.with(|env| { + longjmp(env.borrow_mut().as_mut_ptr().cast(), 1); + }); +} + +fn setup_signal(sig: c_int) { + let sa = libc::sigaction { + sa_sigaction: signal_handler as sighandler_t, + sa_mask: sigset_t::default(), + sa_flags: SA_SIGINFO, + }; + + let mut old_sa = libc::sigaction { + sa_sigaction: SIG_DFL, + sa_mask: sigset_t::default(), + sa_flags: 0, + }; + + unsafe { + sigemptyset(&mut old_sa.sa_mask as *mut sigset_t); + sigaction(sig, &sa, &mut old_sa); + } +} + +fn call_roc(req_bytes: &[u8]) -> Response { + let mut setjmp_result = 0; + + SETJMP_ENV.with(|env| { + setjmp_result = unsafe { setjmp(env.borrow_mut().as_mut_ptr().cast()) }; + }); + + if setjmp_result == 0 { + setup_signal(SIGSEGV); + setup_signal(SIGILL); + setup_signal(SIGFPE); + setup_signal(SIGBUS); + + let req_str: &str = std::str::from_utf8(req_bytes).unwrap(); // TODO don't unwrap + let resp: String = roc_app::mainForHost(req_str.into()).as_str().into(); + + Response::builder() + .status(StatusCode::OK) // TODO get status code from Roc too + .body(Body::from(resp)) + .unwrap() // TODO don't unwrap() here + } else { + let mut crash_msg: String = String::new(); + let mut sig: c_int = 0; + + SIGNAL_CAUGHT.with(|val| { + sig = *val.borrow(); + }); + + if sig == 0 { + ROC_CRASH_MSG.with(|env| { + crash_msg = env.borrow().as_str().into(); + }); + } else { + crash_msg = "Roc crashed with signal {sig}".into(); // TODO print the name of the signal + } - (StatusCode::OK, roc_app::mainForHost(req_str.into()).as_str().into()) + Response::builder() + .status(StatusCode::INTERNAL_SERVER_ERROR) + .body(Body::from(crash_msg)) + .unwrap() // TODO don't unwrap() here + } } -async fn handle(req: Request) -> Response { +async fn handle_req(req: Request) -> Response { match hyper::body::to_bytes(req.into_body()).await { Ok(req_body) => { - spawn_blocking(move || { - let (status_code, resp_bytes) = call_roc(&req_body); - - Response::builder() - .status(status_code) // TODO get status code from Roc too - .body(Body::from(resp_bytes)) - .unwrap() // TODO don't unwrap() here - }) - .then(|resp| async { - resp.unwrap() // TODO don't unwrap here - }) - .await + spawn_blocking(move || call_roc(&req_body)) + .then(|resp| async { + resp.unwrap() // TODO don't unwrap here + }) + .await } Err(_) => todo!(), // TODO } @@ -59,7 +136,7 @@ const LOCALHOST: [u8; 4] = [127, 0, 0, 1]; async fn run_server(port: u16) -> i32 { let addr = SocketAddr::from((LOCALHOST, port)); let server = Server::bind(&addr).serve(hyper::service::make_service_fn(|_conn| async { - Ok::<_, Infallible>(hyper::service::service_fn(|req| handle_panics(handle(req)))) + Ok::<_, Infallible>(hyper::service::service_fn(|req| handle_panics(handle_req(req)))) })); println!("Listening on "); @@ -76,7 +153,10 @@ async fn run_server(port: u16) -> i32 { #[no_mangle] pub extern "C" fn rust_main() -> i32 { - match tokio::runtime::Builder::new_multi_thread().enable_all().build() { + match tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + { Ok(runtime) => runtime.block_on(async { run_server(DEFAULT_PORT).await }), Err(err) => { eprintln!("Error initializing tokio multithreaded runtime: {}", err); // TODO improve this @@ -88,10 +168,6 @@ pub extern "C" fn rust_main() -> i32 { // Externs required by roc_std and by the Roc app -use core::ffi::c_void; -use std::ffi::CStr; -use std::os::raw::c_char; - #[no_mangle] pub unsafe extern "C" fn roc_alloc(size: usize, _alignment: u32) -> *mut c_void { return libc::malloc(size); @@ -113,16 +189,19 @@ pub unsafe extern "C" fn roc_dealloc(c_ptr: *mut c_void, _alignment: u32) { } #[no_mangle] -pub unsafe extern "C" fn roc_panic(c_ptr: *mut c_void, tag_id: u32) { - match tag_id { - 0 => { - let slice = CStr::from_ptr(c_ptr as *const c_char); - let string = slice.to_str().unwrap(); - eprintln!("Roc hit a panic: {}", string); - std::process::exit(1); - } - _ => todo!(), - } +pub unsafe extern "C" fn roc_panic(msg: RocStr) { + // Set the last caught signal to 0, so we don't mistake this for a signal. + SIGNAL_CAUGHT.with(|val| { + *val.borrow_mut() = 0; + }); + + ROC_CRASH_MSG.with(|val| { + *val.borrow_mut() = msg; + }); + + SETJMP_ENV.with(|env| { + longjmp(env.borrow_mut().as_mut_ptr().cast(), 1); + }); } #[no_mangle] From 1c52c23c5faae9582d2cede9c0e6bf57b180283b Mon Sep 17 00:00:00 2001 From: Folkert Date: Tue, 27 Jun 2023 11:02:24 +0200 Subject: [PATCH 081/140] Revert "use 32-bit GEP indices where easily possible" This reverts commit 7c9c3d829cf10ad02ee90527809f7bb435dfc330. --- crates/compiler/gen_llvm/src/llvm/build.rs | 17 ++++++----------- .../compiler/gen_llvm/src/llvm/refcounting.rs | 2 +- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 6bcae600c44..3870d5ba388 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -1931,7 +1931,7 @@ fn tag_pointer_set_tag_id<'ctx>( // we only have 3 bits, so can encode only 0..7 (or on 32-bit targets, 2 bits to encode 0..3) debug_assert!((tag_id as u32) < env.target_info.ptr_width() as u32); - let tag_id_intval = env.context.i32_type().const_int(tag_id as u64, false); + let tag_id_intval = env.ptr_int().const_int(tag_id as u64, false); let cast_pointer = env.builder.build_pointer_cast( pointer, @@ -1991,9 +1991,6 @@ pub fn tag_pointer_clear_tag_id<'ctx>( let current_tag_id = env.builder.build_and(as_int, mask, "masked"); let index = env.builder.build_int_neg(current_tag_id, "index"); - let index = env - .builder - .build_int_cast(index, env.context.i32_type(), "to_i32"); let cast_pointer = env.builder.build_pointer_cast( pointer, @@ -2447,9 +2444,8 @@ fn list_literal<'a, 'ctx>( // all elements are constants, so we can use the memory in the constants section directly // here we make a pointer to the first actual element (skipping the 0 bytes that // represent the refcount) - let i32_type = env.context.i32_type(); - let zero = i32_type.const_zero(); - let offset = i32_type.const_int(zero_elements as _, false); + let zero = env.ptr_int().const_zero(); + let offset = env.ptr_int().const_int(zero_elements as _, false); let ptr = unsafe { env.builder.new_build_in_bounds_gep( @@ -2478,7 +2474,7 @@ fn list_literal<'a, 'ctx>( // then replace the `undef`s with the values that we evaluate at runtime for (index, val) in runtime_evaluated_elements { - let index_val = ctx.i32_type().const_int(index as u64, false); + let index_val = ctx.i64_type().const_int(index as u64, false); let elem_ptr = unsafe { builder.new_build_in_bounds_gep(element_type, ptr, &[index_val], "index") }; @@ -2499,7 +2495,7 @@ fn list_literal<'a, 'ctx>( } ListLiteralElement::Symbol(symbol) => scope.load_symbol(symbol), }; - let index_val = ctx.i32_type().const_int(index as u64, false); + let index_val = ctx.i64_type().const_int(index as u64, false); let elem_ptr = unsafe { builder.new_build_in_bounds_gep(element_type, ptr, &[index_val], "index") }; @@ -6263,8 +6259,7 @@ fn define_global_str_literal_ptr<'ctx>( env.context.i8_type(), ptr, &[env - .context - .i32_type() + .ptr_int() .const_int(env.target_info.ptr_width() as u64, false)], "get_rc_ptr", ) diff --git a/crates/compiler/gen_llvm/src/llvm/refcounting.rs b/crates/compiler/gen_llvm/src/llvm/refcounting.rs index 6d03fa54c29..06f9e73bf1e 100644 --- a/crates/compiler/gen_llvm/src/llvm/refcounting.rs +++ b/crates/compiler/gen_llvm/src/llvm/refcounting.rs @@ -61,7 +61,7 @@ impl<'ctx> PointerToRefcount<'ctx> { builder.build_pointer_cast(data_ptr, refcount_ptr_type, "as_usize_ptr"); // get a pointer to index -1 - let index_intvalue = env.context.i32_type().const_int(-1_i64 as u64, false); + let index_intvalue = refcount_type.const_int(-1_i64 as u64, false); let refcount_ptr = unsafe { builder.new_build_in_bounds_gep( env.ptr_int(), From 38033315cb8a74ce6fd2a24190ed66ee3e037f3c Mon Sep 17 00:00:00 2001 From: eiei114 Date: Tue, 27 Jun 2023 19:24:02 +0900 Subject: [PATCH 082/140] change Cargo.lock --- Cargo.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.lock b/Cargo.lock index 904d6d5066b..38bacbfed90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3759,6 +3759,7 @@ dependencies = [ "roc_build", "roc_builtins", "roc_collections", + "roc_error_macros", "roc_gen_llvm", "roc_load", "roc_module", From 8bdbc22f295e4a32311f78e267a4794818bf9aab Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Tue, 27 Jun 2023 16:11:54 +0200 Subject: [PATCH 083/140] basic-cli old docs site Signed-off-by: Anton-4 <17049058+Anton-4@users.noreply.github.com> --- www/build.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/www/build.sh b/www/build.sh index e2df683f4b8..cdd14f3cfd2 100755 --- a/www/build.sh +++ b/www/build.sh @@ -115,4 +115,13 @@ mkdir -p $BASIC_CLI_PACKAGE_DIR rm generated-docs/*.* # we already copied over the *.js and *.css files earlier, so just drop these. mv generated-docs/* $BASIC_CLI_PACKAGE_DIR # move all the folders to build/packages/basic-cli +# set up docs for basic-cli 0.3.2 +BASIC_CLI_DIR_0_3_2=$BASIC_CLI_PACKAGE_DIR/0-3-2 +mkdir -p $BASIC_CLI_DIR_0_3_2 +curl -fL --output $BASIC_CLI_DIR_0_3_2/docs.tar.gz https://github.com/roc-lang/basic-cli/releases/download/0.3.2/docs.tar.gz +tar -xf $BASIC_CLI_DIR_0_3_2/docs.tar.gz -C $BASIC_CLI_DIR_0_3_2/ +rm $BASIC_CLI_DIR_0_3_2/docs.tar.gz +mv $BASIC_CLI_DIR_0_3_2/generated-docs/* $BASIC_CLI_DIR_0_3_2 +rm -rf $BASIC_CLI_DIR_0_3_2/generated-docs + popd From fc3004da584241bd543aa80a3bd8470004fdeaca Mon Sep 17 00:00:00 2001 From: Folkert Date: Tue, 27 Jun 2023 17:33:53 +0200 Subject: [PATCH 084/140] free or reuse unconditionally when value is unique --- crates/compiler/alias_analysis/src/lib.rs | 6 + crates/compiler/builtins/bitcode/src/main.zig | 2 + .../compiler/builtins/bitcode/src/utils.zig | 34 ++++ crates/compiler/builtins/src/bitcode.rs | 2 + crates/compiler/can/src/builtins.rs | 1 + crates/compiler/gen_dev/src/generic64/mod.rs | 17 +- crates/compiler/gen_dev/src/lib.rs | 40 +++- crates/compiler/gen_llvm/src/llvm/build.rs | 33 ++++ crates/compiler/gen_llvm/src/llvm/lowlevel.rs | 6 + .../compiler/gen_llvm/src/llvm/refcounting.rs | 32 +++- crates/compiler/gen_wasm/src/backend.rs | 44 ++++- crates/compiler/gen_wasm/src/low_level.rs | 13 ++ crates/compiler/load_internal/src/file.rs | 1 + crates/compiler/module/src/low_level.rs | 2 + crates/compiler/mono/src/borrow.rs | 4 +- crates/compiler/mono/src/code_gen_help/mod.rs | 1 + .../mono/src/code_gen_help/refcount.rs | 3 + crates/compiler/mono/src/debug/checker.rs | 4 +- .../compiler/mono/src/drop_specialization.rs | 21 ++- crates/compiler/mono/src/ir.rs | 8 + crates/compiler/mono/src/reset_reuse.rs | 178 +++++++++++++----- 21 files changed, 382 insertions(+), 70 deletions(-) diff --git a/crates/compiler/alias_analysis/src/lib.rs b/crates/compiler/alias_analysis/src/lib.rs index 27a3be99478..82c9944c4d7 100644 --- a/crates/compiler/alias_analysis/src/lib.rs +++ b/crates/compiler/alias_analysis/src/lib.rs @@ -510,6 +510,12 @@ fn apply_refcount_operation( builder.add_recursive_touch(block, argument)?; } ModifyRc::DecRef(symbol) => { + // this is almost certainly suboptimal, but not incorrect + let argument = env.symbols[symbol]; + builder.add_recursive_touch(block, argument)?; + } + ModifyRc::Free(symbol) => { + // this is almost certainly suboptimal, but not incorrect let argument = env.symbols[symbol]; builder.add_recursive_touch(block, argument)?; } diff --git a/crates/compiler/builtins/bitcode/src/main.zig b/crates/compiler/builtins/bitcode/src/main.zig index 82bb7237563..a349ce26c31 100644 --- a/crates/compiler/builtins/bitcode/src/main.zig +++ b/crates/compiler/builtins/bitcode/src/main.zig @@ -195,8 +195,10 @@ comptime { exportUtilsFn(utils.test_panic, "test_panic"); exportUtilsFn(utils.increfRcPtrC, "incref_rc_ptr"); exportUtilsFn(utils.decrefRcPtrC, "decref_rc_ptr"); + exportUtilsFn(utils.freeRcPtrC, "free_rc_ptr"); exportUtilsFn(utils.increfDataPtrC, "incref_data_ptr"); exportUtilsFn(utils.decrefDataPtrC, "decref_data_ptr"); + exportUtilsFn(utils.freeDataPtrC, "free_data_ptr"); exportUtilsFn(utils.isUnique, "is_unique"); exportUtilsFn(utils.decrefCheckNullC, "decref_check_null"); exportUtilsFn(utils.allocateWithRefcountC, "allocate_with_refcount"); diff --git a/crates/compiler/builtins/bitcode/src/utils.zig b/crates/compiler/builtins/bitcode/src/utils.zig index 3a2e07b72da..9157f0aaf5f 100644 --- a/crates/compiler/builtins/bitcode/src/utils.zig +++ b/crates/compiler/builtins/bitcode/src/utils.zig @@ -220,6 +220,29 @@ pub fn increfDataPtrC( return increfRcPtrC(isizes, inc_amount); } +pub fn freeDataPtrC( + bytes_or_null: ?[*]isize, + alignment: u32, +) callconv(.C) void { + var bytes = bytes_or_null orelse return; + + const ptr = @ptrToInt(bytes); + const tag_mask: usize = if (@sizeOf(usize) == 8) 0b111 else 0b11; + const masked_ptr = ptr & ~tag_mask; + + const isizes: [*]isize = @intToPtr([*]isize, masked_ptr); + + return freeRcPtrC(isizes - 1, alignment); +} + +pub fn freeRcPtrC( + bytes_or_null: ?[*]isize, + alignment: u32, +) callconv(.C) void { + var bytes = bytes_or_null orelse return; + return free_ptr_to_refcount(bytes, alignment); +} + pub fn decref( bytes_or_null: ?[*]u8, data_bytes: usize, @@ -236,6 +259,17 @@ pub fn decref( decref_ptr_to_refcount(isizes - 1, alignment); } +inline fn free_ptr_to_refcount( + refcount_ptr: [*]isize, + alignment: u32, +) void { + if (RC_TYPE == Refcount.none) return; + const extra_bytes = std.math.max(alignment, @sizeOf(usize)); + + // NOTE: we don't even check whether the refcount is "infinity" here! + dealloc(@ptrCast([*]u8, refcount_ptr) - (extra_bytes - @sizeOf(usize)), alignment); +} + inline fn decref_ptr_to_refcount( refcount_ptr: [*]isize, alignment: u32, diff --git a/crates/compiler/builtins/src/bitcode.rs b/crates/compiler/builtins/src/bitcode.rs index dfc6a667716..92869d9fc48 100644 --- a/crates/compiler/builtins/src/bitcode.rs +++ b/crates/compiler/builtins/src/bitcode.rs @@ -393,8 +393,10 @@ pub const UTILS_TEST_PANIC: &str = "roc_builtins.utils.test_panic"; pub const UTILS_ALLOCATE_WITH_REFCOUNT: &str = "roc_builtins.utils.allocate_with_refcount"; pub const UTILS_INCREF_RC_PTR: &str = "roc_builtins.utils.incref_rc_ptr"; pub const UTILS_DECREF_RC_PTR: &str = "roc_builtins.utils.decref_rc_ptr"; +pub const UTILS_FREE_RC_PTR: &str = "roc_builtins.utils.free_rc_ptr"; pub const UTILS_INCREF_DATA_PTR: &str = "roc_builtins.utils.incref_data_ptr"; pub const UTILS_DECREF_DATA_PTR: &str = "roc_builtins.utils.decref_data_ptr"; +pub const UTILS_FREE_DATA_PTR: &str = "roc_builtins.utils.free_data_ptr"; pub const UTILS_IS_UNIQUE: &str = "roc_builtins.utils.is_unique"; pub const UTILS_DECREF_CHECK_NULL: &str = "roc_builtins.utils.decref_check_null"; pub const UTILS_DICT_PSEUDO_SEED: &str = "roc_builtins.utils.dict_pseudo_seed"; diff --git a/crates/compiler/can/src/builtins.rs b/crates/compiler/can/src/builtins.rs index 656f9cd1b42..55004df8b3c 100644 --- a/crates/compiler/can/src/builtins.rs +++ b/crates/compiler/can/src/builtins.rs @@ -87,6 +87,7 @@ macro_rules! map_symbol_to_lowlevel_and_arity { LowLevel::PtrCast => unimplemented!(), LowLevel::PtrStore => unimplemented!(), LowLevel::PtrLoad => unimplemented!(), + LowLevel::PtrClearTagId => unimplemented!(), LowLevel::Alloca => unimplemented!(), LowLevel::RefCountIncRcPtr => unimplemented!(), LowLevel::RefCountDecRcPtr=> unimplemented!(), diff --git a/crates/compiler/gen_dev/src/generic64/mod.rs b/crates/compiler/gen_dev/src/generic64/mod.rs index 90804dbc0f8..2057128396a 100644 --- a/crates/compiler/gen_dev/src/generic64/mod.rs +++ b/crates/compiler/gen_dev/src/generic64/mod.rs @@ -2996,12 +2996,17 @@ impl< ); } - fn build_ptr_to_stack_value( - &mut self, - sym: Symbol, - value: Symbol, - element_layout: InLayout<'a>, - ) { + fn build_ptr_clear_tag_id(&mut self, sym: Symbol, ptr: Symbol) { + let buf = &mut self.buf; + + let ptr_reg = self.storage_manager.load_to_general_reg(buf, &ptr); + let sym_reg = self.storage_manager.claim_general_reg(buf, &sym); + + ASM::mov_reg64_imm64(buf, sym_reg, !0b111); + ASM::and_reg64_reg64_reg64(buf, sym_reg, sym_reg, ptr_reg); + } + + fn build_alloca(&mut self, sym: Symbol, value: Symbol, element_layout: InLayout<'a>) { // 1. acquire some stack space let element_width = self.interner().stack_size(element_layout); let allocation = self.debug_symbol("stack_allocation"); diff --git a/crates/compiler/gen_dev/src/lib.rs b/crates/compiler/gen_dev/src/lib.rs index 25bd620e95e..f624165de0d 100644 --- a/crates/compiler/gen_dev/src/lib.rs +++ b/crates/compiler/gen_dev/src/lib.rs @@ -17,7 +17,7 @@ use roc_module::symbol::{Interns, ModuleId, Symbol}; use roc_mono::code_gen_help::{CallerProc, CodeGenHelp}; use roc_mono::ir::{ BranchInfo, CallType, CrashTag, Expr, HigherOrderLowLevel, JoinPointId, ListLiteralElement, - Literal, Param, Proc, ProcLayout, SelfRecursive, Stmt, + Literal, ModifyRc, Param, Proc, ProcLayout, SelfRecursive, Stmt, }; use roc_mono::layout::{ Builtin, InLayout, LambdaName, Layout, LayoutIds, LayoutInterner, LayoutRepr, STLayoutInterner, @@ -525,6 +525,29 @@ trait Backend<'a> { self.return_symbol(sym, ret_layout); self.free_symbols(stmt); } + Stmt::Refcounting(ModifyRc::Free(symbol), following) => { + let dst = Symbol::DEV_TMP; + + let layout = *self.layout_map().get(symbol).unwrap(); + let alignment_bytes = self.interner().allocation_alignment_bytes(layout); + let alignment = self.debug_symbol("alignment"); + self.load_literal_i32(&alignment, alignment_bytes as i32); + + // NOTE: UTILS_FREE_DATA_PTR clears any tag id bits + + self.build_fn_call( + &dst, + bitcode::UTILS_FREE_DATA_PTR.to_string(), + &[*symbol, alignment], + &[Layout::I64, Layout::I32], + &Layout::UNIT, + ); + + self.free_symbol(&dst); + self.free_symbol(&alignment); + + self.build_stmt(layout_ids, following, ret_layout) + } Stmt::Refcounting(modify, following) => { let sym = modify.get_symbol(); let layout = *self.layout_map().get(&sym).unwrap(); @@ -1605,8 +1628,12 @@ trait Backend<'a> { self.build_ptr_load(*sym, args[0], *ret_layout); } + LowLevel::PtrClearTagId => { + self.build_ptr_clear_tag_id(*sym, args[0]); + } + LowLevel::Alloca => { - self.build_ptr_to_stack_value(*sym, args[0], arg_layouts[0]); + self.build_alloca(*sym, args[0], arg_layouts[0]); } LowLevel::RefCountDecRcPtr => self.build_fn_call( @@ -2247,12 +2274,9 @@ trait Backend<'a> { fn build_ptr_load(&mut self, sym: Symbol, ptr: Symbol, element_layout: InLayout<'a>); - fn build_ptr_to_stack_value( - &mut self, - sym: Symbol, - value: Symbol, - element_layout: InLayout<'a>, - ); + fn build_ptr_clear_tag_id(&mut self, sym: Symbol, ptr: Symbol); + + fn build_alloca(&mut self, sym: Symbol, value: Symbol, element_layout: InLayout<'a>); /// literal_map gets the map from symbol to literal and layout, used for lazy loading and literal folding. fn literal_map(&mut self) -> &mut MutMap, *const InLayout<'a>)>; diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 38a06b4dac7..e0eb3db1dbe 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -2919,6 +2919,39 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>( cont, ) } + + Free(symbol) => { + // unconditionally deallocate the symbol + let (value, layout) = scope.load_symbol_and_layout(symbol); + let alignment = layout_interner.alignment_bytes(layout); + + debug_assert!(value.is_pointer_value()); + let value = value.into_pointer_value(); + + let clear_tag_id = match layout_interner.chase_recursive(layout) { + LayoutRepr::Union(union) => union.stores_tag_id_in_pointer(env.target_info), + _ => false, + }; + + let ptr = if clear_tag_id { + tag_pointer_clear_tag_id(env, value) + } else { + value + }; + + let rc_ptr = PointerToRefcount::from_ptr_to_data(env, ptr); + rc_ptr.deallocate(env, alignment); + + build_exp_stmt( + env, + layout_interner, + layout_ids, + func_spec_solutions, + scope, + parent, + cont, + ) + } } } diff --git a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs index 63a9a15e740..fa7f6e39314 100644 --- a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs +++ b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs @@ -1325,6 +1325,12 @@ pub(crate) fn run_low_level<'a, 'ctx>( .new_build_load(element_type, ptr.into_pointer_value(), "ptr_load") } + PtrClearTagId => { + arguments!(ptr); + + tag_pointer_clear_tag_id(env, ptr.into_pointer_value()).into() + } + Alloca => { arguments!(initial_value); diff --git a/crates/compiler/gen_llvm/src/llvm/refcounting.rs b/crates/compiler/gen_llvm/src/llvm/refcounting.rs index 06f9e73bf1e..8164e27d380 100644 --- a/crates/compiler/gen_llvm/src/llvm/refcounting.rs +++ b/crates/compiler/gen_llvm/src/llvm/refcounting.rs @@ -14,7 +14,7 @@ use bumpalo::collections::Vec; use inkwell::basic_block::BasicBlock; use inkwell::module::Linkage; use inkwell::types::{AnyTypeEnum, BasicMetadataTypeEnum, BasicType, BasicTypeEnum}; -use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue}; +use inkwell::values::{BasicValueEnum, FunctionValue, InstructionValue, IntValue, PointerValue}; use inkwell::{AddressSpace, IntPredicate}; use roc_module::symbol::Interns; use roc_module::symbol::Symbol; @@ -193,6 +193,14 @@ impl<'ctx> PointerToRefcount<'ctx> { builder.build_return(None); } + + pub fn deallocate<'a, 'env>( + &self, + env: &Env<'a, 'ctx, 'env>, + alignment: u32, + ) -> InstructionValue<'ctx> { + free_pointer(env, self.value, alignment) + } } fn incref_pointer<'ctx>( @@ -216,6 +224,28 @@ fn incref_pointer<'ctx>( ); } +fn free_pointer<'ctx>( + env: &Env<'_, 'ctx, '_>, + pointer: PointerValue<'ctx>, + alignment: u32, +) -> InstructionValue<'ctx> { + let alignment = env.context.i32_type().const_int(alignment as _, false); + call_void_bitcode_fn( + env, + &[ + env.builder + .build_pointer_cast( + pointer, + env.ptr_int().ptr_type(AddressSpace::default()), + "to_isize_ptr", + ) + .into(), + alignment.into(), + ], + roc_builtins::bitcode::UTILS_FREE_RC_PTR, + ) +} + fn decref_pointer<'ctx>(env: &Env<'_, 'ctx, '_>, pointer: PointerValue<'ctx>, alignment: u32) { let alignment = env.context.i32_type().const_int(alignment as _, false); call_void_bitcode_fn( diff --git a/crates/compiler/gen_wasm/src/backend.rs b/crates/compiler/gen_wasm/src/backend.rs index b333a73999e..557cdbecc2d 100644 --- a/crates/compiler/gen_wasm/src/backend.rs +++ b/crates/compiler/gen_wasm/src/backend.rs @@ -1,7 +1,7 @@ use bitvec::vec::BitVec; use bumpalo::collections::{String, Vec}; -use roc_builtins::bitcode::{FloatWidth, IntWidth}; +use roc_builtins::bitcode::{self, FloatWidth, IntWidth}; use roc_collections::all::MutMap; use roc_error_macros::internal_error; use roc_module::low_level::{LowLevel, LowLevelWrapperType}; @@ -719,7 +719,10 @@ impl<'a, 'r> WasmBackend<'a, 'r> { Stmt::Jump(id, arguments) => self.stmt_jump(*id, arguments), - Stmt::Refcounting(modify, following) => self.stmt_refcounting(modify, following), + Stmt::Refcounting(modify, following) => match modify { + ModifyRc::Free(symbol) => self.stmt_refcounting_free(*symbol, following), + _ => self.stmt_refcounting(modify, following), + }, Stmt::Dbg { .. } => todo!("dbg is not implemented in the wasm backend"), Stmt::Expect { .. } => todo!("expect is not implemented in the wasm backend"), @@ -999,6 +1002,43 @@ impl<'a, 'r> WasmBackend<'a, 'r> { self.stmt(rc_stmt); } + fn stmt_refcounting_free(&mut self, value: Symbol, following: &'a Stmt<'a>) { + let layout = self.storage.symbol_layouts[&value]; + let alignment = self.layout_interner.allocation_alignment_bytes(layout); + + // Get pointer and offset + let value_storage = self.storage.get(&value).to_owned(); + let stored_with_local = + self.storage + .ensure_value_has_local(&mut self.code_builder, value, value_storage); + let (tag_local_id, tag_offset) = match stored_with_local { + StoredValue::StackMemory { location, .. } => { + location.local_and_offset(self.storage.stack_frame_pointer) + } + StoredValue::Local { local_id, .. } => (local_id, 0), + StoredValue::VirtualMachineStack { .. } => { + internal_error!("{:?} should have a local variable", value) + } + }; + + // load pointer, and add the offset to the pointer + self.code_builder.get_local(tag_local_id); + + if tag_offset > 0 { + self.code_builder.i32_const(tag_offset as i32); + self.code_builder.i32_add(); + } + + // NOTE: UTILS_FREE_DATA_PTR clears any tag id bits + + // push the allocation's alignment + self.code_builder.i32_const(alignment as i32); + + self.call_host_fn_after_loading_args(bitcode::UTILS_FREE_DATA_PTR, 2, false); + + self.stmt(following); + } + pub fn stmt_internal_error(&mut self, msg: &'a str) { let msg_sym = self.create_symbol("panic_str"); let msg_storage = self.storage.allocate_var( diff --git a/crates/compiler/gen_wasm/src/low_level.rs b/crates/compiler/gen_wasm/src/low_level.rs index f87807a6da6..22810606d9a 100644 --- a/crates/compiler/gen_wasm/src/low_level.rs +++ b/crates/compiler/gen_wasm/src/low_level.rs @@ -1979,6 +1979,19 @@ impl<'a> LowLevelCall<'a> { ); } PtrLoad => backend.expr_unbox(self.ret_symbol, self.arguments[0]), + PtrClearTagId => { + let ptr = self.arguments[0]; + + let ptr_local_id = match backend.storage.get(&ptr) { + StoredValue::Local { local_id, .. } => *local_id, + _ => internal_error!("A pointer will always be an i32"), + }; + + backend.code_builder.get_local(ptr_local_id); + + backend.code_builder.i32_const(-4); // 11111111...1100 + backend.code_builder.i32_and(); + } Alloca => { // Alloca : a -> Ptr a let arg = self.arguments[0]; diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index 9821a6c8831..661feb9bd8e 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -3141,6 +3141,7 @@ fn update<'a>( arena, &layout_interner, module_id, + state.target_info, ident_ids, &mut update_mode_ids, &mut state.procedures, diff --git a/crates/compiler/module/src/low_level.rs b/crates/compiler/module/src/low_level.rs index bbb30d075cd..bca0692c50c 100644 --- a/crates/compiler/module/src/low_level.rs +++ b/crates/compiler/module/src/low_level.rs @@ -120,6 +120,7 @@ pub enum LowLevel { PtrCast, PtrStore, PtrLoad, + PtrClearTagId, Alloca, RefCountIncRcPtr, RefCountDecRcPtr, @@ -232,6 +233,7 @@ macro_rules! map_symbol_to_lowlevel { LowLevel::PtrCast => unimplemented!(), LowLevel::PtrStore => unimplemented!(), LowLevel::PtrLoad => unimplemented!(), + LowLevel::PtrClearTagId => unimplemented!(), LowLevel::Alloca => unimplemented!(), LowLevel::RefCountIncRcPtr => unimplemented!(), LowLevel::RefCountDecRcPtr=> unimplemented!(), diff --git a/crates/compiler/mono/src/borrow.rs b/crates/compiler/mono/src/borrow.rs index bd03651ecc2..dc5ad52fc19 100644 --- a/crates/compiler/mono/src/borrow.rs +++ b/crates/compiler/mono/src/borrow.rs @@ -1047,8 +1047,8 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[Ownership] { PtrLoad => arena.alloc_slice_copy(&[owned]), Alloca => arena.alloc_slice_copy(&[owned]), - PtrCast | RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr | RefCountDecDataPtr - | RefCountIsUnique => { + PtrClearTagId | PtrCast | RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr + | RefCountDecDataPtr | RefCountIsUnique => { unreachable!("Only inserted *after* borrow checking: {:?}", op); } } diff --git a/crates/compiler/mono/src/code_gen_help/mod.rs b/crates/compiler/mono/src/code_gen_help/mod.rs index a79293294fa..2ea7809d207 100644 --- a/crates/compiler/mono/src/code_gen_help/mod.rs +++ b/crates/compiler/mono/src/code_gen_help/mod.rs @@ -141,6 +141,7 @@ impl<'a> CodeGenHelp<'a> { let jp_decref = JoinPointId(self.create_symbol(ident_ids, "jp_decref")); HelperOp::DecRef(jp_decref) } + ModifyRc::Free(_) => unreachable!("free should be handled by the backend directly"), }; let mut ctx = Context { diff --git a/crates/compiler/mono/src/code_gen_help/refcount.rs b/crates/compiler/mono/src/code_gen_help/refcount.rs index 4174698e097..d0e966855aa 100644 --- a/crates/compiler/mono/src/code_gen_help/refcount.rs +++ b/crates/compiler/mono/src/code_gen_help/refcount.rs @@ -118,6 +118,9 @@ pub fn refcount_stmt<'a>( }, } } + ModifyRc::Free(_) => { + unreachable!("free should be handled by the backend directly") + } } } diff --git a/crates/compiler/mono/src/debug/checker.rs b/crates/compiler/mono/src/debug/checker.rs index 1012fa0842c..afb0917cf83 100644 --- a/crates/compiler/mono/src/debug/checker.rs +++ b/crates/compiler/mono/src/debug/checker.rs @@ -716,8 +716,10 @@ impl<'a, 'r> Ctx<'a, 'r> { } fn check_modify_rc(&mut self, rc: ModifyRc) { + use ModifyRc::*; + match rc { - ModifyRc::Inc(sym, _) | ModifyRc::Dec(sym) | ModifyRc::DecRef(sym) => { + Inc(sym, _) | Dec(sym) | DecRef(sym) | Free(sym) => { // TODO: also check that sym layout needs refcounting self.check_sym_exists(sym); } diff --git a/crates/compiler/mono/src/drop_specialization.rs b/crates/compiler/mono/src/drop_specialization.rs index 6639440583c..a4203dec05b 100644 --- a/crates/compiler/mono/src/drop_specialization.rs +++ b/crates/compiler/mono/src/drop_specialization.rs @@ -582,8 +582,9 @@ fn specialize_drops_stmt<'a, 'i>( updated_stmt } } - ModifyRc::DecRef(_) => { - // Inlining has no point, since it doesn't decrement it's children + ModifyRc::DecRef(_) | ModifyRc::Free(_) => { + // These operations are not recursive (the children are not touched) + // so inlining is not useful arena.alloc(Stmt::Refcounting( *rc, specialize_drops_stmt( @@ -1031,8 +1032,10 @@ fn specialize_union<'a, 'i>( )) }), arena.alloc(Stmt::Refcounting( - // TODO this could be replaced by a free if ever added to the IR. - ModifyRc::DecRef(*symbol), + // we know for sure that the allocation is unique at + // this point. Therefore we can free (or maybe reuse) + // without checking the refcount again. + ModifyRc::Free(*symbol), continuation, )), ) @@ -1101,8 +1104,10 @@ fn specialize_boxed<'a, 'i>( // - free the box |_, _, continuation| { arena.alloc(Stmt::Refcounting( - // TODO can be replaced by free if ever added to the IR. - ModifyRc::DecRef(*symbol), + // we know for sure that the allocation is unique at + // this point. Therefore we can free (or maybe reuse) + // without checking the refcount again. + ModifyRc::Free(*symbol), continuation, )) }, @@ -1682,8 +1687,8 @@ fn low_level_no_rc(lowlevel: &LowLevel) -> RC { PtrLoad => RC::NoRc, Alloca => RC::NoRc, - PtrCast | RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr | RefCountDecDataPtr - | RefCountIsUnique => { + PtrClearTagId | PtrCast | RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr + | RefCountDecDataPtr | RefCountIsUnique => { unreachable!("Only inserted *after* borrow checking: {:?}", lowlevel); } } diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index 4e417b3cdaf..c9013e78f12 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -1612,6 +1612,9 @@ pub enum ModifyRc { /// sometimes we know we already dealt with the elements (e.g. by copying them all over /// to a new list) and so we can just do a DecRef, which is much cheaper in such a case. DecRef(Symbol), + /// Unconditionally deallocate the memory. For tag union that do pointer tagging (store the tag + /// id in the pointer) the backend has to clear the tag id! + Free(Symbol), } impl ModifyRc { @@ -1641,6 +1644,10 @@ impl ModifyRc { .text("decref ") .append(symbol_to_doc(alloc, symbol, pretty)) .append(";"), + Free(symbol) => alloc + .text("free ") + .append(symbol_to_doc(alloc, symbol, pretty)) + .append(";"), } } @@ -1651,6 +1658,7 @@ impl ModifyRc { Inc(symbol, _) => *symbol, Dec(symbol) => *symbol, DecRef(symbol) => *symbol, + Free(symbol) => *symbol, } } } diff --git a/crates/compiler/mono/src/reset_reuse.rs b/crates/compiler/mono/src/reset_reuse.rs index f6fe8264946..1b2fd6a98f6 100644 --- a/crates/compiler/mono/src/reset_reuse.rs +++ b/crates/compiler/mono/src/reset_reuse.rs @@ -19,7 +19,9 @@ use bumpalo::Bump; use bumpalo::collections::vec::Vec; use bumpalo::collections::CollectIn; use roc_collections::{MutMap, MutSet}; +use roc_module::low_level::LowLevel; use roc_module::symbol::{IdentIds, ModuleId, Symbol}; +use roc_target::TargetInfo; /** Insert reset and reuse operations into the IR. @@ -29,6 +31,7 @@ pub fn insert_reset_reuse_operations<'a, 'i>( arena: &'a Bump, layout_interner: &'i STLayoutInterner<'a>, home: ModuleId, + target_info: TargetInfo, ident_ids: &'i mut IdentIds, update_mode_ids: &'i mut UpdateModeIds, procs: &mut MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>, @@ -42,6 +45,7 @@ pub fn insert_reset_reuse_operations<'a, 'i>( let new_proc = insert_reset_reuse_operations_proc( arena, layout_interner, + target_info, home, ident_ids, update_mode_ids, @@ -55,6 +59,7 @@ pub fn insert_reset_reuse_operations<'a, 'i>( fn insert_reset_reuse_operations_proc<'a, 'i>( arena: &'a Bump, layout_interner: &'i STLayoutInterner<'a>, + target_info: TargetInfo, home: ModuleId, ident_ids: &'i mut IdentIds, update_mode_ids: &'i mut UpdateModeIds, @@ -66,6 +71,7 @@ fn insert_reset_reuse_operations_proc<'a, 'i>( } let mut env = ReuseEnvironment { + target_info, symbol_tags: MutMap::default(), non_unique_symbols: MutSet::default(), reuse_tokens: MutMap::default(), @@ -398,33 +404,83 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( }) } Stmt::Refcounting(rc, continuation) => { - let reuse_pair = match rc { - ModifyRc::Dec(symbol) | ModifyRc::DecRef(symbol) - if !environment.non_unique_symbols.contains(symbol) => - { + enum SymbolIsUnique { + Never, + Always(Symbol), + MustCheck(Symbol), + } + + let can_reuse = match rc { + ModifyRc::Dec(symbol) | ModifyRc::DecRef(symbol) => { + // can only reuse if the symbol is (potentially) unique + if environment.non_unique_symbols.contains(symbol) { + SymbolIsUnique::Never + } else { + SymbolIsUnique::MustCheck(*symbol) + } + } + ModifyRc::Free(symbol) => { + // a free'd symbol is guaranteed to be unique + SymbolIsUnique::Always(*symbol) + } + ModifyRc::Inc(_, _) => { + // an incremented symbol is never unique + SymbolIsUnique::Never + } + }; + + enum ResetOperation { + Reset, + ResetRef, + ClearTagId, + Nothing, + } + + let reuse_pair = match can_reuse { + SymbolIsUnique::MustCheck(symbol) | SymbolIsUnique::Always(symbol) => { // Get the layout of the symbol from where it is defined. - let layout_option = environment.get_symbol_layout(*symbol); + let layout_option = environment.get_symbol_layout(symbol); // If the symbol is defined in the current proc, we can use the layout from the environment. - match layout_option.clone() { + match layout_option { LayoutOption::Layout(layout) => { match symbol_layout_reusability( layout_interner, environment, - symbol, + &symbol, layout, ) { Reuse::Reusable(union_layout) => { + let (reuse_symbol, reset_op) = match rc { + ModifyRc::Dec(_) => ( + Symbol::new(home, ident_ids.gen_unique()), + ResetOperation::Reset, + ), + ModifyRc::DecRef(_) => ( + Symbol::new(home, ident_ids.gen_unique()), + ResetOperation::ResetRef, + ), + ModifyRc::Free(_) => { + if union_layout + .stores_tag_id_in_pointer(environment.target_info) + { + ( + Symbol::new(home, ident_ids.gen_unique()), + ResetOperation::ClearTagId, + ) + } else { + (symbol, ResetOperation::Nothing) + } + } + _ => unreachable!(), + }; + let reuse_token = ReuseToken { - symbol: Symbol::new(home, ident_ids.gen_unique()), + symbol: reuse_symbol, update_mode_id: update_mode_ids.next_id(), }; - let dec_ref = match rc { - ModifyRc::Dec(_) => false, - ModifyRc::DecRef(_) => true, - _ => unreachable!(), - }; + let owned_layout = **layout; environment.push_reuse_token( arena, @@ -432,7 +488,14 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( reuse_token, layout, ); - Some((layout, union_layout, *symbol, reuse_token, dec_ref)) + + Some(( + owned_layout, + union_layout, + symbol, + reuse_token, + reset_op, + )) } Reuse::Nonreusable => None, } @@ -440,7 +503,7 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( _ => None, } } - _ => { + SymbolIsUnique::Never => { // We don't need to do anything for an inc or symbols known to be non-unique. None } @@ -457,7 +520,7 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( ); // If we inserted a reuse token, we need to insert a reset reuse operation if the reuse token is consumed. - if let Some((layout, union_layout, symbol, reuse_token, dec_ref)) = reuse_pair { + if let Some((layout, union_layout, symbol, reuse_token, reset_op)) = reuse_pair { let stack_reuse_token = environment .peek_reuse_token(&get_reuse_layout_info(layout_interner, union_layout)); @@ -471,29 +534,56 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( _ => { // The token we inserted is no longer on the stack, it must have been consumed. // So we need to insert a reset operation. - let reset_expr = match dec_ref { - // A decref will be replaced by a resetref. - true => Expr::ResetRef { - symbol, - update_mode: reuse_token.update_mode_id, - }, - // And a dec will be replaced by a reset. - false => Expr::Reset { - symbol, - update_mode: reuse_token.update_mode_id, - }, - }; - - // If we generate a reuse token, we no longer want to use the drop statement anymore. So we just return the reset expression. - // TODO verify if this works for both dec and decref. - // TODO reset probably decrements it's children. So we probably need to create a resetref that only does the token. - return arena.alloc(Stmt::Let( - reuse_token.symbol, - reset_expr, - // TODO not sure what the layout should be for a reset token. Currently it is the layout of the symbol. - *layout, - new_continuation, - )); + match reset_op { + ResetOperation::Reset => { + // a dec will be replaced by a reset. + let reset_expr = Expr::Reset { + symbol, + update_mode: reuse_token.update_mode_id, + }; + + return arena.alloc(Stmt::Let( + reuse_token.symbol, + reset_expr, + layout, + new_continuation, + )); + } + ResetOperation::ResetRef => { + // a decref will be replaced by a resetref. + let reset_expr = Expr::ResetRef { + symbol, + update_mode: reuse_token.update_mode_id, + }; + + return arena.alloc(Stmt::Let( + reuse_token.symbol, + reset_expr, + layout, + new_continuation, + )); + } + ResetOperation::ClearTagId => { + let reset_expr = Expr::Call(crate::ir::Call { + call_type: crate::ir::CallType::LowLevel { + op: LowLevel::PtrClearTagId, + update_mode: update_mode_ids.next_id(), + }, + arguments: arena.alloc([symbol]), + }); + + return arena.alloc(Stmt::Let( + reuse_token.symbol, + reset_expr, + layout, + new_continuation, + )); + } + ResetOperation::Nothing => { + // the reuse token is already in a valid state + return new_continuation; + } + } } } } @@ -661,6 +751,7 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( // Create a new environment for the body. With everything but the jump reuse tokens. As those should be given by the jump. let mut first_pass_body_environment = ReuseEnvironment { + target_info: environment.target_info, symbol_tags: environment.symbol_tags.clone(), non_unique_symbols: environment.non_unique_symbols.clone(), reuse_tokens: max_reuse_token_symbols.clone(), @@ -824,6 +915,7 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( let (second_pass_body_environment, second_pass_body) = { // Create a new environment for the body. With everything but the jump reuse tokens. As those should be given by the jump. let mut body_environment = ReuseEnvironment { + target_info: environment.target_info, symbol_tags: environment.symbol_tags.clone(), non_unique_symbols: environment.non_unique_symbols.clone(), reuse_tokens: used_reuse_tokens.clone(), @@ -889,7 +981,8 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( let mut void_pointer_layout_symbols = Vec::new_in(arena); // See what tokens we can get from the env, if none are available, use a void pointer. - // We process the tokens in reverse order, so that when we consume the tokens we last added, we consume the tokens that are most likely not to be null. + // We process the tokens in reverse order, so that when we consume the tokens we last added, + // we consume the tokens that are most likely not to be null. let tokens = token_layouts_clone .iter() .rev() @@ -1002,7 +1095,7 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( fn create_ptr_cast(arena: &Bump, symbol: Symbol) -> Expr { Expr::Call(crate::ir::Call { call_type: crate::ir::CallType::LowLevel { - op: roc_module::low_level::LowLevel::PtrCast, + op: LowLevel::PtrCast, update_mode: UpdateModeId::BACKEND_DUMMY, }, arguments: Vec::from_iter_in([symbol], arena).into_bump_slice(), @@ -1092,8 +1185,9 @@ enum JoinPointReuseTokens<'a> { RemainderSecond(Vec<'a, (&'a InLayout<'a>, TokenLayout)>), } -#[derive(Default, Clone)] +#[derive(Clone)] struct ReuseEnvironment<'a> { + target_info: TargetInfo, symbol_tags: MutMap, non_unique_symbols: MutSet, reuse_tokens: ReuseTokens<'a>, From ed9d9b12f51fd0d84cb947e31139bffb156caab6 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Tue, 27 Jun 2023 11:38:38 -0400 Subject: [PATCH 085/140] Add some missing Dict and Set functions Also remove some unnecessary Hash and Eq restrictions --- crates/compiler/builtins/roc/Dict.roc | 43 ++++++++++++++++++-- crates/compiler/builtins/roc/List.roc | 3 ++ crates/compiler/builtins/roc/Set.roc | 57 ++++++++++++++++++++++++++- crates/compiler/module/src/symbol.rs | 6 +++ 4 files changed, 104 insertions(+), 5 deletions(-) diff --git a/crates/compiler/builtins/roc/Dict.roc b/crates/compiler/builtins/roc/Dict.roc index 097b0942109..180033b0086 100644 --- a/crates/compiler/builtins/roc/Dict.roc +++ b/crates/compiler/builtins/roc/Dict.roc @@ -7,6 +7,7 @@ interface Dict clear, capacity, len, + isEmpty, get, contains, insert, @@ -21,6 +22,8 @@ interface Dict insertAll, keepShared, removeAll, + map, + joinMap, ] imports [ Bool.{ Bool, Eq }, @@ -139,12 +142,12 @@ empty = \{} -> ## Returns the max number of elements the dictionary can hold before requiring a rehash. ## ``` ## foodDict = -## Dict.empty {} -## |> Dict.insert "apple" "fruit" +## Dict.empty {} +## |> Dict.insert "apple" "fruit" ## ## capacityOfDict = Dict.capacity foodDict ## ``` -capacity : Dict k v -> Nat | k has Hash & Eq +capacity : Dict * * -> Nat capacity = \@Dict { dataIndices } -> cap = List.len dataIndices @@ -192,10 +195,20 @@ fromList = \data -> ## |> Dict.len ## |> Bool.isEq 3 ## ``` -len : Dict k v -> Nat | k has Hash & Eq +len : Dict * * -> Nat len = \@Dict { size } -> size +## Check if the dictinoary is empty. +## ``` +## Dict.isEmpty (Dict.empty {} |> Dict.insert "key" 42) +## +## Dict.isEmpty (Dict.empty {}) +## ``` +isEmpty : Dict * * -> Bool +isEmpty = \@Dict { size } -> + size == 0 + ## Clears all elements from a dictionary keeping around the allocation if it isn't huge. ## ``` ## songs = @@ -225,6 +238,28 @@ clear = \@Dict { metadata, dataIndices, data } -> size: 0, } +## Convert each value in the dictionary to something new, by calling a conversion +## function on each of them which receives both the key and the old value. Then return a +## new dictionary containing the same keys and the converted values. +map : Dict k a, (k, a -> b) -> Dict k b | k has Hash & Eq, b has Hash & Eq +map = \dict, transform -> + init = withCapacity (capacity dict) + + walk dict init \answer, k, v -> + insert answer k (transform k v) + +## Like [Dict.map], except the transformation function wraps the return value +## in a dictionary. At the end, all the dictionaries get joined together +## (using [Dict.insertAll]) into one dictionary. +## +## You may know a similar function named `concatMap` in other languages. +joinMap : Dict a b, (a, b -> Dict x y) -> Dict x y | a has Hash & Eq, x has Hash & Eq +joinMap = \dict, transform -> + init = withCapacity (capacity dict) # Might be a pessimization + + walk dict init \answer, k, v -> + insertAll answer (transform k v) + ## Iterate through the keys and values in the dictionary and call the provided ## function with signature `state, k, v -> state` for each value, with an ## initial `state` value provided for the first call. diff --git a/crates/compiler/builtins/roc/List.roc b/crates/compiler/builtins/roc/List.roc index c9ed2875050..76447c10169 100644 --- a/crates/compiler/builtins/roc/List.roc +++ b/crates/compiler/builtins/roc/List.roc @@ -208,6 +208,9 @@ interface List ## * Even when copying is faster, other list operations may still be slightly slower with persistent data structures. For example, even if it were a persistent data structure, [List.map], [List.walk], and [List.keepIf] would all need to traverse every element in the list and build up the result from scratch. These operations are all ## * Roc's compiler optimizes many list operations into in-place mutations behind the scenes, depending on how the list is being used. For example, [List.map], [List.keepIf], and [List.set] can all be optimized to perform in-place mutations. ## * If possible, it is usually best for performance to use large lists in a way where the optimizer can turn them into in-place mutations. If this is not possible, a persistent data structure might be faster - but this is a rare enough scenario that it would not be good for the average Roc program's performance if this were the way [List] worked by default. Instead, you can look outside Roc's standard modules for an implementation of a persistent data structure - likely built using [List] under the hood! + +# separator so List.isEmpty doesn't absorb the above into its doc comment + ## Check if the list is empty. ## ``` ## List.isEmpty [1, 2, 3] diff --git a/crates/compiler/builtins/roc/Set.roc b/crates/compiler/builtins/roc/Set.roc index 24c54df999f..f8b2072d0d4 100644 --- a/crates/compiler/builtins/roc/Set.roc +++ b/crates/compiler/builtins/roc/Set.roc @@ -7,6 +7,8 @@ interface Set walkUntil, insert, len, + isEmpty, + capacity, remove, contains, toList, @@ -14,6 +16,8 @@ interface Set union, intersection, difference, + map, + joinMap, ] imports [ List, @@ -59,6 +63,13 @@ hashSet = \hasher, @Set inner -> Hash.hash hasher inner empty : {} -> Set k | k has Hash & Eq empty = \{} -> @Set (Dict.empty {}) +## Return a dictionary with space allocated for a number of entries. This +## may provide a performance optimization if you know how many entries will be +## inserted. +withCapacity : Nat -> Set k | k has Hash & Eq +withCapacity = \cap -> + @Set (Dict.withCapacity cap) + ## Creates a new `Set` with a single value. ## ``` ## singleItemSet = Set.single "Apple" @@ -115,10 +126,32 @@ expect ## ## expect countValues == 3 ## ``` -len : Set k -> Nat | k has Hash & Eq +len : Set * -> Nat len = \@Set dict -> Dict.len dict +## Returns the max number of elements the set can hold before requiring a rehash. +## ``` +## foodSet = +## Set.empty {} +## |> Set.insert "apple" +## +## capacityOfSet = Set.capacity foodSet +## ``` +capacity : Set * -> Nat +capacity = \@Set dict -> + Dict.capacity dict + +## Check if the set is empty. +## ``` +## Set.isEmpty (Set.empty {} |> Set.insert 42) +## +## Set.isEmpty (Set.empty {}) +## ``` +isEmpty : Set * -> Bool +isEmpty = \@Set dict -> + Dict.isEmpty dict + # Inserting a duplicate key has no effect on length. expect actual = @@ -261,6 +294,28 @@ walk : Set k, state, (state, k -> state) -> state | k has Hash & Eq walk = \@Set dict, state, step -> Dict.walk dict state (\s, k, _ -> step s k) +## Convert each value in the set to something new, by calling a conversion +## function on each of them which receives the old value. Then return a +## new set containing the converted values. +map : Set a, (a -> b) -> Set b | a has Hash & Eq, b has Hash & Eq +map = \set, transform -> + init = withCapacity (capacity set) + + walk set init \answer, k -> + insert answer (transform k) + +## Like [Set.map], except the transformation function wraps the return value +## in a set. At the end, all the sets get joined together +## (using [Set.union]) into one set. +## +## You may know a similar function named `concatMap` in other languages. +joinMap : Set a, (a -> Set b) -> Set b | a has Hash & Eq, b has Hash & Eq +joinMap = \set, transform -> + init = withCapacity (capacity set) # Might be a pessimization + + walk set init \answer, k -> + union answer (transform k) + ## Iterate through the values of a given `Set` and build a value, can stop ## iterating part way through the collection. ## ``` diff --git a/crates/compiler/module/src/symbol.rs b/crates/compiler/module/src/symbol.rs index 474397654c8..89acf366531 100644 --- a/crates/compiler/module/src/symbol.rs +++ b/crates/compiler/module/src/symbol.rs @@ -1471,6 +1471,9 @@ define_builtins! { 22 DICT_LIST_GET_UNSAFE: "listGetUnsafe" 23 DICT_PSEUDO_SEED: "pseudoSeed" + 24 DICT_IS_EMPTY: "isEmpty" + 25 DICT_MAP: "map" + 26 DICT_JOINMAP: "joinMap" } 9 SET: "Set" => { 0 SET_SET: "Set" exposed_type=true // the Set.Set type alias @@ -1490,6 +1493,9 @@ define_builtins! { 14 SET_CONTAINS: "contains" 15 SET_TO_DICT: "toDict" 16 SET_CAPACITY: "capacity" + 17 SET_IS_EMPTY: "isEmpty" + 18 SET_MAP: "map" + 19 SET_JOIN_MAP: "joinMap" } 10 BOX: "Box" => { 0 BOX_BOX_TYPE: "Box" exposed_apply_type=true // the Box.Box opaque type From f04295863d96fd8276d4e2d88229fdc59967ea50 Mon Sep 17 00:00:00 2001 From: Folkert Date: Tue, 27 Jun 2023 19:37:22 +0200 Subject: [PATCH 086/140] reuse free'ing logic --- crates/compiler/builtins/bitcode/src/utils.zig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/compiler/builtins/bitcode/src/utils.zig b/crates/compiler/builtins/bitcode/src/utils.zig index 9157f0aaf5f..d609aefbf82 100644 --- a/crates/compiler/builtins/bitcode/src/utils.zig +++ b/crates/compiler/builtins/bitcode/src/utils.zig @@ -275,7 +275,6 @@ inline fn decref_ptr_to_refcount( alignment: u32, ) void { if (RC_TYPE == Refcount.none) return; - const extra_bytes = std.math.max(alignment, @sizeOf(usize)); if (DEBUG_INCDEC and builtin.target.cpu.arch != .wasm32) { std.debug.print("| decrement {*}: ", .{refcount_ptr}); @@ -298,13 +297,13 @@ inline fn decref_ptr_to_refcount( } if (refcount == REFCOUNT_ONE_ISIZE) { - dealloc(@ptrCast([*]u8, refcount_ptr) - (extra_bytes - @sizeOf(usize)), alignment); + free_ptr_to_refcount(refcount_ptr, alignment); } }, Refcount.atomic => { var last = @atomicRmw(isize, &refcount_ptr[0], std.builtin.AtomicRmwOp.Sub, 1, Monotonic); if (last == REFCOUNT_ONE_ISIZE) { - dealloc(@ptrCast([*]u8, refcount_ptr) - (extra_bytes - @sizeOf(usize)), alignment); + free_ptr_to_refcount(refcount_ptr, alignment); } }, Refcount.none => unreachable, From 7e380d953382363cae0a8b02518ba69510366fa8 Mon Sep 17 00:00:00 2001 From: Folkert Date: Tue, 27 Jun 2023 19:39:26 +0200 Subject: [PATCH 087/140] update mono tests --- .../test_mono/generated/binary_tree_fbip.txt | 15 +- ...ose_correct_recursion_var_under_record.txt | 4 +- ...lambda_set_productive_nullable_wrapped.txt | 4 +- .../test_mono/generated/issue_3669.txt | 2 +- .../test_mono/generated/issue_4770.txt | 4 +- .../generated/linked_list_filter.txt | 13 +- .../test_mono/generated/linked_list_map.txt | 11 +- .../generated/linked_list_reverse.txt | 11 +- .../compiler/test_mono/generated/peano1.txt | 2 +- .../compiler/test_mono/generated/peano2.txt | 2 +- .../polymorphic_expression_unification.txt | 2 +- .../test_mono/generated/rb_tree_fbip.txt | 198 +++++++++--------- ...d_non_recursive_lambda_sets_issue_5026.txt | 2 +- ..._set_resolved_only_upon_specialization.txt | 2 +- .../generated/recursively_build_effect.txt | 4 +- .../generated/specialize_after_match.txt | 4 +- 16 files changed, 134 insertions(+), 146 deletions(-) diff --git a/crates/compiler/test_mono/generated/binary_tree_fbip.txt b/crates/compiler/test_mono/generated/binary_tree_fbip.txt index 77de42cdbd8..d8b5457f1a9 100644 --- a/crates/compiler/test_mono/generated/binary_tree_fbip.txt +++ b/crates/compiler/test_mono/generated/binary_tree_fbip.txt @@ -16,23 +16,22 @@ procedure Test.5 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): if Test.53 then let Test.32 : [, C *self *self] = UnionAtIndex (Id 0) (Index 0) Test.29; let Test.33 : [, C *self *self] = UnionAtIndex (Id 0) (Index 1) Test.29; - joinpoint #Derived_gen.3 #Derived_gen.7: - let #Derived_gen.8 : [C [, C *self *self] *self, ] = lowlevel PtrCast #Derived_gen.7; - let Test.43 : [C [, C *self *self] *self, ] = Reuse #Derived_gen.8 UpdateModeId { id: 1 } TagId(1) Test.33 Test.30; + joinpoint #Derived_gen.3 #Derived_gen.6: + let #Derived_gen.7 : [C [, C *self *self] *self, ] = lowlevel PtrCast #Derived_gen.6; + let Test.43 : [C [, C *self *self] *self, ] = Reuse #Derived_gen.7 UpdateModeId { id: 1 } TagId(1) Test.33 Test.30; let Test.45 : I64 = 1i64; let Test.44 : I64 = CallByName Num.19 Test.31 Test.45; jump Test.41 Test.32 Test.43 Test.44; in let #Derived_gen.4 : Int1 = lowlevel RefCountIsUnique Test.29; if #Derived_gen.4 then - let #Derived_gen.9 : [, C *self *self] = ResetRef { symbol: Test.29, id: UpdateModeId { id: 2 } }; - jump #Derived_gen.3 #Derived_gen.9; + jump #Derived_gen.3 Test.29; else inc Test.32; inc Test.33; decref Test.29; - let #Derived_gen.10 : [, C *self *self] = NullPointer; - jump #Derived_gen.3 #Derived_gen.10; + let #Derived_gen.8 : [, C *self *self] = NullPointer; + jump #Derived_gen.3 #Derived_gen.8; else let Test.48 : U8 = 1i64; let Test.49 : U8 = GetTagId Test.30; @@ -42,7 +41,7 @@ procedure Test.5 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): let Test.36 : [C [, C *self *self] *self, ] = UnionAtIndex (Id 1) (Index 1) Test.30; let #Derived_gen.5 : Int1 = lowlevel RefCountIsUnique Test.30; if #Derived_gen.5 then - decref Test.30; + free Test.30; jump Test.41 Test.35 Test.36 Test.31; else inc Test.35; diff --git a/crates/compiler/test_mono/generated/choose_correct_recursion_var_under_record.txt b/crates/compiler/test_mono/generated/choose_correct_recursion_var_under_record.txt index 653d6dc3b9e..b52e46a91d9 100644 --- a/crates/compiler/test_mono/generated/choose_correct_recursion_var_under_record.txt +++ b/crates/compiler/test_mono/generated/choose_correct_recursion_var_under_record.txt @@ -90,7 +90,7 @@ procedure Test.2 (Test.6): in let #Derived_gen.2 : Int1 = lowlevel RefCountIsUnique Test.6; if #Derived_gen.2 then - decref Test.6; + free Test.6; jump #Derived_gen.1; else inc Test.7; @@ -108,7 +108,7 @@ procedure Test.2 (Test.6): in let #Derived_gen.4 : Int1 = lowlevel RefCountIsUnique Test.6; if #Derived_gen.4 then - decref Test.6; + free Test.6; jump #Derived_gen.3; else inc Test.9; diff --git a/crates/compiler/test_mono/generated/compose_recursive_lambda_set_productive_nullable_wrapped.txt b/crates/compiler/test_mono/generated/compose_recursive_lambda_set_productive_nullable_wrapped.txt index ca95a51d0b1..6d9e4c3688d 100644 --- a/crates/compiler/test_mono/generated/compose_recursive_lambda_set_productive_nullable_wrapped.txt +++ b/crates/compiler/test_mono/generated/compose_recursive_lambda_set_productive_nullable_wrapped.txt @@ -87,7 +87,7 @@ procedure Test.11 (#Derived_gen.7, #Derived_gen.8): in let #Derived_gen.15 : Int1 = lowlevel RefCountIsUnique #Attr.12; if #Derived_gen.15 then - decref #Attr.12; + free #Attr.12; jump #Derived_gen.14; else inc Test.7; @@ -155,7 +155,7 @@ procedure Test.9 (Test.10, #Attr.12): in let #Derived_gen.13 : Int1 = lowlevel RefCountIsUnique #Attr.12; if #Derived_gen.13 then - decref #Attr.12; + free #Attr.12; jump #Derived_gen.12; else inc Test.7; diff --git a/crates/compiler/test_mono/generated/issue_3669.txt b/crates/compiler/test_mono/generated/issue_3669.txt index 03438ca1040..1b670be63b8 100644 --- a/crates/compiler/test_mono/generated/issue_3669.txt +++ b/crates/compiler/test_mono/generated/issue_3669.txt @@ -15,7 +15,7 @@ procedure Test.2 (#Derived_gen.0): let Test.5 : [, C *self] = UnionAtIndex (Id 0) (Index 0) Test.7; let #Derived_gen.1 : Int1 = lowlevel RefCountIsUnique Test.7; if #Derived_gen.1 then - decref Test.7; + free Test.7; jump Test.13 Test.5; else inc Test.5; diff --git a/crates/compiler/test_mono/generated/issue_4770.txt b/crates/compiler/test_mono/generated/issue_4770.txt index 4f1d14165db..7c010f63343 100644 --- a/crates/compiler/test_mono/generated/issue_4770.txt +++ b/crates/compiler/test_mono/generated/issue_4770.txt @@ -116,7 +116,7 @@ procedure Test.1 (#Derived_gen.0): in let #Derived_gen.7 : Int1 = lowlevel RefCountIsUnique Test.49; if #Derived_gen.7 then - decref Test.49; + free Test.49; jump #Derived_gen.6; else decref Test.49; @@ -161,7 +161,7 @@ procedure Test.1 (#Derived_gen.0): in let #Derived_gen.9 : Int1 = lowlevel RefCountIsUnique Test.51; if #Derived_gen.9 then - decref Test.51; + free Test.51; jump #Derived_gen.8; else inc Test.14; diff --git a/crates/compiler/test_mono/generated/linked_list_filter.txt b/crates/compiler/test_mono/generated/linked_list_filter.txt index e7120f4e91c..988e96f2fa0 100644 --- a/crates/compiler/test_mono/generated/linked_list_filter.txt +++ b/crates/compiler/test_mono/generated/linked_list_filter.txt @@ -22,27 +22,26 @@ procedure Test.2 (#Derived_gen.0, #Derived_gen.1): else let Test.7 : I64 = UnionAtIndex (Id 0) (Index 0) Test.4; let Test.8 : [, C I64 *self] = UnionAtIndex (Id 0) (Index 1) Test.4; - joinpoint #Derived_gen.12 #Derived_gen.15: + joinpoint #Derived_gen.12 #Derived_gen.14: let Test.19 : Int1 = CallByName Num.31 Test.7; if Test.19 then let #Derived_gen.9 : [, C I64 *self] = NullPointer; - let Test.20 : [, C I64 *self] = Reuse #Derived_gen.15 UpdateModeId { id: 1 } TagId(0) Test.7 #Derived_gen.9; + let Test.20 : [, C I64 *self] = Reuse #Derived_gen.14 UpdateModeId { id: 1 } TagId(0) Test.7 #Derived_gen.9; let #Derived_gen.10 : Ptr([, C I64 *self]) = UnionFieldPtrAtIndex (Id 0) (Index 1) Test.20; let #Derived_gen.11 : {} = lowlevel PtrStore #Derived_gen.5 Test.20; jump #Derived_gen.4 Test.8 Test.5 #Derived_gen.10 #Derived_gen.6; else - decref #Derived_gen.15; + decref #Derived_gen.14; jump #Derived_gen.4 Test.8 Test.5 #Derived_gen.5 #Derived_gen.6; in let #Derived_gen.13 : Int1 = lowlevel RefCountIsUnique Test.4; if #Derived_gen.13 then - let #Derived_gen.16 : [, C I64 *self] = ResetRef { symbol: Test.4, id: UpdateModeId { id: 2 } }; - jump #Derived_gen.12 #Derived_gen.16; + jump #Derived_gen.12 Test.4; else inc Test.8; decref Test.4; - let #Derived_gen.17 : [, C I64 *self] = NullPointer; - jump #Derived_gen.12 #Derived_gen.17; + let #Derived_gen.15 : [, C I64 *self] = NullPointer; + jump #Derived_gen.12 #Derived_gen.15; in jump #Derived_gen.4 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.2; diff --git a/crates/compiler/test_mono/generated/linked_list_map.txt b/crates/compiler/test_mono/generated/linked_list_map.txt index 9626e531966..8e57cb49a4e 100644 --- a/crates/compiler/test_mono/generated/linked_list_map.txt +++ b/crates/compiler/test_mono/generated/linked_list_map.txt @@ -22,23 +22,22 @@ procedure Test.2 (#Derived_gen.0, #Derived_gen.1): else let Test.7 : I64 = UnionAtIndex (Id 0) (Index 0) Test.5; let Test.8 : [, C I64 *self] = UnionAtIndex (Id 0) (Index 1) Test.5; - joinpoint #Derived_gen.12 #Derived_gen.15: + joinpoint #Derived_gen.12 #Derived_gen.14: let Test.20 : I64 = CallByName Test.10 Test.7; let #Derived_gen.9 : [, C I64 *self] = NullPointer; - let Test.19 : [, C I64 *self] = Reuse #Derived_gen.15 UpdateModeId { id: 1 } TagId(0) Test.20 #Derived_gen.9; + let Test.19 : [, C I64 *self] = Reuse #Derived_gen.14 UpdateModeId { id: 1 } TagId(0) Test.20 #Derived_gen.9; let #Derived_gen.10 : Ptr([, C I64 *self]) = UnionFieldPtrAtIndex (Id 0) (Index 1) Test.19; let #Derived_gen.11 : {} = lowlevel PtrStore #Derived_gen.5 Test.19; jump #Derived_gen.4 Test.4 Test.8 #Derived_gen.10 #Derived_gen.6; in let #Derived_gen.13 : Int1 = lowlevel RefCountIsUnique Test.5; if #Derived_gen.13 then - let #Derived_gen.16 : [, C I64 *self] = ResetRef { symbol: Test.5, id: UpdateModeId { id: 2 } }; - jump #Derived_gen.12 #Derived_gen.16; + jump #Derived_gen.12 Test.5; else inc Test.8; decref Test.5; - let #Derived_gen.17 : [, C I64 *self] = NullPointer; - jump #Derived_gen.12 #Derived_gen.17; + let #Derived_gen.15 : [, C I64 *self] = NullPointer; + jump #Derived_gen.12 #Derived_gen.15; in jump #Derived_gen.4 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.2; diff --git a/crates/compiler/test_mono/generated/linked_list_reverse.txt b/crates/compiler/test_mono/generated/linked_list_reverse.txt index 00461392a9b..892df1a7132 100644 --- a/crates/compiler/test_mono/generated/linked_list_reverse.txt +++ b/crates/compiler/test_mono/generated/linked_list_reverse.txt @@ -13,19 +13,18 @@ procedure Test.3 (#Derived_gen.0, #Derived_gen.1): else let Test.9 : I64 = UnionAtIndex (Id 0) (Index 0) Test.8; let Test.10 : [, C I64 *self] = UnionAtIndex (Id 0) (Index 1) Test.8; - joinpoint #Derived_gen.2 #Derived_gen.5: - let Test.21 : [, C I64 *self] = Reuse #Derived_gen.5 UpdateModeId { id: 1 } TagId(0) Test.9 Test.7; + joinpoint #Derived_gen.2 #Derived_gen.4: + let Test.21 : [, C I64 *self] = Reuse #Derived_gen.4 UpdateModeId { id: 1 } TagId(0) Test.9 Test.7; jump Test.18 Test.21 Test.10; in let #Derived_gen.3 : Int1 = lowlevel RefCountIsUnique Test.8; if #Derived_gen.3 then - let #Derived_gen.6 : [, C I64 *self] = ResetRef { symbol: Test.8, id: UpdateModeId { id: 2 } }; - jump #Derived_gen.2 #Derived_gen.6; + jump #Derived_gen.2 Test.8; else inc Test.10; decref Test.8; - let #Derived_gen.7 : [, C I64 *self] = NullPointer; - jump #Derived_gen.2 #Derived_gen.7; + let #Derived_gen.5 : [, C I64 *self] = NullPointer; + jump #Derived_gen.2 #Derived_gen.5; in jump Test.18 #Derived_gen.0 #Derived_gen.1; diff --git a/crates/compiler/test_mono/generated/peano1.txt b/crates/compiler/test_mono/generated/peano1.txt index 1d291bf98f9..7ec0b3c2f5f 100644 --- a/crates/compiler/test_mono/generated/peano1.txt +++ b/crates/compiler/test_mono/generated/peano1.txt @@ -17,7 +17,7 @@ procedure Test.0 (): let #Derived_gen.1 : Int1 = lowlevel RefCountIsUnique Test.2; if #Derived_gen.1 then dec Test.13; - decref Test.2; + free Test.2; jump #Derived_gen.0; else decref Test.2; diff --git a/crates/compiler/test_mono/generated/peano2.txt b/crates/compiler/test_mono/generated/peano2.txt index e4d53cc3be9..f090c272ddc 100644 --- a/crates/compiler/test_mono/generated/peano2.txt +++ b/crates/compiler/test_mono/generated/peano2.txt @@ -22,7 +22,7 @@ procedure Test.0 (): in let #Derived_gen.1 : Int1 = lowlevel RefCountIsUnique Test.2; if #Derived_gen.1 then - decref Test.2; + free Test.2; jump #Derived_gen.0; else inc Test.12; diff --git a/crates/compiler/test_mono/generated/polymorphic_expression_unification.txt b/crates/compiler/test_mono/generated/polymorphic_expression_unification.txt index 8984da0b47e..de6d1acdc53 100644 --- a/crates/compiler/test_mono/generated/polymorphic_expression_unification.txt +++ b/crates/compiler/test_mono/generated/polymorphic_expression_unification.txt @@ -37,7 +37,7 @@ procedure Test.0 (): let #Derived_gen.1 : Int1 = lowlevel RefCountIsUnique Test.15; if #Derived_gen.1 then dec Test.16; - decref Test.15; + free Test.15; jump #Derived_gen.0; else decref Test.15; diff --git a/crates/compiler/test_mono/generated/rb_tree_fbip.txt b/crates/compiler/test_mono/generated/rb_tree_fbip.txt index e2db544d2d9..28f4d749260 100644 --- a/crates/compiler/test_mono/generated/rb_tree_fbip.txt +++ b/crates/compiler/test_mono/generated/rb_tree_fbip.txt @@ -30,13 +30,13 @@ procedure Test.3 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): let Test.18 : I64 = UnionAtIndex (Id 1) (Index 1) Test.9; let Test.19 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.9; let Test.17 : I32 = UnionAtIndex (Id 1) (Index 3) Test.9; - joinpoint #Derived_gen.114 #Derived_gen.119: + joinpoint #Derived_gen.114 #Derived_gen.118: let Test.179 : Int1 = CallByName Num.22 Test.10 Test.17; if Test.179 then - joinpoint Test.238 #Derived_gen.181: + joinpoint Test.238 #Derived_gen.166: let Test.232 : Int1 = false; let #Derived_gen.10 : [C *self I64 *self I32 Int1, ] = NullPointer; - let Test.231 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.181 UpdateModeId { id: 56 } TagId(1) #Derived_gen.10 Test.18 Test.19 Test.17 Test.232; + let Test.231 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.166 UpdateModeId { id: 56 } TagId(1) #Derived_gen.10 Test.18 Test.19 Test.17 Test.232; let #Derived_gen.11 : Ptr([C *self I64 *self I32 Int1, ]) = UnionFieldPtrAtIndex (Id 1) (Index 0) Test.231; let #Derived_gen.12 : {} = lowlevel PtrStore #Derived_gen.6 Test.231; jump #Derived_gen.5 Test.16 Test.10 Test.11 #Derived_gen.11 #Derived_gen.7; @@ -50,7 +50,7 @@ procedure Test.3 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): let Test.239 : Int1 = lowlevel Eq Test.235 Test.234; if Test.239 then let Test.180 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.16 Test.10 Test.11; - joinpoint Test.199 #Derived_gen.208: + joinpoint Test.199 #Derived_gen.187: let Test.198 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; let Test.20 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.198; inc Test.20; @@ -61,57 +61,55 @@ procedure Test.3 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): let Test.25 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; let Test.26 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; let Test.24 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; - joinpoint #Derived_gen.72 #Derived_gen.211 #Derived_gen.212 #Derived_gen.213: + joinpoint #Derived_gen.72 #Derived_gen.189 #Derived_gen.190 #Derived_gen.191: let Test.186 : Int1 = false; - let Test.183 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.213 UpdateModeId { id: 85 } TagId(1) Test.20 Test.22 Test.23 Test.21 Test.186; + let Test.183 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.191 UpdateModeId { id: 85 } TagId(1) Test.20 Test.22 Test.23 Test.21 Test.186; let Test.185 : Int1 = false; - let Test.184 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.212 UpdateModeId { id: 84 } TagId(1) Test.26 Test.18 Test.19 Test.17 Test.185; + let Test.184 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.190 UpdateModeId { id: 84 } TagId(1) Test.26 Test.18 Test.19 Test.17 Test.185; let Test.182 : Int1 = true; - let Test.181 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.211 UpdateModeId { id: 83 } TagId(1) Test.183 Test.25 Test.184 Test.24 Test.182; + let Test.181 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.189 UpdateModeId { id: 83 } TagId(1) Test.183 Test.25 Test.184 Test.24 Test.182; let #Derived_gen.14 : {} = lowlevel PtrStore #Derived_gen.6 Test.181; let #Derived_gen.13 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; ret #Derived_gen.13; in let #Derived_gen.73 : Int1 = lowlevel RefCountIsUnique Test.180; if #Derived_gen.73 then - let #Derived_gen.214 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.198, id: UpdateModeId { id: 86 } }; - let #Derived_gen.215 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 87 } }; - jump #Derived_gen.72 #Derived_gen.208 #Derived_gen.214 #Derived_gen.215; + let #Derived_gen.192 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.198, id: UpdateModeId { id: 86 } }; + jump #Derived_gen.72 #Derived_gen.187 #Derived_gen.192 Test.180; else inc Test.26; decref Test.180; - let #Derived_gen.216 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.72 #Derived_gen.216 #Derived_gen.216 #Derived_gen.208; + let #Derived_gen.193 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.72 #Derived_gen.193 #Derived_gen.193 #Derived_gen.187; in let Test.228 : U8 = 1i64; let Test.229 : U8 = GetTagId Test.180; let Test.230 : Int1 = lowlevel Eq Test.228 Test.229; if Test.230 then - joinpoint Test.225 #Derived_gen.226: - joinpoint Test.216 #Derived_gen.227: + joinpoint Test.225 #Derived_gen.201: + joinpoint Test.216 #Derived_gen.202: let Test.46 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; let Test.48 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; let Test.49 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; let Test.47 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; - joinpoint #Derived_gen.66 #Derived_gen.229 #Derived_gen.230: + joinpoint #Derived_gen.66 #Derived_gen.203 #Derived_gen.204: let Test.196 : Int1 = true; - let Test.195 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.230 UpdateModeId { id: 100 } TagId(1) Test.46 Test.48 Test.49 Test.47 Test.196; + let Test.195 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.204 UpdateModeId { id: 100 } TagId(1) Test.46 Test.48 Test.49 Test.47 Test.196; let Test.194 : Int1 = false; - let Test.193 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.229 UpdateModeId { id: 99 } TagId(1) Test.195 Test.18 Test.19 Test.17 Test.194; + let Test.193 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.203 UpdateModeId { id: 99 } TagId(1) Test.195 Test.18 Test.19 Test.17 Test.194; let #Derived_gen.16 : {} = lowlevel PtrStore #Derived_gen.6 Test.193; let #Derived_gen.15 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; ret #Derived_gen.15; in let #Derived_gen.67 : Int1 = lowlevel RefCountIsUnique Test.180; if #Derived_gen.67 then - let #Derived_gen.231 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 101 } }; - jump #Derived_gen.66 #Derived_gen.227 #Derived_gen.231; + jump #Derived_gen.66 #Derived_gen.202 Test.180; else inc Test.46; inc Test.49; decref Test.180; - let #Derived_gen.232 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.66 #Derived_gen.232 #Derived_gen.227; + let #Derived_gen.205 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.66 #Derived_gen.205 #Derived_gen.202; in let Test.213 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; let Test.214 : U8 = 1i64; @@ -123,11 +121,11 @@ procedure Test.3 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): let Test.212 : Int1 = true; let Test.217 : Int1 = lowlevel Eq Test.212 Test.211; if Test.217 then - jump Test.199 #Derived_gen.226; + jump Test.199 #Derived_gen.201; else - jump Test.216 #Derived_gen.226; + jump Test.216 #Derived_gen.201; else - jump Test.216 #Derived_gen.226; + jump Test.216 #Derived_gen.201; in let Test.222 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; let Test.223 : U8 = 1i64; @@ -139,7 +137,7 @@ procedure Test.3 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): let Test.221 : Int1 = true; let Test.226 : Int1 = lowlevel Eq Test.221 Test.220; if Test.226 then - joinpoint Test.207 #Derived_gen.233: + joinpoint Test.207 #Derived_gen.206: let Test.33 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; let Test.35 : I64 = UnionAtIndex (Id 1) (Index 1) Test.180; let Test.200 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.180; @@ -150,27 +148,26 @@ procedure Test.3 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): inc Test.39; let Test.37 : I32 = UnionAtIndex (Id 1) (Index 3) Test.200; let Test.34 : I32 = UnionAtIndex (Id 1) (Index 3) Test.180; - joinpoint #Derived_gen.70 #Derived_gen.236 #Derived_gen.237 #Derived_gen.238: + joinpoint #Derived_gen.70 #Derived_gen.208 #Derived_gen.209 #Derived_gen.210: let Test.192 : Int1 = false; - let Test.189 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.238 UpdateModeId { id: 107 } TagId(1) Test.33 Test.35 Test.36 Test.34 Test.192; + let Test.189 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.210 UpdateModeId { id: 107 } TagId(1) Test.33 Test.35 Test.36 Test.34 Test.192; let Test.191 : Int1 = false; - let Test.190 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.237 UpdateModeId { id: 106 } TagId(1) Test.39 Test.18 Test.19 Test.17 Test.191; + let Test.190 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.209 UpdateModeId { id: 106 } TagId(1) Test.39 Test.18 Test.19 Test.17 Test.191; let Test.188 : Int1 = true; - let Test.187 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.236 UpdateModeId { id: 105 } TagId(1) Test.189 Test.38 Test.190 Test.37 Test.188; + let Test.187 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.208 UpdateModeId { id: 105 } TagId(1) Test.189 Test.38 Test.190 Test.37 Test.188; let #Derived_gen.18 : {} = lowlevel PtrStore #Derived_gen.6 Test.187; let #Derived_gen.17 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; ret #Derived_gen.17; in let #Derived_gen.71 : Int1 = lowlevel RefCountIsUnique Test.180; if #Derived_gen.71 then - let #Derived_gen.239 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.200, id: UpdateModeId { id: 108 } }; - let #Derived_gen.240 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.180, id: UpdateModeId { id: 109 } }; - jump #Derived_gen.70 #Derived_gen.233 #Derived_gen.239 #Derived_gen.240; + let #Derived_gen.211 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.200, id: UpdateModeId { id: 108 } }; + jump #Derived_gen.70 #Derived_gen.206 #Derived_gen.211 Test.180; else inc Test.33; decref Test.180; - let #Derived_gen.241 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.70 #Derived_gen.241 #Derived_gen.241 #Derived_gen.233; + let #Derived_gen.212 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.70 #Derived_gen.212 #Derived_gen.212 #Derived_gen.206; in let Test.204 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.180; let Test.205 : U8 = 1i64; @@ -182,33 +179,33 @@ procedure Test.3 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): let Test.203 : Int1 = true; let Test.208 : Int1 = lowlevel Eq Test.203 Test.202; if Test.208 then - jump Test.199 #Derived_gen.119; + jump Test.199 #Derived_gen.118; else - jump Test.207 #Derived_gen.119; + jump Test.207 #Derived_gen.118; else - jump Test.207 #Derived_gen.119; + jump Test.207 #Derived_gen.118; else - jump Test.225 #Derived_gen.119; + jump Test.225 #Derived_gen.118; else - jump Test.225 #Derived_gen.119; + jump Test.225 #Derived_gen.118; else - decref #Derived_gen.119; + decref #Derived_gen.118; dec Test.19; let Test.197 : [C *self I64 *self I32 Int1, ] = TagId(0) ; let #Derived_gen.20 : {} = lowlevel PtrStore #Derived_gen.6 Test.197; let #Derived_gen.19 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; ret #Derived_gen.19; else - jump Test.238 #Derived_gen.119; + jump Test.238 #Derived_gen.118; else - jump Test.238 #Derived_gen.119; + jump Test.238 #Derived_gen.118; else let Test.117 : Int1 = CallByName Num.24 Test.10 Test.17; if Test.117 then - joinpoint Test.176 #Derived_gen.333: + joinpoint Test.176 #Derived_gen.288: let Test.170 : Int1 = false; let #Derived_gen.21 : [C *self I64 *self I32 Int1, ] = NullPointer; - let Test.169 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.333 UpdateModeId { id: 196 } TagId(1) Test.16 Test.18 #Derived_gen.21 Test.17 Test.170; + let Test.169 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.288 UpdateModeId { id: 196 } TagId(1) Test.16 Test.18 #Derived_gen.21 Test.17 Test.170; let #Derived_gen.22 : Ptr([C *self I64 *self I32 Int1, ]) = UnionFieldPtrAtIndex (Id 1) (Index 2) Test.169; let #Derived_gen.23 : {} = lowlevel PtrStore #Derived_gen.6 Test.169; jump #Derived_gen.5 Test.19 Test.10 Test.11 #Derived_gen.22 #Derived_gen.7; @@ -222,9 +219,9 @@ procedure Test.3 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): let Test.177 : Int1 = lowlevel Eq Test.173 Test.172; if Test.177 then inc Test.19; - let #Derived_gen.334 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.16, id: UpdateModeId { id: 197 } }; + let #Derived_gen.289 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.16, id: UpdateModeId { id: 197 } }; let Test.118 : [C *self I64 *self I32 Int1, ] = CallByName Test.3 Test.19 Test.10 Test.11; - joinpoint Test.137 #Derived_gen.374 #Derived_gen.375: + joinpoint Test.137 #Derived_gen.322 #Derived_gen.323: let Test.136 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; let Test.57 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.136; inc Test.57; @@ -235,58 +232,56 @@ procedure Test.3 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): let Test.62 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; let Test.63 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; let Test.61 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; - joinpoint #Derived_gen.112 #Derived_gen.379 #Derived_gen.380 #Derived_gen.381: + joinpoint #Derived_gen.112 #Derived_gen.326 #Derived_gen.327 #Derived_gen.328: let Test.124 : Int1 = false; - let Test.121 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.381 UpdateModeId { id: 242 } TagId(1) Test.57 Test.59 Test.60 Test.58 Test.124; + let Test.121 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.328 UpdateModeId { id: 242 } TagId(1) Test.57 Test.59 Test.60 Test.58 Test.124; let Test.123 : Int1 = false; - let Test.122 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.380 UpdateModeId { id: 241 } TagId(1) Test.63 Test.18 Test.19 Test.17 Test.123; + let Test.122 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.327 UpdateModeId { id: 241 } TagId(1) Test.63 Test.18 Test.19 Test.17 Test.123; let Test.120 : Int1 = true; - let Test.119 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.379 UpdateModeId { id: 240 } TagId(1) Test.121 Test.62 Test.122 Test.61 Test.120; + let Test.119 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.326 UpdateModeId { id: 240 } TagId(1) Test.121 Test.62 Test.122 Test.61 Test.120; let #Derived_gen.25 : {} = lowlevel PtrStore #Derived_gen.6 Test.119; let #Derived_gen.24 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; ret #Derived_gen.24; in let #Derived_gen.113 : Int1 = lowlevel RefCountIsUnique Test.118; if #Derived_gen.113 then - decref #Derived_gen.374; - let #Derived_gen.382 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.136, id: UpdateModeId { id: 243 } }; - let #Derived_gen.383 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 244 } }; - jump #Derived_gen.112 #Derived_gen.375 #Derived_gen.382 #Derived_gen.383; + decref #Derived_gen.322; + let #Derived_gen.329 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.136, id: UpdateModeId { id: 243 } }; + jump #Derived_gen.112 #Derived_gen.323 #Derived_gen.329 Test.118; else inc Test.63; decref Test.118; - let #Derived_gen.384 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.112 #Derived_gen.384 #Derived_gen.374 #Derived_gen.375; + let #Derived_gen.330 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.112 #Derived_gen.330 #Derived_gen.322 #Derived_gen.323; in let Test.166 : U8 = 1i64; let Test.167 : U8 = GetTagId Test.118; let Test.168 : Int1 = lowlevel Eq Test.166 Test.167; if Test.168 then - joinpoint Test.163 #Derived_gen.396 #Derived_gen.397: - joinpoint Test.154 #Derived_gen.398 #Derived_gen.399: + joinpoint Test.163 #Derived_gen.340 #Derived_gen.341: + joinpoint Test.154 #Derived_gen.342 #Derived_gen.343: let Test.83 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; let Test.85 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; let Test.86 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; let Test.84 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; - joinpoint #Derived_gen.102 #Derived_gen.402 #Derived_gen.403: + joinpoint #Derived_gen.102 #Derived_gen.345 #Derived_gen.346: let Test.134 : Int1 = true; - let Test.133 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.403 UpdateModeId { id: 262 } TagId(1) Test.83 Test.85 Test.86 Test.84 Test.134; + let Test.133 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.346 UpdateModeId { id: 262 } TagId(1) Test.83 Test.85 Test.86 Test.84 Test.134; let Test.132 : Int1 = false; - let Test.131 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.402 UpdateModeId { id: 261 } TagId(1) Test.133 Test.18 Test.19 Test.17 Test.132; + let Test.131 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.345 UpdateModeId { id: 261 } TagId(1) Test.133 Test.18 Test.19 Test.17 Test.132; let #Derived_gen.27 : {} = lowlevel PtrStore #Derived_gen.6 Test.131; let #Derived_gen.26 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; ret #Derived_gen.26; in let #Derived_gen.103 : Int1 = lowlevel RefCountIsUnique Test.118; if #Derived_gen.103 then - decref #Derived_gen.398; - let #Derived_gen.404 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 263 } }; - jump #Derived_gen.102 #Derived_gen.399 #Derived_gen.404; + decref #Derived_gen.342; + jump #Derived_gen.102 #Derived_gen.343 Test.118; else inc Test.83; inc Test.86; decref Test.118; - jump #Derived_gen.102 #Derived_gen.398 #Derived_gen.399; + jump #Derived_gen.102 #Derived_gen.342 #Derived_gen.343; in let Test.151 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; let Test.152 : U8 = 1i64; @@ -298,11 +293,11 @@ procedure Test.3 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): let Test.150 : Int1 = true; let Test.155 : Int1 = lowlevel Eq Test.150 Test.149; if Test.155 then - jump Test.137 #Derived_gen.396 #Derived_gen.397; + jump Test.137 #Derived_gen.340 #Derived_gen.341; else - jump Test.154 #Derived_gen.396 #Derived_gen.397; + jump Test.154 #Derived_gen.340 #Derived_gen.341; else - jump Test.154 #Derived_gen.396 #Derived_gen.397; + jump Test.154 #Derived_gen.340 #Derived_gen.341; in let Test.160 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; let Test.161 : U8 = 1i64; @@ -314,7 +309,7 @@ procedure Test.3 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): let Test.159 : Int1 = true; let Test.164 : Int1 = lowlevel Eq Test.159 Test.158; if Test.164 then - joinpoint Test.145 #Derived_gen.405 #Derived_gen.406: + joinpoint Test.145 #Derived_gen.347 #Derived_gen.348: let Test.70 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; let Test.72 : I64 = UnionAtIndex (Id 1) (Index 1) Test.118; let Test.138 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.118; @@ -325,28 +320,27 @@ procedure Test.3 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): inc Test.76; let Test.74 : I32 = UnionAtIndex (Id 1) (Index 3) Test.138; let Test.71 : I32 = UnionAtIndex (Id 1) (Index 3) Test.118; - joinpoint #Derived_gen.106 #Derived_gen.410 #Derived_gen.411 #Derived_gen.412: + joinpoint #Derived_gen.106 #Derived_gen.351 #Derived_gen.352 #Derived_gen.353: let Test.130 : Int1 = false; - let Test.127 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.412 UpdateModeId { id: 271 } TagId(1) Test.70 Test.72 Test.73 Test.71 Test.130; + let Test.127 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.353 UpdateModeId { id: 271 } TagId(1) Test.70 Test.72 Test.73 Test.71 Test.130; let Test.129 : Int1 = false; - let Test.128 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.411 UpdateModeId { id: 270 } TagId(1) Test.76 Test.18 Test.19 Test.17 Test.129; + let Test.128 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.352 UpdateModeId { id: 270 } TagId(1) Test.76 Test.18 Test.19 Test.17 Test.129; let Test.126 : Int1 = true; - let Test.125 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.410 UpdateModeId { id: 269 } TagId(1) Test.127 Test.75 Test.128 Test.74 Test.126; + let Test.125 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.351 UpdateModeId { id: 269 } TagId(1) Test.127 Test.75 Test.128 Test.74 Test.126; let #Derived_gen.29 : {} = lowlevel PtrStore #Derived_gen.6 Test.125; let #Derived_gen.28 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; ret #Derived_gen.28; in let #Derived_gen.107 : Int1 = lowlevel RefCountIsUnique Test.118; if #Derived_gen.107 then - decref #Derived_gen.405; - let #Derived_gen.413 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.138, id: UpdateModeId { id: 272 } }; - let #Derived_gen.414 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.118, id: UpdateModeId { id: 273 } }; - jump #Derived_gen.106 #Derived_gen.406 #Derived_gen.413 #Derived_gen.414; + decref #Derived_gen.347; + let #Derived_gen.354 : [C *self I64 *self I32 Int1, ] = Reset { symbol: Test.138, id: UpdateModeId { id: 272 } }; + jump #Derived_gen.106 #Derived_gen.348 #Derived_gen.354 Test.118; else inc Test.70; decref Test.118; - let #Derived_gen.415 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.106 #Derived_gen.415 #Derived_gen.405 #Derived_gen.406; + let #Derived_gen.355 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.106 #Derived_gen.355 #Derived_gen.347 #Derived_gen.348; in let Test.142 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.118; let Test.143 : U8 = 1i64; @@ -358,18 +352,18 @@ procedure Test.3 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): let Test.141 : Int1 = true; let Test.146 : Int1 = lowlevel Eq Test.141 Test.140; if Test.146 then - jump Test.137 #Derived_gen.119 #Derived_gen.334; + jump Test.137 #Derived_gen.118 #Derived_gen.289; else - jump Test.145 #Derived_gen.119 #Derived_gen.334; + jump Test.145 #Derived_gen.118 #Derived_gen.289; else - jump Test.145 #Derived_gen.119 #Derived_gen.334; + jump Test.145 #Derived_gen.118 #Derived_gen.289; else - jump Test.163 #Derived_gen.119 #Derived_gen.334; + jump Test.163 #Derived_gen.118 #Derived_gen.289; else - jump Test.163 #Derived_gen.119 #Derived_gen.334; + jump Test.163 #Derived_gen.118 #Derived_gen.289; else - decref #Derived_gen.334; - decref #Derived_gen.119; + decref #Derived_gen.289; + decref #Derived_gen.118; joinpoint #Derived_gen.108: let Test.135 : [C *self I64 *self I32 Int1, ] = TagId(0) ; let #Derived_gen.31 : {} = lowlevel PtrStore #Derived_gen.6 Test.135; @@ -382,43 +376,42 @@ procedure Test.3 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): dec #Derived_gen.110; let #Derived_gen.109 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.19; dec #Derived_gen.109; - decref Test.19; + free Test.19; jump #Derived_gen.108; else decref Test.19; jump #Derived_gen.108; else - jump Test.176 #Derived_gen.119; + jump Test.176 #Derived_gen.118; else - jump Test.176 #Derived_gen.119; + jump Test.176 #Derived_gen.118; else let Test.116 : Int1 = false; - let Test.115 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.119 UpdateModeId { id: 1 } TagId(1) Test.16 Test.11 Test.19 Test.10 Test.116; + let Test.115 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.118 UpdateModeId { id: 1 } TagId(1) Test.16 Test.11 Test.19 Test.10 Test.116; let #Derived_gen.33 : {} = lowlevel PtrStore #Derived_gen.6 Test.115; let #Derived_gen.32 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; ret #Derived_gen.32; in let #Derived_gen.115 : Int1 = lowlevel RefCountIsUnique Test.9; if #Derived_gen.115 then - let #Derived_gen.424 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.9, id: UpdateModeId { id: 282 } }; - jump #Derived_gen.114 #Derived_gen.424; + jump #Derived_gen.114 Test.9; else inc Test.16; inc Test.19; decref Test.9; - let #Derived_gen.425 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.114 #Derived_gen.425; + let #Derived_gen.363 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.114 #Derived_gen.363; else let Test.96 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 0) Test.9; let Test.98 : I64 = UnionAtIndex (Id 1) (Index 1) Test.9; let Test.99 : [C *self I64 *self I32 Int1, ] = UnionAtIndex (Id 1) (Index 2) Test.9; let Test.97 : I32 = UnionAtIndex (Id 1) (Index 3) Test.9; - joinpoint #Derived_gen.116 #Derived_gen.427: + joinpoint #Derived_gen.116 #Derived_gen.364: let Test.247 : Int1 = CallByName Num.22 Test.10 Test.97; if Test.247 then let Test.249 : Int1 = true; let #Derived_gen.34 : [C *self I64 *self I32 Int1, ] = NullPointer; - let Test.248 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.427 UpdateModeId { id: 284 } TagId(1) #Derived_gen.34 Test.98 Test.99 Test.97 Test.249; + let Test.248 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.364 UpdateModeId { id: 284 } TagId(1) #Derived_gen.34 Test.98 Test.99 Test.97 Test.249; let #Derived_gen.35 : Ptr([C *self I64 *self I32 Int1, ]) = UnionFieldPtrAtIndex (Id 1) (Index 0) Test.248; let #Derived_gen.36 : {} = lowlevel PtrStore #Derived_gen.6 Test.248; jump #Derived_gen.5 Test.96 Test.10 Test.11 #Derived_gen.35 #Derived_gen.7; @@ -427,27 +420,26 @@ procedure Test.3 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): if Test.243 then let Test.245 : Int1 = true; let #Derived_gen.37 : [C *self I64 *self I32 Int1, ] = NullPointer; - let Test.244 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.427 UpdateModeId { id: 284 } TagId(1) Test.96 Test.98 #Derived_gen.37 Test.97 Test.245; + let Test.244 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.364 UpdateModeId { id: 284 } TagId(1) Test.96 Test.98 #Derived_gen.37 Test.97 Test.245; let #Derived_gen.38 : Ptr([C *self I64 *self I32 Int1, ]) = UnionFieldPtrAtIndex (Id 1) (Index 2) Test.244; let #Derived_gen.39 : {} = lowlevel PtrStore #Derived_gen.6 Test.244; jump #Derived_gen.5 Test.99 Test.10 Test.11 #Derived_gen.38 #Derived_gen.7; else let Test.242 : Int1 = true; - let Test.241 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.427 UpdateModeId { id: 284 } TagId(1) Test.96 Test.11 Test.99 Test.10 Test.242; + let Test.241 : [C *self I64 *self I32 Int1, ] = Reuse #Derived_gen.364 UpdateModeId { id: 284 } TagId(1) Test.96 Test.11 Test.99 Test.10 Test.242; let #Derived_gen.41 : {} = lowlevel PtrStore #Derived_gen.6 Test.241; let #Derived_gen.40 : [C *self I64 *self I32 Int1, ] = lowlevel PtrLoad #Derived_gen.7; ret #Derived_gen.40; in let #Derived_gen.117 : Int1 = lowlevel RefCountIsUnique Test.9; if #Derived_gen.117 then - let #Derived_gen.428 : [C *self I64 *self I32 Int1, ] = ResetRef { symbol: Test.9, id: UpdateModeId { id: 285 } }; - jump #Derived_gen.116 #Derived_gen.428; + jump #Derived_gen.116 Test.9; else inc Test.96; inc Test.99; decref Test.9; - let #Derived_gen.429 : [C *self I64 *self I32 Int1, ] = NullPointer; - jump #Derived_gen.116 #Derived_gen.429; + let #Derived_gen.365 : [C *self I64 *self I32 Int1, ] = NullPointer; + jump #Derived_gen.116 #Derived_gen.365; in jump #Derived_gen.5 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.3; diff --git a/crates/compiler/test_mono/generated/recursive_lambda_set_has_nested_non_recursive_lambda_sets_issue_5026.txt b/crates/compiler/test_mono/generated/recursive_lambda_set_has_nested_non_recursive_lambda_sets_issue_5026.txt index 3e08cd465da..c6a00595d7d 100644 --- a/crates/compiler/test_mono/generated/recursive_lambda_set_has_nested_non_recursive_lambda_sets_issue_5026.txt +++ b/crates/compiler/test_mono/generated/recursive_lambda_set_has_nested_non_recursive_lambda_sets_issue_5026.txt @@ -44,7 +44,7 @@ procedure Test.6 (Test.16, #Attr.12): in let #Derived_gen.3 : Int1 = lowlevel RefCountIsUnique #Attr.12; if #Derived_gen.3 then - decref #Attr.12; + free #Attr.12; jump #Derived_gen.2; else decref #Attr.12; diff --git a/crates/compiler/test_mono/generated/recursive_lambda_set_resolved_only_upon_specialization.txt b/crates/compiler/test_mono/generated/recursive_lambda_set_resolved_only_upon_specialization.txt index f053cf0a19c..a6ad8acc154 100644 --- a/crates/compiler/test_mono/generated/recursive_lambda_set_resolved_only_upon_specialization.txt +++ b/crates/compiler/test_mono/generated/recursive_lambda_set_resolved_only_upon_specialization.txt @@ -54,7 +54,7 @@ procedure Test.4 (#Derived_gen.2, #Derived_gen.3): in let #Derived_gen.5 : Int1 = lowlevel RefCountIsUnique #Attr.12; if #Derived_gen.5 then - decref #Attr.12; + free #Attr.12; jump #Derived_gen.4; else inc Test.3; diff --git a/crates/compiler/test_mono/generated/recursively_build_effect.txt b/crates/compiler/test_mono/generated/recursively_build_effect.txt index 72edafead47..d1f4bd9809b 100644 --- a/crates/compiler/test_mono/generated/recursively_build_effect.txt +++ b/crates/compiler/test_mono/generated/recursively_build_effect.txt @@ -10,7 +10,7 @@ procedure Test.11 (Test.29, #Attr.12): let Test.10 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12; let #Derived_gen.9 : Int1 = lowlevel RefCountIsUnique #Attr.12; if #Derived_gen.9 then - decref #Attr.12; + free #Attr.12; ret Test.10; else decref #Attr.12; @@ -40,7 +40,7 @@ procedure Test.14 (#Derived_gen.2, #Derived_gen.3): in let #Derived_gen.11 : Int1 = lowlevel RefCountIsUnique #Attr.12; if #Derived_gen.11 then - decref #Attr.12; + free #Attr.12; jump #Derived_gen.10; else decref #Attr.12; diff --git a/crates/compiler/test_mono/generated/specialize_after_match.txt b/crates/compiler/test_mono/generated/specialize_after_match.txt index 7dd9c9c5eb0..dfb63f7e7da 100644 --- a/crates/compiler/test_mono/generated/specialize_after_match.txt +++ b/crates/compiler/test_mono/generated/specialize_after_match.txt @@ -39,7 +39,7 @@ procedure Test.2 (Test.9, Test.10): let #Derived_gen.5 : Int1 = lowlevel RefCountIsUnique Test.9; if #Derived_gen.5 then dec Test.11; - decref Test.9; + free Test.9; jump #Derived_gen.4; else inc Test.12; @@ -65,7 +65,7 @@ procedure Test.3 (Test.17): if #Derived_gen.3 then let #Derived_gen.2 : Str = UnionAtIndex (Id 0) (Index 0) Test.17; dec #Derived_gen.2; - decref Test.17; + free Test.17; jump #Derived_gen.1; else inc Test.18; From bf2c01554fba1e8eb607f2dc53d57405c52f0049 Mon Sep 17 00:00:00 2001 From: Kilian Vounckx Date: Tue, 27 Jun 2023 20:12:02 +0200 Subject: [PATCH 088/140] Give better error messages when provides is missing in header --- crates/reporting/src/error/parse.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/reporting/src/error/parse.rs b/crates/reporting/src/error/parse.rs index abf66192240..3d1cba1403a 100644 --- a/crates/reporting/src/error/parse.rs +++ b/crates/reporting/src/error/parse.rs @@ -3469,7 +3469,7 @@ fn to_provides_report<'a>( } } - EProvides::Provides(pos) => { + EProvides::Provides(pos) | EProvides::IndentProvides(pos) => { let surroundings = Region::new(start, pos); let region = LineColumnRegion::from_pos(lines.convert_pos(pos)); From 8c02cc4ef0e1795631d5c1e2529d091bfeddc35a Mon Sep 17 00:00:00 2001 From: Folkert Date: Tue, 27 Jun 2023 20:25:32 +0200 Subject: [PATCH 089/140] only clear tag id in reset when needed --- crates/compiler/gen_llvm/src/llvm/build.rs | 26 ++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index e0eb3db1dbe..f8da031dcae 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -1180,8 +1180,14 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( let then_block = ctx.append_basic_block(parent, "then_reset"); let else_block = ctx.append_basic_block(parent, "else_decref"); - let refcount_ptr = - PointerToRefcount::from_ptr_to_data(env, tag_pointer_clear_tag_id(env, tag_ptr)); + let refcount_ptr = PointerToRefcount::from_ptr_to_data( + env, + if union_layout.stores_tag_id_in_pointer(env.target_info) { + tag_pointer_clear_tag_id(env, tag_ptr) + } else { + tag_ptr + }, + ); let is_unique = match update_mode { UpdateMode::InPlace => env.context.bool_type().const_int(1, false), @@ -1265,8 +1271,20 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( let not_unique_block = ctx.append_basic_block(parent, "else_decref"); - let refcount_ptr = - PointerToRefcount::from_ptr_to_data(env, tag_pointer_clear_tag_id(env, tag_ptr)); + // reset is only generated for union values + let union_layout = match layout_interner.get_repr(layout) { + LayoutRepr::Union(ul) => ul, + _ => unreachable!(), + }; + + let refcount_ptr = PointerToRefcount::from_ptr_to_data( + env, + if union_layout.stores_tag_id_in_pointer(env.target_info) { + tag_pointer_clear_tag_id(env, tag_ptr) + } else { + tag_ptr + }, + ); let is_unique = match update_mode { UpdateMode::InPlace => env.context.bool_type().const_int(1, false), From e95d093461a63809a5a3e88bcfe305d6877c0f35 Mon Sep 17 00:00:00 2001 From: Folkert Date: Tue, 27 Jun 2023 20:50:43 +0200 Subject: [PATCH 090/140] in dev/wasm backends, always clear tag id bits from a reset pointer --- .../mono/src/code_gen_help/refcount.rs | 88 ++++++++----------- 1 file changed, 35 insertions(+), 53 deletions(-) diff --git a/crates/compiler/mono/src/code_gen_help/refcount.rs b/crates/compiler/mono/src/code_gen_help/refcount.rs index d0e966855aa..7fcea26f453 100644 --- a/crates/compiler/mono/src/code_gen_help/refcount.rs +++ b/crates/compiler/mono/src/code_gen_help/refcount.rs @@ -456,8 +456,10 @@ pub fn refcount_reset_proc_body<'a>( root.arena.alloc(refcount_1_stmt), ); - // a Box never masks bits - let mask_lower_bits = false; + let mask_lower_bits = match layout_interner.get_repr(layout) { + LayoutRepr::Union(ul) => ul.stores_tag_id_in_pointer(root.target_info), + _ => false, + }; // Refcount pointer let rc_ptr_stmt = { @@ -579,8 +581,10 @@ pub fn refcount_resetref_proc_body<'a>( root.arena.alloc(refcount_1_stmt), ); - // a Box never masks bits - let mask_lower_bits = false; + let mask_lower_bits = match layout_interner.get_repr(layout) { + LayoutRepr::Union(ul) => ul.stores_tag_id_in_pointer(root.target_info), + _ => false, + }; // Refcount pointer let rc_ptr_stmt = { @@ -632,39 +636,33 @@ fn rc_ptr_from_data_ptr_help<'a>( addr_sym: Symbol, recursion_ptr: InLayout<'a>, ) -> Stmt<'a> { - use std::ops::Neg; - - // Typecast the structure pointer to an integer - // Backends expect a number Layout to choose the right "subtract" instruction - let as_int_sym = if mask_lower_bits { - root.create_symbol(ident_ids, "as_int") + // symbol of a pointer with any tag id bits cleared + let cleared_sym = if mask_lower_bits { + root.create_symbol(ident_ids, "cleared") } else { - addr_sym + structure }; - let as_int_expr = Expr::Call(Call { + + let clear_tag_id_expr = Expr::Call(Call { call_type: CallType::LowLevel { - op: LowLevel::PtrCast, + op: LowLevel::PtrClearTagId, update_mode: UpdateModeId::BACKEND_DUMMY, }, arguments: root.arena.alloc([structure]), }); - let as_int_stmt = |next| Stmt::Let(as_int_sym, as_int_expr, root.layout_isize, next); + let clear_tag_id_stmt = + |next| Stmt::Let(cleared_sym, clear_tag_id_expr, root.layout_isize, next); - // Mask for lower bits (for tag union id) - let mask_sym = root.create_symbol(ident_ids, "mask"); - let mask_expr = Expr::Literal(Literal::Int( - (root.target_info.ptr_width() as i128).neg().to_ne_bytes(), - )); - let mask_stmt = |next| Stmt::Let(mask_sym, mask_expr, root.layout_isize, next); - - let and_expr = Expr::Call(Call { + // Typecast the structure pointer to an integer + // Backends expect a number Layout to choose the right "subtract" instruction + let as_int_expr = Expr::Call(Call { call_type: CallType::LowLevel { - op: LowLevel::And, + op: LowLevel::PtrCast, update_mode: UpdateModeId::BACKEND_DUMMY, }, - arguments: root.arena.alloc([as_int_sym, mask_sym]), + arguments: root.arena.alloc([cleared_sym]), }); - let and_stmt = |next| Stmt::Let(addr_sym, and_expr, root.layout_isize, next); + let as_int_stmt = |next| Stmt::Let(addr_sym, as_int_expr, root.layout_isize, next); // Pointer size constant let ptr_size_sym = root.create_symbol(ident_ids, "ptr_size"); @@ -694,40 +692,24 @@ fn rc_ptr_from_data_ptr_help<'a>( }); let cast_stmt = |next| Stmt::Let(rc_ptr_sym, cast_expr, recursion_ptr, next); - if mask_lower_bits { - as_int_stmt(root.arena.alloc( + let body = as_int_stmt(root.arena.alloc( + // + ptr_size_stmt(root.arena.alloc( // - mask_stmt(root.arena.alloc( + sub_stmt(root.arena.alloc( // - and_stmt(root.arena.alloc( + cast_stmt(root.arena.alloc( // - ptr_size_stmt(root.arena.alloc( - // - sub_stmt(root.arena.alloc( - // - cast_stmt(root.arena.alloc( - // - following, - )), - )), - )), + following, )), )), - )) + )), + )); + + if mask_lower_bits { + clear_tag_id_stmt(root.arena.alloc(body)) } else { - as_int_stmt(root.arena.alloc( - // - ptr_size_stmt(root.arena.alloc( - // - sub_stmt(root.arena.alloc( - // - cast_stmt(root.arena.alloc( - // - following, - )), - )), - )), - )) + body } } From 3bc8a33668bfe62d757816cc1da71b9562884172 Mon Sep 17 00:00:00 2001 From: Kilian Vounckx Date: Tue, 27 Jun 2023 20:50:48 +0200 Subject: [PATCH 091/140] Add missing provides error message test --- crates/reporting/tests/test_reporting.rs | 34 ++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/crates/reporting/tests/test_reporting.rs b/crates/reporting/tests/test_reporting.rs index aeed31a9fcc..d186cd20bed 100644 --- a/crates/reporting/tests/test_reporting.rs +++ b/crates/reporting/tests/test_reporting.rs @@ -5938,6 +5938,40 @@ In roc, functions are always written as a lambda, like{} ) } + #[test] + fn missing_provides_in_app_header() { + report_header_problem_as( + indoc!( + r#" + app "broken" + packages { + pf: "https://github.com/roc-lang/basic-cli/releases/download/0.3.2/tE4xS_zLdmmxmHwHih9kHWQ7fsXtJr7W7h3425-eZFk.tar.br", + } + imports [ + pf.Stdout, + ] + + main = + Stdout.line "answer" + "# + ), + indoc!( + r#" + ── WEIRD PROVIDES ──────────────────────────────────────── /code/proj/Main.roc ─ + + I am partway through parsing a header, but I got stuck here: + + 7│ ] + ^ + + I am expecting the `provides` keyword next, like + + provides [Animal, default, tame] + "# + ), + ) + } + #[test] fn platform_requires_rigids() { report_header_problem_as( From 437fb7e46c04d6ff280e8b34ea03bfdd49e7f6a8 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Tue, 27 Jun 2023 14:53:48 -0400 Subject: [PATCH 092/140] Update mono tests --- crates/compiler/test_mono/generated/dict.txt | 40 ++++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/crates/compiler/test_mono/generated/dict.txt b/crates/compiler/test_mono/generated/dict.txt index faed8e7fc74..1cb0f5bc2b1 100644 --- a/crates/compiler/test_mono/generated/dict.txt +++ b/crates/compiler/test_mono/generated/dict.txt @@ -1,28 +1,28 @@ -procedure Dict.1 (Dict.537): - let Dict.546 : List {[], []} = Array []; - let Dict.553 : U64 = 0i64; - let Dict.554 : U64 = 8i64; - let Dict.547 : List U64 = CallByName List.11 Dict.553 Dict.554; - let Dict.550 : I8 = CallByName Dict.36; - let Dict.551 : U64 = 8i64; - let Dict.548 : List I8 = CallByName List.11 Dict.550 Dict.551; - let Dict.549 : U64 = 0i64; - let Dict.545 : {List {[], []}, List U64, List I8, U64} = Struct {Dict.546, Dict.547, Dict.548, Dict.549}; - ret Dict.545; +procedure Dict.1 (Dict.556): + let Dict.565 : List {[], []} = Array []; + let Dict.572 : U64 = 0i64; + let Dict.573 : U64 = 8i64; + let Dict.566 : List U64 = CallByName List.11 Dict.572 Dict.573; + let Dict.569 : I8 = CallByName Dict.39; + let Dict.570 : U64 = 8i64; + let Dict.567 : List I8 = CallByName List.11 Dict.569 Dict.570; + let Dict.568 : U64 = 0i64; + let Dict.564 : {List {[], []}, List U64, List I8, U64} = Struct {Dict.565, Dict.566, Dict.567, Dict.568}; + ret Dict.564; -procedure Dict.36 (): - let Dict.552 : I8 = -128i64; - ret Dict.552; +procedure Dict.39 (): + let Dict.571 : I8 = -128i64; + ret Dict.571; -procedure Dict.4 (Dict.543): - let Dict.97 : U64 = StructAtIndex 3 Dict.543; - let #Derived_gen.8 : List {[], []} = StructAtIndex 0 Dict.543; +procedure Dict.4 (Dict.562): + let Dict.100 : U64 = StructAtIndex 3 Dict.562; + let #Derived_gen.8 : List {[], []} = StructAtIndex 0 Dict.562; dec #Derived_gen.8; - let #Derived_gen.7 : List U64 = StructAtIndex 1 Dict.543; + let #Derived_gen.7 : List U64 = StructAtIndex 1 Dict.562; dec #Derived_gen.7; - let #Derived_gen.6 : List I8 = StructAtIndex 2 Dict.543; + let #Derived_gen.6 : List I8 = StructAtIndex 2 Dict.562; dec #Derived_gen.6; - ret Dict.97; + ret Dict.100; procedure List.11 (List.121, List.122): let List.522 : List I8 = CallByName List.68 List.122; From 48e6ef79a42c9088642f2815d2b2a3e44adffb1d Mon Sep 17 00:00:00 2001 From: Folkert Date: Tue, 27 Jun 2023 20:55:28 +0200 Subject: [PATCH 093/140] we no longer care where a tag layout stores the tag id --- crates/compiler/mono/src/reset_reuse.rs | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/crates/compiler/mono/src/reset_reuse.rs b/crates/compiler/mono/src/reset_reuse.rs index 1b2fd6a98f6..1fb2b581641 100644 --- a/crates/compiler/mono/src/reset_reuse.rs +++ b/crates/compiler/mono/src/reset_reuse.rs @@ -1122,7 +1122,6 @@ Struct to to check whether two reuse layouts are interchangeable. */ #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] struct TokenLayout { - has_tag: bool, size: u32, alignment: u32, } @@ -1416,16 +1415,6 @@ fn get_reuse_layout_info<'a, 'i>( union_layout: UnionLayout<'a>, ) -> TokenLayout { let (size, alignment) = union_layout.data_size_and_alignment(layout_interner); - let has_tag = match union_layout { - UnionLayout::NonRecursive(_) => unreachable!("Non recursive unions should not be reused."), - // The memory for union layouts that has a tag_id can be reused for new allocations with tag_id. - UnionLayout::Recursive(_) | UnionLayout::NullableWrapped { .. } => true, - // The memory for union layouts that have no tag_id can be reused for new allocations without tag_id - UnionLayout::NonNullableUnwrapped(_) | UnionLayout::NullableUnwrapped { .. } => false, - }; - TokenLayout { - has_tag, - size, - alignment, - } + + TokenLayout { size, alignment } } From f12b378249916aaef141c58d182ada07a456b632 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Tue, 27 Jun 2023 16:20:27 -0400 Subject: [PATCH 094/140] cargo uitest --- .../uitest/tests/ability/specialize/set_eq_issue_4761.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/compiler/uitest/tests/ability/specialize/set_eq_issue_4761.txt b/crates/compiler/uitest/tests/ability/specialize/set_eq_issue_4761.txt index 1387893fab3..b8fa24db29a 100644 --- a/crates/compiler/uitest/tests/ability/specialize/set_eq_issue_4761.txt +++ b/crates/compiler/uitest/tests/ability/specialize/set_eq_issue_4761.txt @@ -8,5 +8,5 @@ main = s2 = Set.empty {} Bool.isEq s1 s1 && Bool.isEq s2 s2 -# ^^^^^^^^^ Set#Bool.isEq(17): Set Str, Set Str -[[Set.isEq(17)]]-> Bool -# ^^^^^^^^^ Set#Bool.isEq(17): Set U8, Set U8 -[[Set.isEq(17)]]-> Bool +# ^^^^^^^^^ Set#Bool.isEq(20): Set Str, Set Str -[[Set.isEq(20)]]-> Bool +# ^^^^^^^^^ Set#Bool.isEq(20): Set U8, Set U8 -[[Set.isEq(20)]]-> Bool From 40f2dd7030f73e51822b755ad417186a8a90a51e Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Wed, 28 Jun 2023 22:22:36 -0400 Subject: [PATCH 095/140] Extract some modules out of file.rs --- crates/compiler/load/src/lib.rs | 7 +- crates/compiler/load_internal/src/file.rs | 394 +----------------- crates/compiler/load_internal/src/lib.rs | 2 + crates/compiler/load_internal/src/module.rs | 306 ++++++++++++++ .../load_internal/src/module_cache.rs | 110 +++++ .../compiler/load_internal/tests/test_load.rs | 6 +- crates/compiler/test_derive/src/util.rs | 3 +- 7 files changed, 440 insertions(+), 388 deletions(-) create mode 100644 crates/compiler/load_internal/src/module.rs create mode 100644 crates/compiler/load_internal/src/module_cache.rs diff --git a/crates/compiler/load/src/lib.rs b/crates/compiler/load/src/lib.rs index 3f66ff742a3..ff7e4ec5749 100644 --- a/crates/compiler/load/src/lib.rs +++ b/crates/compiler/load/src/lib.rs @@ -18,8 +18,11 @@ const SKIP_SUBS_CACHE: bool = { pub use roc_load_internal::docs; pub use roc_load_internal::file::{ - EntryPoint, ExecutionMode, ExpectMetadata, Expectations, ExposedToHost, LoadConfig, LoadResult, - LoadStart, LoadedModule, LoadingProblem, MonomorphizedModule, Phase, Threading, + ExecutionMode, ExpectMetadata, LoadConfig, LoadResult, LoadStart, LoadingProblem, Phase, + Threading, +}; +pub use roc_load_internal::module::{ + EntryPoint, Expectations, ExposedToHost, LoadedModule, MonomorphizedModule, }; #[allow(clippy::too_many_arguments)] diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index 661feb9bd8e..f219ae0a602 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -1,6 +1,12 @@ #![allow(clippy::too_many_arguments)] use crate::docs::ModuleDocumentation; +use crate::module::{ + ConstrainedModule, EntryPoint, Expectations, ExposedToHost, FoundSpecializationsModule, + LateSpecializationsModule, LoadedModule, ModuleHeader, ModuleTiming, MonomorphizedModule, + ParsedModule, ToplevelExpects, TypeCheckedModule, +}; +use crate::module_cache::ModuleCache; use bumpalo::{collections::CollectIn, Bump}; use crossbeam::channel::{bounded, Sender}; use crossbeam::deque::{Injector, Stealer, Worker}; @@ -32,8 +38,8 @@ use roc_module::symbol::{ PackageQualified, Symbol, }; use roc_mono::ir::{ - CapturedSymbols, ExternalSpecializations, GlueLayouts, LambdaSetId, PartialProc, Proc, - ProcLayout, Procs, ProcsBase, UpdateModeIds, UsageTrackingMap, + CapturedSymbols, ExternalSpecializations, GlueLayouts, PartialProc, Proc, ProcLayout, Procs, + ProcsBase, UpdateModeIds, UsageTrackingMap, }; use roc_mono::layout::LayoutInterner; use roc_mono::layout::{ @@ -43,13 +49,12 @@ use roc_mono::reset_reuse; use roc_mono::{drop_specialization, inc_dec}; use roc_packaging::cache::RocCacheDir; use roc_parse::ast::{ - self, CommentOrNewline, Defs, Expr, ExtractSpaces, Pattern, Spaced, StrLiteral, TypeAnnotation, - ValueDef, + self, CommentOrNewline, Expr, ExtractSpaces, Pattern, Spaced, StrLiteral, ValueDef, }; use roc_parse::header::{ - ExposedName, ImportsEntry, PackageEntry, PackageHeader, PlatformHeader, To, TypedIdent, + ExposedName, HeaderType, ImportsEntry, PackageEntry, PackageHeader, PlatformHeader, To, + TypedIdent, }; -use roc_parse::header::{HeaderType, PackageName}; use roc_parse::module::module_defs; use roc_parse::parser::{FileError, Parser, SourceError, SyntaxError}; use roc_problem::Severity; @@ -136,101 +141,6 @@ impl ExecutionMode { } } -/// Struct storing various intermediate stages by their ModuleId -#[derive(Debug)] -struct ModuleCache<'a> { - module_names: MutMap>, - - /// Phases - headers: MutMap>, - parsed: MutMap>, - aliases: MutMap>, - pending_abilities: MutMap, - constrained: MutMap, - typechecked: MutMap>, - found_specializations: MutMap>, - late_specializations: MutMap>, - external_specializations_requested: MutMap>>, - - /// Various information - imports: MutMap>, - top_level_thunks: MutMap>, - documentation: VecMap, - can_problems: MutMap>, - type_problems: MutMap>, - - sources: MutMap, -} - -impl<'a> ModuleCache<'a> { - fn has_can_errors(&self) -> bool { - self.can_problems - .values() - .flatten() - .any(|problem| problem.severity() == Severity::RuntimeError) - } - - fn has_type_errors(&self) -> bool { - self.type_problems - .values() - .flatten() - .any(|problem| problem.severity() == Severity::RuntimeError) - } - - pub fn has_errors(&self) -> bool { - self.has_can_errors() || self.has_type_errors() - } -} - -impl Default for ModuleCache<'_> { - fn default() -> Self { - let mut module_names = MutMap::default(); - - macro_rules! insert_builtins { - ($($name:ident,)*) => {$( - module_names.insert( - ModuleId::$name, - PQModuleName::Unqualified(ModuleName::from(ModuleName::$name)), - ); - )*} - } - - insert_builtins! { - RESULT, - LIST, - STR, - DICT, - SET, - BOOL, - NUM, - BOX, - ENCODE, - DECODE, - HASH, - JSON, - } - - Self { - module_names, - headers: Default::default(), - parsed: Default::default(), - aliases: Default::default(), - pending_abilities: Default::default(), - constrained: Default::default(), - typechecked: Default::default(), - found_specializations: Default::default(), - late_specializations: Default::default(), - external_specializations_requested: Default::default(), - imports: Default::default(), - top_level_thunks: Default::default(), - documentation: Default::default(), - can_problems: Default::default(), - type_problems: Default::default(), - sources: Default::default(), - } - } -} - type SharedIdentIdsByModule = Arc>; fn start_phase<'a>( @@ -625,157 +535,6 @@ fn start_phase<'a>( vec![task] } -#[derive(Debug)] -pub struct LoadedModule { - pub module_id: ModuleId, - pub interns: Interns, - pub solved: Solved, - pub can_problems: MutMap>, - pub type_problems: MutMap>, - pub declarations_by_id: MutMap, - pub exposed_to_host: MutMap, - pub dep_idents: IdentIdsByModule, - pub exposed_aliases: MutMap, - pub exposed_values: Vec, - pub exposed_types_storage: ExposedTypesStorageSubs, - pub resolved_implementations: ResolvedImplementations, - pub sources: MutMap)>, - pub timings: MutMap, - pub docs_by_module: VecMap, - pub abilities_store: AbilitiesStore, -} - -impl LoadedModule { - pub fn total_problems(&self) -> usize { - let mut total = 0; - - for problems in self.can_problems.values() { - total += problems.len(); - } - - for problems in self.type_problems.values() { - total += problems.len(); - } - - total - } - - pub fn exposed_values_str(&self) -> Vec<&str> { - self.exposed_values - .iter() - .map(|symbol| symbol.as_str(&self.interns)) - .collect() - } - - pub fn exposed_aliases_str(&self) -> Vec<&str> { - self.exposed_aliases - .keys() - .map(|symbol| symbol.as_str(&self.interns)) - .collect() - } -} - -#[derive(Debug)] -pub enum BuildProblem<'a> { - FileNotFound(&'a Path), -} - -#[derive(Debug)] -struct ModuleHeader<'a> { - module_id: ModuleId, - module_path: PathBuf, - is_root_module: bool, - exposed_ident_ids: IdentIds, - deps_by_name: MutMap, ModuleId>, - packages: MutMap<&'a str, PackageName<'a>>, - imported_modules: MutMap, - package_qualified_imported_modules: MutSet>, - exposes: Vec, - exposed_imports: MutMap, - parse_state: roc_parse::state::State<'a>, - header_type: HeaderType<'a>, - header_comments: &'a [CommentOrNewline<'a>], - symbols_from_requires: Vec<(Loc, Loc>)>, - module_timing: ModuleTiming, - defined_values: Vec>, -} - -#[derive(Debug)] -struct ConstrainedModule { - module: Module, - declarations: Declarations, - imported_modules: MutMap, - constraints: Constraints, - constraint: ConstraintSoa, - ident_ids: IdentIds, - var_store: VarStore, - dep_idents: IdentIdsByModule, - module_timing: ModuleTiming, - types: Types, - // Rather than adding pending derives as constraints, hand them directly to solve because they - // must be solved at the end of a module. - pending_derives: PendingDerives, -} - -#[derive(Debug)] -pub struct TypeCheckedModule<'a> { - pub module_id: ModuleId, - pub layout_cache: LayoutCache<'a>, - pub module_timing: ModuleTiming, - pub solved_subs: Solved, - pub decls: Declarations, - pub ident_ids: IdentIds, - pub abilities_store: AbilitiesStore, - pub expectations: Option, -} - -#[derive(Debug)] -struct FoundSpecializationsModule<'a> { - ident_ids: IdentIds, - layout_cache: LayoutCache<'a>, - procs_base: ProcsBase<'a>, - subs: Subs, - module_timing: ModuleTiming, - abilities_store: AbilitiesStore, - expectations: Option, -} - -#[derive(Debug)] -struct LateSpecializationsModule<'a> { - ident_ids: IdentIds, - subs: Subs, - module_timing: ModuleTiming, - layout_cache: LayoutCache<'a>, - procs_base: ProcsBase<'a>, - expectations: Option, -} - -#[derive(Debug, Default)] -pub struct ToplevelExpects { - pub pure: VecMap, - pub fx: VecMap, -} - -#[derive(Debug)] -pub struct MonomorphizedModule<'a> { - pub module_id: ModuleId, - pub interns: Interns, - pub subs: Subs, - pub layout_interner: STLayoutInterner<'a>, - pub output_path: Box, - pub can_problems: MutMap>, - pub type_problems: MutMap>, - pub procedures: MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>, - pub toplevel_expects: ToplevelExpects, - pub entry_point: EntryPoint<'a>, - pub exposed_to_host: ExposedToHost, - pub sources: MutMap)>, - pub timings: MutMap, - pub expectations: VecMap, - pub uses_prebuilt_platform: bool, - pub glue_layouts: GlueLayouts<'a>, -} - /// Values used to render expect output pub struct ExpectMetadata<'a> { pub interns: Interns, @@ -783,67 +542,6 @@ pub struct ExpectMetadata<'a> { pub expectations: VecMap, } -#[derive(Debug)] -pub enum EntryPoint<'a> { - Executable { - exposed_to_host: &'a [(Symbol, ProcLayout<'a>)], - platform_path: PathBuf, - }, - Test, -} - -#[derive(Debug)] -pub struct Expectations { - pub subs: roc_types::subs::Subs, - pub path: PathBuf, - pub expectations: VecMap>, - pub dbgs: VecMap, - pub ident_ids: IdentIds, -} - -#[derive(Clone, Debug, Default)] -pub struct ExposedToHost { - /// usually `mainForHost` - pub top_level_values: MutMap, - /// exposed closure types, typically `Fx` - pub closure_types: Vec, - /// lambda_sets - pub lambda_sets: Vec<(Symbol, LambdaSetId)>, - pub getters: Vec, -} - -impl<'a> MonomorphizedModule<'a> { - pub fn total_problems(&self) -> usize { - let mut total = 0; - - for problems in self.can_problems.values() { - total += problems.len(); - } - - for problems in self.type_problems.values() { - total += problems.len(); - } - - total - } -} - -#[derive(Debug)] -struct ParsedModule<'a> { - module_id: ModuleId, - module_path: PathBuf, - src: &'a str, - module_timing: ModuleTiming, - deps_by_name: MutMap, ModuleId>, - imported_modules: MutMap, - exposed_ident_ids: IdentIds, - exposed_imports: MutMap, - parsed_defs: Defs<'a>, - symbols_from_requires: Vec<(Loc, Loc>)>, - header_type: HeaderType<'a>, - header_comments: &'a [CommentOrNewline<'a>], -} - type LocExpects = VecMap>; type LocDbgs = VecMap; @@ -1091,76 +789,6 @@ impl<'a> State<'a> { } } -#[derive(Debug)] -pub struct ModuleTiming { - pub read_roc_file: Duration, - pub parse_header: Duration, - pub parse_body: Duration, - pub canonicalize: Duration, - pub constrain: Duration, - pub solve: Duration, - pub find_specializations: Duration, - // indexed by make specializations pass - pub make_specializations: Vec, - // TODO pub monomorphize: Duration, - /// Total duration will always be more than the sum of the other fields, due - /// to things like state lookups in between phases, waiting on other threads, etc. - start_time: Instant, - end_time: Instant, -} - -impl ModuleTiming { - pub fn new(start_time: Instant) -> Self { - ModuleTiming { - read_roc_file: Duration::default(), - parse_header: Duration::default(), - parse_body: Duration::default(), - canonicalize: Duration::default(), - constrain: Duration::default(), - solve: Duration::default(), - find_specializations: Duration::default(), - make_specializations: Vec::with_capacity(2), - start_time, - end_time: start_time, // just for now; we'll overwrite this at the end - } - } - - pub fn total(&self) -> Duration { - self.end_time.duration_since(self.start_time) - } - - /// Subtract all the other fields from total_start_to_finish - pub fn other(&self) -> Duration { - let Self { - read_roc_file, - parse_header, - parse_body, - canonicalize, - constrain, - solve, - find_specializations, - make_specializations, - start_time, - end_time, - } = self; - - let calculate = |d: Option| -> Option { - make_specializations - .iter() - .fold(d, |d, pass_time| d?.checked_sub(*pass_time))? - .checked_sub(*find_specializations)? - .checked_sub(*solve)? - .checked_sub(*constrain)? - .checked_sub(*canonicalize)? - .checked_sub(*parse_body)? - .checked_sub(*parse_header)? - .checked_sub(*read_roc_file) - }; - - calculate(Some(end_time.duration_since(*start_time))).unwrap_or_default() - } -} - fn report_timing( buf: &mut impl std::fmt::Write, label: &str, diff --git a/crates/compiler/load_internal/src/lib.rs b/crates/compiler/load_internal/src/lib.rs index 5aca83faa41..6bdb0cabbd7 100644 --- a/crates/compiler/load_internal/src/lib.rs +++ b/crates/compiler/load_internal/src/lib.rs @@ -6,6 +6,8 @@ use roc_module::symbol::ModuleId; pub mod docs; pub mod file; +pub mod module; +mod module_cache; mod work; #[cfg(target_family = "wasm")] diff --git a/crates/compiler/load_internal/src/module.rs b/crates/compiler/load_internal/src/module.rs new file mode 100644 index 00000000000..8eb1b29d4cb --- /dev/null +++ b/crates/compiler/load_internal/src/module.rs @@ -0,0 +1,306 @@ +use crate::docs::ModuleDocumentation; +use roc_can::constraint::{Constraint as ConstraintSoa, Constraints}; +use roc_can::expr::{DbgLookup, ExpectLookup}; +use roc_can::{ + abilities::AbilitiesStore, + expr::{Declarations, PendingDerives}, + module::{Module, ResolvedImplementations}, +}; +use roc_collections::{MutMap, MutSet, VecMap}; +use roc_module::ident::Ident; +use roc_module::symbol::{ + IdentIds, IdentIdsByModule, Interns, ModuleId, PQModuleName, PackageQualified, Symbol, +}; +use roc_mono::ir::{GlueLayouts, LambdaSetId, Proc, ProcLayout, ProcsBase}; +use roc_mono::layout::{LayoutCache, STLayoutInterner}; +use roc_parse::ast::{CommentOrNewline, Defs, TypeAnnotation, ValueDef}; +use roc_parse::header::{HeaderType, PackageName}; +use roc_region::all::{Loc, Region}; +use roc_solve::module::Solved; +use roc_solve_problem::TypeError; +use roc_types::subs::{ExposedTypesStorageSubs, Subs, VarStore, Variable}; +use roc_types::types::{Alias, Types}; +use std::path::Path; +use std::path::PathBuf; + +#[cfg(target_family = "wasm")] +use crate::wasm_instant::{Duration, Instant}; +#[cfg(not(target_family = "wasm"))] +use std::time::{Duration, Instant}; + +#[derive(Debug)] +pub struct LoadedModule { + pub module_id: ModuleId, + pub interns: Interns, + pub solved: Solved, + pub can_problems: MutMap>, + pub type_problems: MutMap>, + pub declarations_by_id: MutMap, + pub exposed_to_host: MutMap, + pub dep_idents: IdentIdsByModule, + pub exposed_aliases: MutMap, + pub exposed_values: Vec, + pub exposed_types_storage: ExposedTypesStorageSubs, + pub resolved_implementations: ResolvedImplementations, + pub sources: MutMap)>, + pub timings: MutMap, + pub docs_by_module: VecMap, + pub abilities_store: AbilitiesStore, +} + +impl LoadedModule { + pub fn total_problems(&self) -> usize { + let mut total = 0; + + for problems in self.can_problems.values() { + total += problems.len(); + } + + for problems in self.type_problems.values() { + total += problems.len(); + } + + total + } + + pub fn exposed_values_str(&self) -> Vec<&str> { + self.exposed_values + .iter() + .map(|symbol| symbol.as_str(&self.interns)) + .collect() + } + + pub fn exposed_aliases_str(&self) -> Vec<&str> { + self.exposed_aliases + .keys() + .map(|symbol| symbol.as_str(&self.interns)) + .collect() + } +} + +#[derive(Debug)] +pub(crate) struct ModuleHeader<'a> { + pub(crate) module_id: ModuleId, + pub(crate) module_path: PathBuf, + pub(crate) is_root_module: bool, + pub(crate) exposed_ident_ids: IdentIds, + pub(crate) deps_by_name: MutMap, ModuleId>, + pub(crate) packages: MutMap<&'a str, PackageName<'a>>, + pub(crate) imported_modules: MutMap, + pub(crate) package_qualified_imported_modules: MutSet>, + pub(crate) exposes: Vec, + pub(crate) exposed_imports: MutMap, + pub(crate) parse_state: roc_parse::state::State<'a>, + pub(crate) header_type: HeaderType<'a>, + pub(crate) header_comments: &'a [CommentOrNewline<'a>], + pub(crate) symbols_from_requires: Vec<(Loc, Loc>)>, + pub(crate) module_timing: ModuleTiming, + pub(crate) defined_values: Vec>, +} + +#[derive(Debug)] +pub(crate) struct ConstrainedModule { + pub(crate) module: Module, + pub(crate) declarations: Declarations, + pub(crate) imported_modules: MutMap, + pub(crate) constraints: Constraints, + pub(crate) constraint: ConstraintSoa, + pub(crate) ident_ids: IdentIds, + pub(crate) var_store: VarStore, + pub(crate) dep_idents: IdentIdsByModule, + pub(crate) module_timing: ModuleTiming, + pub(crate) types: Types, + // Rather than adding pending derives as constraints, hand them directly to solve because they + // must be solved at the end of a module. + pub(crate) pending_derives: PendingDerives, +} + +#[derive(Debug)] +pub struct TypeCheckedModule<'a> { + pub module_id: ModuleId, + pub layout_cache: LayoutCache<'a>, + pub module_timing: ModuleTiming, + pub solved_subs: Solved, + pub decls: Declarations, + pub ident_ids: IdentIds, + pub abilities_store: AbilitiesStore, + pub expectations: Option, +} + +#[derive(Debug)] +pub(crate) struct FoundSpecializationsModule<'a> { + pub(crate) ident_ids: IdentIds, + pub(crate) layout_cache: LayoutCache<'a>, + pub(crate) procs_base: ProcsBase<'a>, + pub(crate) subs: Subs, + pub(crate) module_timing: ModuleTiming, + pub(crate) abilities_store: AbilitiesStore, + pub(crate) expectations: Option, +} + +#[derive(Debug)] +pub(crate) struct LateSpecializationsModule<'a> { + pub(crate) ident_ids: IdentIds, + pub(crate) subs: Subs, + pub(crate) module_timing: ModuleTiming, + pub(crate) layout_cache: LayoutCache<'a>, + pub(crate) procs_base: ProcsBase<'a>, + pub(crate) expectations: Option, +} + +#[derive(Debug, Default)] +pub struct ToplevelExpects { + pub pure: VecMap, + pub fx: VecMap, +} + +#[derive(Debug)] +pub struct MonomorphizedModule<'a> { + pub module_id: ModuleId, + pub interns: Interns, + pub subs: Subs, + pub layout_interner: STLayoutInterner<'a>, + pub output_path: Box, + pub can_problems: MutMap>, + pub type_problems: MutMap>, + pub procedures: MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>, + pub toplevel_expects: ToplevelExpects, + pub entry_point: EntryPoint<'a>, + pub exposed_to_host: ExposedToHost, + pub sources: MutMap)>, + pub timings: MutMap, + pub expectations: VecMap, + pub uses_prebuilt_platform: bool, + pub glue_layouts: GlueLayouts<'a>, +} + +#[derive(Debug)] +pub struct ParsedModule<'a> { + pub module_id: ModuleId, + pub module_path: PathBuf, + pub src: &'a str, + pub module_timing: ModuleTiming, + pub deps_by_name: MutMap, ModuleId>, + pub imported_modules: MutMap, + pub exposed_ident_ids: IdentIds, + pub exposed_imports: MutMap, + pub parsed_defs: Defs<'a>, + pub symbols_from_requires: Vec<(Loc, Loc>)>, + pub header_type: HeaderType<'a>, + pub header_comments: &'a [CommentOrNewline<'a>], +} + +#[derive(Debug)] +pub enum EntryPoint<'a> { + Executable { + exposed_to_host: &'a [(Symbol, ProcLayout<'a>)], + platform_path: PathBuf, + }, + Test, +} + +#[derive(Debug)] +pub struct Expectations { + pub subs: roc_types::subs::Subs, + pub path: PathBuf, + pub expectations: VecMap>, + pub dbgs: VecMap, + pub ident_ids: IdentIds, +} + +#[derive(Clone, Debug, Default)] +pub struct ExposedToHost { + /// usually `mainForHost` + pub top_level_values: MutMap, + /// exposed closure types, typically `Fx` + pub closure_types: Vec, + /// lambda_sets + pub lambda_sets: Vec<(Symbol, LambdaSetId)>, + pub getters: Vec, +} + +impl<'a> MonomorphizedModule<'a> { + pub fn total_problems(&self) -> usize { + let mut total = 0; + + for problems in self.can_problems.values() { + total += problems.len(); + } + + for problems in self.type_problems.values() { + total += problems.len(); + } + + total + } +} + +#[derive(Debug)] +pub struct ModuleTiming { + pub read_roc_file: Duration, + pub parse_header: Duration, + pub parse_body: Duration, + pub canonicalize: Duration, + pub constrain: Duration, + pub solve: Duration, + pub find_specializations: Duration, + // indexed by make specializations pass + pub make_specializations: Vec, + // TODO pub monomorphize: Duration, + /// Total duration will always be more than the sum of the other fields, due + /// to things like state lookups in between phases, waiting on other threads, etc. + pub start_time: Instant, + pub end_time: Instant, +} + +impl ModuleTiming { + pub fn new(start_time: Instant) -> Self { + ModuleTiming { + read_roc_file: Duration::default(), + parse_header: Duration::default(), + parse_body: Duration::default(), + canonicalize: Duration::default(), + constrain: Duration::default(), + solve: Duration::default(), + find_specializations: Duration::default(), + make_specializations: Vec::with_capacity(2), + start_time, + end_time: start_time, // just for now; we'll overwrite this at the end + } + } + + pub fn total(&self) -> Duration { + self.end_time.duration_since(self.start_time) + } + + /// Subtract all the other fields from total_start_to_finish + pub fn other(&self) -> Duration { + let Self { + read_roc_file, + parse_header, + parse_body, + canonicalize, + constrain, + solve, + find_specializations, + make_specializations, + start_time, + end_time, + } = self; + + let calculate = |d: Option| -> Option { + make_specializations + .iter() + .fold(d, |d, pass_time| d?.checked_sub(*pass_time))? + .checked_sub(*find_specializations)? + .checked_sub(*solve)? + .checked_sub(*constrain)? + .checked_sub(*canonicalize)? + .checked_sub(*parse_body)? + .checked_sub(*parse_header)? + .checked_sub(*read_roc_file) + }; + + calculate(Some(end_time.duration_since(*start_time))).unwrap_or_default() + } +} diff --git a/crates/compiler/load_internal/src/module_cache.rs b/crates/compiler/load_internal/src/module_cache.rs new file mode 100644 index 00000000000..ec2bea79f79 --- /dev/null +++ b/crates/compiler/load_internal/src/module_cache.rs @@ -0,0 +1,110 @@ +use crate::docs::ModuleDocumentation; +use crate::module::{ + ConstrainedModule, FoundSpecializationsModule, LateSpecializationsModule, ModuleHeader, + ParsedModule, TypeCheckedModule, +}; +use roc_can::abilities::PendingAbilitiesStore; +use roc_collections::{MutMap, MutSet, VecMap}; +use roc_module::ident::ModuleName; +use roc_module::symbol::{ModuleId, PQModuleName, Symbol}; +use roc_mono::ir::ExternalSpecializations; +use roc_problem::Severity; +use roc_solve_problem::TypeError; +use roc_types::types::Alias; +use std::path::PathBuf; + +/// Struct storing various intermediate stages by their ModuleId +#[derive(Debug)] +pub(crate) struct ModuleCache<'a> { + pub(crate) module_names: MutMap>, + + /// Phases + pub(crate) headers: MutMap>, + pub(crate) parsed: MutMap>, + pub(crate) aliases: MutMap>, + pub(crate) pending_abilities: MutMap, + pub(crate) constrained: MutMap, + pub(crate) typechecked: MutMap>, + pub(crate) found_specializations: MutMap>, + pub(crate) late_specializations: MutMap>, + pub(crate) external_specializations_requested: + MutMap>>, + + /// Various information + pub(crate) imports: MutMap>, + pub(crate) top_level_thunks: MutMap>, + pub(crate) documentation: VecMap, + pub(crate) can_problems: MutMap>, + pub(crate) type_problems: MutMap>, + + pub(crate) sources: MutMap, +} + +impl<'a> ModuleCache<'a> { + pub(crate) fn has_can_errors(&self) -> bool { + self.can_problems + .values() + .flatten() + .any(|problem| problem.severity() == Severity::RuntimeError) + } + + pub(crate) fn has_type_errors(&self) -> bool { + self.type_problems + .values() + .flatten() + .any(|problem| problem.severity() == Severity::RuntimeError) + } + + pub fn has_errors(&self) -> bool { + self.has_can_errors() || self.has_type_errors() + } +} + +impl Default for ModuleCache<'_> { + fn default() -> Self { + let mut module_names = MutMap::default(); + + macro_rules! insert_builtins { + ($($name:ident,)*) => {$( + module_names.insert( + ModuleId::$name, + PQModuleName::Unqualified(ModuleName::from(ModuleName::$name)), + ); + )*} + } + + insert_builtins! { + RESULT, + LIST, + STR, + DICT, + SET, + BOOL, + NUM, + BOX, + ENCODE, + DECODE, + HASH, + JSON, + } + + Self { + module_names, + headers: Default::default(), + parsed: Default::default(), + aliases: Default::default(), + pending_abilities: Default::default(), + constrained: Default::default(), + typechecked: Default::default(), + found_specializations: Default::default(), + late_specializations: Default::default(), + external_specializations_requested: Default::default(), + imports: Default::default(), + top_level_thunks: Default::default(), + documentation: Default::default(), + can_problems: Default::default(), + type_problems: Default::default(), + sources: Default::default(), + } + } +} diff --git a/crates/compiler/load_internal/tests/test_load.rs b/crates/compiler/load_internal/tests/test_load.rs index b16990c61a6..39f570c2a24 100644 --- a/crates/compiler/load_internal/tests/test_load.rs +++ b/crates/compiler/load_internal/tests/test_load.rs @@ -17,8 +17,10 @@ mod helpers; use crate::helpers::fixtures_dir; use bumpalo::Bump; use roc_can::module::ExposedByModule; -use roc_load_internal::file::{ExecutionMode, LoadConfig, Threading}; -use roc_load_internal::file::{LoadResult, LoadStart, LoadedModule, LoadingProblem}; +use roc_load_internal::file::{ + ExecutionMode, LoadConfig, LoadResult, LoadStart, LoadingProblem, Threading, +}; +use roc_load_internal::module::LoadedModule; use roc_module::ident::ModuleName; use roc_module::symbol::{Interns, ModuleId}; use roc_packaging::cache::RocCacheDir; diff --git a/crates/compiler/test_derive/src/util.rs b/crates/compiler/test_derive/src/util.rs index 5d050827386..26d4b6040ce 100644 --- a/crates/compiler/test_derive/src/util.rs +++ b/crates/compiler/test_derive/src/util.rs @@ -22,7 +22,8 @@ use roc_constrain::expr::constrain_decls; use roc_debug_flags::dbg_do; use roc_derive::DerivedModule; use roc_derive_key::{DeriveBuiltin, DeriveError, DeriveKey, Derived}; -use roc_load_internal::file::{add_imports, LoadedModule, Threading}; +use roc_load_internal::file::{add_imports, Threading}; +use roc_load_internal::module::LoadedModule; use roc_module::symbol::{IdentIds, Interns, ModuleId, Symbol}; use roc_region::all::LineInfo; use roc_reporting::report::{type_problem, RocDocAllocator}; From 8fef5379b381935c1841a6471139fcbb8d28591b Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Wed, 28 Jun 2023 22:36:05 -0400 Subject: [PATCH 096/140] clippy --- crates/packaging/src/https.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/packaging/src/https.rs b/crates/packaging/src/https.rs index bfe02aaa3fb..3ef428de5f2 100644 --- a/crates/packaging/src/https.rs +++ b/crates/packaging/src/https.rs @@ -13,7 +13,7 @@ use crate::tarball::Compression; // let's try to avoid doing that. const BROTLI_BUFFER_BYTES: usize = 8 * 1_000_000; // MB -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub struct PackageMetadata<'a> { /// The BLAKE3 hash of the tarball's contents. Also the .tar filename on disk. pub content_hash: &'a str, @@ -45,7 +45,7 @@ const MISLEADING_CHARACTERS_IN_URL: [char; 5] = [ '\u{29F8}', // U+29F8 == ⧸ Big Solidus ]; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub enum UrlProblem { InvalidExtensionSuffix(String), MissingTarExt, From 463f739c0664dd09c56219711cb0a5fb94cee75b Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 28 Jun 2023 21:26:19 +0200 Subject: [PATCH 097/140] add reuse info to normal Tag ir constructor --- crates/compiler/alias_analysis/src/lib.rs | 1 + crates/compiler/gen_dev/src/lib.rs | 5 +- crates/compiler/gen_llvm/src/llvm/build.rs | 26 +++++----- crates/compiler/gen_wasm/src/backend.rs | 7 ++- crates/compiler/mono/src/debug/checker.rs | 7 +++ crates/compiler/mono/src/ir.rs | 57 +++++++++++++++++++++- crates/compiler/mono/src/reset_reuse.rs | 3 ++ crates/compiler/mono/src/tail_recursion.rs | 4 ++ 8 files changed, 94 insertions(+), 16 deletions(-) diff --git a/crates/compiler/alias_analysis/src/lib.rs b/crates/compiler/alias_analysis/src/lib.rs index 82c9944c4d7..7aa2cea7852 100644 --- a/crates/compiler/alias_analysis/src/lib.rs +++ b/crates/compiler/alias_analysis/src/lib.rs @@ -1325,6 +1325,7 @@ fn expr_spec<'a>( tag_layout, tag_id, arguments, + reuse: _, } => { let data_id = build_tuple_value(builder, env, block, arguments)?; diff --git a/crates/compiler/gen_dev/src/lib.rs b/crates/compiler/gen_dev/src/lib.rs index f624165de0d..d446038288a 100644 --- a/crates/compiler/gen_dev/src/lib.rs +++ b/crates/compiler/gen_dev/src/lib.rs @@ -838,10 +838,11 @@ trait Backend<'a> { tag_layout, tag_id, arguments, - .. + reuse, } => { self.load_literal_symbols(arguments); - self.tag(sym, arguments, tag_layout, *tag_id, None); + let reuse = reuse.map(|ru| ru.symbol); + self.tag(sym, arguments, tag_layout, *tag_id, reuse); } Expr::ExprBox { symbol: value } => { let element_layout = match self.interner().get_repr(*layout) { diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 9d14ab0fe2e..d902fa63b08 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -1088,17 +1088,21 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( arguments, tag_layout: union_layout, tag_id, - .. - } => build_tag( - env, - layout_interner, - scope, - union_layout, - *tag_id, - arguments, - None, - parent, - ), + reuse, + } => { + let reuse_ptr = reuse.map(|ru| scope.load_symbol(&ru.symbol).into_pointer_value()); + + build_tag( + env, + layout_interner, + scope, + union_layout, + *tag_id, + arguments, + reuse_ptr, + parent, + ) + } ExprBox { symbol } => { let (value, layout) = scope.load_symbol_and_layout(symbol); diff --git a/crates/compiler/gen_wasm/src/backend.rs b/crates/compiler/gen_wasm/src/backend.rs index 557cdbecc2d..b236d5c027f 100644 --- a/crates/compiler/gen_wasm/src/backend.rs +++ b/crates/compiler/gen_wasm/src/backend.rs @@ -1104,8 +1104,11 @@ impl<'a, 'r> WasmBackend<'a, 'r> { tag_layout: union_layout, tag_id, arguments, - .. - } => self.expr_tag(union_layout, *tag_id, arguments, sym, storage, None), + reuse, + } => { + let reuse = reuse.map(|ru| ru.symbol); + self.expr_tag(union_layout, *tag_id, arguments, sym, storage, reuse) + } Expr::GetTagId { structure, diff --git a/crates/compiler/mono/src/debug/checker.rs b/crates/compiler/mono/src/debug/checker.rs index afb0917cf83..9c030a068dc 100644 --- a/crates/compiler/mono/src/debug/checker.rs +++ b/crates/compiler/mono/src/debug/checker.rs @@ -397,11 +397,18 @@ impl<'a, 'r> Ctx<'a, 'r> { tag_layout, tag_id, arguments, + reuse, } => { let interned_layout = self .interner .insert_direct_no_semantic(LayoutRepr::Union(tag_layout)); + + if let Some(reuse_token) = reuse { + self.check_sym_layout(reuse_token.symbol, interned_layout, UseKind::TagReuse); + } + self.check_tag_expr(interned_layout, tag_layout, tag_id, arguments); + Some(interned_layout) } Expr::Struct(syms) => { diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index c9013e78f12..82c6da4e024 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -1825,6 +1825,13 @@ pub struct HigherOrderLowLevel<'a> { pub passed_function: PassedFunction<'a>, } +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct ReuseToken { + pub symbol: Symbol, + pub update_tag_id: bool, + pub update_mode: UpdateModeId, +} + #[derive(Clone, Debug, PartialEq)] pub enum Expr<'a> { Literal(Literal<'a>), @@ -1836,6 +1843,7 @@ pub enum Expr<'a> { tag_layout: UnionLayout<'a>, tag_id: TagIdIntType, arguments: &'a [Symbol], + reuse: Option, }, Struct(&'a [Symbol]), NullPointer, @@ -1977,7 +1985,10 @@ impl<'a> Expr<'a> { Call(call) => call.to_doc(alloc, pretty), Tag { - tag_id, arguments, .. + tag_id, + arguments, + reuse: None, + .. } => { let doc_tag = alloc .text("TagId(") @@ -1990,6 +2001,30 @@ impl<'a> Expr<'a> { .append(alloc.space()) .append(alloc.intersperse(it, " ")) } + + Tag { + tag_id, + arguments, + reuse: Some(reuse_token), + .. + } => { + let doc_tag = alloc + .text("TagId(") + .append(alloc.text(tag_id.to_string())) + .append(")"); + + let it = arguments.iter().map(|s| symbol_to_doc(alloc, *s, pretty)); + + alloc + .text("Reuse ") + .append(symbol_to_doc(alloc, reuse_token.symbol, pretty)) + .append(alloc.space()) + .append(format!("{:?}", reuse_token.update_mode)) + .append(alloc.space()) + .append(doc_tag) + .append(alloc.space()) + .append(alloc.intersperse(it, " ")) + } NullPointer => alloc.text("NullPointer"), Reuse { symbol, @@ -6005,6 +6040,7 @@ where tag_id, tag_layout: union_layout, arguments: symbols, + reuse: None, }; Stmt::Let(assigned, expr, lambda_set_layout, env.arena.alloc(hole)) @@ -6274,6 +6310,7 @@ fn convert_tag_union<'a>( tag_layout: union_layout, tag_id: tag_id as _, arguments: field_symbols, + reuse: None, }; (tag, union_layout) @@ -6296,6 +6333,7 @@ fn convert_tag_union<'a>( tag_layout: union_layout, tag_id: tag_id as _, arguments: field_symbols, + reuse: None, }; (tag, union_layout) @@ -6320,6 +6358,7 @@ fn convert_tag_union<'a>( tag_layout: union_layout, tag_id: tag_id as _, arguments: field_symbols, + reuse: None, }; (tag, union_layout) @@ -6346,6 +6385,7 @@ fn convert_tag_union<'a>( tag_layout: union_layout, tag_id: tag_id as _, arguments: field_symbols, + reuse: None, }; (tag, union_layout) @@ -6363,6 +6403,7 @@ fn convert_tag_union<'a>( tag_layout: union_layout, tag_id: tag_id as _, arguments: field_symbols, + reuse: None, }; (tag, union_layout) @@ -7532,6 +7573,7 @@ fn substitute_in_expr<'a>( tag_layout, tag_id, arguments: args, + reuse, } => { let mut did_change = false; let new_args = Vec::from_iter_in( @@ -7545,6 +7587,18 @@ fn substitute_in_expr<'a>( arena, ); + let reuse = match *reuse { + Some(mut ru) => match substitute(subs, ru.symbol) { + Some(s) => { + did_change = true; + ru.symbol = s; + Some(ru) + } + None => Some(ru), + }, + None => None, + }; + if did_change { let arguments = new_args.into_bump_slice(); @@ -7552,6 +7606,7 @@ fn substitute_in_expr<'a>( tag_layout: *tag_layout, tag_id: *tag_id, arguments, + reuse, }) } else { None diff --git a/crates/compiler/mono/src/reset_reuse.rs b/crates/compiler/mono/src/reset_reuse.rs index 1fb2b581641..05cb06b8467 100644 --- a/crates/compiler/mono/src/reset_reuse.rs +++ b/crates/compiler/mono/src/reset_reuse.rs @@ -134,7 +134,10 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( tag_layout, tag_id, arguments, + reuse, } => { + debug_assert!(reuse.is_none()); + // The value of the tag is currently only used in the case of nullable recursive unions. // But for completeness we add every kind of union to the layout_tags. environment.add_symbol_tag(*binding, *tag_id); diff --git a/crates/compiler/mono/src/tail_recursion.rs b/crates/compiler/mono/src/tail_recursion.rs index 46b0684ce2e..a55820c8172 100644 --- a/crates/compiler/mono/src/tail_recursion.rs +++ b/crates/compiler/mono/src/tail_recursion.rs @@ -639,8 +639,11 @@ impl<'a> TrmcEnv<'a> { tag_layout, tag_id, arguments, + reuse, } = expr { + debug_assert!(reuse.is_none()); + let info = ConstructorInfo { tag_layout: *tag_layout, tag_id: *tag_id, @@ -910,6 +913,7 @@ impl<'a> TrmcEnv<'a> { tag_layout: cons_info.tag_layout, tag_id: cons_info.tag_id, arguments: arguments.into_bump_slice(), + reuse: None, }; let let_tag = |next| Stmt::Let(*symbol, tag_expr, *layout, next); From 1daf975391da9178ec8b3f861294b909f8ec0851 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 28 Jun 2023 21:47:36 +0200 Subject: [PATCH 098/140] use Tag instead of Reuse constructor --- crates/compiler/mono/src/reset_reuse.rs | 54 +++++++++++++++---------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/crates/compiler/mono/src/reset_reuse.rs b/crates/compiler/mono/src/reset_reuse.rs index 05cb06b8467..e011302771a 100644 --- a/crates/compiler/mono/src/reset_reuse.rs +++ b/crates/compiler/mono/src/reset_reuse.rs @@ -156,42 +156,52 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( token: reuse_token, inlayout: layout_info, }) => { - // The reuse token layout is the same, we can use it without casting. + let reuse_token = crate::ir::ReuseToken { + symbol: reuse_token.symbol, + update_mode: reuse_token.update_mode_id, + // for now, always overwrite the tag ID just to be sure + update_tag_id: true, + }; + if layout_info == layout { + // The reuse token layout is the same, we can use it without casting. ( None, - Expr::Reuse { - symbol: reuse_token.symbol, - update_mode: reuse_token.update_mode_id, - // for now, always overwrite the tag ID just to be sure - update_tag_id: true, + Expr::Tag { tag_layout: *tag_layout, tag_id: *tag_id, arguments, + reuse: Some(reuse_token), }, ) - } - // The reuse token has a different layout from the tag, we need to pointercast it before. - else { + } else { + // The reuse token has a different layout from the tag, we need to pointercast it before. let new_symbol = Symbol::new(home, ident_ids.gen_unique()); + + let ptr_cast = move |new_let| { + arena.alloc(Stmt::Let( + new_symbol, + create_ptr_cast(arena, reuse_token.symbol), + *layout, + new_let, + )) + }; + + let reuse_token = crate::ir::ReuseToken { + symbol: new_symbol, + update_mode: reuse_token.update_mode, + // for now, always overwrite the tag ID just to be sure + update_tag_id: true, + }; + ( - Some(move |new_let| { - arena.alloc(Stmt::Let( - new_symbol, - create_ptr_cast(arena, reuse_token.symbol), - *layout, - new_let, - )) - }), - Expr::Reuse { - symbol: new_symbol, - update_mode: reuse_token.update_mode_id, - // for now, always overwrite the tag ID just to be sure - update_tag_id: true, + Some(ptr_cast), + Expr::Tag { tag_layout: *tag_layout, tag_id: *tag_id, arguments, + reuse: Some(reuse_token), }, ) } From f27cb83a025870ebbc15ee7d51edb7053a052323 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 28 Jun 2023 22:02:02 +0200 Subject: [PATCH 099/140] remove Reuse --- crates/compiler/alias_analysis/src/lib.rs | 8 +--- crates/compiler/gen_dev/src/lib.rs | 26 ++++--------- crates/compiler/gen_llvm/src/llvm/build.rs | 20 ---------- crates/compiler/gen_wasm/src/backend.rs | 8 ---- crates/compiler/mono/src/borrow.rs | 27 +++++++++----- crates/compiler/mono/src/debug/checker.rs | 15 -------- .../compiler/mono/src/drop_specialization.rs | 3 -- crates/compiler/mono/src/inc_dec.rs | 2 +- crates/compiler/mono/src/ir.rs | 37 +------------------ crates/compiler/mono/src/reset_reuse.rs | 9 +++-- crates/compiler/mono/src/tail_recursion.rs | 3 -- 11 files changed, 33 insertions(+), 125 deletions(-) diff --git a/crates/compiler/alias_analysis/src/lib.rs b/crates/compiler/alias_analysis/src/lib.rs index 7aa2cea7852..9ded9c3c3db 100644 --- a/crates/compiler/alias_analysis/src/lib.rs +++ b/crates/compiler/alias_analysis/src/lib.rs @@ -1315,13 +1315,7 @@ fn expr_spec<'a>( builder.add_unknown_with(block, &[], pointer_type) } Call(call) => call_spec(builder, interner, env, block, layout, call), - Reuse { - tag_layout, - tag_id, - arguments, - .. - } - | Tag { + Tag { tag_layout, tag_id, arguments, diff --git a/crates/compiler/gen_dev/src/lib.rs b/crates/compiler/gen_dev/src/lib.rs index d446038288a..b4d1464cc95 100644 --- a/crates/compiler/gen_dev/src/lib.rs +++ b/crates/compiler/gen_dev/src/lib.rs @@ -138,7 +138,13 @@ impl<'a> LastSeenMap<'a> { Expr::Call(call) => self.scan_ast_call(call, stmt), - Expr::Tag { arguments, .. } => { + Expr::Tag { + arguments, reuse, .. + } => { + if let Some(ru) = reuse { + self.set_last_seen(ru.symbol, stmt); + } + for sym in *arguments { self.set_last_seen(*sym, stmt); } @@ -173,14 +179,6 @@ impl<'a> LastSeenMap<'a> { } } } - Expr::Reuse { - symbol, arguments, .. - } => { - self.set_last_seen(*symbol, stmt); - for sym in *arguments { - self.set_last_seen(*sym, stmt); - } - } Expr::Reset { symbol, .. } | Expr::ResetRef { symbol, .. } => { self.set_last_seen(*symbol, stmt); } @@ -862,16 +860,6 @@ trait Backend<'a> { Expr::NullPointer => { self.load_literal_i64(sym, 0); } - Expr::Reuse { - tag_layout, - tag_id, - symbol: reused, - arguments, - .. - } => { - self.load_literal_symbols(arguments); - self.tag(sym, arguments, tag_layout, *tag_id, Some(*reused)); - } Expr::Reset { symbol, .. } => { let layout = *self.layout_map().get(symbol).unwrap(); diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index d902fa63b08..67748e4a1ef 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -1064,26 +1064,6 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( ) .into(), - Reuse { - arguments, - tag_layout: union_layout, - tag_id, - symbol, - .. - } => { - let reset = scope.load_symbol(symbol).into_pointer_value(); - build_tag( - env, - layout_interner, - scope, - union_layout, - *tag_id, - arguments, - Some(reset), - parent, - ) - } - Tag { arguments, tag_layout: union_layout, diff --git a/crates/compiler/gen_wasm/src/backend.rs b/crates/compiler/gen_wasm/src/backend.rs index b236d5c027f..9472b014f57 100644 --- a/crates/compiler/gen_wasm/src/backend.rs +++ b/crates/compiler/gen_wasm/src/backend.rs @@ -1140,14 +1140,6 @@ impl<'a, 'r> WasmBackend<'a, 'r> { Expr::ExprUnbox { symbol: arg_sym } => self.expr_unbox(sym, *arg_sym), - Expr::Reuse { - tag_layout, - tag_id, - arguments, - symbol: reused, - .. - } => self.expr_tag(tag_layout, *tag_id, arguments, sym, storage, Some(*reused)), - Expr::Reset { symbol: arg, .. } => self.expr_reset(*arg, sym, storage), Expr::ResetRef { symbol: arg, .. } => self.expr_resetref(*arg, sym, storage), diff --git a/crates/compiler/mono/src/borrow.rs b/crates/compiler/mono/src/borrow.rs index dc5ad52fc19..8a95c793216 100644 --- a/crates/compiler/mono/src/borrow.rs +++ b/crates/compiler/mono/src/borrow.rs @@ -680,7 +680,22 @@ impl<'a> BorrowInfState<'a> { // the function must take it as an owned parameter self.own_args_if_param(&xs); } - Tag { arguments: xs, .. } | Struct(xs) => { + + Struct(xs) => { + self.own_var(z); + + // if the used symbol is an argument to the current function, + // the function must take it as an owned parameter + self.own_args_if_param(xs); + } + + Tag { + arguments: xs, + reuse, + .. + } => { + debug_assert!(reuse.is_none()); + self.own_var(z); // if the used symbol is an argument to the current function, @@ -708,15 +723,7 @@ impl<'a> BorrowInfState<'a> { self.own_var(z); self.own_var(*x); } - Reuse { - symbol: x, - arguments: ys, - .. - } => { - self.own_var(z); - self.own_var(*x); - self.own_args_if_param(ys); - } + EmptyArray => { self.own_var(z); } diff --git a/crates/compiler/mono/src/debug/checker.rs b/crates/compiler/mono/src/debug/checker.rs index 9c030a068dc..a1d89874785 100644 --- a/crates/compiler/mono/src/debug/checker.rs +++ b/crates/compiler/mono/src/debug/checker.rs @@ -481,21 +481,6 @@ impl<'a, 'r> Ctx<'a, 'r> { } } }), - &Expr::Reuse { - symbol, - update_tag_id: _, - update_mode: _, - tag_layout, - tag_id: _, - arguments: _, - } => { - let union = self - .interner - .insert_direct_no_semantic(LayoutRepr::Union(tag_layout)); - self.check_sym_layout(symbol, union, UseKind::TagReuse); - // TODO also check update arguments - Some(union) - } &Expr::Reset { symbol, update_mode: _, diff --git a/crates/compiler/mono/src/drop_specialization.rs b/crates/compiler/mono/src/drop_specialization.rs index a4203dec05b..6d976130541 100644 --- a/crates/compiler/mono/src/drop_specialization.rs +++ b/crates/compiler/mono/src/drop_specialization.rs @@ -231,9 +231,6 @@ fn specialize_drops_stmt<'a, 'i>( alloc_let_with_continuation!(environment) } - Expr::Reuse { .. } => { - alloc_let_with_continuation!(environment) - } Expr::Reset { .. } => { // TODO allow to inline this to replace it with resetref alloc_let_with_continuation!(environment) diff --git a/crates/compiler/mono/src/inc_dec.rs b/crates/compiler/mono/src/inc_dec.rs index 960a45bf10e..9b421b77e72 100644 --- a/crates/compiler/mono/src/inc_dec.rs +++ b/crates/compiler/mono/src/inc_dec.rs @@ -1093,7 +1093,7 @@ fn insert_refcount_operations_binding<'a>( } } } - Expr::Reuse { .. } | Expr::Reset { .. } | Expr::ResetRef { .. } => { + Expr::Reset { .. } | Expr::ResetRef { .. } => { unreachable!("Reset(ref) and reuse should not exist at this point") } } diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index 82c6da4e024..7a135dd3a17 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -1825,7 +1825,7 @@ pub struct HigherOrderLowLevel<'a> { pub passed_function: PassedFunction<'a>, } -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct ReuseToken { pub symbol: Symbol, pub update_tag_id: bool, @@ -1886,15 +1886,6 @@ pub enum Expr<'a> { symbol: Symbol, }, - Reuse { - symbol: Symbol, - update_tag_id: bool, - update_mode: UpdateModeId, - // normal Tag fields - tag_layout: UnionLayout<'a>, - tag_id: TagIdIntType, - arguments: &'a [Symbol], - }, Reset { symbol: Symbol, update_mode: UpdateModeId, @@ -2026,30 +2017,6 @@ impl<'a> Expr<'a> { .append(alloc.intersperse(it, " ")) } NullPointer => alloc.text("NullPointer"), - Reuse { - symbol, - tag_id, - arguments, - update_mode, - .. - } => { - let doc_tag = alloc - .text("TagId(") - .append(alloc.text(tag_id.to_string())) - .append(")"); - - let it = arguments.iter().map(|s| symbol_to_doc(alloc, *s, pretty)); - - alloc - .text("Reuse ") - .append(symbol_to_doc(alloc, *symbol, pretty)) - .append(alloc.space()) - .append(format!("{:?}", update_mode)) - .append(alloc.space()) - .append(doc_tag) - .append(alloc.space()) - .append(alloc.intersperse(it, " ")) - } Reset { symbol, update_mode, @@ -7615,7 +7582,7 @@ fn substitute_in_expr<'a>( NullPointer => None, - Reuse { .. } | Reset { .. } | ResetRef { .. } => { + Reset { .. } | ResetRef { .. } => { unreachable!("reset/resetref/reuse have not been introduced yet") } diff --git a/crates/compiler/mono/src/reset_reuse.rs b/crates/compiler/mono/src/reset_reuse.rs index e011302771a..a5d5ee48b66 100644 --- a/crates/compiler/mono/src/reset_reuse.rs +++ b/crates/compiler/mono/src/reset_reuse.rs @@ -234,12 +234,13 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( new_triplets.into_iter().rev().fold( new_continuation, - |new_continuation, (binding, (reused, new_expr), layout)| { + |new_continuation, (binding, (opt_ptr_cast, new_expr), layout)| { let new_let = arena.alloc(Stmt::Let(*binding, new_expr, *layout, new_continuation)); - match reused { - // The layout for the reuse does not match that of the reset, use PtrCast to convert the layout. - Some(wrap) => wrap(new_let), + + // if the layout for the reuse does not match that of the reset, use PtrCast to convert the layout. + match opt_ptr_cast { + Some(ptr_cast) => ptr_cast(new_let), None => new_let, } }, diff --git a/crates/compiler/mono/src/tail_recursion.rs b/crates/compiler/mono/src/tail_recursion.rs index a55820c8172..074843fc7b7 100644 --- a/crates/compiler/mono/src/tail_recursion.rs +++ b/crates/compiler/mono/src/tail_recursion.rs @@ -1102,9 +1102,6 @@ fn expr_contains_symbol(expr: &Expr, needle: Symbol) -> bool { }), Expr::EmptyArray => false, Expr::ExprBox { symbol } | Expr::ExprUnbox { symbol } => needle == *symbol, - Expr::Reuse { - symbol, arguments, .. - } => needle == *symbol || arguments.contains(&needle), Expr::Reset { symbol, .. } | Expr::ResetRef { symbol, .. } => needle == *symbol, Expr::RuntimeErrorFunction(_) => false, } From b29e612a4df799a451ab87267da9afcf7c507552 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 28 Jun 2023 22:08:47 +0200 Subject: [PATCH 100/140] refactor --- crates/compiler/mono/src/reset_reuse.rs | 46 +++++++------------------ 1 file changed, 13 insertions(+), 33 deletions(-) diff --git a/crates/compiler/mono/src/reset_reuse.rs b/crates/compiler/mono/src/reset_reuse.rs index a5d5ee48b66..d51e522fa0b 100644 --- a/crates/compiler/mono/src/reset_reuse.rs +++ b/crates/compiler/mono/src/reset_reuse.rs @@ -9,8 +9,8 @@ use std::hash::Hash; use crate::borrow::Ownership; use crate::ir::{ - BranchInfo, Expr, JoinPointId, ModifyRc, Param, Proc, ProcLayout, Stmt, UpdateModeId, - UpdateModeIds, + BranchInfo, Expr, JoinPointId, ModifyRc, Param, Proc, ProcLayout, ReuseToken, Stmt, + UpdateModeId, UpdateModeIds, }; use crate::layout::{InLayout, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout}; @@ -153,16 +153,9 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( )) { // We have a reuse token for this layout, use it. Some(TokenWithInLayout { - token: reuse_token, + token: mut reuse_token, inlayout: layout_info, }) => { - let reuse_token = crate::ir::ReuseToken { - symbol: reuse_token.symbol, - update_mode: reuse_token.update_mode_id, - // for now, always overwrite the tag ID just to be sure - update_tag_id: true, - }; - if layout_info == layout { // The reuse token layout is the same, we can use it without casting. ( @@ -188,12 +181,8 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( )) }; - let reuse_token = crate::ir::ReuseToken { - symbol: new_symbol, - update_mode: reuse_token.update_mode, - // for now, always overwrite the tag ID just to be sure - update_tag_id: true, - }; + // we now want to reuse the cast pointer + reuse_token.symbol = new_symbol; ( Some(ptr_cast), @@ -491,7 +480,9 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( let reuse_token = ReuseToken { symbol: reuse_symbol, - update_mode_id: update_mode_ids.next_id(), + update_mode: update_mode_ids.next_id(), + // for now, always overwrite the tag ID just to be sure + update_tag_id: true, }; let owned_layout = **layout; @@ -553,7 +544,7 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( // a dec will be replaced by a reset. let reset_expr = Expr::Reset { symbol, - update_mode: reuse_token.update_mode_id, + update_mode: reuse_token.update_mode, }; return arena.alloc(Stmt::Let( @@ -567,7 +558,7 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( // a decref will be replaced by a resetref. let reset_expr = Expr::ResetRef { symbol, - update_mode: reuse_token.update_mode_id, + update_mode: reuse_token.update_mode, }; return arena.alloc(Stmt::Let( @@ -753,7 +744,9 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( tokens.iter().map(|token| TokenWithInLayout { token: ReuseToken { symbol: Symbol::new(home, ident_ids.gen_unique()), - update_mode_id: update_mode_ids.next_id(), + update_mode: update_mode_ids.next_id(), + // for now, always overwrite the tag ID just to be sure + update_tag_id: true, }, inlayout: token.inlayout, }), @@ -1140,19 +1133,6 @@ struct TokenLayout { alignment: u32, } -/** -A reuse token is a symbol that is used to reset a layout. -Matches symbols that are pointers. -*/ -#[derive(Clone, Copy, PartialEq, Eq)] -struct ReuseToken { - // The symbol of the reuse token. - symbol: Symbol, - - // Index that can be used later to determine if in place mutation is possible. - update_mode_id: UpdateModeId, -} - /** Combines a reuse token with it's possible layout info. */ From 0308e02ba9406c411d452919f4e53156a895e99e Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 29 Jun 2023 18:40:14 +0200 Subject: [PATCH 101/140] update some logic and comments --- crates/compiler/mono/src/inc_dec.rs | 2 +- crates/compiler/mono/src/ir.rs | 2 +- crates/compiler/mono/src/tail_recursion.rs | 7 ++++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/crates/compiler/mono/src/inc_dec.rs b/crates/compiler/mono/src/inc_dec.rs index 9b421b77e72..139303dc0cc 100644 --- a/crates/compiler/mono/src/inc_dec.rs +++ b/crates/compiler/mono/src/inc_dec.rs @@ -1094,7 +1094,7 @@ fn insert_refcount_operations_binding<'a>( } } Expr::Reset { .. } | Expr::ResetRef { .. } => { - unreachable!("Reset(ref) and reuse should not exist at this point") + unreachable!("Reset(ref) should not exist at this point") } } } diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index 7a135dd3a17..8ef7a13e27d 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -7583,7 +7583,7 @@ fn substitute_in_expr<'a>( NullPointer => None, Reset { .. } | ResetRef { .. } => { - unreachable!("reset/resetref/reuse have not been introduced yet") + unreachable!("reset(ref) has not been introduced yet") } Struct(args) => { diff --git a/crates/compiler/mono/src/tail_recursion.rs b/crates/compiler/mono/src/tail_recursion.rs index 074843fc7b7..bb7680a5033 100644 --- a/crates/compiler/mono/src/tail_recursion.rs +++ b/crates/compiler/mono/src/tail_recursion.rs @@ -1089,7 +1089,12 @@ fn expr_contains_symbol(expr: &Expr, needle: Symbol) -> bool { match expr { Expr::Literal(_) => false, Expr::Call(call) => call.arguments.contains(&needle), - Expr::Tag { arguments, .. } => arguments.contains(&needle), + Expr::Tag { + arguments, reuse, .. + } => match reuse { + None => arguments.contains(&needle), + Some(ru) => ru.symbol == needle || arguments.contains(&needle), + }, Expr::Struct(fields) => fields.contains(&needle), Expr::NullPointer => false, Expr::StructAtIndex { structure, .. } From e27a06849d4b9274d5d7b9c2e0e322ce6bd7506a Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Thu, 29 Jun 2023 14:51:29 -0500 Subject: [PATCH 102/140] Unwrap rec pointers when getting lambda set --- crates/compiler/types/src/subs.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/crates/compiler/types/src/subs.rs b/crates/compiler/types/src/subs.rs index 15b895de732..3eb40deb754 100644 --- a/crates/compiler/types/src/subs.rs +++ b/crates/compiler/types/src/subs.rs @@ -2163,10 +2163,15 @@ impl Subs { self.utable.vars_since_snapshot(&snapshot.utable_snapshot) } - pub fn get_lambda_set(&self, lambda_set: Variable) -> LambdaSet { - match self.get_content_without_compacting(lambda_set) { - Content::LambdaSet(lambda_set) => *lambda_set, - _ => internal_error!("not a lambda set"), + pub fn get_lambda_set(&self, mut lambda_set: Variable) -> LambdaSet { + loop { + match self.get_content_without_compacting(lambda_set) { + Content::LambdaSet(lambda_set) => return *lambda_set, + Content::RecursionVar { structure, .. } => { + lambda_set = *structure; + } + _ => internal_error!("not a lambda set"), + } } } From a5e1558a6e841e37bc027715c1b70a4cbbc552ba Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Thu, 29 Jun 2023 17:32:09 -0500 Subject: [PATCH 103/140] Do not drop uninhabited captures from lambda sets Previously, we would drop uninhabited captures from lambda sets' runtime representations, which meant sets like ``` [L1 {a: Str}, L2 {a: []}] ``` had runtime representation ``` {Str} ``` rather than ``` Union({Str}, {[]}) ``` if we drop unreachable lambdas from the representation, then the reachable lambdas are somewhat more efficient to compile (as there are less material tag options), but the compiler complexity increases because we must represent voided capture sets in the lambda set. Even if a lambda has voided captures, we must specialize it, because failing to do so opens us up to losing relevant specializations needed later on. See https://github.com/roc-lang/roc/commit/2f7020aa31 for a previous occurence of that. As such, simply keep voided layouts in place during lambda set compilation. The optimizer should elide them anyway. --- crates/compiler/mono/src/layout.rs | 45 ++++- .../generated/capture_void_layout_task.txt | 174 ++++++++++++++++++ crates/compiler/test_mono/src/tests.rs | 44 +++++ 3 files changed, 253 insertions(+), 10 deletions(-) create mode 100644 crates/compiler/test_mono/generated/capture_void_layout_task.txt diff --git a/crates/compiler/mono/src/layout.rs b/crates/compiler/mono/src/layout.rs index afa9abaa646..78a2c72d22f 100644 --- a/crates/compiler/mono/src/layout.rs +++ b/crates/compiler/mono/src/layout.rs @@ -1914,6 +1914,11 @@ impl<'a> LambdaSet<'a> { ) -> Cacheable> { let union_labels = UnsortedUnionLabels { tags: set }; + // Even if a variant in the lambda set has uninhabitable captures (and is hence + // unreachable as a function), we want to keep it in the representation. Failing to do so + // risks dropping relevant specializations needed during monomorphization. + let drop_uninhabited_variants = DropUninhabitedVariants(false); + match opt_rec_var { Some(rec_var) => { let Cacheable(result, criteria) = @@ -1922,7 +1927,7 @@ impl<'a> LambdaSet<'a> { Cacheable(result, criteria) } - None => layout_from_non_recursive_union(env, &union_labels), + None => layout_from_non_recursive_union(env, &union_labels, drop_uninhabited_variants), } } @@ -3330,7 +3335,7 @@ fn layout_from_flat_type<'a>( debug_assert!(ext_var_is_empty_tag_union(subs, ext_var)); - layout_from_non_recursive_union(env, &tags).map(Ok) + layout_from_non_recursive_union(env, &tags, DropUninhabitedVariants(true)).map(Ok) } FunctionOrTagUnion(tag_names, _, ext_var) => { debug_assert!( @@ -3343,7 +3348,8 @@ fn layout_from_flat_type<'a>( tags: tag_names.iter().map(|t| (t, &[] as &[Variable])).collect(), }; - layout_from_non_recursive_union(env, &unsorted_tags).map(Ok) + layout_from_non_recursive_union(env, &unsorted_tags, DropUninhabitedVariants(true)) + .map(Ok) } RecursiveTagUnion(rec_var, tags, ext_var) => { let (tags, ext_var) = tags.unsorted_tags_and_ext(subs, ext_var); @@ -3621,11 +3627,14 @@ pub fn union_sorted_tags<'a>( var }; + let drop_uninhabited_variants = DropUninhabitedVariants(true); + let mut tags_vec = std::vec::Vec::new(); let result = match roc_types::pretty_print::chase_ext_tag_union(env.subs, var, &mut tags_vec) { ChasedExt::Empty => { let opt_rec_var = get_recursion_var(env.subs, var); - let Cacheable(result, _) = union_sorted_tags_help(env, tags_vec, opt_rec_var); + let Cacheable(result, _) = + union_sorted_tags_help(env, tags_vec, opt_rec_var, drop_uninhabited_variants); result } ChasedExt::NonEmpty { content, .. } => { @@ -3638,12 +3647,22 @@ pub fn union_sorted_tags<'a>( // x // In such cases it's fine to drop the variable. We may be proven wrong in the future... let opt_rec_var = get_recursion_var(env.subs, var); - let Cacheable(result, _) = union_sorted_tags_help(env, tags_vec, opt_rec_var); + let Cacheable(result, _) = union_sorted_tags_help( + env, + tags_vec, + opt_rec_var, + drop_uninhabited_variants, + ); result } RecursionVar { .. } => { let opt_rec_var = get_recursion_var(env.subs, var); - let Cacheable(result, _) = union_sorted_tags_help(env, tags_vec, opt_rec_var); + let Cacheable(result, _) = union_sorted_tags_help( + env, + tags_vec, + opt_rec_var, + drop_uninhabited_variants, + ); result } @@ -3694,9 +3713,12 @@ impl Label for Symbol { } } +struct DropUninhabitedVariants(bool); + fn union_sorted_non_recursive_tags_help<'a, L>( env: &mut Env<'a, '_>, tags_list: &mut Vec<'_, &'_ (&'_ L, &[Variable])>, + drop_uninhabited_variants: DropUninhabitedVariants, ) -> Cacheable> where L: Label + Ord + Clone + Into, @@ -3816,7 +3838,7 @@ where answer.push((tag_name.clone().into(), arg_layouts.into_bump_slice())); } - if inhabited_tag_ids.count_ones() == 1 { + if inhabited_tag_ids.count_ones() == 1 && drop_uninhabited_variants.0 { let kept_tag_id = inhabited_tag_ids.first_one().unwrap(); let kept = answer.get(kept_tag_id).unwrap(); @@ -3869,13 +3891,14 @@ pub fn union_sorted_tags_pub<'a, L>( where L: Into + Ord + Clone, { - union_sorted_tags_help(env, tags_vec, opt_rec_var).value() + union_sorted_tags_help(env, tags_vec, opt_rec_var, DropUninhabitedVariants(true)).value() } fn union_sorted_tags_help<'a, L>( env: &mut Env<'a, '_>, mut tags_vec: std::vec::Vec<(L, std::vec::Vec)>, opt_rec_var: Option, + drop_uninhabited_variants: DropUninhabitedVariants, ) -> Cacheable> where L: Into + Ord + Clone, @@ -4028,7 +4051,7 @@ where answer.push((tag_name.into(), arg_layouts.into_bump_slice())); } - if inhabited_tag_ids.count_ones() == 1 && !is_recursive { + if inhabited_tag_ids.count_ones() == 1 && !is_recursive && drop_uninhabited_variants.0 { let kept_tag_id = inhabited_tag_ids.first_one().unwrap(); let kept = answer.get(kept_tag_id).unwrap(); @@ -4131,6 +4154,7 @@ fn layout_from_newtype<'a, L: Label>( fn layout_from_non_recursive_union<'a, L>( env: &mut Env<'a, '_>, tags: &UnsortedUnionLabels, + drop_uninhabited_variants: DropUninhabitedVariants, ) -> Cacheable> where L: Label + Ord + Into, @@ -4146,7 +4170,8 @@ where let mut criteria = CACHEABLE; let variant = - union_sorted_non_recursive_tags_help(env, &mut tags_vec).decompose(&mut criteria, env.subs); + union_sorted_non_recursive_tags_help(env, &mut tags_vec, drop_uninhabited_variants) + .decompose(&mut criteria, env.subs); let compute_semantic = || L::semantic_repr(env.arena, tags_vec.iter().map(|(l, _)| *l)); diff --git a/crates/compiler/test_mono/generated/capture_void_layout_task.txt b/crates/compiler/test_mono/generated/capture_void_layout_task.txt new file mode 100644 index 00000000000..166b384497e --- /dev/null +++ b/crates/compiler/test_mono/generated/capture_void_layout_task.txt @@ -0,0 +1,174 @@ +procedure List.145 (List.146, List.147, List.144): + let List.540 : [C {}, C *self {{}, []}] = CallByName Test.29 List.146 List.147 List.144; + ret List.540; + +procedure List.18 (List.142, List.143, List.144): + let List.521 : [C {}, C *self {{}, []}] = CallByName List.93 List.142 List.143 List.144; + ret List.521; + +procedure List.6 (#Attr.2): + let List.538 : U64 = lowlevel ListLen #Attr.2; + ret List.538; + +procedure List.66 (#Attr.2, #Attr.3): + let List.537 : [] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.537; + +procedure List.80 (#Derived_gen.6, #Derived_gen.7, #Derived_gen.8, #Derived_gen.9, #Derived_gen.10): + joinpoint List.527 List.439 List.440 List.441 List.442 List.443: + let List.529 : Int1 = CallByName Num.22 List.442 List.443; + if List.529 then + let List.536 : [] = CallByName List.66 List.439 List.442; + let List.530 : [C {}, C *self {{}, []}] = CallByName List.145 List.440 List.536 List.441; + let List.533 : U64 = 1i64; + let List.532 : U64 = CallByName Num.19 List.442 List.533; + jump List.527 List.439 List.530 List.441 List.532 List.443; + else + dec List.439; + ret List.440; + in + jump List.527 #Derived_gen.6 #Derived_gen.7 #Derived_gen.8 #Derived_gen.9 #Derived_gen.10; + +procedure List.93 (List.436, List.437, List.438): + let List.525 : U64 = 0i64; + let List.526 : U64 = CallByName List.6 List.436; + let List.524 : [C {}, C *self {{}, []}] = CallByName List.80 List.436 List.437 List.438 List.525 List.526; + ret List.524; + +procedure Num.19 (#Attr.2, #Attr.3): + let Num.292 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.292; + +procedure Num.22 (#Attr.2, #Attr.3): + let Num.293 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; + ret Num.293; + +procedure Test.10 (Test.66, #Attr.12): + let Test.9 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12; + let #Derived_gen.20 : Int1 = lowlevel RefCountIsUnique #Attr.12; + if #Derived_gen.20 then + free #Attr.12; + ret Test.9; + else + decref #Attr.12; + ret Test.9; + +procedure Test.10 (Test.66, #Attr.12): + let Test.9 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12; + ret Test.9; + +procedure Test.14 (Test.45, #Attr.12): + let Test.13 : {{}, []} = UnionAtIndex (Id 1) (Index 1) #Attr.12; + let Test.12 : [C {}, C *self {{}, []}] = UnionAtIndex (Id 1) (Index 0) #Attr.12; + joinpoint #Derived_gen.18: + let Test.50 : {} = Struct {}; + let Test.51 : U8 = GetTagId Test.12; + joinpoint Test.52 Test.15: + let Test.16 : [C {}, C []] = CallByName Test.20 Test.15 Test.13; + let Test.48 : {} = Struct {}; + let Test.49 : U8 = GetTagId Test.16; + switch Test.49: + case 0: + let Test.47 : {} = CallByName Test.10 Test.48 Test.16; + ret Test.47; + + default: + let Test.47 : {} = CallByName Test.25 Test.48 Test.16; + ret Test.47; + + in + switch Test.51: + case 0: + let Test.53 : {} = CallByName Test.10 Test.50 Test.12; + jump Test.52 Test.53; + + default: + let Test.53 : {} = CallByName Test.14 Test.50 Test.12; + jump Test.52 Test.53; + + in + let #Derived_gen.19 : Int1 = lowlevel RefCountIsUnique #Attr.12; + if #Derived_gen.19 then + free #Attr.12; + jump #Derived_gen.18; + else + inc Test.12; + decref #Attr.12; + jump #Derived_gen.18; + +procedure Test.20 (Test.21, Test.18): + let Test.23 : [C {}, C []] = CallByName Test.32 Test.21 Test.18; + ret Test.23; + +procedure Test.25 (Test.57, #Attr.12): + let Test.24 : [] = UnionAtIndex (Id 1) (Index 0) #Attr.12; + let Test.60 : Str = "voided tag constructor is unreachable"; + Crash Test.60 + +procedure Test.29 (Test.30, Test.31, Test.28): + let Test.42 : {{}, []} = Struct {Test.28, Test.31}; + let Test.41 : [C {}, C *self {{}, []}] = CallByName Test.5 Test.30 Test.42; + ret Test.41; + +procedure Test.3 (Test.9): + let Test.65 : [C {}, C *self {{}, []}] = TagId(0) Test.9; + ret Test.65; + +procedure Test.3 (Test.9): + let Test.72 : [C {}, C []] = TagId(0) Test.9; + ret Test.72; + +procedure Test.32 (Test.61, #Attr.12): + let Test.31 : [] = StructAtIndex 1 #Attr.12; + let Test.28 : {} = StructAtIndex 0 #Attr.12; + let Test.63 : [C {}, C []] = CallByName Test.33 Test.31; + ret Test.63; + +procedure Test.33 (Test.69): + let Test.71 : {} = Struct {}; + let Test.70 : [C {}, C []] = CallByName Test.3 Test.71; + ret Test.70; + +procedure Test.4 (Test.12, Test.13): + let Test.46 : [C {}, C *self {{}, []}] = TagId(1) Test.12 Test.13; + ret Test.46; + +procedure Test.5 (Test.17, Test.18): + let Test.19 : [C {}, C *self {{}, []}] = CallByName Test.4 Test.17 Test.18; + ret Test.19; + +procedure Test.6 (Test.27, Test.28): + let Test.64 : {} = Struct {}; + let Test.38 : [C {}, C *self {{}, []}] = CallByName Test.3 Test.64; + let Test.37 : [C {}, C *self {{}, []}] = CallByName List.18 Test.27 Test.38 Test.28; + ret Test.37; + +procedure Test.76 (Test.77): + let Test.78 : {{}, []} = Unbox Test.77; + dec Test.77; + let Test.79 : {} = StructAtIndex 0 Test.78; + ret Test.79; + +procedure Test.80 (Test.81): + let Test.82 : {{}, []} = Unbox Test.81; + dec Test.81; + let Test.83 : [] = StructAtIndex 1 Test.82; + ret Test.83; + +procedure Test.84 (Test.86, #Attr.12): + let Test.87 : U8 = GetTagId #Attr.12; + switch Test.87: + case 0: + let Test.85 : {} = CallByName Test.10 Test.86 #Attr.12; + ret Test.85; + + default: + let Test.85 : {} = CallByName Test.14 Test.86 #Attr.12; + ret Test.85; + + +procedure Test.0 (): + let Test.35 : List [] = Array []; + let Test.36 : {} = Struct {}; + let Test.34 : [C {}, C *self {{}, []}] = CallByName Test.6 Test.35 Test.36; + ret Test.34; diff --git a/crates/compiler/test_mono/src/tests.rs b/crates/compiler/test_mono/src/tests.rs index 71064f8baf3..da86d734310 100644 --- a/crates/compiler/test_mono/src/tests.rs +++ b/crates/compiler/test_mono/src/tests.rs @@ -3216,3 +3216,47 @@ fn linked_list_filter() { "# ) } + +#[mono_test] +fn capture_void_layout_task() { + indoc!( + r#" + app "test" provides [main] to "./platform" + + Fx a : {} -> a + + Task ok err : Fx (Result ok err) + + succeed : ok -> Task ok * + succeed = \ok -> \{} -> Ok ok + + after : Fx a, (a -> Fx b) -> Fx b + after = \fx, toNext -> + afterInner = \{} -> + fxOut = fx {} + next = toNext fxOut + next {} + + afterInner + + await : Task a err, (a -> Task b err) -> Task b err + await = \fx, toNext -> + inner = after fx \result -> + when result is + Ok a -> + bFx = toNext a + bFx + Err e -> (\{} -> Err e) + inner + + forEach : List a, (a -> Task {} err) -> Task {} err + forEach = \list, fromElem -> + List.walk list (succeed {}) \task, elem -> + await task \{} -> fromElem elem + + main : Task {} [] + main = + forEach [] \_ -> succeed {} + "# + ) +} From 3b18494ddd0a3d90c45f4727b865e78e7f162e81 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 28 Jun 2023 22:35:39 +0200 Subject: [PATCH 104/140] use Ptr instead of Boxed in the code-gen-help --- .../mono/src/code_gen_help/equality.rs | 40 +++++----- crates/compiler/mono/src/code_gen_help/mod.rs | 77 +++++++++---------- .../mono/src/code_gen_help/refcount.rs | 36 ++++----- crates/compiler/mono/src/ir.rs | 10 +++ 4 files changed, 83 insertions(+), 80 deletions(-) diff --git a/crates/compiler/mono/src/code_gen_help/equality.rs b/crates/compiler/mono/src/code_gen_help/equality.rs index 6c212d4c3d1..2e6c6163324 100644 --- a/crates/compiler/mono/src/code_gen_help/equality.rs +++ b/crates/compiler/mono/src/code_gen_help/equality.rs @@ -609,8 +609,8 @@ fn eq_boxed<'a>( let b = root.create_symbol(ident_ids, "b"); let result = root.create_symbol(ident_ids, "result"); - let a_expr = Expr::ExprUnbox { symbol: ARG_1 }; - let b_expr = Expr::ExprUnbox { symbol: ARG_2 }; + let a_expr = Expr::ptr_load(&ARG_1); + let b_expr = Expr::ptr_load(&ARG_2); let eq_call_expr = root .call_specialized_op( ident_ids, @@ -649,8 +649,8 @@ fn eq_boxed<'a>( /// TODO, ListGetUnsafe no longer increments the refcount, so we can use it here. /// We can't use `ListGetUnsafe` because it increments the refcount, and we don't want that. /// Another way to dereference a heap pointer is to use `Expr::UnionAtIndex`. -/// To achieve this we use `PtrCast` to cast the element pointer to a "Box" layout. -/// Then we can increment the Box pointer in a loop, dereferencing it each time. +/// To achieve this we use `PtrCast` to cast the element pointer to a "Ptr" layout. +/// Then we can increment the pointer in a loop, dereferencing it each time. /// (An alternative approach would be to create a new lowlevel like ListPeekUnsafe.) fn eq_list<'a>( root: &mut CodeGenHelp<'a>, @@ -663,8 +663,8 @@ fn eq_list<'a>( let layout_isize = root.layout_isize; let arena = root.arena; - // A "Box" layout (heap pointer to a single list element) - let box_layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(elem_layout)); + // A pointer layout (heap pointer to a single list element) + let ptr_layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Ptr(elem_layout)); // Compare lengths @@ -683,16 +683,16 @@ fn eq_list<'a>( let elements_2 = root.create_symbol(ident_ids, "elements_2"); let elements_1_expr = Expr::StructAtIndex { index: 0, - field_layouts: root.arena.alloc([box_layout, layout_isize]), + field_layouts: root.arena.alloc([ptr_layout, layout_isize]), structure: ARG_1, }; let elements_2_expr = Expr::StructAtIndex { index: 0, - field_layouts: root.arena.alloc([box_layout, layout_isize]), + field_layouts: root.arena.alloc([ptr_layout, layout_isize]), structure: ARG_2, }; - let elements_1_stmt = |next| Stmt::Let(elements_1, elements_1_expr, box_layout, next); - let elements_2_stmt = |next| Stmt::Let(elements_2, elements_2_expr, box_layout, next); + let elements_1_stmt = |next| Stmt::Let(elements_1, elements_1_expr, ptr_layout, next); + let elements_2_stmt = |next| Stmt::Let(elements_2, elements_2_expr, ptr_layout, next); // Cast to integers let start_1 = root.create_symbol(ident_ids, "start_1"); @@ -758,17 +758,17 @@ fn eq_list<'a>( // if we haven't reached the end yet... // - // Cast integers to box pointers - let box1 = root.create_symbol(ident_ids, "box1"); - let box2 = root.create_symbol(ident_ids, "box2"); - let box1_stmt = |next| let_lowlevel(arena, box_layout, box1, PtrCast, &[addr1], next); - let box2_stmt = |next| let_lowlevel(arena, box_layout, box2, PtrCast, &[addr2], next); + // Cast integers to pointers + let ptr1 = root.create_symbol(ident_ids, "ptr1"); + let ptr2 = root.create_symbol(ident_ids, "ptr2"); + let ptr1_stmt = |next| let_lowlevel(arena, ptr_layout, ptr1, PtrCast, &[addr1], next); + let ptr2_stmt = |next| let_lowlevel(arena, ptr_layout, ptr2, PtrCast, &[addr2], next); - // Dereference the box pointers to get the current elements + // Dereference the pointers to get the current elements let elem1 = root.create_symbol(ident_ids, "elem1"); let elem2 = root.create_symbol(ident_ids, "elem2"); - let elem1_expr = Expr::ExprUnbox { symbol: box1 }; - let elem2_expr = Expr::ExprUnbox { symbol: box2 }; + let elem1_expr = Expr::ptr_load(arena.alloc(ptr1)); + let elem2_expr = Expr::ptr_load(arena.alloc(ptr2)); let elem1_stmt = |next| Stmt::Let(elem1, elem1_expr, elem_layout, next); let elem2_stmt = |next| Stmt::Let(elem2, elem2_expr, elem_layout, next); @@ -819,9 +819,9 @@ fn eq_list<'a>( Stmt::Ret(Symbol::BOOL_TRUE), root.arena.alloc( // - box1_stmt(root.arena.alloc( + ptr1_stmt(root.arena.alloc( // - box2_stmt(root.arena.alloc( + ptr2_stmt(root.arena.alloc( // elem1_stmt(root.arena.alloc( // diff --git a/crates/compiler/mono/src/code_gen_help/mod.rs b/crates/compiler/mono/src/code_gen_help/mod.rs index 2ea7809d207..08872ba6865 100644 --- a/crates/compiler/mono/src/code_gen_help/mod.rs +++ b/crates/compiler/mono/src/code_gen_help/mod.rs @@ -302,14 +302,14 @@ impl<'a> CodeGenHelp<'a> { let (ret_layout, arg_layouts): (InLayout<'a>, &'a [InLayout<'a>]) = { let arg = self.replace_rec_ptr(ctx, layout_interner, layout); - let box_arg = layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(arg)); + let ptr_arg = layout_interner.insert_direct_no_semantic(LayoutRepr::Ptr(arg)); match ctx.op { Dec | DecRef(_) => (LAYOUT_UNIT, self.arena.alloc([arg])), Reset | ResetRef => (layout, self.arena.alloc([layout])), Inc => (LAYOUT_UNIT, self.arena.alloc([arg, self.layout_isize])), - IndirectDec => (LAYOUT_UNIT, arena.alloc([box_arg])), - IndirectInc => (LAYOUT_UNIT, arena.alloc([box_arg, self.layout_isize])), + IndirectDec => (LAYOUT_UNIT, arena.alloc([ptr_arg])), + IndirectInc => (LAYOUT_UNIT, arena.alloc([ptr_arg, self.layout_isize])), Eq => (LAYOUT_BOOL, self.arena.alloc([arg, arg])), } }; @@ -431,15 +431,15 @@ impl<'a> CodeGenHelp<'a> { } Dec | DecRef(_) | Reset | ResetRef => self.arena.alloc([roc_value]), IndirectInc => { - let box_layout = - layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(layout)); + let ptr_layout = + layout_interner.insert_direct_no_semantic(LayoutRepr::Ptr(layout)); let inc_amount = (self.layout_isize, ARG_2); - self.arena.alloc([(box_layout, ARG_1), inc_amount]) + self.arena.alloc([(ptr_layout, ARG_1), inc_amount]) } IndirectDec => { - let box_layout = - layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(layout)); - self.arena.alloc([(box_layout, ARG_1)]) + let ptr_layout = + layout_interner.insert_direct_no_semantic(LayoutRepr::Ptr(layout)); + self.arena.alloc([(ptr_layout, ARG_1)]) } Eq => self.arena.alloc([roc_value, (layout, ARG_2)]), } @@ -486,21 +486,19 @@ impl<'a> CodeGenHelp<'a> { niche: Niche::NONE, }, HelperOp::IndirectInc => { - let box_layout = - layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(layout)); + let ptr_layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Ptr(layout)); ProcLayout { - arguments: self.arena.alloc([box_layout, self.layout_isize]), + arguments: self.arena.alloc([ptr_layout, self.layout_isize]), result: LAYOUT_UNIT, niche: Niche::NONE, } } HelperOp::IndirectDec => { - let box_layout = - layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(layout)); + let ptr_layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Ptr(layout)); ProcLayout { - arguments: self.arena.alloc([box_layout]), + arguments: self.arena.alloc([ptr_layout]), result: LAYOUT_UNIT, niche: Niche::NONE, } @@ -674,20 +672,20 @@ impl<'a> CallerProc<'a> { op: HelperOp::Eq, }; - let box_capture_layout = if let Some(capture_layout) = capture_layout { - layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(capture_layout)) + let ptr_capture_layout = if let Some(capture_layout) = capture_layout { + layout_interner.insert_direct_no_semantic(LayoutRepr::Ptr(capture_layout)) } else { - layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(Layout::UNIT)) + layout_interner.insert_direct_no_semantic(LayoutRepr::Ptr(Layout::UNIT)) }; - let box_argument_layout = layout_interner - .insert_direct_no_semantic(LayoutRepr::Boxed(passed_function.argument_layouts[0])); + let ptr_argument_layout = layout_interner + .insert_direct_no_semantic(LayoutRepr::Ptr(passed_function.argument_layouts[0])); - let box_return_layout = layout_interner - .insert_direct_no_semantic(LayoutRepr::Boxed(passed_function.return_layout)); + let ptr_return_layout = layout_interner + .insert_direct_no_semantic(LayoutRepr::Ptr(passed_function.return_layout)); let proc_layout = ProcLayout { - arguments: arena.alloc([box_capture_layout, box_argument_layout, box_return_layout]), + arguments: arena.alloc([ptr_capture_layout, ptr_argument_layout, ptr_return_layout]), result: Layout::UNIT, niche: Niche::NONE, }; @@ -697,16 +695,11 @@ impl<'a> CallerProc<'a> { ctx.new_linker_data.push((proc_symbol, proc_layout)); - let unbox_capture = Expr::ExprUnbox { - symbol: Symbol::ARG_1, - }; - - let unbox_argument = Expr::ExprUnbox { - symbol: Symbol::ARG_2, - }; + let load_capture = Expr::ptr_load(arena.alloc(Symbol::ARG_1)); + let load_argument = Expr::ptr_load(arena.alloc(Symbol::ARG_2)); - let unboxed_capture = Self::create_symbol(home, ident_ids, "unboxed_capture"); - let unboxed_argument = Self::create_symbol(home, ident_ids, "unboxed_argument"); + let loaded_capture = Self::create_symbol(home, ident_ids, "loaded_capture"); + let loaded_argument = Self::create_symbol(home, ident_ids, "loaded_argument"); let call_result = Self::create_symbol(home, ident_ids, "call_result"); let unit_symbol = Self::create_symbol(home, ident_ids, "unit_symbol"); let ignored = Self::create_symbol(home, ident_ids, "ignored"); @@ -719,9 +712,9 @@ impl<'a> CallerProc<'a> { specialization_id: passed_function.specialization_id, }, arguments: if capture_layout.is_some() { - arena.alloc([unboxed_argument, unboxed_capture]) + arena.alloc([loaded_argument, loaded_capture]) } else { - arena.alloc([unboxed_argument]) + arena.alloc([loaded_argument]) }, }); @@ -734,8 +727,8 @@ impl<'a> CallerProc<'a> { }); let mut body = Stmt::Let( - unboxed_argument, - unbox_argument, + loaded_argument, + load_argument, passed_function.argument_layouts[0], arena.alloc(Stmt::Let( call_result, @@ -744,7 +737,7 @@ impl<'a> CallerProc<'a> { arena.alloc(Stmt::Let( ignored, ptr_write, - box_return_layout, + ptr_return_layout, arena.alloc(Stmt::Let( unit_symbol, Expr::Struct(&[]), @@ -757,8 +750,8 @@ impl<'a> CallerProc<'a> { if let Some(capture_layout) = capture_layout { body = Stmt::Let( - unboxed_capture, - unbox_capture, + loaded_capture, + load_capture, capture_layout, arena.alloc(body), ); @@ -766,9 +759,9 @@ impl<'a> CallerProc<'a> { let args: &'a [(InLayout<'a>, Symbol)] = { arena.alloc([ - (box_capture_layout, ARG_1), - (box_argument_layout, ARG_2), - (box_return_layout, ARG_3), + (ptr_capture_layout, ARG_1), + (ptr_argument_layout, ARG_2), + (ptr_return_layout, ARG_3), ]) }; diff --git a/crates/compiler/mono/src/code_gen_help/refcount.rs b/crates/compiler/mono/src/code_gen_help/refcount.rs index 7fcea26f453..c6c563fd283 100644 --- a/crates/compiler/mono/src/code_gen_help/refcount.rs +++ b/crates/compiler/mono/src/code_gen_help/refcount.rs @@ -135,7 +135,7 @@ pub fn refcount_indirect<'a>( let arena = root.arena; let unit = root.create_symbol(ident_ids, "unit"); - let unboxed = root.create_symbol(ident_ids, "unboxed"); + let loaded = root.create_symbol(ident_ids, "loaded"); let indirect_op = ctx.op; let direct_op = match ctx.op { @@ -147,7 +147,7 @@ pub fn refcount_indirect<'a>( // we've done the indirection, the inner value shoud be inc- or decremented directly ctx.op = direct_op; - let mod_args = refcount_args(root, ctx, unboxed); + let mod_args = refcount_args(root, ctx, loaded); let opt_mod_expr = root.call_specialized_op(ident_ids, ctx, layout_interner, element_layout, mod_args); @@ -156,8 +156,8 @@ pub fn refcount_indirect<'a>( if let Some(mod_expr) = opt_mod_expr { Stmt::Let( - unboxed, - Expr::ExprUnbox { symbol: structure }, + loaded, + Expr::ptr_load(arena.alloc(structure)), element_layout, arena.alloc( // @@ -447,7 +447,7 @@ pub fn refcount_reset_proc_body<'a>( ); // Refcount value - let rc_expr = Expr::ExprUnbox { symbol: rc_ptr }; + let rc_expr = Expr::ptr_load(root.arena.alloc(rc_ptr)); let rc_stmt = Stmt::Let( rc, @@ -572,7 +572,7 @@ pub fn refcount_resetref_proc_body<'a>( ); // Refcount value - let rc_expr = Expr::ExprUnbox { symbol: rc_ptr }; + let rc_expr = Expr::ptr_load(root.arena.alloc(rc_ptr)); let rc_stmt = Stmt::Let( rc, @@ -968,8 +968,8 @@ fn refcount_list<'a>( let layout_isize = root.layout_isize; let arena = root.arena; - // A "Box" layout (heap pointer to a single list element) - let box_layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(elem_layout)); + // A "Ptr" layout (heap pointer to a single list element) + let ptr_layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Ptr(elem_layout)); // // Check if the list is empty @@ -993,7 +993,7 @@ fn refcount_list<'a>( // let capacity = StructAtIndex 2 structure let capacity = root.create_symbol(ident_ids, "capacity"); - let list_field_layouts = arena.alloc([box_layout, layout_isize, layout_isize]); + let list_field_layouts = arena.alloc([ptr_layout, layout_isize, layout_isize]); let capacity_expr = Expr::StructAtIndex { index: 2, field_layouts: list_field_layouts, @@ -1017,7 +1017,7 @@ fn refcount_list<'a>( field_layouts: list_field_layouts, structure, }; - let first_element_stmt = |next| Stmt::Let(first_element, first_element_expr, box_layout, next); + let first_element_stmt = |next| Stmt::Let(first_element, first_element_expr, ptr_layout, next); let jp_elements = JoinPointId(root.create_symbol(ident_ids, "jp_elements")); let data_pointer = root.create_symbol(ident_ids, "data_pointer"); @@ -1104,7 +1104,7 @@ fn refcount_list<'a>( layout_interner, elem_layout, LAYOUT_UNIT, - box_layout, + ptr_layout, len, first_element_pointer, modify_list, @@ -1166,7 +1166,7 @@ fn refcount_list_elems<'a>( layout_interner: &mut STLayoutInterner<'a>, elem_layout: InLayout<'a>, ret_layout: InLayout<'a>, - box_layout: InLayout<'a>, + ptr_layout: InLayout<'a>, length: Symbol, elements: Symbol, following: Stmt<'a>, @@ -1224,13 +1224,13 @@ fn refcount_list_elems<'a>( // if we haven't reached the end yet... // - // Cast integer to box pointer - let box_ptr = root.create_symbol(ident_ids, "box"); - let box_stmt = |next| let_lowlevel(arena, box_layout, box_ptr, PtrCast, &[addr], next); + // Cast integer to pointer + let ptr_symbol = root.create_symbol(ident_ids, "ptr"); + let ptr_stmt = |next| let_lowlevel(arena, ptr_layout, ptr_symbol, PtrCast, &[addr], next); - // Dereference the box pointer to get the current element + // Dereference the pointer to get the current element let elem = root.create_symbol(ident_ids, "elem"); - let elem_expr = Expr::ExprUnbox { symbol: box_ptr }; + let elem_expr = Expr::ptr_load(arena.alloc(ptr_symbol)); let elem_stmt = |next| Stmt::Let(elem, elem_expr, elem_layout, next); // @@ -1273,7 +1273,7 @@ fn refcount_list_elems<'a>( is_end, ret_layout, following, - arena.alloc(box_stmt(arena.alloc( + arena.alloc(ptr_stmt(arena.alloc( // elem_stmt(arena.alloc( // diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index 8ef7a13e27d..3bbddbbb8e2 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -2108,6 +2108,16 @@ impl<'a> Expr<'a> { w.push(b'\n'); String::from_utf8(w).unwrap() } + + pub(crate) fn ptr_load(symbol: &'a Symbol) -> Expr<'a> { + Expr::Call(Call { + call_type: CallType::LowLevel { + op: LowLevel::PtrLoad, + update_mode: UpdateModeId::BACKEND_DUMMY, + }, + arguments: std::slice::from_ref(symbol), + }) + } } impl<'a> Stmt<'a> { From 7e86539e3dbd7f63d26658d4bbe1db433e4333c0 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Fri, 30 Jun 2023 18:05:39 +0200 Subject: [PATCH 105/140] c_char fix The i8 is a u8 on raspberry pi 4 aarch64 linux, c_char takes care of this automatically. --- crates/linker/src/elf.rs | 2 +- crates/linker/src/macho.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/linker/src/elf.rs b/crates/linker/src/elf.rs index de5920b8849..40b2c8948d0 100644 --- a/crates/linker/src/elf.rs +++ b/crates/linker/src/elf.rs @@ -1023,7 +1023,7 @@ fn scan_elf_dynamic_deps( ) .unwrap(), ) as usize; - let c_buf: *const c_char = dynstr_data[dynstr_off..].as_ptr() as *const i8; + let c_buf = dynstr_data[dynstr_off..].as_ptr() as *const c_char; let c_str = unsafe { CStr::from_ptr(c_buf) }.to_str().unwrap(); if Path::new(c_str).file_name() == shared_lib_filename { shared_lib_index = Some(dyn_lib_index); diff --git a/crates/linker/src/macho.rs b/crates/linker/src/macho.rs index 1d481b6de71..cfcf3bc18c9 100644 --- a/crates/linker/src/macho.rs +++ b/crates/linker/src/macho.rs @@ -11,7 +11,7 @@ use roc_collections::all::MutMap; use roc_error_macros::internal_error; use serde::{Deserialize, Serialize}; use std::{ - ffi::CStr, + ffi::{CStr, c_char}, io::{BufReader, BufWriter}, mem, path::Path, @@ -499,7 +499,7 @@ pub(crate) fn preprocess_macho( // std::ffi::CStr is actually not a char* under // the hood (!) but rather an array, so to strip // the trailing null bytes we have to use from_ptr. - let c_str = unsafe { CStr::from_ptr(str_bytes.as_ptr() as *const i8) }; + let c_str = unsafe { CStr::from_ptr(str_bytes.as_ptr() as *const c_char) }; Path::new(c_str.to_str().unwrap()) } else { From 4e9bffca0be2845fb459991dc2d11c46bd9a08b3 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Fri, 30 Jun 2023 18:27:47 +0200 Subject: [PATCH 106/140] fmt --- crates/linker/src/macho.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/linker/src/macho.rs b/crates/linker/src/macho.rs index cfcf3bc18c9..c64cd350cef 100644 --- a/crates/linker/src/macho.rs +++ b/crates/linker/src/macho.rs @@ -11,7 +11,7 @@ use roc_collections::all::MutMap; use roc_error_macros::internal_error; use serde::{Deserialize, Serialize}; use std::{ - ffi::{CStr, c_char}, + ffi::{c_char, CStr}, io::{BufReader, BufWriter}, mem, path::Path, From ae84745c2e4f95bbde4bed5751b04e33e4161240 Mon Sep 17 00:00:00 2001 From: Kilian Vounckx Date: Mon, 3 Jul 2023 13:40:14 +0200 Subject: [PATCH 107/140] Rename digits parser to positiveInt and fix bug --- examples/parser/Parser/Str.roc | 8 ++++---- examples/parser/package/ParserStr.roc | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/parser/Parser/Str.roc b/examples/parser/Parser/Str.roc index 0d7cdbf02c8..2c5bb33e206 100644 --- a/examples/parser/Parser/Str.roc +++ b/examples/parser/Parser/Str.roc @@ -15,7 +15,7 @@ interface Parser.Str scalar, oneOf, digit, - digits, + positiveInt, strFromRaw, ] imports [Parser.Core.{ Parser, ParseResult, map, oneOrMore, parse, parsePartial, buildPrimitiveParser }] @@ -186,12 +186,12 @@ digit = oneOf digitParsers # NOTE: Currently happily accepts leading zeroes -digits : Parser RawStr (Int *) -digits = +positiveInt : Parser RawStr (Int *) +positiveInt = oneOrMore digit |> map \digitsList -> digitsList - |> List.map Num.intCast + |> List.map \char -> Num.intCast char - '0' |> List.walk 0 \sum, digitVal -> 10 * sum + digitVal ## Try a bunch of different parsers. diff --git a/examples/parser/package/ParserStr.roc b/examples/parser/package/ParserStr.roc index 8b62b318881..f433c030236 100644 --- a/examples/parser/package/ParserStr.roc +++ b/examples/parser/package/ParserStr.roc @@ -15,7 +15,7 @@ interface ParserStr scalar, oneOf, digit, - digits, + positiveInt, strFromRaw, ] imports [ @@ -196,12 +196,12 @@ digit = oneOf digitParsers # NOTE: Currently happily accepts leading zeroes -digits : Parser RawStr (Int *) -digits = +positiveInt : Parser RawStr (Int *) +positiveInt = oneOrMore digit |> map \digitsList -> digitsList - |> List.map Num.intCast + |> List.map \char -> Num.intCast char - '0' |> List.walk 0 \sum, digitVal -> 10 * sum + digitVal ## Try a bunch of different parsers. From 654248ad47fa334978cb53f66a38ddb9d1912580 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Mon, 3 Jul 2023 15:41:34 -0700 Subject: [PATCH 108/140] Allow spaces before and after the colon in the `packages` header section Fixes #4902 --- crates/compiler/parse/src/header.rs | 18 ++- .../space_before_colon.full.formatted.roc | 6 + .../pass/space_before_colon.full.result-ast | 116 ++++++++++++++++++ .../pass/space_before_colon.full.roc | 6 + .../test_syntax/tests/test_snapshots.rs | 1 + 5 files changed, 142 insertions(+), 5 deletions(-) create mode 100644 crates/compiler/test_syntax/tests/snapshots/pass/space_before_colon.full.formatted.roc create mode 100644 crates/compiler/test_syntax/tests/snapshots/pass/space_before_colon.full.result-ast create mode 100644 crates/compiler/test_syntax/tests/snapshots/pass/space_before_colon.full.roc diff --git a/crates/compiler/parse/src/header.rs b/crates/compiler/parse/src/header.rs index 5c02bc580bb..3425f465738 100644 --- a/crates/compiler/parse/src/header.rs +++ b/crates/compiler/parse/src/header.rs @@ -2,6 +2,7 @@ use crate::ast::{ Collection, CommentOrNewline, Malformed, Spaced, Spaces, StrLiteral, TypeAnnotation, }; use crate::blankspace::space0_e; +use crate::expr::merge_spaces; use crate::ident::{lowercase_ident, UppercaseIdent}; use crate::parser::{optional, then}; use crate::parser::{specialize, word1, EPackageEntry, EPackageName, Parser}; @@ -300,7 +301,7 @@ pub struct PackageEntry<'a> { } pub fn package_entry<'a>() -> impl Parser<'a, Spaced<'a, PackageEntry<'a>>, EPackageEntry<'a>> { - map!( + map_with_arena!( // You may optionally have a package shorthand, // e.g. "uc" in `uc: roc/unicode 1.0.0` // @@ -308,18 +309,25 @@ pub fn package_entry<'a>() -> impl Parser<'a, Spaced<'a, PackageEntry<'a>>, EPac and!( optional(and!( skip_second!( - specialize(|_, pos| EPackageEntry::Shorthand(pos), lowercase_ident()), + and!( + specialize(|_, pos| EPackageEntry::Shorthand(pos), lowercase_ident()), + space0_e(EPackageEntry::IndentPackage) + ), word1(b':', EPackageEntry::Colon) ), space0_e(EPackageEntry::IndentPackage) )), loc!(specialize(EPackageEntry::BadPackage, package_name())) ), - move |(opt_shorthand, package_or_path)| { + move |arena, (opt_shorthand, package_or_path)| { let entry = match opt_shorthand { - Some((shorthand, spaces_after_shorthand)) => PackageEntry { + Some(((shorthand, spaces_before_colon), spaces_after_colon)) => PackageEntry { shorthand, - spaces_after_shorthand, + spaces_after_shorthand: merge_spaces( + arena, + spaces_before_colon, + spaces_after_colon, + ), package_name: package_or_path, }, None => PackageEntry { diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/space_before_colon.full.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/space_before_colon.full.formatted.roc new file mode 100644 index 00000000000..48ccd21f646 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/space_before_colon.full.formatted.roc @@ -0,0 +1,6 @@ +app "example" + packages { pf: "path" } + imports [pf.Stdout] + provides [main] to pf + +main = Stdout.line "Hello" diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/space_before_colon.full.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/space_before_colon.full.result-ast new file mode 100644 index 00000000000..dd4a45a9f21 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/space_before_colon.full.result-ast @@ -0,0 +1,116 @@ +Full { + header: Module { + comments: [], + header: App( + AppHeader { + before_name: [], + name: @4-13 PlainLine( + "example", + ), + packages: Some( + KeywordItem { + keyword: Spaces { + before: [ + Newline, + ], + item: PackagesKeyword, + after: [], + }, + item: [ + @29-40 PackageEntry { + shorthand: "pf", + spaces_after_shorthand: [], + package_name: @34-40 PackageName( + "path", + ), + }, + ], + }, + ), + imports: Some( + KeywordItem { + keyword: Spaces { + before: [ + Newline, + ], + item: ImportsKeyword, + after: [], + }, + item: [ + @57-66 Package( + "pf", + ModuleName( + "Stdout", + ), + [], + ), + ], + }, + ), + provides: ProvidesTo { + provides_keyword: Spaces { + before: [ + Newline, + ], + item: ProvidesKeyword, + after: [], + }, + entries: [ + @84-88 ExposedName( + "main", + ), + ], + types: None, + to_keyword: Spaces { + before: [], + item: ToKeyword, + after: [], + }, + to: @94-96 ExistingPackage( + "pf", + ), + }, + }, + ), + }, + module_defs: Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @98-124, + ], + space_before: [ + Slice(start = 0, length = 2), + ], + space_after: [ + Slice(start = 2, length = 0), + ], + spaces: [ + Newline, + Newline, + ], + type_defs: [], + value_defs: [ + Body( + @98-102 Identifier( + "main", + ), + @105-124 Apply( + @105-116 Var { + module_name: "Stdout", + ident: "line", + }, + [ + @117-124 Str( + PlainLine( + "Hello", + ), + ), + ], + Space, + ), + ), + ], + }, +} diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/space_before_colon.full.roc b/crates/compiler/test_syntax/tests/snapshots/pass/space_before_colon.full.roc new file mode 100644 index 00000000000..e6d070fc184 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/space_before_colon.full.roc @@ -0,0 +1,6 @@ +app "example" + packages { pf : "path" } + imports [ pf.Stdout ] + provides [ main ] to pf + +main = Stdout.line "Hello" \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/test_snapshots.rs b/crates/compiler/test_syntax/tests/test_snapshots.rs index eb12ac3da7d..92ab0e6c790 100644 --- a/crates/compiler/test_syntax/tests/test_snapshots.rs +++ b/crates/compiler/test_syntax/tests/test_snapshots.rs @@ -430,6 +430,7 @@ mod test_snapshots { pass/requires_type.header, pass/single_arg_closure.expr, pass/single_underscore_closure.expr, + pass/space_before_colon.full, pass/space_only_after_minus.expr, pass/spaced_singleton_list.expr, pass/spaces_inside_empty_list.expr, From 6031c0cc9f33fc967c4cacc8d6c852f20c6256b7 Mon Sep 17 00:00:00 2001 From: Kiryl Dziamura Date: Fri, 23 Jun 2023 00:56:19 +0200 Subject: [PATCH 109/140] Fix desugar step for pizza operator --- .../ast/src/lang/core/expr/expr_to_expr2.rs | 8 +--- crates/compiler/can/src/expr.rs | 11 +++-- crates/compiler/can/src/operator.rs | 18 ++++++++- crates/reporting/tests/test_reporting.rs | 40 +++++++++++++++++++ 4 files changed, 63 insertions(+), 14 deletions(-) diff --git a/crates/ast/src/lang/core/expr/expr_to_expr2.rs b/crates/ast/src/lang/core/expr/expr_to_expr2.rs index cdbc12a054f..c76375d478c 100644 --- a/crates/ast/src/lang/core/expr/expr_to_expr2.rs +++ b/crates/ast/src/lang/core/expr/expr_to_expr2.rs @@ -665,14 +665,10 @@ pub fn expr_to_expr2<'a>( ident, } => canonicalize_lookup(env, scope, module_name, ident, region), + ParensAround(sub_expr) => expr_to_expr2(env, scope, sub_expr, region), + // Below this point, we shouln't see any of these nodes anymore because // operator desugaring should have removed them! - bad_expr @ ParensAround(_) => { - panic!( - "A ParensAround did not get removed during operator desugaring somehow: {:#?}", - bad_expr - ); - } bad_expr @ SpaceBefore(_, _) => { panic!( "A SpaceBefore did not get removed during operator desugaring somehow: {:#?}", diff --git a/crates/compiler/can/src/expr.rs b/crates/compiler/can/src/expr.rs index 62ee13504ba..0beecfd7004 100644 --- a/crates/compiler/can/src/expr.rs +++ b/crates/compiler/can/src/expr.rs @@ -1403,14 +1403,13 @@ pub fn canonicalize_expr<'a>( (answer, Output::default()) } + &ast::Expr::ParensAround(sub_expr) => { + let (loc_expr, output) = canonicalize_expr(env, var_store, scope, region, sub_expr); + + (loc_expr.value, output) + } // Below this point, we shouln't see any of these nodes anymore because // operator desugaring should have removed them! - bad_expr @ ast::Expr::ParensAround(_) => { - internal_error!( - "A ParensAround did not get removed during operator desugaring somehow: {:#?}", - bad_expr - ); - } bad_expr @ ast::Expr::SpaceBefore(_, _) => { internal_error!( "A SpaceBefore did not get removed during operator desugaring somehow: {:#?}", diff --git a/crates/compiler/can/src/operator.rs b/crates/compiler/can/src/operator.rs index 8db8f8ff76c..0efd582a9d0 100644 --- a/crates/compiler/can/src/operator.rs +++ b/crates/compiler/can/src/operator.rs @@ -288,7 +288,7 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc break builder_arg.closure; } - SpaceBefore(expr, _) | SpaceAfter(expr, _) | ParensAround(expr) => { + SpaceBefore(expr, _) | SpaceAfter(expr, _) => { current = *expr; } _ => break loc_arg, @@ -382,7 +382,7 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc region: loc_expr.region, }) } - SpaceBefore(expr, _) | SpaceAfter(expr, _) | ParensAround(expr) => { + SpaceBefore(expr, _) | SpaceAfter(expr, _) => { // Since we've already begun canonicalization, spaces and parens // are no longer needed and should be dropped. desugar_expr( @@ -393,6 +393,20 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc }), ) } + ParensAround(expr) => { + let desugared = desugar_expr( + arena, + arena.alloc(Loc { + value: **expr, + region: loc_expr.region, + }), + ); + + arena.alloc(Loc { + value: ParensAround(&desugared.value), + region: loc_expr.region, + }) + } If(if_thens, final_else_branch) => { // If does not get desugared into `when` so we can give more targeted error messages during type checking. let desugared_final_else = &*arena.alloc(desugar_expr(arena, final_else_branch)); diff --git a/crates/reporting/tests/test_reporting.rs b/crates/reporting/tests/test_reporting.rs index d186cd20bed..9a4d66e4b7f 100644 --- a/crates/reporting/tests/test_reporting.rs +++ b/crates/reporting/tests/test_reporting.rs @@ -13875,4 +13875,44 @@ In roc, functions are always written as a lambda, like{} Tip: It looks like it takes too many arguments. I'm seeing 1 extra. "### ); + + test_report!( + pizza_parens_right, + indoc!( + r#" + 2 |> (Num.sub 3) + "# + ), + @r###" + ── TOO FEW ARGS ────────────────────────────────────────── /code/proj/Main.roc ─ + + The `sub` function expects 2 arguments, but it got only 1: + + 4│ 2 |> (Num.sub 3) + ^^^^^^^ + + Roc does not allow functions to be partially applied. Use a closure to + make partial application explicit. + "### + ); + + test_report!( + pizza_parens_middle, + indoc!( + r#" + 2 |> (Num.sub 3) |> Num.sub 3 + "# + ), + @r###" + ── TOO FEW ARGS ────────────────────────────────────────── /code/proj/Main.roc ─ + + The `sub` function expects 2 arguments, but it got only 1: + + 4│ 2 |> (Num.sub 3) |> Num.sub 3 + ^^^^^^^ + + Roc does not allow functions to be partially applied. Use a closure to + make partial application explicit. + "### + ); } From 29592ddb9b7e35235750e23b5f036fe4cdc290f1 Mon Sep 17 00:00:00 2001 From: Kiryl Dziamura Date: Wed, 28 Jun 2023 21:39:10 +0200 Subject: [PATCH 110/140] Drop parens during body canonicalization --- crates/compiler/can/src/def.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/compiler/can/src/def.rs b/crates/compiler/can/src/def.rs index 79c05a58716..187a9d61075 100644 --- a/crates/compiler/can/src/def.rs +++ b/crates/compiler/can/src/def.rs @@ -2272,12 +2272,17 @@ fn canonicalize_pending_body<'a>( opt_loc_annotation: Option>, ) -> DefOutput { + let loc_value = match &loc_expr.value { + ast::Expr::ParensAround(loc_value) => loc_value, + _ => &loc_expr.value, + }; + // We treat closure definitions `foo = \a, b -> ...` differently from other body expressions, // because they need more bookkeeping (for tail calls, closure captures, etc.) // // Only defs of the form `foo = ...` can be closure declarations or self tail calls. let (loc_can_expr, def_references) = { - match (&loc_can_pattern.value, &loc_expr.value) { + match (&loc_can_pattern.value, &loc_value) { ( Pattern::Identifier(defined_symbol) | Pattern::AbilityMemberSpecialization { From 3ccb6114b2825f907f4b12964f02f6bb5e8bf8b3 Mon Sep 17 00:00:00 2001 From: Kiryl Dziamura Date: Mon, 3 Jul 2023 15:38:59 +0200 Subject: [PATCH 111/140] Unwrap expr in loop --- crates/compiler/can/src/def.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/compiler/can/src/def.rs b/crates/compiler/can/src/def.rs index 187a9d61075..29fcf69b5b2 100644 --- a/crates/compiler/can/src/def.rs +++ b/crates/compiler/can/src/def.rs @@ -2272,10 +2272,11 @@ fn canonicalize_pending_body<'a>( opt_loc_annotation: Option>, ) -> DefOutput { - let loc_value = match &loc_expr.value { - ast::Expr::ParensAround(loc_value) => loc_value, - _ => &loc_expr.value, - }; + let mut loc_value = &loc_expr.value; + + while let ast::Expr::ParensAround(value) = loc_value { + loc_value = value; + } // We treat closure definitions `foo = \a, b -> ...` differently from other body expressions, // because they need more bookkeeping (for tail calls, closure captures, etc.) From c90c399751d3d2d8f742c4895b4b82e57166e85a Mon Sep 17 00:00:00 2001 From: Kiryl Dziamura Date: Mon, 3 Jul 2023 15:41:06 +0200 Subject: [PATCH 112/140] Test closure definition with parens around --- .../compiler/test_gen/src/gen_definitions.rs | 47 +++++++++++++++++++ crates/compiler/test_gen/src/tests.rs | 1 + 2 files changed, 48 insertions(+) create mode 100644 crates/compiler/test_gen/src/gen_definitions.rs diff --git a/crates/compiler/test_gen/src/gen_definitions.rs b/crates/compiler/test_gen/src/gen_definitions.rs new file mode 100644 index 00000000000..ef575efc480 --- /dev/null +++ b/crates/compiler/test_gen/src/gen_definitions.rs @@ -0,0 +1,47 @@ +#[cfg(feature = "gen-llvm")] +use crate::helpers::llvm::assert_evals_to; + +#[cfg(feature = "gen-dev")] +use crate::helpers::dev::assert_evals_to; + +#[cfg(feature = "gen-wasm")] +use crate::helpers::wasm::assert_evals_to; + +// use crate::helpers::with_larger_debug_stack; +//use crate::assert_wasm_evals_to as assert_evals_to; +#[allow(unused_imports)] +use indoc::indoc; +#[allow(unused_imports)] +use roc_std::{RocList, RocResult, RocStr}; + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))] +fn def_closure_in_parens() { + assert_evals_to!( + indoc!( + r#" + id = (\x -> x) + + id 42u32 + "# + ), + 42, + u32 + ); +} + +#[test] +#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))] +fn def_closure_in_multiple_parens() { + assert_evals_to!( + indoc!( + r#" + id = (((\x -> x))) + + id 42u32 + "# + ), + 42, + u32 + ); +} diff --git a/crates/compiler/test_gen/src/tests.rs b/crates/compiler/test_gen/src/tests.rs index b7d87f148aa..5ca507478ba 100644 --- a/crates/compiler/test_gen/src/tests.rs +++ b/crates/compiler/test_gen/src/tests.rs @@ -6,6 +6,7 @@ pub mod gen_abilities; pub mod gen_compare; +pub mod gen_definitions; pub mod gen_dict; pub mod gen_list; pub mod gen_num; From 1bb3c3d1dd46f3c58f63a7c498821f67ef1eb6b6 Mon Sep 17 00:00:00 2001 From: Kiryl Dziamura Date: Tue, 4 Jul 2023 11:24:40 +0200 Subject: [PATCH 113/140] Make `has` have 4 identation spaces --- crates/compiler/builtins/roc/Dict.roc | 36 ++++---- crates/compiler/builtins/roc/Set.roc | 16 ++-- .../compiler/builtins/roc/TotallyNotJson.roc | 86 +++++++++---------- crates/compiler/fmt/src/def.rs | 2 +- .../opaque_has_abilities.expr.formatted.roc | 6 +- crates/compiler/test_syntax/tests/test_fmt.rs | 16 ++-- examples/cli/cli-platform/EnvDecoding.roc | 42 ++++----- 7 files changed, 102 insertions(+), 102 deletions(-) diff --git a/crates/compiler/builtins/roc/Dict.roc b/crates/compiler/builtins/roc/Dict.roc index 180033b0086..ec316cf351b 100644 --- a/crates/compiler/builtins/roc/Dict.roc +++ b/crates/compiler/builtins/roc/Dict.roc @@ -101,14 +101,14 @@ Dict k v := { data : List (k, v), size : Nat, } | k has Hash & Eq - has [ - Eq { - isEq, - }, - Hash { - hash: hashDict, - }, - ] + has [ + Eq { + isEq, + }, + Hash { + hash: hashDict, + }, + ] isEq : Dict k v, Dict k v -> Bool | k has Hash & Eq, v has Eq isEq = \xs, ys -> @@ -1011,16 +1011,16 @@ expect # TODO: Add a builtin to distinguish big endian systems and change loading orders. # TODO: Switch out Wymum on systems with slow 128bit multiplication. LowLevelHasher := { originalSeed : U64, state : U64 } has [ - Hasher { - addBytes, - addU8, - addU16, - addU32, - addU64, - addU128, - complete, - }, - ] + Hasher { + addBytes, + addU8, + addU16, + addU32, + addU64, + addU128, + complete, + }, + ] # unsafe primitive that does not perform a bounds check # TODO hide behind an InternalList.roc module diff --git a/crates/compiler/builtins/roc/Set.roc b/crates/compiler/builtins/roc/Set.roc index f8b2072d0d4..7fc76c98078 100644 --- a/crates/compiler/builtins/roc/Set.roc +++ b/crates/compiler/builtins/roc/Set.roc @@ -30,14 +30,14 @@ interface Set ## Provides a [set](https://en.wikipedia.org/wiki/Set_(abstract_data_type)) ## type which stores a collection of unique values, without any ordering Set k := Dict.Dict k {} | k has Hash & Eq - has [ - Eq { - isEq, - }, - Hash { - hash: hashSet, - }, - ] + has [ + Eq { + isEq, + }, + Hash { + hash: hashSet, + }, + ] isEq : Set k, Set k -> Bool | k has Hash & Eq isEq = \xs, ys -> diff --git a/crates/compiler/builtins/roc/TotallyNotJson.roc b/crates/compiler/builtins/roc/TotallyNotJson.roc index 93c0feb9126..6df2a9cf7c0 100644 --- a/crates/compiler/builtins/roc/TotallyNotJson.roc +++ b/crates/compiler/builtins/roc/TotallyNotJson.roc @@ -44,49 +44,49 @@ interface TotallyNotJson ## An opaque type with the `EncoderFormatting` and ## `DecoderFormatting` abilities. Json := { fieldNameMapping : FieldNameMapping } - has [ - EncoderFormatting { - u8: encodeU8, - u16: encodeU16, - u32: encodeU32, - u64: encodeU64, - u128: encodeU128, - i8: encodeI8, - i16: encodeI16, - i32: encodeI32, - i64: encodeI64, - i128: encodeI128, - f32: encodeF32, - f64: encodeF64, - dec: encodeDec, - bool: encodeBool, - string: encodeString, - list: encodeList, - record: encodeRecord, - tuple: encodeTuple, - tag: encodeTag, - }, - DecoderFormatting { - u8: decodeU8, - u16: decodeU16, - u32: decodeU32, - u64: decodeU64, - u128: decodeU128, - i8: decodeI8, - i16: decodeI16, - i32: decodeI32, - i64: decodeI64, - i128: decodeI128, - f32: decodeF32, - f64: decodeF64, - dec: decodeDec, - bool: decodeBool, - string: decodeString, - list: decodeList, - record: decodeRecord, - tuple: decodeTuple, - }, - ] + has [ + EncoderFormatting { + u8: encodeU8, + u16: encodeU16, + u32: encodeU32, + u64: encodeU64, + u128: encodeU128, + i8: encodeI8, + i16: encodeI16, + i32: encodeI32, + i64: encodeI64, + i128: encodeI128, + f32: encodeF32, + f64: encodeF64, + dec: encodeDec, + bool: encodeBool, + string: encodeString, + list: encodeList, + record: encodeRecord, + tuple: encodeTuple, + tag: encodeTag, + }, + DecoderFormatting { + u8: decodeU8, + u16: decodeU16, + u32: decodeU32, + u64: decodeU64, + u128: decodeU128, + i8: decodeI8, + i16: decodeI16, + i32: decodeI32, + i64: decodeI64, + i128: decodeI128, + f32: decodeF32, + f64: decodeF64, + dec: decodeDec, + bool: decodeBool, + string: decodeString, + list: decodeList, + record: decodeRecord, + tuple: decodeTuple, + }, + ] ## Returns a JSON `Encoder` and `Decoder` json = @Json { fieldNameMapping: Default } diff --git a/crates/compiler/fmt/src/def.rs b/crates/compiler/fmt/src/def.rs index bb5268bcc28..997edb8a376 100644 --- a/crates/compiler/fmt/src/def.rs +++ b/crates/compiler/fmt/src/def.rs @@ -117,7 +117,7 @@ impl<'a> Formattable for TypeDef<'a> { buf, Parens::NotNeeded, Newlines::from_bool(make_multiline), - indent + 1 + INDENT, + indent + INDENT, ); } } diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/opaque_has_abilities.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_has_abilities.expr.formatted.roc index 783b9d8c175..768b1dab9d5 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/opaque_has_abilities.expr.formatted.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_has_abilities.expr.formatted.roc @@ -1,10 +1,10 @@ A := U8 has [Eq, Hash] A := a | a has Other - has [Eq, Hash] + has [Eq, Hash] A := a | a has Other - has [Eq, Hash] + has [Eq, Hash] A := U8 has [Eq { eq }, Hash { hash }] @@ -17,7 +17,7 @@ A := U8 has [Hash, Eq { eq, eq1 }] A := U8 has [] A := a | a has Other - has [Eq { eq }, Hash { hash }] + has [Eq { eq }, Hash { hash }] A := U8 has [Eq {}] diff --git a/crates/compiler/test_syntax/tests/test_fmt.rs b/crates/compiler/test_syntax/tests/test_fmt.rs index 751b3f080b4..ff7cb5dd04d 100644 --- a/crates/compiler/test_syntax/tests/test_fmt.rs +++ b/crates/compiler/test_syntax/tests/test_fmt.rs @@ -5447,7 +5447,7 @@ mod test_fmt { indoc!( r#" A := U8 - has [Eq, Hash] + has [Eq, Hash] 0 "# @@ -5465,7 +5465,7 @@ mod test_fmt { indoc!( r#" A := a | a has Hash - has [Eq, Hash] + has [Eq, Hash] 0 "# @@ -5555,11 +5555,11 @@ mod test_fmt { r#" A := U8 has [Eq { eq, eq1 }] A := U8 has [ - Eq { - eq, - eq1, - }, - ] + Eq { + eq, + eq1, + }, + ] 0 "# @@ -5569,7 +5569,7 @@ mod test_fmt { expr_formats_same(indoc!( r#" A := a | a has Other - has [Eq { eq }, Hash { hash }] + has [Eq { eq }, Hash { hash }] 0 "# diff --git a/examples/cli/cli-platform/EnvDecoding.roc b/examples/cli/cli-platform/EnvDecoding.roc index ccc4a9f2bb6..d6be7f2b2cb 100644 --- a/examples/cli/cli-platform/EnvDecoding.roc +++ b/examples/cli/cli-platform/EnvDecoding.roc @@ -1,27 +1,27 @@ interface EnvDecoding exposes [EnvFormat, format] imports [] EnvFormat := {} has [ - DecoderFormatting { - u8: envU8, - u16: envU16, - u32: envU32, - u64: envU64, - u128: envU128, - i8: envI8, - i16: envI16, - i32: envI32, - i64: envI64, - i128: envI128, - f32: envF32, - f64: envF64, - dec: envDec, - bool: envBool, - string: envString, - list: envList, - record: envRecord, - tuple: envTuple, - }, - ] + DecoderFormatting { + u8: envU8, + u16: envU16, + u32: envU32, + u64: envU64, + u128: envU128, + i8: envI8, + i16: envI16, + i32: envI32, + i64: envI64, + i128: envI128, + f32: envF32, + f64: envF64, + dec: envDec, + bool: envBool, + string: envString, + list: envList, + record: envRecord, + tuple: envTuple, + }, + ] format : {} -> EnvFormat format = \{} -> @EnvFormat {} From 626ca609b8ea6d32f4be04f8d1788248d0fd765b Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Wed, 5 Jul 2023 12:33:17 +0200 Subject: [PATCH 114/140] readme visibility Someone missed the group chat link in the README, so I'm trying to make it stand out more Signed-off-by: Anton-4 <17049058+Anton-4@users.noreply.github.com> --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d701a872935..dd81e597cbe 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ Roc is not ready for a 0.1 release yet, but we do have: - [**tutorial**](https://roc-lang.org/tutorial) - [**docs** for the standard library](https://www.roc-lang.org/builtins) - [**examples**](https://github.com/roc-lang/examples/tree/main/examples) -- [frequently asked questions](https://github.com/roc-lang/roc/blob/main/FAQ.md) -- [Group chat](https://roc.zulipchat.com) for help, questions and discussions +- [**faq**: frequently asked questions](https://github.com/roc-lang/roc/blob/main/FAQ.md) +- [**group chat**](https://roc.zulipchat.com) for help, questions and discussions If you'd like to contribute, check out [good first issues](https://github.com/roc-lang/roc/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22). Don't hesitate to ask for help on our [group chat](https://roc.zulipchat.com), we're friendly! From ff4b4cb3a34035eb3a7f29ffc0cc61fcbf9e2b6f Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Wed, 5 Jul 2023 18:54:28 +0200 Subject: [PATCH 115/140] deploy wip website, minor changes --- www/build.sh | 20 +++++++---- www/wip_new_website/build.roc | 35 +++++++------------ .../{community_page.md => community.md} | 0 .../{design_goals_page.md => design_goals.md} | 0 .../content/{docs_page.md => docs.md} | 0 .../content/{home_page.md => index.md} | 12 +++---- .../content/{install_page.md => install.md} | 0 .../content/{sponsor_page.md => sponsor.md} | 0 .../content/{tutorial_page.md => tutorial.md} | 0 www/wip_new_website/main.roc | 28 +++++++-------- 10 files changed, 46 insertions(+), 49 deletions(-) rename www/wip_new_website/content/{community_page.md => community.md} (100%) rename www/wip_new_website/content/{design_goals_page.md => design_goals.md} (100%) rename www/wip_new_website/content/{docs_page.md => docs.md} (100%) rename www/wip_new_website/content/{home_page.md => index.md} (87%) rename www/wip_new_website/content/{install_page.md => install.md} (100%) rename www/wip_new_website/content/{sponsor_page.md => sponsor.md} (100%) rename www/wip_new_website/content/{tutorial_page.md => tutorial.md} (100%) diff --git a/www/build.sh b/www/build.sh index a8b0f0230fb..2412344fba0 100755 --- a/www/build.sh +++ b/www/build.sh @@ -69,7 +69,8 @@ if ! [ -v GITHUB_TOKEN_READ_ONLY ]; then echo 'Building tutorial.html from tutorial.md...' mkdir www/build/tutorial - cargo run --release --bin roc run www/generate_tutorial/src/tutorial.roc -- www/generate_tutorial/src/input/ www/build/tutorial/ + cargo build --release --bin roc + roc=target/release/roc else echo 'Fetching latest roc nightly...' @@ -81,17 +82,22 @@ else ls | grep "roc_nightly.*tar.gz" | xargs rm # simplify dir name mv roc_nightly* roc_nightly + roc='./roc_nightly/roc' echo 'Building tutorial.html from tutorial.md...' mkdir www/build/tutorial - - ./roc_nightly/roc version - ./roc_nightly/roc run www/generate_tutorial/src/tutorial.roc -- www/generate_tutorial/src/input/ www/build/tutorial/ - - # cleanup - rm -rf roc_nightly roc_releases.json fi +$roc version +$roc run www/generate_tutorial/src/tutorial.roc -- www/generate_tutorial/src/input/ www/build/tutorial/ mv www/build/tutorial/tutorial.html www/build/tutorial/index.html +# for new wip site +mkdir www/build/wip +roc run www/wip_new_website/main.roc -- www/wip_new_website/content/ www/build/wip +cp -r www/wip_new_website/static/site.css www/build/wip + +# cleanup +rm -rf roc_nightly roc_releases.json + popd diff --git a/www/wip_new_website/build.roc b/www/wip_new_website/build.roc index cb7a1283e50..79f6c878f59 100755 --- a/www/wip_new_website/build.roc +++ b/www/wip_new_website/build.roc @@ -1,55 +1,46 @@ #!/usr/bin/env roc app "website-builder" - # TODO update to basic-cli release when Command module is available - packages { pf: "https://github.com/lukewilliamboswell/roc-things/releases/download/test/VQYlmhbzLld4kAE4Y8sWt349md89iyGBg5hgoIBfvcs.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.4.0-rc1/hbIodFf7kULTYZJkzgsvgsnFAvQexm5hVeBaOMZk84I.tar.br" } imports [ pf.Task.{ Task }, pf.Command, + pf.Arg ] provides [main] to pf main = - + # TODO take dist folder name and main.roc path as args once https://github.com/roc-lang/basic-cli/issues/82 is fixed + # TODO add function to remove boilerplate # Remove dist folder {} <- Command.new "rm" - |> Command.arg "-rf" - |> Command.arg "dist/" + |> Command.args ["-rf", "dist/"] |> Command.status - |> Task.onFail \_ -> crash "Failed to remove dist folder" + |> Task.onErr \_ -> crash "Failed to remove dist folder" |> Task.await # Build site {} <- Command.new "roc" - |> Command.arg "run" - |> Command.arg "main.roc" - |> Command.arg "--" - |> Command.arg "content/" - |> Command.arg "dist/" + |> Command.args ["run", "main.roc", "--", "content/", "dist/"] |> Command.status - |> Task.onFail \_ -> crash "Failed to build site" + |> Task.onErr \_ -> crash "Failed to build site" |> Task.await # Copy static files {} <- Command.new "cp" - |> Command.arg "-r" - |> Command.arg "static/site.css" - |> Command.arg "dist/" + |> Command.args ["-r", "static/site.css", "dist/"] |> Command.status - |> Task.onFail \_ -> crash "Failed to copy static files" + |> Task.onErr \_ -> crash "Failed to copy static files" |> Task.await # Start file server {} <- Command.new "simple-http-server" - |> Command.arg "-p" - |> Command.arg "8080" - |> Command.arg "--" - |> Command.arg "dist/" + |> Command.args ["-p", "8080", "--", "dist/"] |> Command.status - |> Task.onFail \_ -> crash "Failed to run file server; consider intalling with `cargo install simple-http-server`" + |> Task.onErr \_ -> crash "Failed to run file server; consider intalling with `cargo install simple-http-server`" |> Task.await - Task.succeed {} + Task.ok {} diff --git a/www/wip_new_website/content/community_page.md b/www/wip_new_website/content/community.md similarity index 100% rename from www/wip_new_website/content/community_page.md rename to www/wip_new_website/content/community.md diff --git a/www/wip_new_website/content/design_goals_page.md b/www/wip_new_website/content/design_goals.md similarity index 100% rename from www/wip_new_website/content/design_goals_page.md rename to www/wip_new_website/content/design_goals.md diff --git a/www/wip_new_website/content/docs_page.md b/www/wip_new_website/content/docs.md similarity index 100% rename from www/wip_new_website/content/docs_page.md rename to www/wip_new_website/content/docs.md diff --git a/www/wip_new_website/content/home_page.md b/www/wip_new_website/content/index.md similarity index 87% rename from www/wip_new_website/content/home_page.md rename to www/wip_new_website/content/index.md index d99a586d701..60f7c5e4b92 100644 --- a/www/wip_new_website/content/home_page.md +++ b/www/wip_new_website/content/index.md @@ -10,16 +10,16 @@ A systems programming language that is fast, friendly, and functional.
-

a fast language

-

We want Roc to run faster than any non-systems language that sees mainstream use in industry. Learn more

+

Fast

+

We want Roc to run faster than any non-systems language that sees mainstream use in industry. Learn more

-

a friendly language

-

Roc aims to be a user-friendly language with a friendly community of users. Learn more

+

Friendly

+

Roc aims to be a user-friendly language with a friendly community of users. Learn more

-

a functional language

-

Roc aims to be a purely functional programming language. Learn more

+

Functional

+

Roc aims to be a purely functional programming language. Learn more

## Try Roc diff --git a/www/wip_new_website/content/install_page.md b/www/wip_new_website/content/install.md similarity index 100% rename from www/wip_new_website/content/install_page.md rename to www/wip_new_website/content/install.md diff --git a/www/wip_new_website/content/sponsor_page.md b/www/wip_new_website/content/sponsor.md similarity index 100% rename from www/wip_new_website/content/sponsor_page.md rename to www/wip_new_website/content/sponsor.md diff --git a/www/wip_new_website/content/tutorial_page.md b/www/wip_new_website/content/tutorial.md similarity index 100% rename from www/wip_new_website/content/tutorial_page.md rename to www/wip_new_website/content/tutorial.md diff --git a/www/wip_new_website/main.roc b/www/wip_new_website/main.roc index 27e863291bd..bf23c0a8f4b 100644 --- a/www/wip_new_website/main.roc +++ b/www/wip_new_website/main.roc @@ -8,13 +8,13 @@ app "roc-website" pageData = Dict.empty {} - |> Dict.insert "community_page.html" { title: "Community", description: "The Roc community" } - |> Dict.insert "design_goals_page.html" { title: "Design Goals", description: "Roc's design goals" } - |> Dict.insert "docs_page.html" { title: "Documentation", description: "Learn the Roc programming language" } - |> Dict.insert "home_page.html" { title: "Roc Lang", description: "The Roc programming language" } - |> Dict.insert "install_page.html" { title: "Install", description: "Getting started with the Roc programming language" } - |> Dict.insert "sponsor_page.html" { title: "Sponsor", description: "Sponsor Roc" } - |> Dict.insert "tutorial_page.html" { title: "Tutorial", description: "The Roc tutorial" } + |> Dict.insert "community.html" { title: "Community", description: "The Roc community" } + |> Dict.insert "design_goals.html" { title: "Design Goals", description: "Roc's design goals" } + |> Dict.insert "docs.html" { title: "Documentation", description: "Learn the Roc programming language" } + |> Dict.insert "home.html" { title: "Roc Lang", description: "The Roc programming language" } + |> Dict.insert "install.html" { title: "Install", description: "Getting started with the Roc programming language" } + |> Dict.insert "sponsor.html" { title: "Sponsor", description: "Sponsor Roc" } + |> Dict.insert "tutorial.html" { title: "Tutorial", description: "The Roc tutorial" } getPage : Str -> {title : Str, description : Str} getPage = \current -> @@ -41,7 +41,7 @@ view = \page, htmlContent -> Html.title [] [text (getTitle page)], meta [name "description", content (getDescription page)] [], meta [name "viewport", content "width=device-width"] [], - link [rel "stylesheet", href "/site.css"] [], + link [rel "stylesheet", href "./site.css"] [], link [rel "icon", href "/favicon.svg"] [], ], body [] [ @@ -69,16 +69,16 @@ viewNavbar : Html.Node viewNavbar = div [id "top-bar"] [ nav [] [ - a [href "/home_page.html", title "The Roc Programming Language"] [ + a [href "./home.html", title "The Roc Programming Language"] [ rocLogo ], div [id "top-bar-links"] [ - a [href "/tutorial_page.html"] [text "tutorial"], - a [href "/install_page.html"] [text "install"], + a [href "./tutorial.html"] [text "tutorial"], + a [href "./install.html"] [text "install"], a [href "#todo-link-to-examples-site"] [text "examples"], - a [href "/community_page.html"] [text "community"], - a [href "/sponsor_page.html"] [text "sponsor"], - a [href "/docs_page.html"] [text "docs"], + a [href "./community.html"] [text "community"], + a [href "./sponsor.html"] [text "sponsor"], + a [href "./docs.html"] [text "docs"], ], ], ] From 02f7039b140210f6afab2ae10d3f81686f6f78a9 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Wed, 5 Jul 2023 19:11:46 +0200 Subject: [PATCH 116/140] fix java link Signed-off-by: Anton-4 <17049058+Anton-4@users.noreply.github.com> --- www/wip_new_website/content/design_goals.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/wip_new_website/content/design_goals.md b/www/wip_new_website/content/design_goals.md index 5168538080d..045bc71b785 100644 --- a/www/wip_new_website/content/design_goals.md +++ b/www/wip_new_website/content/design_goals.md @@ -41,7 +41,7 @@ benchmarking?? We want Roc to run faster than any non-systems language (like C, C++, Rust, or Zig) that sees mainstream use in industry. The goal is that nobody should find themselves thinking "I should rewrite my Roc program in \[some mainstream garbage-collected language\] because that will make it run significantly faster." -When benchmarking Roc code against similarly-optimized programs written in [Go](https://go.dev), [Swift](https://www.swift.org/), [Java](https://www.java.com), [C#](https://learn.microsoft.com/en-us/dotnet/csharp), or [JavaScript](https://www.ecma-international.org/publications-and-standards/standards/ecma-262), we generally aim for Roc to outperform all of those languages. Outperforming systems languages like Rust, Zig, C, D, and C++ is a non-goal, as is outperforming research languages that see little or no use in industry. (Realistically, there will always be certain specific benchmarks where some popular non-systems-level languages outperform Roc, but the goal is to usually be at the front of that pack.) +When benchmarking Roc code against similarly-optimized programs written in [Go](https://go.dev), [Swift](https://www.swift.org/), [Java](https://www.oracle.com/java/), [C#](https://learn.microsoft.com/en-us/dotnet/csharp), or [JavaScript](https://www.ecma-international.org/publications-and-standards/standards/ecma-262), we generally aim for Roc to outperform all of those languages. Outperforming systems languages like Rust, Zig, C, D, and C++ is a non-goal, as is outperforming research languages that see little or no use in industry. (Realistically, there will always be certain specific benchmarks where some popular non-systems-level languages outperform Roc, but the goal is to usually be at the front of that pack.) ## Current progress From 781fba8f732a67b6ca05508167fbda5cf98950e2 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Wed, 5 Jul 2023 19:34:00 +0200 Subject: [PATCH 117/140] aarch64 linux error fix This fixes the error relocation R_AARCH64_MOVW_UABS_G0_NC cannot be used against local symbol --- crates/compiler/build/src/target.rs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/crates/compiler/build/src/target.rs b/crates/compiler/build/src/target.rs index 4acd2ce8c4a..878f6ba1109 100644 --- a/crates/compiler/build/src/target.rs +++ b/crates/compiler/build/src/target.rs @@ -149,23 +149,14 @@ pub fn target_machine( init_arch(target); - let code_model = match target.architecture { - // LLVM 12 will not compile our programs without a large code model. - // The reason is not totally clear to me, but my guess is a few special-cases in - // llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (instructions) - // llvm/lib/Target/AArch64/AArch64Subtarget.cpp (GoT tables) - // Revisit when upgrading to LLVM 13. - Architecture::Aarch64(..) => CodeModel::Large, - _ => CodeModel::Default, - }; Target::from_name(arch).unwrap().create_target_machine( &TargetTriple::create(target_triple_str(target)), "generic", - "", // TODO: this probably should be TargetMachine::get_host_cpu_features() to enable all features. + "", opt, reloc, - code_model, + CodeModel::Default, ) } From 03af6749ed571bb0eb9a6f446f33734c124bac66 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Wed, 5 Jul 2023 19:39:20 +0200 Subject: [PATCH 118/140] fmt --- crates/compiler/build/src/target.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/compiler/build/src/target.rs b/crates/compiler/build/src/target.rs index 878f6ba1109..9a62421c166 100644 --- a/crates/compiler/build/src/target.rs +++ b/crates/compiler/build/src/target.rs @@ -149,7 +149,6 @@ pub fn target_machine( init_arch(target); - Target::from_name(arch).unwrap().create_target_machine( &TargetTriple::create(target_triple_str(target)), "generic", From 832272dfd71c96709288e767a481933b0615f259 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Fri, 7 Jul 2023 10:37:59 +0200 Subject: [PATCH 119/140] forgot dollar sign Signed-off-by: Anton-4 <17049058+Anton-4@users.noreply.github.com> --- www/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/build.sh b/www/build.sh index 2e4e8508476..d544710e7e5 100755 --- a/www/build.sh +++ b/www/build.sh @@ -94,7 +94,7 @@ mv www/build/tutorial/tutorial.html www/build/tutorial/index.html # for new wip site mkdir www/build/wip -roc run www/wip_new_website/main.roc -- www/wip_new_website/content/ www/build/wip +$roc run www/wip_new_website/main.roc -- www/wip_new_website/content/ www/build/wip cp -r www/wip_new_website/static/site.css www/build/wip # cleanup From 820ed5a7f6a34076a5cd24d275547b584f9069f0 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Sat, 8 Jul 2023 13:56:02 +0200 Subject: [PATCH 120/140] added http-server arg --index makes it so that you don't need to go explicitly to /index.html Signed-off-by: Anton-4 <17049058+Anton-4@users.noreply.github.com> --- www/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/README.md b/www/README.md index b4828a8d4b8..3ffdf87a216 100644 --- a/www/README.md +++ b/www/README.md @@ -4,7 +4,7 @@ To view the website after you've made a change, execute: ```bash ./www/build.sh cd www/build -simple-http-server --nocache # If you're using the nix flake simple-http-server will already be installed. Without nix you can install it with `cargo install simple-http-server`. +simple-http-server --nocache --index # already installed if you're using `nix develop`, otherwise use `cargo install simple-http-server` ``` Open http://0.0.0.0:8000 in your browser. From 49eb6ad8f4e8aa9c05e7a4000c2b9af2795d8d46 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Sat, 8 Jul 2023 18:13:58 +0200 Subject: [PATCH 121/140] added sponsor links Signed-off-by: Anton-4 <17049058+Anton-4@users.noreply.github.com> --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index dd81e597cbe..f6d0e5e217f 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,10 @@ If you'd like to contribute, check out [good first issues](https://github.com/ro ## Sponsors +You can :purple_heart: sponsor :purple_heart: Roc on: +- [GitHub](https://github.com/sponsors/roc-lang) +- [Liberapay](https://liberapay.com/roc_lang) + We are very grateful for our corporate sponsors [Vendr](https://www.vendr.com/), [RWX](https://www.rwx.com), and [Tweede golf](https://tweedegolf.nl/en). [Vendr logo](https://www.vendr.com) From 90ac95ea9267789e16c985ac6acfcd33c90f3a2b Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Sat, 8 Jul 2023 18:35:19 +0200 Subject: [PATCH 122/140] don't check liberapay the link checker gets a 403 here even though the link works Signed-off-by: Anton-4 <17049058+Anton-4@users.noreply.github.com> --- mlc_config.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mlc_config.json b/mlc_config.json index 38b8efc73fc..c8341a6907a 100644 --- a/mlc_config.json +++ b/mlc_config.json @@ -41,6 +41,9 @@ }, { "pattern": "https://www.roc-lang.org/packages/basic-cli/Stdout#line" + }, + { + "pattern": "https://liberapay.com/" } ] } From c7ccc2092a450ea162d337387a1dafe293654eff Mon Sep 17 00:00:00 2001 From: Folkert Date: Sat, 8 Jul 2023 20:35:33 +0200 Subject: [PATCH 123/140] add the memory.fill and memory.copy commands to our wasm interpreter --- crates/wasm_interp/src/instance.rs | 41 +++++++++++++++ crates/wasm_interp/src/tests/test_mem.rs | 66 ++++++++++++++++++++++++ crates/wasm_interp/src/wasi.rs | 21 +++++++- crates/wasm_module/src/opcodes.rs | 2 + 4 files changed, 128 insertions(+), 2 deletions(-) diff --git a/crates/wasm_interp/src/instance.rs b/crates/wasm_interp/src/instance.rs index 7040b8757e1..7b454bf0754 100644 --- a/crates/wasm_interp/src/instance.rs +++ b/crates/wasm_interp/src/instance.rs @@ -976,6 +976,47 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> { self.value_store.push(Value::I32(-1)); } } + MEMORY => { + // the first argument determines exactly which memory operation we have + let op = module.code.bytes[self.program_counter]; + self.program_counter += 1; + + match op { + 8 => { + // memory.init + todo!("WASM instruction: memory.init") + } + 9 => { + // data.drop x + todo!("WASM instruction: data.drop") + } + 10 => { + // memory.copy + let size = self.value_store.pop_u32()? as usize; + let source = self.value_store.pop_u32()? as usize; + let destination = self.value_store.pop_u32()? as usize; + + // skip two zero bytes; in future versions of WebAssembly this byte may be + // used to index additional memories + self.program_counter += 2; + + self.memory.copy_within(source..source + size, destination) + } + 11 => { + // memory.fill + let size = self.value_store.pop_u32()? as usize; + let byte_value = self.value_store.pop_u32()? as u8; + let destination = self.value_store.pop_u32()? as usize; + + // skip a zero byte; in future versions of WebAssembly this byte may be + // used to index additional memories + self.program_counter += 1; + + self.memory[destination..][..size].fill(byte_value); + } + other => unreachable!("invalid memory instruction {:?}", other), + } + } I32CONST => { let value = i32::parse((), &module.code.bytes, &mut self.program_counter).unwrap(); self.write_debug(value); diff --git a/crates/wasm_interp/src/tests/test_mem.rs b/crates/wasm_interp/src/tests/test_mem.rs index 731b2b12b97..09f54d8e544 100644 --- a/crates/wasm_interp/src/tests/test_mem.rs +++ b/crates/wasm_interp/src/tests/test_mem.rs @@ -49,6 +49,72 @@ fn test_growmemory() { assert_eq!(state.memory.len(), 5 * MemorySection::PAGE_SIZE as usize); } +#[test] +fn test_memory_fill() { + let arena = Bump::new(); + let mut module = WasmModule::new(&arena); + + let pages = 3; + let pc = 0; + module.memory = MemorySection::new(&arena, pages * MemorySection::PAGE_SIZE); + + const SIZE: i32 = 16; + let byte_value = 0xAA; + let destination = 0x4; + + let bytes = [OpCode::MEMORY as u8, 11, 0x0]; + module.code.bytes.extend(bytes); + + let mut state = Instance::new(&arena, pages, pc, [], DefaultImportDispatcher::default()); + + state.value_store.push(Value::I32(destination)); + state.value_store.push(Value::I32(byte_value)); + state.value_store.push(Value::I32(SIZE)); + + // before the instruction, the memory is all zeros + let slice = &state.memory[destination as usize..][..SIZE as usize]; + assert_eq!(slice, &[0; SIZE as usize]); + + state.execute_next_instruction(&module).unwrap(); + + let slice = &state.memory[destination as usize..][..SIZE as usize]; + assert_eq!(slice, &[byte_value as u8; SIZE as usize]) +} + +#[test] +fn test_memory_copy() { + let arena = Bump::new(); + let mut module = WasmModule::new(&arena); + + let pages = 3; + let pc = 0; + module.memory = MemorySection::new(&arena, pages * MemorySection::PAGE_SIZE); + + const SIZE: i32 = 4; + let source = 0x4; + let destination = 0x8; + + let bytes = [OpCode::MEMORY as u8, 10, 0x0, 0x0]; + module.code.bytes.extend(bytes); + + let mut state = Instance::new(&arena, pages, pc, [], DefaultImportDispatcher::default()); + + state.value_store.push(Value::I32(destination)); + state.value_store.push(Value::I32(source)); + state.value_store.push(Value::I32(SIZE)); + + // before the instruction, the memory is all zeros + let slice = &mut state.memory[source as usize..][..SIZE as usize]; + assert_eq!(slice, &[0; SIZE as usize]); + + slice.fill(0xAA); + + state.execute_next_instruction(&module).unwrap(); + + let slice = &state.memory[destination as usize..][..SIZE as usize]; + assert_eq!(slice, &[0xAA; SIZE as usize]) +} + fn test_load(load_op: OpCode, ty: ValueType, data: &[u8], addr: u32, offset: u32) -> Value { let arena = Bump::new(); let mut module = WasmModule::new(&arena); diff --git a/crates/wasm_interp/src/wasi.rs b/crates/wasm_interp/src/wasi.rs index a8a288de247..b6a9242ef3a 100644 --- a/crates/wasm_interp/src/wasi.rs +++ b/crates/wasm_interp/src/wasi.rs @@ -88,8 +88,25 @@ impl<'a> WasiDispatcher<'a> { success_code } - "environ_get" => todo!("WASI {}({:?})", function_name, arguments), - "environ_sizes_get" => todo!("WASI {}({:?})", function_name, arguments), + "environ_get" => { + // `environ_sizes_get` always reports 0 environment variables + // so we don't have to do anything here. + + success_code + } + "environ_sizes_get" => { + let num_env_ptr = arguments[0].expect_i32().unwrap() as usize; + let size_env_ptr = arguments[1].expect_i32().unwrap() as usize; + + // Calculate the total size required for environment variables + let total_size = 0; + let count = 0; + + write_u32(memory, num_env_ptr, count); + write_u32(memory, size_env_ptr, total_size as u32); + + success_code + } "clock_res_get" => success_code, // this dummy implementation seems to be good enough for some functions "clock_time_get" => success_code, "fd_advise" => todo!("WASI {}({:?})", function_name, arguments), diff --git a/crates/wasm_module/src/opcodes.rs b/crates/wasm_module/src/opcodes.rs index a6058f01bf4..c294cc47d17 100644 --- a/crates/wasm_module/src/opcodes.rs +++ b/crates/wasm_module/src/opcodes.rs @@ -50,6 +50,7 @@ pub enum OpCode { I64STORE32 = 0x3e, CURRENTMEMORY = 0x3f, GROWMEMORY = 0x40, + MEMORY = 0xFC, I32CONST = 0x41, I64CONST = 0x42, F32CONST = 0x43, @@ -232,6 +233,7 @@ fn immediates_for(op: OpCode) -> Result { | I64STORE32 => Leb32x2, CURRENTMEMORY | GROWMEMORY => Byte1, + MEMORY => Leb32x2, I32CONST => Leb32x1, I64CONST => Leb64x1, From af75a4cc190b37924a87c2c16e8735186777c165 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sat, 8 Jul 2023 16:51:31 -0400 Subject: [PATCH 124/140] Use emoji in readme Signed-off-by: Richard Feldman --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f6d0e5e217f..3ad91f478f3 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ If you'd like to contribute, check out [good first issues](https://github.com/ro ## Sponsors -You can :purple_heart: sponsor :purple_heart: Roc on: +You can 💜 sponsor 💜 Roc on: - [GitHub](https://github.com/sponsors/roc-lang) - [Liberapay](https://liberapay.com/roc_lang) From 0996ca0f4c0690373f476c79dc08f614d6dbaa5b Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sat, 8 Jul 2023 16:52:12 -0400 Subject: [PATCH 125/140] Bold the word sponsor Signed-off-by: Richard Feldman --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3ad91f478f3..0fa78c47c83 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ If you'd like to contribute, check out [good first issues](https://github.com/ro ## Sponsors -You can 💜 sponsor 💜 Roc on: +You can 💜 **sponsor** 💜 Roc on: - [GitHub](https://github.com/sponsors/roc-lang) - [Liberapay](https://liberapay.com/roc_lang) From b7e7059b364be7358c9b9528ba8ea857203c9aac Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sat, 8 Jul 2023 16:52:40 -0400 Subject: [PATCH 126/140] Update README.md Signed-off-by: Richard Feldman --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0fa78c47c83..3b6283d4b8d 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ You can 💜 **sponsor** 💜 Roc on: - [GitHub](https://github.com/sponsors/roc-lang) - [Liberapay](https://liberapay.com/roc_lang) -We are very grateful for our corporate sponsors [Vendr](https://www.vendr.com/), [RWX](https://www.rwx.com), and [Tweede golf](https://tweedegolf.nl/en). +We are very grateful for our corporate sponsors [Vendr](https://www.vendr.com/), [RWX](https://www.rwx.com), and [Tweede golf](https://tweedegolf.nl/en): [Vendr logo](https://www.vendr.com)      From f813591042dbb65e25b737313de800e4626cfde3 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sat, 8 Jul 2023 23:07:15 +0200 Subject: [PATCH 127/140] fix skipping immediates for memory instructions --- crates/wasm_interp/src/instance.rs | 65 +++++++++++++----------------- crates/wasm_module/src/opcodes.rs | 49 +++++++++++++++++++++- 2 files changed, 76 insertions(+), 38 deletions(-) diff --git a/crates/wasm_interp/src/instance.rs b/crates/wasm_interp/src/instance.rs index 7b454bf0754..4197365ea5e 100644 --- a/crates/wasm_interp/src/instance.rs +++ b/crates/wasm_interp/src/instance.rs @@ -2,7 +2,7 @@ use bumpalo::{collections::Vec, Bump}; use std::fmt::{self, Write}; use std::iter::{self, once, Iterator}; -use roc_wasm_module::opcodes::OpCode; +use roc_wasm_module::opcodes::{MemoryInstruction, OpCode}; use roc_wasm_module::parse::{Parse, SkipBytes}; use roc_wasm_module::sections::{ImportDesc, MemorySection, SignatureParamsIter}; use roc_wasm_module::{ExportType, WasmModule}; @@ -978,44 +978,35 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> { } MEMORY => { // the first argument determines exactly which memory operation we have - let op = module.code.bytes[self.program_counter]; - self.program_counter += 1; - - match op { - 8 => { - // memory.init - todo!("WASM instruction: memory.init") - } - 9 => { - // data.drop x - todo!("WASM instruction: data.drop") - } - 10 => { - // memory.copy - let size = self.value_store.pop_u32()? as usize; - let source = self.value_store.pop_u32()? as usize; - let destination = self.value_store.pop_u32()? as usize; - - // skip two zero bytes; in future versions of WebAssembly this byte may be - // used to index additional memories - self.program_counter += 2; - - self.memory.copy_within(source..source + size, destination) - } - 11 => { - // memory.fill - let size = self.value_store.pop_u32()? as usize; - let byte_value = self.value_store.pop_u32()? as u8; - let destination = self.value_store.pop_u32()? as usize; + match MemoryInstruction::try_from(module.code.bytes[self.program_counter]) { + Ok(op) => match op { + MemoryInstruction::MemoryInit => todo!("WASM instruction: memory.init"), + MemoryInstruction::DataDrop => todo!("WASM instruction: data.drop"), + MemoryInstruction::MemoryCopy => { + let size = self.value_store.pop_u32()? as usize; + let source = self.value_store.pop_u32()? as usize; + let destination = self.value_store.pop_u32()? as usize; + + // skip the op byte and an extra two zero bytes. + // in future versions of WebAssembly this byte may be used to index additional memories + self.program_counter += 1 + 2; + + self.memory.copy_within(source..source + size, destination) + } + MemoryInstruction::MemoryFill => { + let size = self.value_store.pop_u32()? as usize; + let byte_value = self.value_store.pop_u32()? as u8; + let destination = self.value_store.pop_u32()? as usize; - // skip a zero byte; in future versions of WebAssembly this byte may be - // used to index additional memories - self.program_counter += 1; + // skip the op byte and an extra zero byte. + // in future versions of WebAssembly this byte may be used to index additional memories + self.program_counter += 1 + 1; - self.memory[destination..][..size].fill(byte_value); - } - other => unreachable!("invalid memory instruction {:?}", other), - } + self.memory[destination..][..size].fill(byte_value); + } + }, + Err(other) => unreachable!("invalid memory instruction {other:?}"), + }; } I32CONST => { let value = i32::parse((), &module.code.bytes, &mut self.program_counter).unwrap(); diff --git a/crates/wasm_module/src/opcodes.rs b/crates/wasm_module/src/opcodes.rs index c294cc47d17..c5245dde831 100644 --- a/crates/wasm_module/src/opcodes.rs +++ b/crates/wasm_module/src/opcodes.rs @@ -192,6 +192,29 @@ impl From for OpCode { } } +#[repr(u8)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum MemoryInstruction { + MemoryInit = 8, + DataDrop = 9, + MemoryCopy = 10, + MemoryFill = 11, +} + +impl TryFrom for MemoryInstruction { + type Error = u8; + + fn try_from(value: u8) -> Result { + match value { + 8 => Ok(Self::MemoryInit), + 9 => Ok(Self::DataDrop), + 10 => Ok(Self::MemoryCopy), + 11 => Ok(Self::MemoryFill), + _ => Err(value), + } + } +} + /// The format of the *immediate* operands of an operator /// Immediates appear directly in the byte stream after the opcode, /// rather than being popped off the value stack. These are the possible forms. @@ -205,6 +228,7 @@ enum OpImmediates { Leb64x1, Leb32x2, BrTable, + Memory, } fn immediates_for(op: OpCode) -> Result { @@ -233,7 +257,7 @@ fn immediates_for(op: OpCode) -> Result { | I64STORE32 => Leb32x2, CURRENTMEMORY | GROWMEMORY => Byte1, - MEMORY => Leb32x2, + MEMORY => Memory, I32CONST => Leb32x1, I64CONST => Leb64x1, @@ -314,6 +338,29 @@ impl SkipBytes for OpCode { u32::skip_bytes(bytes, cursor)?; } } + Memory => { + match MemoryInstruction::try_from(bytes[*cursor + 1]) { + Ok(op) => match op { + MemoryInstruction::MemoryInit => { + // memory.init + todo!("WASM instruction: memory.init") + } + MemoryInstruction::DataDrop => { + // data.drop x + todo!("WASM instruction: data.drop") + } + MemoryInstruction::MemoryCopy => { + // memory.copy + *cursor += 1 + 1 + 2; + } + MemoryInstruction::MemoryFill => { + // memory.fill + *cursor += 1 + 1 + 1; + } + }, + Err(other) => unreachable!("invalid memory instruction {other:?}"), + } + } } Ok(()) } From a9813aeae7553e1f38cfe94327c1df73446d46cf Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 5 Jul 2023 17:53:03 +0200 Subject: [PATCH 128/140] use a NonNullableUnwrapped union for Box --- crates/compiler/mono/src/ir.rs | 31 ++++++++++++++++++++++++++++-- crates/compiler/mono/src/layout.rs | 7 ++++++- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index 3bbddbbb8e2..6310b4ad1c7 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -2118,6 +2118,24 @@ impl<'a> Expr<'a> { arguments: std::slice::from_ref(symbol), }) } + + pub(crate) fn expr_box(symbol: &'a Symbol, element_layout: &'a InLayout<'a>) -> Expr<'a> { + Expr::Tag { + tag_layout: UnionLayout::NonNullableUnwrapped(std::slice::from_ref(element_layout)), + tag_id: 0, + arguments: std::slice::from_ref(symbol), + reuse: None, + } + } + + pub(crate) fn expr_unbox(symbol: Symbol, element_layout: &'a InLayout<'a>) -> Expr<'a> { + Expr::UnionAtIndex { + structure: symbol, + tag_id: 0, + union_layout: UnionLayout::NonNullableUnwrapped(std::slice::from_ref(element_layout)), + index: 0, + } + } } impl<'a> Stmt<'a> { @@ -5614,13 +5632,22 @@ pub fn with_hole<'a>( debug_assert_eq!(arg_symbols.len(), 1); let x = arg_symbols[0]; - Stmt::Let(assigned, Expr::ExprBox { symbol: x }, layout, hole) + let element_layout = match layout_cache.interner.get_repr(layout) { + LayoutRepr::Union(UnionLayout::NonNullableUnwrapped([l])) => l, + _ => unreachable!("invalid layout for a box expression"), + }; + + let expr = Expr::expr_box(arena.alloc(x), element_layout); + + Stmt::Let(assigned, expr, layout, hole) } UnboxExpr => { debug_assert_eq!(arg_symbols.len(), 1); let x = arg_symbols[0]; - Stmt::Let(assigned, Expr::ExprUnbox { symbol: x }, layout, hole) + let expr = Expr::expr_unbox(x, arena.alloc(layout)); + + Stmt::Let(assigned, expr, layout, hole) } _ => { let call = self::Call { diff --git a/crates/compiler/mono/src/layout.rs b/crates/compiler/mono/src/layout.rs index 78a2c72d22f..39dc839a04b 100644 --- a/crates/compiler/mono/src/layout.rs +++ b/crates/compiler/mono/src/layout.rs @@ -3206,8 +3206,13 @@ fn layout_from_flat_type<'a>( let inner_var = args[0]; let inner_layout = cached!(Layout::from_var(env, inner_var), criteria, env.subs); + + let repr = LayoutRepr::Union(UnionLayout::NonNullableUnwrapped( + arena.alloc([inner_layout]), + )); + let boxed_layout = env.cache.put_in(Layout { - repr: LayoutRepr::Boxed(inner_layout).direct(), + repr: repr.direct(), semantic: SemanticRepr::NONE, }); From d64930c17fcd421a871c8f5b2f76357361ab0f64 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 5 Jul 2023 18:01:00 +0200 Subject: [PATCH 129/140] remove box and unbox expressions --- crates/compiler/alias_analysis/src/lib.rs | 14 ------- crates/compiler/gen_dev/src/lib.rs | 21 ---------- crates/compiler/gen_llvm/src/llvm/build.rs | 36 ----------------- crates/compiler/gen_wasm/src/backend.rs | 39 +------------------ crates/compiler/gen_wasm/src/low_level.rs | 2 +- crates/compiler/mono/src/borrow.rs | 16 -------- .../mono/src/code_gen_help/refcount.rs | 2 +- crates/compiler/mono/src/debug/checker.rs | 17 -------- .../compiler/mono/src/drop_specialization.rs | 16 -------- crates/compiler/mono/src/inc_dec.rs | 13 ++----- crates/compiler/mono/src/ir.rs | 28 +------------ crates/compiler/mono/src/tail_recursion.rs | 1 - 12 files changed, 9 insertions(+), 196 deletions(-) diff --git a/crates/compiler/alias_analysis/src/lib.rs b/crates/compiler/alias_analysis/src/lib.rs index 9ded9c3c3db..058bfc06454 100644 --- a/crates/compiler/alias_analysis/src/lib.rs +++ b/crates/compiler/alias_analysis/src/lib.rs @@ -1358,16 +1358,6 @@ fn expr_spec<'a>( builder.add_make_named(block, MOD_APP, type_name, tag_value_id) } - ExprBox { symbol } => { - let value_id = env.symbols[symbol]; - - with_new_heap_cell(builder, block, value_id) - } - ExprUnbox { symbol } => { - let tuple_id = env.symbols[symbol]; - - builder.add_get_tuple_field(block, tuple_id, BOX_VALUE_INDEX) - } Struct(fields) => build_tuple_value(builder, env, block, fields), UnionAtIndex { index, @@ -1684,10 +1674,6 @@ fn static_list_type(builder: &mut TC) -> Result { const LIST_CELL_INDEX: u32 = 0; const LIST_BAG_INDEX: u32 = 1; -#[allow(dead_code)] -const BOX_CELL_INDEX: u32 = LIST_CELL_INDEX; -const BOX_VALUE_INDEX: u32 = LIST_BAG_INDEX; - const TAG_CELL_INDEX: u32 = 0; const TAG_DATA_INDEX: u32 = 1; diff --git a/crates/compiler/gen_dev/src/lib.rs b/crates/compiler/gen_dev/src/lib.rs index b4d1464cc95..344f67c71c7 100644 --- a/crates/compiler/gen_dev/src/lib.rs +++ b/crates/compiler/gen_dev/src/lib.rs @@ -149,12 +149,6 @@ impl<'a> LastSeenMap<'a> { self.set_last_seen(*sym, stmt); } } - Expr::ExprBox { symbol } => { - self.set_last_seen(*symbol, stmt); - } - Expr::ExprUnbox { symbol } => { - self.set_last_seen(*symbol, stmt); - } Expr::Struct(syms) => { for sym in *syms { self.set_last_seen(*sym, stmt); @@ -842,21 +836,6 @@ trait Backend<'a> { let reuse = reuse.map(|ru| ru.symbol); self.tag(sym, arguments, tag_layout, *tag_id, reuse); } - Expr::ExprBox { symbol: value } => { - let element_layout = match self.interner().get_repr(*layout) { - LayoutRepr::Boxed(boxed) => boxed, - _ => unreachable!("{:?}", self.interner().dbg(*layout)), - }; - - self.load_literal_symbols([*value].as_slice()); - self.expr_box(*sym, *value, element_layout, None) - } - Expr::ExprUnbox { symbol: ptr } => { - let element_layout = *layout; - - self.load_literal_symbols([*ptr].as_slice()); - self.expr_unbox(*sym, *ptr, element_layout) - } Expr::NullPointer => { self.load_literal_i64(sym, 0); } diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 67748e4a1ef..ae92d4dc486 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -1084,42 +1084,6 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( ) } - ExprBox { symbol } => { - let (value, layout) = scope.load_symbol_and_layout(symbol); - let basic_type = - basic_type_from_layout(env, layout_interner, layout_interner.get_repr(layout)); - let allocation = reserve_with_refcount_help( - env, - basic_type, - layout_interner.stack_size(layout), - layout_interner.alignment_bytes(layout), - ); - - store_roc_value( - env, - layout_interner, - layout_interner.get_repr(layout), - allocation, - value, - ); - - allocation.into() - } - - ExprUnbox { symbol } => { - let value = scope.load_symbol(symbol); - - debug_assert!(value.is_pointer_value()); - - load_roc_value( - env, - layout_interner, - layout_interner.get_repr(layout), - value.into_pointer_value(), - "load_boxed_value", - ) - } - Reset { symbol, update_mode, diff --git a/crates/compiler/gen_wasm/src/backend.rs b/crates/compiler/gen_wasm/src/backend.rs index 9472b014f57..16a90efc5b0 100644 --- a/crates/compiler/gen_wasm/src/backend.rs +++ b/crates/compiler/gen_wasm/src/backend.rs @@ -1136,10 +1136,6 @@ impl<'a, 'r> WasmBackend<'a, 'r> { storage, ), - Expr::ExprBox { symbol: arg_sym } => self.expr_box(sym, *arg_sym, layout, storage), - - Expr::ExprUnbox { symbol: arg_sym } => self.expr_unbox(sym, *arg_sym), - Expr::Reset { symbol: arg, .. } => self.expr_reset(*arg, sym, storage), Expr::ResetRef { symbol: arg, .. } => self.expr_resetref(*arg, sym, storage), @@ -2005,40 +2001,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> { * Box *******************************************************************/ - pub fn expr_box( - &mut self, - ret_sym: Symbol, - arg_sym: Symbol, - layout: InLayout<'a>, - storage: &StoredValue, - ) { - // create a local variable for the heap pointer - let ptr_local_id = match self.storage.ensure_value_has_local( - &mut self.code_builder, - ret_sym, - storage.clone(), - ) { - StoredValue::Local { local_id, .. } => local_id, - _ => internal_error!("A heap pointer will always be an i32"), - }; - - // allocate heap memory and load its data address onto the value stack - let arg_layout = match self.layout_interner.get_repr(layout) { - LayoutRepr::Boxed(arg) => arg, - _ => internal_error!("ExprBox should always produce a Boxed layout"), - }; - let (size, alignment) = self.layout_interner.stack_size_and_alignment(arg_layout); - self.allocate_with_refcount(Some(size), alignment, 1); - - // store the pointer value from the value stack into the local variable - self.code_builder.set_local(ptr_local_id); - - // copy the argument to the pointer address - self.storage - .copy_value_to_memory(&mut self.code_builder, ptr_local_id, 0, arg_sym); - } - - pub(crate) fn expr_unbox(&mut self, ret_sym: Symbol, arg_sym: Symbol) { + pub(crate) fn ptr_load(&mut self, ret_sym: Symbol, arg_sym: Symbol) { let (from_addr_val, from_offset) = match self.storage.get(&arg_sym) { StoredValue::VirtualMachineStack { .. } => { self.storage diff --git a/crates/compiler/gen_wasm/src/low_level.rs b/crates/compiler/gen_wasm/src/low_level.rs index 22810606d9a..fb861ca3e68 100644 --- a/crates/compiler/gen_wasm/src/low_level.rs +++ b/crates/compiler/gen_wasm/src/low_level.rs @@ -1978,7 +1978,7 @@ impl<'a> LowLevelCall<'a> { value, ); } - PtrLoad => backend.expr_unbox(self.ret_symbol, self.arguments[0]), + PtrLoad => backend.ptr_load(self.ret_symbol, self.arguments[0]), PtrClearTagId => { let ptr = self.arguments[0]; diff --git a/crates/compiler/mono/src/borrow.rs b/crates/compiler/mono/src/borrow.rs index 8a95c793216..4fd9ccc0da9 100644 --- a/crates/compiler/mono/src/borrow.rs +++ b/crates/compiler/mono/src/borrow.rs @@ -703,22 +703,6 @@ impl<'a> BorrowInfState<'a> { self.own_args_if_param(xs); } - ExprBox { symbol: x } => { - self.own_var(z); - - // if the used symbol is an argument to the current function, - // the function must take it as an owned parameter - self.own_args_if_param(&[*x]); - } - - ExprUnbox { symbol: x } => { - // if the boxed value is owned, the box is - self.if_is_owned_then_own(*x, z); - - // if the extracted value is owned, the structure must be too - self.if_is_owned_then_own(z, *x); - } - Reset { symbol: x, .. } | ResetRef { symbol: x, .. } => { self.own_var(z); self.own_var(*x); diff --git a/crates/compiler/mono/src/code_gen_help/refcount.rs b/crates/compiler/mono/src/code_gen_help/refcount.rs index c6c563fd283..055fd728810 100644 --- a/crates/compiler/mono/src/code_gen_help/refcount.rs +++ b/crates/compiler/mono/src/code_gen_help/refcount.rs @@ -2010,7 +2010,7 @@ fn refcount_boxed<'a>( // decrement the inner value if the operation is a decrement and the box itself is unique if layout_interner.is_refcounted(inner_layout) && ctx.op.is_dec() { let inner = root.create_symbol(ident_ids, "inner"); - let inner_expr = Expr::ExprUnbox { symbol: outer }; + let inner_expr = Expr::ptr_load(arena.alloc(outer)); let mod_inner_unit = root.create_symbol(ident_ids, "mod_inner_unit"); let mod_inner_args = refcount_args(root, ctx, inner); diff --git a/crates/compiler/mono/src/debug/checker.rs b/crates/compiler/mono/src/debug/checker.rs index a1d89874785..b74743c30d5 100644 --- a/crates/compiler/mono/src/debug/checker.rs +++ b/crates/compiler/mono/src/debug/checker.rs @@ -464,23 +464,6 @@ impl<'a, 'r> Ctx<'a, 'r> { // TODO don't know what the element layout is None } - &Expr::ExprBox { symbol } => self.with_sym_layout(symbol, |ctx, _def_line, layout| { - let inner = layout; - Some( - ctx.interner - .insert_direct_no_semantic(LayoutRepr::Boxed(inner)), - ) - }), - &Expr::ExprUnbox { symbol } => self.with_sym_layout(symbol, |ctx, def_line, layout| { - let layout = ctx.resolve(layout); - match ctx.interner.get_repr(layout) { - LayoutRepr::Boxed(inner) => Some(inner), - _ => { - ctx.problem(ProblemKind::UnboxNotABox { symbol, def_line }); - None - } - } - }), &Expr::Reset { symbol, update_mode: _, diff --git a/crates/compiler/mono/src/drop_specialization.rs b/crates/compiler/mono/src/drop_specialization.rs index 6d976130541..e21340b9285 100644 --- a/crates/compiler/mono/src/drop_specialization.rs +++ b/crates/compiler/mono/src/drop_specialization.rs @@ -169,11 +169,6 @@ fn specialize_drops_stmt<'a, 'i>( alloc_let_with_continuation!(environment) } - Expr::ExprBox { symbol: child } => { - environment.add_box_child(*binding, *child); - - alloc_let_with_continuation!(environment) - } Expr::Array { elems: children, .. } => { @@ -226,10 +221,6 @@ fn specialize_drops_stmt<'a, 'i>( environment.symbol_tag.insert(*structure, *tag_id); alloc_let_with_continuation!(environment) } - Expr::ExprUnbox { symbol } => { - environment.add_box_child(*symbol, *binding); - alloc_let_with_continuation!(environment) - } Expr::Reset { .. } => { // TODO allow to inline this to replace it with resetref @@ -1533,13 +1524,6 @@ impl<'a> DropSpecializationEnvironment<'a> { .push((child, tag, index)); } - fn add_box_child(&mut self, parent: Parent, child: Child) { - self.box_children - .entry(parent) - .or_insert_with(|| Vec::new_in(self.arena)) - .push(child); - } - fn add_list_child(&mut self, parent: Parent, child: Child, index: u64) { self.list_children .entry(parent) diff --git a/crates/compiler/mono/src/inc_dec.rs b/crates/compiler/mono/src/inc_dec.rs index 139303dc0cc..a8c78c05ccb 100644 --- a/crates/compiler/mono/src/inc_dec.rs +++ b/crates/compiler/mono/src/inc_dec.rs @@ -882,17 +882,11 @@ fn insert_refcount_operations_binding<'a>( inc_owned!(arguments.iter().copied(), new_let) } - Expr::ExprBox { symbol } => { - let new_let = new_let!(stmt); - - inc_owned!([*symbol], new_let) - } Expr::GetTagId { structure, .. } | Expr::StructAtIndex { structure, .. } | Expr::UnionAtIndex { structure, .. } - | Expr::UnionFieldPtrAtIndex { structure, .. } - | Expr::ExprUnbox { symbol: structure } => { + | Expr::UnionFieldPtrAtIndex { structure, .. } => { // All structures are alive at this point and don't have to be copied in order to take an index out/get tag id/copy values to the stack. // But we do want to make sure to decrement this item if it is the last reference. let new_stmt = dec_borrowed!([*structure], stmt); @@ -905,8 +899,9 @@ fn insert_refcount_operations_binding<'a>( match expr { Expr::StructAtIndex { .. } | Expr::UnionAtIndex { .. } - | Expr::UnionFieldPtrAtIndex { .. } - | Expr::ExprUnbox { .. } => insert_inc_stmt(arena, *binding, 1, new_stmt), + | Expr::UnionFieldPtrAtIndex { .. } => { + insert_inc_stmt(arena, *binding, 1, new_stmt) + } // No usage of an element of a reference counted symbol. No need to increment. Expr::GetTagId { .. } => new_stmt, _ => unreachable!("Unexpected expression type"), diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index 6310b4ad1c7..97a3ff788e7 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -1878,14 +1878,6 @@ pub enum Expr<'a> { }, EmptyArray, - ExprBox { - symbol: Symbol, - }, - - ExprUnbox { - symbol: Symbol, - }, - Reset { symbol: Symbol, update_mode: UpdateModeId, @@ -2067,14 +2059,6 @@ impl<'a> Expr<'a> { .text("GetTagId ") .append(symbol_to_doc(alloc, *structure, pretty)), - ExprBox { symbol, .. } => alloc - .text("Box ") - .append(symbol_to_doc(alloc, *symbol, pretty)), - - ExprUnbox { symbol, .. } => alloc - .text("Unbox ") - .append(symbol_to_doc(alloc, *symbol, pretty)), - UnionAtIndex { tag_id, structure, @@ -7679,14 +7663,6 @@ fn substitute_in_expr<'a>( } } - ExprBox { symbol } => { - substitute(subs, *symbol).map(|new_symbol| ExprBox { symbol: new_symbol }) - } - - ExprUnbox { symbol } => { - substitute(subs, *symbol).map(|new_symbol| ExprUnbox { symbol: new_symbol }) - } - StructAtIndex { index, structure, @@ -10053,7 +10029,7 @@ where let field_get_stmt = Stmt::Let(result, field_get_expr, *field, ret_stmt); - let unbox_expr = Expr::ExprUnbox { symbol: argument }; + let unbox_expr = Expr::ptr_load(arena.alloc(argument)); let unbox_stmt = Stmt::Let( unboxed, @@ -10153,7 +10129,7 @@ where let field_get_stmt = Stmt::Let(result, field_get_expr, *field, ret_stmt); - let unbox_expr = Expr::ExprUnbox { symbol: argument }; + let unbox_expr = Expr::ptr_load(arena.alloc(argument)); let unbox_stmt = Stmt::Let(unboxed, unbox_expr, interned, arena.alloc(field_get_stmt)); diff --git a/crates/compiler/mono/src/tail_recursion.rs b/crates/compiler/mono/src/tail_recursion.rs index bb7680a5033..7b7bb793903 100644 --- a/crates/compiler/mono/src/tail_recursion.rs +++ b/crates/compiler/mono/src/tail_recursion.rs @@ -1106,7 +1106,6 @@ fn expr_contains_symbol(expr: &Expr, needle: Symbol) -> bool { crate::ir::ListLiteralElement::Symbol(symbol) => needle == *symbol, }), Expr::EmptyArray => false, - Expr::ExprBox { symbol } | Expr::ExprUnbox { symbol } => needle == *symbol, Expr::Reset { symbol, .. } | Expr::ResetRef { symbol, .. } => needle == *symbol, Expr::RuntimeErrorFunction(_) => false, } From 6d2d65bb1ea155ef86a16362505317f824a2b67b Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 5 Jul 2023 18:57:29 +0200 Subject: [PATCH 130/140] remove Boxed layout --- crates/compiler/alias_analysis/src/lib.rs | 2 +- crates/compiler/gen_dev/src/generic64/mod.rs | 3 +- crates/compiler/gen_dev/src/lib.rs | 5 +- crates/compiler/gen_dev/src/object_builder.rs | 2 +- crates/compiler/gen_llvm/src/llvm/align.rs | 2 +- crates/compiler/gen_llvm/src/llvm/compare.rs | 4 +- crates/compiler/gen_llvm/src/llvm/convert.rs | 2 +- crates/compiler/gen_llvm/src/llvm/expect.rs | 39 +- .../compiler/gen_llvm/src/llvm/refcounting.rs | 130 --- crates/compiler/gen_wasm/src/backend.rs | 10 +- crates/compiler/gen_wasm/src/layout.rs | 1 - crates/compiler/gen_wasm/src/low_level.rs | 5 +- crates/compiler/gen_wasm/src/wasm32_result.rs | 2 +- .../mono/src/code_gen_help/equality.rs | 1 - crates/compiler/mono/src/code_gen_help/mod.rs | 6 - .../mono/src/code_gen_help/refcount.rs | 123 --- .../compiler/mono/src/drop_specialization.rs | 68 -- crates/compiler/mono/src/ir.rs | 8 +- crates/compiler/mono/src/layout.rs | 15 +- crates/compiler/mono/src/layout/intern.rs | 10 +- crates/compiler/mono/src/layout_soa.rs | 907 ------------------ crates/compiler/mono/src/lib.rs | 1 - crates/glue/src/types.rs | 10 - crates/repl_eval/src/eval.rs | 73 +- 24 files changed, 52 insertions(+), 1377 deletions(-) delete mode 100644 crates/compiler/mono/src/layout_soa.rs diff --git a/crates/compiler/alias_analysis/src/lib.rs b/crates/compiler/alias_analysis/src/lib.rs index 058bfc06454..920371944c4 100644 --- a/crates/compiler/alias_analysis/src/lib.rs +++ b/crates/compiler/alias_analysis/src/lib.rs @@ -1612,7 +1612,7 @@ fn layout_spec_help<'a>( } } - Ptr(inner_layout) | Boxed(inner_layout) => { + Ptr(inner_layout) => { let inner_type = layout_spec_help(env, builder, interner, interner.get_repr(inner_layout))?; let cell_type = builder.add_heap_cell_type(); diff --git a/crates/compiler/gen_dev/src/generic64/mod.rs b/crates/compiler/gen_dev/src/generic64/mod.rs index 2057128396a..68d850b63c2 100644 --- a/crates/compiler/gen_dev/src/generic64/mod.rs +++ b/crates/compiler/gen_dev/src/generic64/mod.rs @@ -4518,8 +4518,7 @@ macro_rules! single_register_layouts { #[macro_export] macro_rules! pointer_layouts { () => { - LayoutRepr::Boxed(_) - | LayoutRepr::Ptr(_) + LayoutRepr::Ptr(_) | LayoutRepr::RecursivePointer(_) | LayoutRepr::Union( UnionLayout::Recursive(_) diff --git a/crates/compiler/gen_dev/src/lib.rs b/crates/compiler/gen_dev/src/lib.rs index 344f67c71c7..e8c1182ba28 100644 --- a/crates/compiler/gen_dev/src/lib.rs +++ b/crates/compiler/gen_dev/src/lib.rs @@ -388,7 +388,7 @@ trait Backend<'a> { fn increment_fn_pointer(&mut self, layout: InLayout<'a>) -> Symbol { let box_layout = self .interner_mut() - .insert_direct_no_semantic(LayoutRepr::Boxed(layout)); + .insert_direct_no_semantic(LayoutRepr::Ptr(layout)); let element_increment = self.debug_symbol("element_increment"); let element_increment_symbol = self.build_indirect_inc(layout); @@ -408,7 +408,7 @@ trait Backend<'a> { fn decrement_fn_pointer(&mut self, layout: InLayout<'a>) -> Symbol { let box_layout = self .interner_mut() - .insert_direct_no_semantic(LayoutRepr::Boxed(layout)); + .insert_direct_no_semantic(LayoutRepr::Ptr(layout)); let element_decrement = self.debug_symbol("element_decrement"); let element_decrement_symbol = self.build_indirect_dec(layout); @@ -1586,7 +1586,6 @@ trait Backend<'a> { LowLevel::PtrStore => { let element_layout = match self.interner().get_repr(arg_layouts[0]) { LayoutRepr::Ptr(inner) => inner, - LayoutRepr::Boxed(inner) => inner, _ => unreachable!("cannot write to {:?}", self.interner().dbg(*ret_layout)), }; diff --git a/crates/compiler/gen_dev/src/object_builder.rs b/crates/compiler/gen_dev/src/object_builder.rs index a5f44c61da3..991e1ddcbf0 100644 --- a/crates/compiler/gen_dev/src/object_builder.rs +++ b/crates/compiler/gen_dev/src/object_builder.rs @@ -464,7 +464,7 @@ fn build_exposed_generic_proc<'a, B: Backend<'a>>(backend: &mut B, proc: &Proc<' let box_layout = backend .interner_mut() - .insert_direct_no_semantic(roc_mono::layout::LayoutRepr::Boxed(proc.ret_layout)); + .insert_direct_no_semantic(roc_mono::layout::LayoutRepr::Ptr(proc.ret_layout)); let mut args = bumpalo::collections::Vec::new_in(arena); args.extend(proc.args); diff --git a/crates/compiler/gen_llvm/src/llvm/align.rs b/crates/compiler/gen_llvm/src/llvm/align.rs index 8209feb06c1..68ed5fbf13d 100644 --- a/crates/compiler/gen_llvm/src/llvm/align.rs +++ b/crates/compiler/gen_llvm/src/llvm/align.rs @@ -120,7 +120,7 @@ impl<'a> LlvmAlignment<'a> for LayoutRepr<'a> { .llvm_alignment_bytes(interner), Builtin(builtin) => builtin.llvm_alignment_bytes(interner), RecursivePointer(_) => interner.target_info().ptr_width() as u32, - Ptr(_) | Boxed(_) => interner.target_info().ptr_width() as u32, + Ptr(_) => interner.target_info().ptr_width() as u32, } } } diff --git a/crates/compiler/gen_llvm/src/llvm/compare.rs b/crates/compiler/gen_llvm/src/llvm/compare.rs index 02dcbea26bf..abb94462872 100644 --- a/crates/compiler/gen_llvm/src/llvm/compare.rs +++ b/crates/compiler/gen_llvm/src/llvm/compare.rs @@ -179,7 +179,7 @@ fn build_eq<'a, 'ctx>( rhs_val, ), - LayoutRepr::Ptr(inner_layout) | LayoutRepr::Boxed(inner_layout) => build_box_eq( + LayoutRepr::Ptr(inner_layout) => build_box_eq( env, layout_interner, layout_ids, @@ -379,7 +379,7 @@ fn build_neq<'a, 'ctx>( result.into() } - LayoutRepr::Ptr(inner_layout) | LayoutRepr::Boxed(inner_layout) => { + LayoutRepr::Ptr(inner_layout) => { let is_equal = build_box_eq( env, layout_interner, diff --git a/crates/compiler/gen_llvm/src/llvm/convert.rs b/crates/compiler/gen_llvm/src/llvm/convert.rs index 65b9a1a1c95..e0042c4c461 100644 --- a/crates/compiler/gen_llvm/src/llvm/convert.rs +++ b/crates/compiler/gen_llvm/src/llvm/convert.rs @@ -31,7 +31,7 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>( layout_interner.get_repr(lambda_set.runtime_representation()), ), - Ptr(inner_layout) | Boxed(inner_layout) => { + Ptr(inner_layout) => { let inner_type = basic_type_from_layout( env, layout_interner, diff --git a/crates/compiler/gen_llvm/src/llvm/expect.rs b/crates/compiler/gen_llvm/src/llvm/expect.rs index 3bf0fa3960e..b6a5eb73a62 100644 --- a/crates/compiler/gen_llvm/src/llvm/expect.rs +++ b/crates/compiler/gen_llvm/src/llvm/expect.rs @@ -18,7 +18,7 @@ use roc_mono::layout::{ use roc_region::all::Region; use super::build::BuilderExt; -use super::build::{add_func, load_roc_value, FunctionSpec, LlvmBackendMode}; +use super::build::{add_func, FunctionSpec, LlvmBackendMode}; use super::convert::struct_type_from_union_layout; use super::scope::Scope; use super::struct_::RocStruct; @@ -353,43 +353,6 @@ fn build_clone<'a, 'ctx>( } } - LayoutRepr::Boxed(inner_layout) => { - // write the offset - build_copy(env, ptr, cursors.offset, cursors.extra_offset.into()); - - let source = value.into_pointer_value(); - let value = load_roc_value( - env, - layout_interner, - layout_interner.get_repr(inner_layout), - source, - "inner", - ); - - let inner_width = env - .ptr_int() - .const_int(layout_interner.stack_size(inner_layout) as u64, false); - - let new_extra = env - .builder - .build_int_add(cursors.offset, inner_width, "new_extra"); - - let cursors = Cursors { - offset: cursors.extra_offset, - extra_offset: new_extra, - }; - - build_clone( - env, - layout_interner, - layout_ids, - ptr, - cursors, - value, - layout_interner.get_repr(inner_layout), - ) - } - LayoutRepr::Ptr(_) => { unreachable!("for internal use only") } diff --git a/crates/compiler/gen_llvm/src/llvm/refcounting.rs b/crates/compiler/gen_llvm/src/llvm/refcounting.rs index 8164e27d380..90ec11107dc 100644 --- a/crates/compiler/gen_llvm/src/llvm/refcounting.rs +++ b/crates/compiler/gen_llvm/src/llvm/refcounting.rs @@ -561,12 +561,6 @@ fn modify_refcount_layout_build_function<'a, 'ctx>( modify_refcount_builtin(env, layout_interner, layout_ids, mode, layout, &builtin) } - Boxed(inner) => { - let function = modify_refcount_boxed(env, layout_interner, layout_ids, mode, inner); - - Some(function) - } - Ptr(_inner) => { debug_assert_eq!(true, false); @@ -897,130 +891,6 @@ fn modify_refcount_str_help<'a, 'ctx>( builder.build_return(None); } -fn modify_refcount_boxed<'a, 'ctx>( - env: &Env<'a, 'ctx, '_>, - layout_interner: &STLayoutInterner<'a>, - layout_ids: &mut LayoutIds<'a>, - mode: Mode, - inner_layout: InLayout<'a>, -) -> FunctionValue<'ctx> { - let block = env.builder.get_insert_block().expect("to be in a function"); - let di_location = env.builder.get_current_debug_location().unwrap(); - - let boxed_layout = LayoutRepr::Boxed(inner_layout); - - let (_, fn_name) = function_name_from_mode( - layout_ids, - &env.interns, - "increment_boxed", - "decrement_boxed", - boxed_layout, - mode, - ); - - let function = match env.module.get_function(fn_name.as_str()) { - Some(function_value) => function_value, - None => { - let basic_type = basic_type_from_layout(env, layout_interner, boxed_layout); - let function_value = build_header(env, basic_type, mode, &fn_name); - - modify_refcount_box_help( - env, - layout_interner, - layout_ids, - mode, - inner_layout, - function_value, - ); - - function_value - } - }; - - env.builder.position_at_end(block); - env.builder.set_current_debug_location(di_location); - - function -} - -fn modify_refcount_box_help<'a, 'ctx>( - env: &Env<'a, 'ctx, '_>, - layout_interner: &STLayoutInterner<'a>, - layout_ids: &mut LayoutIds<'a>, - mode: Mode, - inner_layout: InLayout<'a>, - fn_val: FunctionValue<'ctx>, -) { - let builder = env.builder; - let ctx = env.context; - - // Add a basic block for the entry point - let entry = ctx.append_basic_block(fn_val, "entry"); - - builder.position_at_end(entry); - - debug_info_init!(env, fn_val); - - // Add args to scope - let arg_symbol = Symbol::ARG_1; - let arg_val = fn_val.get_param_iter().next().unwrap(); - arg_val.set_name(arg_symbol.as_str(&env.interns)); - - let boxed = arg_val.into_pointer_value(); - let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, boxed); - let call_mode = mode_to_call_mode(fn_val, mode); - let boxed_layout = LayoutRepr::Boxed(inner_layout); - - match mode { - Mode::Inc => { - refcount_ptr.modify(call_mode, boxed_layout, env, layout_interner); - builder.build_return(None); - } - Mode::Dec => { - // if the box is unique, also decrement its inner value - let do_recurse_block = env.context.append_basic_block(fn_val, "do_recurse"); - let no_recurse_block = env.context.append_basic_block(fn_val, "no_recurse"); - - builder.build_conditional_branch( - refcount_ptr.is_1(env), - do_recurse_block, - no_recurse_block, - ); - - { - env.builder.position_at_end(do_recurse_block); - - let inner = load_roc_value( - env, - layout_interner, - layout_interner.get_repr(inner_layout), - boxed, - "inner", - ); - - modify_refcount_layout( - env, - layout_interner, - layout_ids, - call_mode, - inner, - inner_layout, - ); - - refcount_ptr.modify(call_mode, boxed_layout, env, layout_interner); - env.builder.build_return(None); - } - - { - env.builder.position_at_end(no_recurse_block); - - refcount_ptr.modify(call_mode, boxed_layout, env, layout_interner); - env.builder.build_return(None); - } - } - } -} - /// Build an increment or decrement function for a specific layout fn build_header<'ctx>( env: &Env<'_, 'ctx, '_>, diff --git a/crates/compiler/gen_wasm/src/backend.rs b/crates/compiler/gen_wasm/src/backend.rs index 16a90efc5b0..0d989d5eec4 100644 --- a/crates/compiler/gen_wasm/src/backend.rs +++ b/crates/compiler/gen_wasm/src/backend.rs @@ -509,7 +509,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> { .last() .map(|l| self.layout_interner.get_repr(*l)) { - Some(LayoutRepr::Boxed(inner)) => WasmLayout::new(self.layout_interner, inner), + Some(LayoutRepr::Ptr(inner)) => WasmLayout::new(self.layout_interner, inner), x => internal_error!("Higher-order wrapper: invalid return layout {:?}", x), }; @@ -540,8 +540,8 @@ impl<'a, 'r> WasmBackend<'a, 'r> { } let inner_layout = match self.layout_interner.get_repr(*wrapper_arg) { - LayoutRepr::Boxed(inner) => inner, - x => internal_error!("Expected a Boxed layout, got {:?}", x), + LayoutRepr::Ptr(inner) => inner, + x => internal_error!("Expected a Ptr layout, got {:?}", x), }; if self.layout_interner.stack_size(inner_layout) == 0 { continue; @@ -634,8 +634,8 @@ impl<'a, 'r> WasmBackend<'a, 'r> { } let inner_layout = match self.layout_interner.get_repr(value_layout) { - LayoutRepr::Boxed(inner) => inner, - x => internal_error!("Expected a Boxed layout, got {:?}", x), + LayoutRepr::Ptr(inner) => inner, + x => internal_error!("Expected a Ptr layout, got {:?}", x), }; self.code_builder.get_local(LocalId(1)); self.dereference_boxed_value(inner_layout); diff --git a/crates/compiler/gen_wasm/src/layout.rs b/crates/compiler/gen_wasm/src/layout.rs index 853d951e0d6..0745fc4bc9c 100644 --- a/crates/compiler/gen_wasm/src/layout.rs +++ b/crates/compiler/gen_wasm/src/layout.rs @@ -97,7 +97,6 @@ impl WasmLayout { | NullableWrapped { .. } | NullableUnwrapped { .. }, ) - | LayoutRepr::Boxed(_) | LayoutRepr::Ptr(_) | LayoutRepr::RecursivePointer(_) => Self::Primitive(PTR_TYPE, PTR_SIZE), } diff --git a/crates/compiler/gen_wasm/src/low_level.rs b/crates/compiler/gen_wasm/src/low_level.rs index fb861ca3e68..44d79484944 100644 --- a/crates/compiler/gen_wasm/src/low_level.rs +++ b/crates/compiler/gen_wasm/src/low_level.rs @@ -2097,7 +2097,6 @@ impl<'a> LowLevelCall<'a> { | LayoutRepr::Struct { .. } | LayoutRepr::Union(_) | LayoutRepr::LambdaSet(_) - | LayoutRepr::Boxed(_) | LayoutRepr::Ptr(_) => { // Don't want Zig calling convention here, we're calling internal Roc functions backend @@ -2518,7 +2517,7 @@ pub fn call_higher_order_lowlevel<'a>( argument_layouts.iter().take(n_non_closure_args).map(|lay| { backend .layout_interner - .insert_direct_no_semantic(LayoutRepr::Boxed(*lay)) + .insert_direct_no_semantic(LayoutRepr::Ptr(*lay)) }); wrapper_arg_layouts.push(wrapped_captures_layout); @@ -2530,7 +2529,7 @@ pub fn call_higher_order_lowlevel<'a>( wrapper_arg_layouts.push( backend .layout_interner - .insert_direct_no_semantic(LayoutRepr::Boxed(*result_layout)), + .insert_direct_no_semantic(LayoutRepr::Ptr(*result_layout)), ); ProcLayout { arguments: wrapper_arg_layouts.into_bump_slice(), diff --git a/crates/compiler/gen_wasm/src/wasm32_result.rs b/crates/compiler/gen_wasm/src/wasm32_result.rs index b1410091975..db05c5ec123 100644 --- a/crates/compiler/gen_wasm/src/wasm32_result.rs +++ b/crates/compiler/gen_wasm/src/wasm32_result.rs @@ -78,7 +78,7 @@ pub fn insert_wrapper_for_layout<'a>( bool::insert_wrapper(arena, module, wrapper_name, main_fn_index); } LayoutRepr::Union(UnionLayout::NonRecursive(_)) => stack_data_structure(), - LayoutRepr::Union(_) | LayoutRepr::Boxed(_) => { + LayoutRepr::Union(_) => { i32::insert_wrapper(arena, module, wrapper_name, main_fn_index); } _ => stack_data_structure(), diff --git a/crates/compiler/mono/src/code_gen_help/equality.rs b/crates/compiler/mono/src/code_gen_help/equality.rs index 2e6c6163324..71210b4b459 100644 --- a/crates/compiler/mono/src/code_gen_help/equality.rs +++ b/crates/compiler/mono/src/code_gen_help/equality.rs @@ -37,7 +37,6 @@ pub fn eq_generic<'a>( Builtin(List(elem_layout)) => eq_list(root, ident_ids, ctx, layout_interner, elem_layout), Struct(field_layouts) => eq_struct(root, ident_ids, ctx, layout_interner, field_layouts), Union(union_layout) => eq_tag_union(root, ident_ids, ctx, layout_interner, union_layout), - Boxed(inner_layout) => eq_boxed(root, ident_ids, ctx, layout_interner, inner_layout), Ptr(inner_layout) => eq_boxed(root, ident_ids, ctx, layout_interner, inner_layout), LambdaSet(_) => unreachable!("`==` is not defined on functions"), RecursivePointer(_) => { diff --git a/crates/compiler/mono/src/code_gen_help/mod.rs b/crates/compiler/mono/src/code_gen_help/mod.rs index 08872ba6865..cf80c5e5324 100644 --- a/crates/compiler/mono/src/code_gen_help/mod.rs +++ b/crates/compiler/mono/src/code_gen_help/mod.rs @@ -571,11 +571,6 @@ impl<'a> CodeGenHelp<'a> { return layout; } - LayoutRepr::Boxed(inner) => { - let inner = self.replace_rec_ptr(ctx, layout_interner, inner); - LayoutRepr::Boxed(inner) - } - LayoutRepr::Ptr(inner) => { let inner = self.replace_rec_ptr(ctx, layout_interner, inner); LayoutRepr::Ptr(inner) @@ -842,7 +837,6 @@ fn layout_needs_helper_proc<'a>( LayoutRepr::Union(_) => true, LayoutRepr::LambdaSet(_) => true, LayoutRepr::RecursivePointer(_) => false, - LayoutRepr::Boxed(_) => true, LayoutRepr::Ptr(_) => false, } } diff --git a/crates/compiler/mono/src/code_gen_help/refcount.rs b/crates/compiler/mono/src/code_gen_help/refcount.rs index 055fd728810..20d9bd58bf6 100644 --- a/crates/compiler/mono/src/code_gen_help/refcount.rs +++ b/crates/compiler/mono/src/code_gen_help/refcount.rs @@ -233,66 +233,12 @@ pub fn refcount_generic<'a>( LayoutRepr::RecursivePointer(_) => unreachable!( "We should never call a refcounting helper on a RecursivePointer layout directly" ), - LayoutRepr::Boxed(inner_layout) => refcount_boxed( - root, - ident_ids, - ctx, - layout_interner, - layout, - inner_layout, - structure, - ), LayoutRepr::Ptr(_) => { unreachable!("We should never call a refcounting helper on a Ptr layout directly") } } } -fn if_unique<'a>( - root: &mut CodeGenHelp<'a>, - ident_ids: &mut IdentIds, - value: Symbol, - when_unique: impl FnOnce(JoinPointId) -> Stmt<'a>, - when_done: Stmt<'a>, -) -> Stmt<'a> { - // joinpoint f = - // - // in - // if is_unique then - // (f) - // else - // jump f - - let joinpoint = root.create_symbol(ident_ids, "is_unique_joinpoint"); - let joinpoint = JoinPointId(joinpoint); - - let is_unique = root.create_symbol(ident_ids, "is_unique"); - - let mut stmt = Stmt::if_then_else( - root.arena, - is_unique, - Layout::UNIT, - when_unique(joinpoint), - root.arena.alloc(Stmt::Jump(joinpoint, &[])), - ); - - stmt = Stmt::Join { - id: joinpoint, - parameters: &[], - body: root.arena.alloc(when_done), - remainder: root.arena.alloc(stmt), - }; - - let_lowlevel( - root.arena, - root.layout_isize, - is_unique, - LowLevel::RefCountIsUnique, - &[value], - root.arena.alloc(stmt), - ) -} - pub fn refcount_reset_proc_body<'a>( root: &mut CodeGenHelp<'a>, ident_ids: &mut IdentIds, @@ -1978,72 +1924,3 @@ fn refcount_tag_fields<'a>( stmt } - -fn refcount_boxed<'a>( - root: &mut CodeGenHelp<'a>, - ident_ids: &mut IdentIds, - ctx: &mut Context<'a>, - layout_interner: &mut STLayoutInterner<'a>, - layout: InLayout<'a>, - inner_layout: InLayout<'a>, - outer: Symbol, -) -> Stmt<'a> { - let arena = root.arena; - - // - // modify refcount of the inner and outer structures - // RC on inner first, to avoid use-after-free for Dec - // We're defining statements in reverse, so define outer first - // - - let alignment = layout_interner.allocation_alignment_bytes(layout); - let ret_stmt = rc_return_stmt(root, ident_ids, ctx); - let modify_outer = modify_refcount( - root, - ident_ids, - ctx, - Pointer::ToData(outer), - alignment, - arena.alloc(ret_stmt), - ); - - // decrement the inner value if the operation is a decrement and the box itself is unique - if layout_interner.is_refcounted(inner_layout) && ctx.op.is_dec() { - let inner = root.create_symbol(ident_ids, "inner"); - let inner_expr = Expr::ptr_load(arena.alloc(outer)); - - let mod_inner_unit = root.create_symbol(ident_ids, "mod_inner_unit"); - let mod_inner_args = refcount_args(root, ctx, inner); - let mod_inner_expr = root - .call_specialized_op( - ident_ids, - ctx, - layout_interner, - inner_layout, - mod_inner_args, - ) - .unwrap(); - - if_unique( - root, - ident_ids, - outer, - |id| { - Stmt::Let( - inner, - inner_expr, - inner_layout, - arena.alloc(Stmt::Let( - mod_inner_unit, - mod_inner_expr, - LAYOUT_UNIT, - arena.alloc(Stmt::Jump(id, &[])), - )), - ) - }, - modify_outer, - ) - } else { - modify_outer - } -} diff --git a/crates/compiler/mono/src/drop_specialization.rs b/crates/compiler/mono/src/drop_specialization.rs index e21340b9285..be2edd43d3f 100644 --- a/crates/compiler/mono/src/drop_specialization.rs +++ b/crates/compiler/mono/src/drop_specialization.rs @@ -526,15 +526,6 @@ fn specialize_drops_stmt<'a, 'i>( &mut incremented_children, continuation, ), - LayoutRepr::Boxed(_layout) => specialize_boxed( - arena, - layout_interner, - ident_ids, - environment, - &mut incremented_children, - symbol, - continuation, - ), LayoutRepr::Builtin(Builtin::List(layout)) => specialize_list( arena, layout_interner, @@ -1059,65 +1050,6 @@ fn specialize_union<'a, 'i>( } } -fn specialize_boxed<'a, 'i>( - arena: &'a Bump, - layout_interner: &'i mut STLayoutInterner<'a>, - ident_ids: &'i mut IdentIds, - environment: &mut DropSpecializationEnvironment<'a>, - incremented_children: &mut CountingMap, - symbol: &Symbol, - continuation: &'a Stmt<'a>, -) -> &'a Stmt<'a> { - let removed = match incremented_children.map.iter().next() { - Some((s, _)) => { - let s = *s; - incremented_children.pop(&s); - Some(s) - } - None => None, - }; - - let new_continuation = - specialize_drops_stmt(arena, layout_interner, ident_ids, environment, continuation); - - match removed { - Some(s) => { - branch_uniqueness( - arena, - ident_ids, - layout_interner, - environment, - *symbol, - // If the symbol is unique: - // - free the box - |_, _, continuation| { - arena.alloc(Stmt::Refcounting( - // we know for sure that the allocation is unique at - // this point. Therefore we can free (or maybe reuse) - // without checking the refcount again. - ModifyRc::Free(*symbol), - continuation, - )) - }, - // If the symbol is not unique: - // - increment the child - // - decref the box - |_, _, continuation| { - arena.alloc(Stmt::Refcounting( - ModifyRc::Inc(s, 1), - arena.alloc(Stmt::Refcounting(ModifyRc::DecRef(*symbol), continuation)), - )) - }, - new_continuation, - ) - } - None => { - // No known children, keep decrementing the symbol. - arena.alloc(Stmt::Refcounting(ModifyRc::Dec(*symbol), new_continuation)) - } - } -} - fn specialize_list<'a, 'i>( arena: &'a Bump, layout_interner: &'i mut STLayoutInterner<'a>, diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index 97a3ff788e7..c2d799fbeb1 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -9915,9 +9915,6 @@ where stack.push(layout_interner.get(*in_layout)); } } - LayoutRepr::Boxed(boxed) => { - stack.push(layout_interner.get(boxed)); - } LayoutRepr::Ptr(inner) => { stack.push(layout_interner.get(inner)); } @@ -9989,7 +9986,7 @@ where { let interned_unboxed_struct_layout = layout_interner.insert(*unboxed_struct_layout); let boxed_struct_layout = - Layout::no_semantic(LayoutRepr::Boxed(interned_unboxed_struct_layout).direct()); + Layout::no_semantic(LayoutRepr::Ptr(interned_unboxed_struct_layout).direct()); let boxed_struct_layout = layout_interner.insert(boxed_struct_layout); let mut answer = bumpalo::collections::Vec::with_capacity_in(field_layouts.len(), arena); @@ -10100,7 +10097,7 @@ where I: LayoutInterner<'a>, { let interned = layout_interner.insert(*unboxed_struct_layout); - let boxed_struct_layout = Layout::no_semantic(LayoutRepr::Boxed(interned).direct()); + let boxed_struct_layout = Layout::no_semantic(LayoutRepr::Ptr(interned).direct()); let boxed_struct_layout = layout_interner.insert(boxed_struct_layout); let mut answer = bumpalo::collections::Vec::with_capacity_in(field_layouts.len(), arena); @@ -10130,7 +10127,6 @@ where let field_get_stmt = Stmt::Let(result, field_get_expr, *field, ret_stmt); let unbox_expr = Expr::ptr_load(arena.alloc(argument)); - let unbox_stmt = Stmt::Let(unboxed, unbox_expr, interned, arena.alloc(field_get_stmt)); let proc = Proc { diff --git a/crates/compiler/mono/src/layout.rs b/crates/compiler/mono/src/layout.rs index 39dc839a04b..d6ffe895106 100644 --- a/crates/compiler/mono/src/layout.rs +++ b/crates/compiler/mono/src/layout.rs @@ -674,8 +674,6 @@ pub(crate) enum LayoutWrapper<'a> { pub enum LayoutRepr<'a> { Builtin(Builtin<'a>), Struct(&'a [InLayout<'a>]), - // A (heap allocated) reference-counted value - Boxed(InLayout<'a>), // A pointer (heap or stack) without any reference counting // Ptr is not user-facing. The compiler author must make sure that invariants are upheld Ptr(InLayout<'a>), @@ -2534,7 +2532,7 @@ impl<'a> LayoutRepr<'a> { pub const F64: Self = LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)); pub const DEC: Self = LayoutRepr::Builtin(Builtin::Decimal); pub const STR: Self = LayoutRepr::Builtin(Builtin::Str); - pub const OPAQUE_PTR: Self = LayoutRepr::Boxed(Layout::VOID); + pub const OPAQUE_PTR: Self = LayoutRepr::Ptr(Layout::VOID); pub const fn struct_(field_layouts: &'a [InLayout<'a>]) -> Self { Self::Struct(field_layouts) @@ -2576,7 +2574,7 @@ impl<'a> LayoutRepr<'a> { LambdaSet(lambda_set) => interner .get_repr(lambda_set.runtime_representation()) .safe_to_memcpy(interner), - Boxed(_) | Ptr(_) | RecursivePointer(_) => { + Ptr(_) | RecursivePointer(_) => { // We cannot memcpy pointers, because then we would have the same pointer in multiple places! false } @@ -2666,7 +2664,6 @@ impl<'a> LayoutRepr<'a> { .get_repr(lambda_set.runtime_representation()) .stack_size_without_alignment(interner), RecursivePointer(_) => interner.target_info().ptr_width() as u32, - Boxed(_) => interner.target_info().ptr_width() as u32, Ptr(_) => interner.target_info().ptr_width() as u32, } } @@ -2720,7 +2717,6 @@ impl<'a> LayoutRepr<'a> { .alignment_bytes(interner), Builtin(builtin) => builtin.alignment_bytes(interner.target_info()), RecursivePointer(_) => interner.target_info().ptr_width() as u32, - Boxed(_) => interner.target_info().ptr_width() as u32, Ptr(_) => interner.target_info().ptr_width() as u32, } } @@ -2742,10 +2738,6 @@ impl<'a> LayoutRepr<'a> { RecursivePointer(_) => { unreachable!("should be looked up to get an actual layout") } - Boxed(inner) => Ord::max( - ptr_width, - interner.get_repr(*inner).alignment_bytes(interner), - ), Ptr(inner) => interner.get_repr(*inner).alignment_bytes(interner), } } @@ -2815,7 +2807,6 @@ impl<'a> LayoutRepr<'a> { .get_repr(lambda_set.runtime_representation()) .contains_refcounted(interner), RecursivePointer(_) => true, - Boxed(_) => true, Ptr(_) => { // we never consider pointers for refcounting. Ptr is not user-facing. The compiler // author must make sure that invariants are upheld @@ -2876,7 +2867,7 @@ impl<'a> LayoutRepr<'a> { } }, LambdaSet(_) => return true, - Boxed(_) | Ptr(_) => { + Ptr(_) => { // If there's any layer of indirection (behind a pointer), then it doesn't vary! } RecursivePointer(_) => { diff --git a/crates/compiler/mono/src/layout/intern.rs b/crates/compiler/mono/src/layout/intern.rs index 024f32b63b4..321b4b2e355 100644 --- a/crates/compiler/mono/src/layout/intern.rs +++ b/crates/compiler/mono/src/layout/intern.rs @@ -76,7 +76,7 @@ cache_interned_layouts! { 16, STR, pub, nosema!(LayoutRepr::STR) 17, OPAQUE_PTR, pub, nosema!(LayoutRepr::OPAQUE_PTR) 18, NAKED_RECURSIVE_PTR, pub(super), nosema!(LayoutRepr::RecursivePointer(Layout::VOID)) - 19, STR_PTR, pub, nosema!(LayoutRepr::Boxed(Layout::STR)) + 19, STR_PTR, pub, nosema!(LayoutRepr::Ptr(Layout::STR)) 20, LIST_U8, pub, nosema!(LayoutRepr::Builtin(crate::layout::Builtin::List(Layout::U8))) ; 21 @@ -350,10 +350,6 @@ pub trait LayoutInterner<'a>: Sized { self.to_doc(rec_layout, alloc, seen_rec, parens) } } - Boxed(inner) => alloc - .text("Boxed(") - .append(self.to_doc(inner, alloc, seen_rec, parens)) - .append(")"), Ptr(inner) => alloc .text("Ptr(") .append(self.to_doc(inner, alloc, seen_rec, parens)) @@ -1115,7 +1111,6 @@ mod reify { LayoutRepr::Struct(field_layouts) => { LayoutRepr::Struct(reify_layout_slice(arena, interner, slot, field_layouts)) } - LayoutRepr::Boxed(lay) => LayoutRepr::Boxed(reify_layout(arena, interner, slot, lay)), LayoutRepr::Ptr(lay) => LayoutRepr::Ptr(reify_layout(arena, interner, slot, lay)), LayoutRepr::Union(un) => LayoutRepr::Union(reify_union(arena, interner, slot, un)), LayoutRepr::LambdaSet(ls) => { @@ -1320,7 +1315,6 @@ mod equiv { (Struct(fl1), Struct(fl2)) => { equiv_fields!(fl1, fl2) } - (Boxed(b1), Boxed(b2)) => stack.push((b1, b2)), (Ptr(b1), Ptr(b2)) => stack.push((b1, b2)), (Union(u1), Union(u2)) => { use UnionLayout::*; @@ -1441,7 +1435,6 @@ pub mod dbg_deep { .debug_struct("Struct") .field("fields", &DbgFields(self.0, field_layouts)) .finish(), - LayoutRepr::Boxed(b) => f.debug_tuple("Boxed").field(&Dbg(self.0, *b)).finish(), LayoutRepr::Ptr(b) => f.debug_tuple("Ptr").field(&Dbg(self.0, *b)).finish(), LayoutRepr::Union(un) => f .debug_tuple("Union") @@ -1615,7 +1608,6 @@ pub mod dbg_stable { .debug_struct("Struct") .field("fields", &DbgFields(self.0, field_layouts)) .finish(), - LayoutRepr::Boxed(b) => f.debug_tuple("Boxed").field(&Dbg(self.0, *b)).finish(), LayoutRepr::Ptr(b) => f.debug_tuple("Ptr").field(&Dbg(self.0, *b)).finish(), LayoutRepr::Union(un) => f .debug_tuple("Union") diff --git a/crates/compiler/mono/src/layout_soa.rs b/crates/compiler/mono/src/layout_soa.rs deleted file mode 100644 index 30dd83e1276..00000000000 --- a/crates/compiler/mono/src/layout_soa.rs +++ /dev/null @@ -1,907 +0,0 @@ -use crate::layout::{ext_var_is_empty_record, ext_var_is_empty_tag_union}; -use roc_builtins::bitcode::{FloatWidth, IntWidth}; -use roc_collections::all::MutMap; -use roc_module::symbol::Symbol; -use roc_target::TargetInfo; -use roc_types::subs::{self, Content, FlatType, Subs, Variable}; -use roc_types::types::RecordField; -use std::collections::hash_map::Entry; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Index { - index: u32, - _marker: std::marker::PhantomData, -} - -impl Index { - pub const fn new(index: u32) -> Self { - Self { - index, - _marker: std::marker::PhantomData, - } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Slice { - start: u32, - length: u16, - _marker: std::marker::PhantomData, -} - -impl Slice { - pub const fn new(start: u32, length: u16) -> Self { - Self { - start, - length, - _marker: std::marker::PhantomData, - } - } - - pub const fn len(&self) -> usize { - self.length as _ - } - - pub const fn is_empty(&self) -> bool { - self.length == 0 - } - - pub const fn indices(&self) -> std::ops::Range { - self.start as usize..(self.start as usize + self.length as usize) - } - - pub fn into_iter(&self) -> impl Iterator> { - self.indices().map(|i| Index::new(i as _)) - } -} - -trait Reserve { - fn reserve(layouts: &mut Layouts, length: usize) -> Self; -} - -impl Reserve for Slice { - fn reserve(layouts: &mut Layouts, length: usize) -> Self { - let start = layouts.layouts.len() as u32; - - let it = std::iter::repeat(Layout::Reserved).take(length); - layouts.layouts.extend(it); - - Self { - start, - length: length as u16, - _marker: Default::default(), - } - } -} - -impl Reserve for Slice> { - fn reserve(layouts: &mut Layouts, length: usize) -> Self { - let start = layouts.layout_slices.len() as u32; - - let empty: Slice = Slice::new(0, 0); - let it = std::iter::repeat(empty).take(length); - layouts.layout_slices.extend(it); - - Self { - start, - length: length as u16, - _marker: Default::default(), - } - } -} - -static_assertions::assert_eq_size!([u8; 12], Layout); - -pub struct Layouts { - layouts: Vec, - layout_slices: Vec>, - // function_layouts: Vec<(Slice, Index)>, - lambda_sets: Vec, - symbols: Vec, - recursion_variable_to_structure_variable_map: MutMap>, - target_info: TargetInfo, -} - -pub struct FunctionLayout { - /// last element is the result, prior elements the arguments - arguments_and_result: Slice, - pub lambda_set: Index, -} - -impl FunctionLayout { - pub fn from_var( - layouts: &mut Layouts, - subs: &Subs, - var: Variable, - ) -> Result { - // so we can set some things/clean up - Self::from_var_help(layouts, subs, var) - } - - fn from_var_help( - layouts: &mut Layouts, - subs: &Subs, - var: Variable, - ) -> Result { - let content = &subs.get_content_without_compacting(var); - Self::from_content(layouts, subs, var, content) - } - - fn from_content( - layouts: &mut Layouts, - subs: &Subs, - var: Variable, - content: &Content, - ) -> Result { - use LayoutError::*; - - match content { - Content::FlexVar(_) - | Content::RigidVar(_) - | Content::FlexAbleVar(_, _) - | Content::RigidAbleVar(_, _) => Err(UnresolvedVariable(var)), - Content::RecursionVar { .. } => Err(TypeError(())), - Content::LambdaSet(lset) => Self::from_lambda_set(layouts, subs, *lset), - Content::Structure(flat_type) => Self::from_flat_type(layouts, subs, flat_type), - Content::Alias(_, _, actual, _) => Self::from_var_help(layouts, subs, *actual), - Content::RangedNumber(_) => todo!(), - Content::Error => Err(TypeError(())), - } - } - - fn from_lambda_set( - _layouts: &mut Layouts, - _subs: &Subs, - _lset: subs::LambdaSet, - ) -> Result { - todo!(); - } - - fn from_flat_type( - layouts: &mut Layouts, - subs: &Subs, - flat_type: &FlatType, - ) -> Result { - match flat_type { - FlatType::Func(arguments, lambda_set, result) => { - let slice = Slice::reserve(layouts, arguments.len() + 1); - - let variable_slice = &subs.variables[arguments.indices()]; - let it = slice.indices().zip(variable_slice); - for (target_index, var) in it { - let layout = Layout::from_var_help(layouts, subs, *var)?; - layouts.layouts[target_index] = layout; - } - - let result_layout = Layout::from_var_help(layouts, subs, *result)?; - let result_index: Index = Index::new(slice.start + slice.len() as u32 - 1); - layouts.layouts[result_index.index as usize] = result_layout; - - let lambda_set = LambdaSet::from_var(layouts, subs, *lambda_set)?; - let lambda_set_index = Index::new(layouts.lambda_sets.len() as u32); - layouts.lambda_sets.push(lambda_set); - - Ok(Self { - arguments_and_result: slice, - lambda_set: lambda_set_index, - }) - } - - _ => todo!(), - } - } - - pub fn argument_slice(&self) -> Slice { - let mut result = self.arguments_and_result; - result.length -= 1; - - result - } - pub fn result_index(&self) -> Index { - Index::new(self.arguments_and_result.start + self.arguments_and_result.length as u32 - 1) - } -} - -/// Idea: don't include the symbols for the first 3 cases in --optimize mode -pub enum LambdaSet { - Empty { - symbol: Index, - }, - Single { - symbol: Index, - layout: Index, - }, - Struct { - symbol: Index, - layouts: Slice, - }, - Union { - symbols: Slice, - layouts: Slice>, - }, -} - -impl LambdaSet { - pub fn from_var( - layouts: &mut Layouts, - subs: &Subs, - var: Variable, - ) -> Result { - // so we can set some things/clean up - Self::from_var_help(layouts, subs, var) - } - - fn from_var_help( - layouts: &mut Layouts, - subs: &Subs, - var: Variable, - ) -> Result { - let content = &subs.get_content_without_compacting(var); - Self::from_content(layouts, subs, var, content) - } - - fn from_content( - layouts: &mut Layouts, - subs: &Subs, - var: Variable, - content: &Content, - ) -> Result { - use LayoutError::*; - - match content { - Content::FlexVar(_) - | Content::RigidVar(_) - | Content::FlexAbleVar(_, _) - | Content::RigidAbleVar(_, _) => Err(UnresolvedVariable(var)), - Content::RecursionVar { .. } => { - unreachable!("lambda sets cannot currently be recursive") - } - Content::LambdaSet(lset) => Self::from_lambda_set(layouts, subs, *lset), - Content::Structure(_flat_type) => unreachable!(), - Content::Alias(_, _, actual, _) => Self::from_var_help(layouts, subs, *actual), - Content::RangedNumber(_) => todo!(), - Content::Error => Err(TypeError(())), - } - } - - fn from_lambda_set( - layouts: &mut Layouts, - subs: &Subs, - lset: subs::LambdaSet, - ) -> Result { - let subs::LambdaSet { - solved, - recursion_var: _, - unspecialized: _, - ambient_function: _, - } = lset; - - // TODO: handle unspecialized - - debug_assert!( - !solved.is_empty(), - "lambda set must contain atleast the function itself" - ); - - let lambda_names = solved.labels(); - let closure_names = Self::get_closure_names(layouts, subs, lambda_names); - - let variables = solved.variables(); - if variables.len() == 1 { - let symbol = subs.symbol_names[lambda_names.start as usize]; - let symbol_index = Index::new(layouts.symbols.len() as u32); - layouts.symbols.push(symbol); - let variable_slice = subs.variable_slices[variables.start as usize]; - - match variable_slice.len() { - 0 => Ok(LambdaSet::Empty { - symbol: symbol_index, - }), - 1 => { - let var = subs.variables[variable_slice.start as usize]; - let layout = Layout::from_var(layouts, subs, var)?; - - let index = Index::new(layouts.layouts.len() as u32); - layouts.layouts.push(layout); - - Ok(LambdaSet::Single { - symbol: symbol_index, - layout: index, - }) - } - _ => { - let slice = Layout::from_variable_slice(layouts, subs, variable_slice)?; - - Ok(LambdaSet::Struct { - symbol: symbol_index, - layouts: slice, - }) - } - } - } else { - let layouts = Layout::from_slice_variable_slice(layouts, subs, solved.variables())?; - - Ok(LambdaSet::Union { - symbols: closure_names, - layouts, - }) - } - } - - fn get_closure_names( - layouts: &mut Layouts, - subs: &Subs, - subs_slice: roc_types::subs::SubsSlice, - ) -> Slice { - let slice = Slice::new(layouts.symbols.len() as u32, subs_slice.len() as u16); - - let symbols = &subs.symbol_names[subs_slice.indices()]; - - for symbol in symbols { - layouts.symbols.push(*symbol); - } - - slice - } -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum Layout { - // theory: we can zero out memory to reserve space for many layouts - Reserved, - - // Question: where to store signedness information? - Int(IntWidth), - Float(FloatWidth), - Decimal, - - Str, - Dict(Index<(Layout, Layout)>), - Set(Index), - List(Index), - - Struct(Slice), - - UnionNonRecursive(Slice>), - - Boxed(Index), - UnionRecursive(Slice>), - // UnionNonNullableUnwrapped(Slice), - // UnionNullableWrapper { - // data: NullableUnionIndex, - // tag_id: u16, - // }, - // - // UnionNullableUnwrappedTrue(Slice), - // UnionNullableUnwrappedFalse(Slice), - - // RecursivePointer, -} - -fn round_up_to_alignment(unaligned: u16, alignment_bytes: u16) -> u16 { - let unaligned = unaligned as i32; - let alignment_bytes = alignment_bytes as i32; - if alignment_bytes <= 1 { - return unaligned as u16; - } - if alignment_bytes.count_ones() != 1 { - panic!( - "Cannot align to {} bytes. Not a power of 2.", - alignment_bytes - ); - } - let mut aligned = unaligned; - aligned += alignment_bytes - 1; // if lower bits are non-zero, push it over the next boundary - aligned &= -alignment_bytes; // mask with a flag that has upper bits 1, lower bits 0 - - aligned as u16 -} - -impl Layouts { - const VOID_INDEX: Index = Index::new(0); - const VOID_TUPLE: Index<(Layout, Layout)> = Index::new(0); - const UNIT_INDEX: Index = Index::new(2); - - pub fn new(target_info: TargetInfo) -> Self { - let mut layouts = Vec::with_capacity(64); - - layouts.push(Layout::VOID); - layouts.push(Layout::VOID); - layouts.push(Layout::UNIT); - - // sanity check - debug_assert_eq!(layouts[Self::VOID_INDEX.index as usize], Layout::VOID); - debug_assert_eq!(layouts[Self::VOID_TUPLE.index as usize + 1], Layout::VOID); - debug_assert_eq!(layouts[Self::UNIT_INDEX.index as usize], Layout::UNIT); - - Layouts { - layouts: Vec::default(), - layout_slices: Vec::default(), - lambda_sets: Vec::default(), - symbols: Vec::default(), - recursion_variable_to_structure_variable_map: MutMap::default(), - target_info, - } - } - - /// sort a slice according to elements' alignment - fn sort_slice_by_alignment(&mut self, layout_slice: Slice) { - let slice = &mut self.layouts[layout_slice.indices()]; - - // SAFETY: the align_of function does not mutate the layouts vector - // this unsafety is required to circumvent the borrow checker - let sneaky_slice = - unsafe { std::slice::from_raw_parts_mut(slice.as_mut_ptr(), slice.len()) }; - - sneaky_slice.sort_by(|layout1, layout2| { - let align1 = self.align_of_layout(*layout1); - let align2 = self.align_of_layout(*layout2); - - // we want the biggest alignment first - align2.cmp(&align1) - }); - } - - fn usize(&self) -> Layout { - let usize_int_width = match self.target_info.ptr_width() { - roc_target::PtrWidth::Bytes4 => IntWidth::U32, - roc_target::PtrWidth::Bytes8 => IntWidth::U64, - }; - - Layout::Int(usize_int_width) - } - - fn align_of_layout_index(&self, index: Index) -> u16 { - let layout = self.layouts[index.index as usize]; - - self.align_of_layout(layout) - } - - fn align_of_layout(&self, layout: Layout) -> u16 { - let usize_int_width = match self.target_info.ptr_width() { - roc_target::PtrWidth::Bytes4 => IntWidth::U32, - roc_target::PtrWidth::Bytes8 => IntWidth::U64, - }; - - let ptr_alignment = usize_int_width.alignment_bytes(self.target_info) as u16; - - match layout { - Layout::Reserved => unreachable!(), - Layout::Int(int_width) => int_width.alignment_bytes(self.target_info) as u16, - Layout::Float(float_width) => float_width.alignment_bytes(self.target_info) as u16, - Layout::Decimal => IntWidth::U128.alignment_bytes(self.target_info) as u16, - Layout::Str | Layout::Dict(_) | Layout::Set(_) | Layout::List(_) => ptr_alignment, - Layout::Struct(slice) => self.align_of_layout_slice(slice), - Layout::Boxed(_) | Layout::UnionRecursive(_) => ptr_alignment, - Layout::UnionNonRecursive(slices) => { - let tag_id_align = IntWidth::I64.alignment_bytes(self.target_info) as u16; - - self.align_of_layout_slices(slices).max(tag_id_align) - } -// Layout::UnionNonNullableUnwrapped(_) => todo!(), -// Layout::UnionNullableWrapper { data, tag_id } => todo!(), -// Layout::UnionNullableUnwrappedTrue(_) => todo!(), -// Layout::UnionNullableUnwrappedFalse(_) => todo!(), -// Layout::RecursivePointer => todo!(), - } - } - - /// Invariant: the layouts are sorted from biggest to smallest alignment - fn align_of_layout_slice(&self, slice: Slice) -> u16 { - match slice.into_iter().next() { - None => 0, - Some(first_index) => self.align_of_layout_index(first_index), - } - } - - fn align_of_layout_slices(&self, slice: Slice>) -> u16 { - slice - .into_iter() - .map(|index| self.layout_slices[index.index as usize]) - .map(|slice| self.align_of_layout_slice(slice)) - .max() - .unwrap_or_default() - } - - /// Invariant: the layouts are sorted from biggest to smallest alignment - fn size_of_layout_slice(&self, slice: Slice) -> u16 { - match slice.into_iter().next() { - None => 0, - Some(first_index) => { - let alignment = self.align_of_layout_index(first_index); - - let mut sum = 0; - - for index in slice.into_iter() { - sum += self.size_of_layout_index(index); - } - - round_up_to_alignment(sum, alignment) - } - } - } - - pub fn size_of_layout_index(&self, index: Index) -> u16 { - let layout = self.layouts[index.index as usize]; - - self.size_of_layout(layout) - } - - pub fn size_of_layout(&self, layout: Layout) -> u16 { - let usize_int_width = match self.target_info.ptr_width() { - roc_target::PtrWidth::Bytes4 => IntWidth::U32, - roc_target::PtrWidth::Bytes8 => IntWidth::U64, - }; - - let ptr_width = usize_int_width.stack_size() as u16; - - match layout { - Layout::Reserved => unreachable!(), - Layout::Int(int_width) => int_width.stack_size() as _, - Layout::Float(float_width) => float_width as _, - Layout::Decimal => (std::mem::size_of::()) as _, - Layout::Str | Layout::Dict(_) | Layout::Set(_) | Layout::List(_) => 2 * ptr_width, - Layout::Struct(slice) => self.size_of_layout_slice(slice), - Layout::Boxed(_) | Layout::UnionRecursive(_) => ptr_width, - Layout::UnionNonRecursive(slices) if slices.is_empty() => 0, - Layout::UnionNonRecursive(slices) => { - let tag_id = IntWidth::I64; - - let max_slice_size = slices - .into_iter() - .map(|index| self.layout_slices[index.index as usize]) - .map(|slice| self.align_of_layout_slice(slice)) - .max() - .unwrap_or_default(); - - tag_id.stack_size() as u16 + max_slice_size - } -// Layout::UnionNonNullableUnwrapped(_) => todo!(), -// Layout::UnionNullableWrapper { data, tag_id } => todo!(), -// Layout::UnionNullableUnwrappedTrue(_) => todo!(), -// Layout::UnionNullableUnwrappedFalse(_) => todo!(), -// Layout::RecursivePointer => todo!(), - } - } -} - -pub enum LayoutError { - UnresolvedVariable(Variable), - TypeError(()), -} - -impl Layout { - pub const UNIT: Self = Self::Struct(Slice::new(0, 0)); - pub const VOID: Self = Self::UnionNonRecursive(Slice::new(0, 0)); - - pub const EMPTY_LIST: Self = Self::List(Layouts::VOID_INDEX); - pub const EMPTY_DICT: Self = Self::Dict(Layouts::VOID_TUPLE); - pub const EMPTY_SET: Self = Self::Set(Layouts::VOID_INDEX); - - pub fn from_var( - layouts: &mut Layouts, - subs: &Subs, - var: Variable, - ) -> Result { - // so we can set some things/clean up - Self::from_var_help(layouts, subs, var) - } - - fn from_var_help( - layouts: &mut Layouts, - subs: &Subs, - var: Variable, - ) -> Result { - let content = &subs.get_content_without_compacting(var); - Self::from_content(layouts, subs, var, content) - } - - /// Used in situations where an unspecialized variable is not a problem, - /// and we can substitute with `[]`, the empty tag union. - /// e.g. an empty list literal has type `List *`. We can still generate code - /// in those cases by just picking any concrete type for the list element, - /// and we pick the empty tag union in practice. - fn from_var_help_or_void( - layouts: &mut Layouts, - subs: &Subs, - var: Variable, - ) -> Result { - let content = &subs.get_content_without_compacting(var); - - match content { - Content::FlexVar(_) | Content::RigidVar(_) => Ok(Layout::VOID), - - _ => Self::from_content(layouts, subs, var, content), - } - } - - fn from_content( - layouts: &mut Layouts, - subs: &Subs, - var: Variable, - content: &Content, - ) -> Result { - use LayoutError::*; - - match content { - Content::FlexVar(_) - | Content::RigidVar(_) - | Content::FlexAbleVar(_, _) - | Content::RigidAbleVar(_, _) => Err(UnresolvedVariable(var)), - Content::RecursionVar { - structure, - opt_name: _, - } => { - let structure = subs.get_root_key_without_compacting(*structure); - - let entry = layouts - .recursion_variable_to_structure_variable_map - .entry(structure); - - match entry { - Entry::Vacant(vacant) => { - let reserved = Index::new(layouts.layouts.len() as _); - layouts.layouts.push(Layout::Reserved); - - vacant.insert(reserved); - - let layout = Layout::from_var(layouts, subs, structure)?; - - layouts.layouts[reserved.index as usize] = layout; - - Ok(Layout::Boxed(reserved)) - } - Entry::Occupied(occupied) => { - let index = occupied.get(); - - Ok(Layout::Boxed(*index)) - } - } - } - // Lambda set layout is same as tag union - Content::LambdaSet(lset) => Self::from_lambda_set(layouts, subs, *lset), - Content::Structure(flat_type) => Self::from_flat_type(layouts, subs, flat_type), - Content::Alias(symbol, _, actual, _) => { - let symbol = *symbol; - - if let Some(int_width) = IntWidth::try_from_symbol(symbol) { - return Ok(Layout::Int(int_width)); - } - - if let Some(float_width) = FloatWidth::try_from_symbol(symbol) { - return Ok(Layout::Float(float_width)); - } - - match symbol { - Symbol::NUM_DECIMAL => Ok(Layout::Decimal), - - Symbol::NUM_NAT | Symbol::NUM_NATURAL => Ok(layouts.usize()), - - _ => { - // at this point we throw away alias information - Self::from_var_help(layouts, subs, *actual) - } - } - } - Content::RangedNumber(_) => todo!(), - Content::Error => Err(TypeError(())), - } - } - - fn from_lambda_set( - layouts: &mut Layouts, - subs: &Subs, - lset: subs::LambdaSet, - ) -> Result { - let subs::LambdaSet { - solved, - recursion_var, - unspecialized: _, - ambient_function: _, - } = lset; - - // TODO: handle unspecialized lambda set - - match recursion_var.into_variable() { - Some(rec_var) => { - let rec_var = subs.get_root_key_without_compacting(rec_var); - - let cached = layouts - .recursion_variable_to_structure_variable_map - .get(&rec_var); - - if let Some(layout_index) = cached { - match layouts.layouts[layout_index.index as usize] { - Layout::Reserved => { - // we have to do the work here to fill this reserved variable in - } - other => { - return Ok(other); - } - } - } - - let slices = Self::from_slice_variable_slice(layouts, subs, solved.variables())?; - - Ok(Layout::UnionRecursive(slices)) - } - None => { - let slices = Self::from_slice_variable_slice(layouts, subs, solved.variables())?; - - Ok(Layout::UnionNonRecursive(slices)) - } - } - } - - fn from_flat_type( - layouts: &mut Layouts, - subs: &Subs, - flat_type: &FlatType, - ) -> Result { - match flat_type { - FlatType::Apply(Symbol::LIST_LIST, arguments) => { - debug_assert_eq!(arguments.len(), 1); - - let element_var = subs.variables[arguments.start as usize]; - let element_layout = Self::from_var_help_or_void(layouts, subs, element_var)?; - - let element_index = Index::new(layouts.layouts.len() as _); - layouts.layouts.push(element_layout); - - Ok(Layout::List(element_index)) - } - - FlatType::Apply(Symbol::DICT_DICT, arguments) => { - debug_assert_eq!(arguments.len(), 2); - - let key_var = subs.variables[arguments.start as usize]; - let value_var = subs.variables[arguments.start as usize + 1]; - - let key_layout = Self::from_var_help_or_void(layouts, subs, key_var)?; - let value_layout = Self::from_var_help_or_void(layouts, subs, value_var)?; - - let index = Index::new(layouts.layouts.len() as _); - layouts.layouts.push(key_layout); - layouts.layouts.push(value_layout); - - Ok(Layout::Dict(index)) - } - - FlatType::Apply(Symbol::SET_SET, arguments) => { - debug_assert_eq!(arguments.len(), 1); - - let element_var = subs.variables[arguments.start as usize]; - let element_layout = Self::from_var_help_or_void(layouts, subs, element_var)?; - - let element_index = Index::new(layouts.layouts.len() as _); - layouts.layouts.push(element_layout); - - Ok(Layout::Set(element_index)) - } - - FlatType::Apply(symbol, _) => { - unreachable!("Symbol {:?} does not have a layout", symbol) - } - - FlatType::Func(_arguments, lambda_set, _result) => { - // in this case, a function (pointer) is represented by the environment it - // captures: the lambda set - - Self::from_var_help(layouts, subs, *lambda_set) - } - FlatType::Record(fields, ext) => { - debug_assert!(ext_var_is_empty_record(subs, *ext)); - - let mut slice = Slice::reserve(layouts, fields.len()); - - let mut non_optional_fields = 0; - let it = slice.indices().zip(fields.iter_all()); - for (target_index, (_, field_index, var_index)) in it { - match subs.record_fields[field_index.index as usize] { - RecordField::Optional(_) | RecordField::RigidOptional(_) => { - // do nothing - } - RecordField::Required(_) - | RecordField::Demanded(_) - | RecordField::RigidRequired(_) => { - let var = subs.variables[var_index.index as usize]; - let layout = Layout::from_var_help(layouts, subs, var)?; - - layouts.layouts[target_index] = layout; - - non_optional_fields += 1; - } - } - } - - // we have some wasted space in the case of optional fields; so be it - slice.length = non_optional_fields; - - layouts.sort_slice_by_alignment(slice); - - Ok(Layout::Struct(slice)) - } - FlatType::Tuple(_elems, _ext) => { - todo!(); - } - FlatType::TagUnion(union_tags, ext) => { - debug_assert!(ext_var_is_empty_tag_union(subs, *ext)); - - let slices = - Self::from_slice_variable_slice(layouts, subs, union_tags.variables())?; - - Ok(Layout::UnionNonRecursive(slices)) - } - - FlatType::FunctionOrTagUnion(_, _, ext) => { - debug_assert!(ext_var_is_empty_tag_union(subs, *ext)); - - // at this point we know this is a tag - Ok(Layout::UNIT) - } - FlatType::RecursiveTagUnion(rec_var, union_tags, ext) => { - debug_assert!(ext_var_is_empty_tag_union(subs, *ext)); - - let rec_var = subs.get_root_key_without_compacting(*rec_var); - - let cached = layouts - .recursion_variable_to_structure_variable_map - .get(&rec_var); - - if let Some(layout_index) = cached { - match layouts.layouts[layout_index.index as usize] { - Layout::Reserved => { - // we have to do the work here to fill this reserved variable in - } - other => { - return Ok(other); - } - } - } - - let slices = - Self::from_slice_variable_slice(layouts, subs, union_tags.variables())?; - - Ok(Layout::UnionRecursive(slices)) - } - FlatType::EmptyRecord | FlatType::EmptyTuple => Ok(Layout::UNIT), - FlatType::EmptyTagUnion => Ok(Layout::VOID), - } - } - - fn from_slice_variable_slice( - layouts: &mut Layouts, - subs: &Subs, - slice_variable_slice: roc_types::subs::SubsSlice, - ) -> Result>, LayoutError> { - let slice = Slice::reserve(layouts, slice_variable_slice.len()); - - let variable_slices = &subs.variable_slices[slice_variable_slice.indices()]; - let it = slice.indices().zip(variable_slices); - for (target_index, variable_slice) in it { - let layout_slice = Layout::from_variable_slice(layouts, subs, *variable_slice)?; - layouts.layout_slices[target_index] = layout_slice; - } - - Ok(slice) - } - - fn from_variable_slice( - layouts: &mut Layouts, - subs: &Subs, - variable_subs_slice: roc_types::subs::VariableSubsSlice, - ) -> Result, LayoutError> { - let slice = Slice::reserve(layouts, variable_subs_slice.len()); - - let variable_slice = &subs.variables[variable_subs_slice.indices()]; - let it = slice.indices().zip(variable_slice); - for (target_index, var) in it { - let layout = Layout::from_var_help(layouts, subs, *var)?; - layouts.layouts[target_index] = layout; - } - - layouts.sort_slice_by_alignment(slice); - - Ok(slice) - } -} diff --git a/crates/compiler/mono/src/lib.rs b/crates/compiler/mono/src/lib.rs index 1104473800f..0a0f96c22f1 100644 --- a/crates/compiler/mono/src/lib.rs +++ b/crates/compiler/mono/src/lib.rs @@ -15,7 +15,6 @@ pub mod drop_specialization; pub mod inc_dec; pub mod ir; pub mod layout; -pub mod layout_soa; pub mod low_level; pub mod reset_reuse; pub mod tail_recursion; diff --git a/crates/glue/src/types.rs b/crates/glue/src/types.rs index 1f7fde4239b..86d8bbacad8 100644 --- a/crates/glue/src/types.rs +++ b/crates/glue/src/types.rs @@ -2086,16 +2086,6 @@ fn tag_union_type_from_layout<'a>( } } LayoutRepr::Ptr(_) => unreachable!("Ptr values are never publicly exposed"), - LayoutRepr::Boxed(elem_layout) => { - let (tag_name, payload_fields) = - single_tag_payload_fields(env, union_tags, subs, layout, &[elem_layout], types); - - RocTagUnion::SingleTagStruct { - name: name.clone(), - tag_name, - payload: payload_fields, - } - } LayoutRepr::LambdaSet(lambda_set) => tag_union_type_from_layout( env, opt_name, diff --git a/crates/repl_eval/src/eval.rs b/crates/repl_eval/src/eval.rs index 1afadb66466..31d2f3b2d07 100644 --- a/crates/repl_eval/src/eval.rs +++ b/crates/repl_eval/src/eval.rs @@ -538,20 +538,6 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>( unreachable!("Ptr will never be visible to users") } LayoutRepr::LambdaSet(_) => OPAQUE_FUNCTION, - LayoutRepr::Boxed(_) => { - let size = env.layout_cache.interner.stack_size(layout); - - app.call_function_dynamic_size(main_fn_name, size as usize, |mem: &A::Memory, addr| { - addr_to_ast( - env, - mem, - addr, - env.layout_cache.get_repr(layout), - WhenRecursive::Unreachable, - env.subs.get_root_key_without_compacting(raw_var), - ) - }) - } }; apply_newtypes(env, newtype_containers.into_bump_slice(), expr) @@ -776,6 +762,34 @@ fn addr_to_ast<'a, M: ReplAppMemory>( when_recursive, ) } + ( + Content::Structure(FlatType::Apply(Symbol::BOX_BOX_TYPE, args)), + LayoutRepr::Union(UnionLayout::NonNullableUnwrapped([inner_layout])), + ) => { + debug_assert_eq!(args.len(), 1); + + let inner_var_index = args.into_iter().next().unwrap(); + let inner_var = env.subs[inner_var_index]; + + let addr_of_inner = mem.deref_usize(addr); + let inner_expr = addr_to_ast( + env, + mem, + addr_of_inner, + env.layout_cache.get_repr(*inner_layout), + WhenRecursive::Unreachable, + inner_var, + ); + + let box_box = env.arena.alloc(Loc::at_zero(Expr::Var { + module_name: "Box", + ident: "box", + })); + let box_box_arg = &*env.arena.alloc(Loc::at_zero(inner_expr)); + let box_box_args = env.arena.alloc([box_box_arg]); + + Expr::Apply(box_box, box_box_args, CalledVia::Space) + } (_, LayoutRepr::Union(UnionLayout::NonNullableUnwrapped(_))) => { let (rec_var, tags) = match unroll_recursion_var(env, raw_content) { Content::Structure(FlatType::RecursiveTagUnion(rec_var, tags, _)) => { @@ -890,37 +904,6 @@ fn addr_to_ast<'a, M: ReplAppMemory>( ) } } - ( - Content::Structure(FlatType::Apply(Symbol::BOX_BOX_TYPE, args)), - LayoutRepr::Boxed(inner_layout), - ) => { - debug_assert_eq!(args.len(), 1); - - let inner_var_index = args.into_iter().next().unwrap(); - let inner_var = env.subs[inner_var_index]; - - let addr_of_inner = mem.deref_usize(addr); - let inner_expr = addr_to_ast( - env, - mem, - addr_of_inner, - env.layout_cache.get_repr(inner_layout), - WhenRecursive::Unreachable, - inner_var, - ); - - let box_box = env.arena.alloc(Loc::at_zero(Expr::Var { - module_name: "Box", - ident: "box", - })); - let box_box_arg = &*env.arena.alloc(Loc::at_zero(inner_expr)); - let box_box_args = env.arena.alloc([box_box_arg]); - - Expr::Apply(box_box, box_box_args, CalledVia::Space) - } - (_, LayoutRepr::Boxed(_)) => { - unreachable!("Box layouts can only be behind a `Box.Box` application") - } (_, LayoutRepr::Ptr(_)) => { unreachable!("Ptr layouts are never available in user code") } From bb97c384bb68b8f26fe17ab5d0eb7cd88d7d1f09 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 9 Jul 2023 14:03:40 +0200 Subject: [PATCH 131/140] preserve semantics in the glue generation --- crates/compiler/mono/src/ir.rs | 12 +++++++----- .../test_mono/generated/capture_void_layout_task.txt | 4 ++-- .../generated/tail_call_with_different_layout.txt | 4 ++-- ...l_call_with_same_layout_different_lambda_sets.txt | 4 ++-- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index c2d799fbeb1..49e89196ac2 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -9985,8 +9985,9 @@ where I: LayoutInterner<'a>, { let interned_unboxed_struct_layout = layout_interner.insert(*unboxed_struct_layout); - let boxed_struct_layout = - Layout::no_semantic(LayoutRepr::Ptr(interned_unboxed_struct_layout).direct()); + let union_layout = + UnionLayout::NonNullableUnwrapped(arena.alloc([interned_unboxed_struct_layout])); + let boxed_struct_layout = Layout::no_semantic(LayoutRepr::Union(union_layout).direct()); let boxed_struct_layout = layout_interner.insert(boxed_struct_layout); let mut answer = bumpalo::collections::Vec::with_capacity_in(field_layouts.len(), arena); @@ -10026,7 +10027,7 @@ where let field_get_stmt = Stmt::Let(result, field_get_expr, *field, ret_stmt); - let unbox_expr = Expr::ptr_load(arena.alloc(argument)); + let unbox_expr = Expr::expr_unbox(argument, arena.alloc(interned_unboxed_struct_layout)); let unbox_stmt = Stmt::Let( unboxed, @@ -10097,7 +10098,8 @@ where I: LayoutInterner<'a>, { let interned = layout_interner.insert(*unboxed_struct_layout); - let boxed_struct_layout = Layout::no_semantic(LayoutRepr::Ptr(interned).direct()); + let box_union_layout = UnionLayout::NonNullableUnwrapped(arena.alloc([interned])); + let boxed_struct_layout = Layout::no_semantic(LayoutRepr::Union(box_union_layout).direct()); let boxed_struct_layout = layout_interner.insert(boxed_struct_layout); let mut answer = bumpalo::collections::Vec::with_capacity_in(field_layouts.len(), arena); @@ -10126,7 +10128,7 @@ where let field_get_stmt = Stmt::Let(result, field_get_expr, *field, ret_stmt); - let unbox_expr = Expr::ptr_load(arena.alloc(argument)); + let unbox_expr = Expr::expr_unbox(argument, arena.alloc(interned)); let unbox_stmt = Stmt::Let(unboxed, unbox_expr, interned, arena.alloc(field_get_stmt)); let proc = Proc { diff --git a/crates/compiler/test_mono/generated/capture_void_layout_task.txt b/crates/compiler/test_mono/generated/capture_void_layout_task.txt index 166b384497e..156638d67a3 100644 --- a/crates/compiler/test_mono/generated/capture_void_layout_task.txt +++ b/crates/compiler/test_mono/generated/capture_void_layout_task.txt @@ -144,13 +144,13 @@ procedure Test.6 (Test.27, Test.28): ret Test.37; procedure Test.76 (Test.77): - let Test.78 : {{}, []} = Unbox Test.77; + let Test.78 : {{}, []} = UnionAtIndex (Id 0) (Index 0) Test.77; dec Test.77; let Test.79 : {} = StructAtIndex 0 Test.78; ret Test.79; procedure Test.80 (Test.81): - let Test.82 : {{}, []} = Unbox Test.81; + let Test.82 : {{}, []} = UnionAtIndex (Id 0) (Index 0) Test.81; dec Test.81; let Test.83 : [] = StructAtIndex 1 Test.82; ret Test.83; diff --git a/crates/compiler/test_mono/generated/tail_call_with_different_layout.txt b/crates/compiler/test_mono/generated/tail_call_with_different_layout.txt index f1a49ed0713..07005ec6d69 100644 --- a/crates/compiler/test_mono/generated/tail_call_with_different_layout.txt +++ b/crates/compiler/test_mono/generated/tail_call_with_different_layout.txt @@ -7,13 +7,13 @@ procedure Test.1 (Test.2, Test.3): ret Test.21; procedure Test.30 (Test.31): - let Test.32 : {U8, {}} = Unbox Test.31; + let Test.32 : {U8, {}} = UnionAtIndex (Id 0) (Index 0) Test.31; dec Test.31; let Test.33 : U8 = StructAtIndex 0 Test.32; ret Test.33; procedure Test.34 (Test.35): - let Test.36 : {U8, {}} = Unbox Test.35; + let Test.36 : {U8, {}} = UnionAtIndex (Id 0) (Index 0) Test.35; dec Test.35; let Test.37 : {} = StructAtIndex 1 Test.36; ret Test.37; diff --git a/crates/compiler/test_mono/generated/tail_call_with_same_layout_different_lambda_sets.txt b/crates/compiler/test_mono/generated/tail_call_with_same_layout_different_lambda_sets.txt index af7ef46c476..1c87417bc35 100644 --- a/crates/compiler/test_mono/generated/tail_call_with_same_layout_different_lambda_sets.txt +++ b/crates/compiler/test_mono/generated/tail_call_with_same_layout_different_lambda_sets.txt @@ -7,13 +7,13 @@ procedure Test.1 (Test.2, Test.3): ret Test.21; procedure Test.30 (Test.31): - let Test.32 : {U8, {}} = Unbox Test.31; + let Test.32 : {U8, {}} = UnionAtIndex (Id 0) (Index 0) Test.31; dec Test.31; let Test.33 : U8 = StructAtIndex 0 Test.32; ret Test.33; procedure Test.34 (Test.35): - let Test.36 : {U8, {}} = Unbox Test.35; + let Test.36 : {U8, {}} = UnionAtIndex (Id 0) (Index 0) Test.35; dec Test.35; let Test.37 : {} = StructAtIndex 1 Test.36; ret Test.37; From 6a19009acf88a062bf08e400663f55b45d80a35f Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 9 Jul 2023 15:41:41 +0200 Subject: [PATCH 132/140] 32-bit float mov instruction --- .../compiler/gen_dev/src/generic64/aarch64.rs | 4 ++ crates/compiler/gen_dev/src/generic64/mod.rs | 1 + .../compiler/gen_dev/src/generic64/storage.rs | 6 ++- .../compiler/gen_dev/src/generic64/x86_64.rs | 41 +++++++++++++++++++ 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/crates/compiler/gen_dev/src/generic64/aarch64.rs b/crates/compiler/gen_dev/src/generic64/aarch64.rs index 6f06abf6611..24e09234adb 100644 --- a/crates/compiler/gen_dev/src/generic64/aarch64.rs +++ b/crates/compiler/gen_dev/src/generic64/aarch64.rs @@ -832,6 +832,10 @@ impl Assembler for AArch64Assembler { todo!("saving floating point reg to base offset for AArch64"); } #[inline(always)] + fn mov_base32_freg32(_buf: &mut Vec<'_, u8>, _offset: i32, _src: AArch64FloatReg) { + todo!("saving floating point reg to base offset for AArch64"); + } + #[inline(always)] fn movesd_mem64_offset32_freg64( _buf: &mut Vec<'_, u8>, _ptr: AArch64GeneralReg, diff --git a/crates/compiler/gen_dev/src/generic64/mod.rs b/crates/compiler/gen_dev/src/generic64/mod.rs index 68d850b63c2..32261887609 100644 --- a/crates/compiler/gen_dev/src/generic64/mod.rs +++ b/crates/compiler/gen_dev/src/generic64/mod.rs @@ -321,6 +321,7 @@ pub trait Assembler: Sized + Copy { fn mov_reg8_base32(buf: &mut Vec<'_, u8>, dst: GeneralReg, offset: i32); fn mov_base32_freg64(buf: &mut Vec<'_, u8>, offset: i32, src: FloatReg); + fn mov_base32_freg32(buf: &mut Vec<'_, u8>, offset: i32, src: FloatReg); fn mov_base32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg); fn mov_base32_reg32(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg); diff --git a/crates/compiler/gen_dev/src/generic64/storage.rs b/crates/compiler/gen_dev/src/generic64/storage.rs index 318f9dc0f65..6c053a1e33d 100644 --- a/crates/compiler/gen_dev/src/generic64/storage.rs +++ b/crates/compiler/gen_dev/src/generic64/storage.rs @@ -783,7 +783,11 @@ impl< let reg = self.load_to_float_reg(buf, sym); ASM::mov_base32_freg64(buf, to_offset, reg); } - FloatWidth::F32 => todo!(), + FloatWidth::F32 => { + debug_assert_eq!(to_offset % 4, 0); + let reg = self.load_to_float_reg(buf, sym); + ASM::mov_base32_freg64(buf, to_offset, reg); + } }, Builtin::Bool => { // same as 8-bit integer, but we special-case true/false because these symbols diff --git a/crates/compiler/gen_dev/src/generic64/x86_64.rs b/crates/compiler/gen_dev/src/generic64/x86_64.rs index efeb6d8cce5..32299672035 100644 --- a/crates/compiler/gen_dev/src/generic64/x86_64.rs +++ b/crates/compiler/gen_dev/src/generic64/x86_64.rs @@ -1584,6 +1584,11 @@ impl Assembler for X86_64Assembler { movsd_base64_offset32_freg64(buf, X86_64GeneralReg::RBP, offset, src) } + #[inline(always)] + fn mov_base32_freg32(buf: &mut Vec<'_, u8>, offset: i32, src: X86_64FloatReg) { + movss_base32_offset32_freg32(buf, X86_64GeneralReg::RBP, offset, src) + } + #[inline(always)] fn movesd_mem64_offset32_freg64( buf: &mut Vec<'_, u8>, @@ -3180,6 +3185,31 @@ fn movsd_base64_offset32_freg64( buf.extend(offset.to_le_bytes()); } +// `MOVSS r/m64,xmm1` -> Move xmm1 to r/m64. where m64 references the base pointer. +#[inline(always)] +fn movss_base32_offset32_freg32( + buf: &mut Vec<'_, u8>, + base: X86_64GeneralReg, + offset: i32, + src: X86_64FloatReg, +) { + let rex = add_rm_extension(base, REX_W); + let rex = add_reg_extension(src, rex); + let src_mod = (src as u8 % 8) << 3; + let base_mod = base as u8 % 8; + buf.reserve(10); + buf.push(0xF3); + if src as u8 > 7 || base as u8 > 7 { + buf.push(rex); + } + buf.extend([0x0F, 0x11, 0x80 | src_mod | base_mod]); + // Using RSP or R12 requires a secondary index byte. + if base == X86_64GeneralReg::RSP || base == X86_64GeneralReg::R12 { + buf.push(0x24); + } + buf.extend(offset.to_le_bytes()); +} + /// `MOVSD xmm1,r/m64` -> Move r/m64 to xmm1. where m64 references the base pointer. #[inline(always)] fn movsd_freg64_base64_offset32( @@ -3966,6 +3996,17 @@ mod tests { ); } + #[test] + fn test_movss_base64_offset32_freg64() { + disassembler_test!( + movss_base32_offset32_freg32, + |reg1, imm, reg2| format!("movss dword ptr [{} + 0x{:x}], {}", reg1, imm, reg2), + ALL_GENERAL_REGS, + [TEST_I32], + ALL_FLOAT_REGS + ); + } + #[test] fn test_mov_reg64_base64_offset32() { disassembler_test!( From 5bc75b7a03ff90c5f2d16ddf697f4716856a1a5c Mon Sep 17 00:00:00 2001 From: Folkert Date: Mon, 10 Jul 2023 12:11:54 +0200 Subject: [PATCH 133/140] clarify comments in tests --- crates/wasm_interp/src/tests/test_mem.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/crates/wasm_interp/src/tests/test_mem.rs b/crates/wasm_interp/src/tests/test_mem.rs index 09f54d8e544..9d24e0df0d1 100644 --- a/crates/wasm_interp/src/tests/test_mem.rs +++ b/crates/wasm_interp/src/tests/test_mem.rs @@ -72,13 +72,14 @@ fn test_memory_fill() { state.value_store.push(Value::I32(SIZE)); // before the instruction, the memory is all zeros - let slice = &state.memory[destination as usize..][..SIZE as usize]; - assert_eq!(slice, &[0; SIZE as usize]); + let memory_before = &state.memory[destination as usize..][..SIZE as usize]; + assert_eq!(memory_before, &[0; SIZE as usize]); state.execute_next_instruction(&module).unwrap(); - let slice = &state.memory[destination as usize..][..SIZE as usize]; - assert_eq!(slice, &[byte_value as u8; SIZE as usize]) + // after the fill, the same memory range is now all 0xAA bytes + let memory_after = &state.memory[destination as usize..][..SIZE as usize]; + assert_eq!(memory_after, &[byte_value as u8; SIZE as usize]) } #[test] @@ -103,16 +104,19 @@ fn test_memory_copy() { state.value_store.push(Value::I32(source)); state.value_store.push(Value::I32(SIZE)); - // before the instruction, the memory is all zeros - let slice = &mut state.memory[source as usize..][..SIZE as usize]; - assert_eq!(slice, &[0; SIZE as usize]); + // fill the source slice with 0xAA bytes + let source_slice = &mut state.memory[source as usize..][..SIZE as usize]; + source_slice.fill(0xAA); - slice.fill(0xAA); + // before the copy, the destination slice is all 0x00 bytes + let dest_slice = &state.memory[destination as usize..][..SIZE as usize]; + assert_eq!(dest_slice, &[0x00; SIZE as usize]); state.execute_next_instruction(&module).unwrap(); - let slice = &state.memory[destination as usize..][..SIZE as usize]; - assert_eq!(slice, &[0xAA; SIZE as usize]) + // after the copy, the destination slice is all 0xAA bytes + let dest_slice = &state.memory[destination as usize..][..SIZE as usize]; + assert_eq!(dest_slice, &[0xAA; SIZE as usize]) } fn test_load(load_op: OpCode, ty: ValueType, data: &[u8], addr: u32, offset: u32) -> Value { From fbbfba65d71e325c4d083c3a677515c556eff577 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Mon, 10 Jul 2023 13:59:19 +0200 Subject: [PATCH 134/140] fix basic-cli docs index.html Signed-off-by: Anton-4 <17049058+Anton-4@users.noreply.github.com> --- www/build.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/www/build.sh b/www/build.sh index d544710e7e5..499ee39f2c4 100755 --- a/www/build.sh +++ b/www/build.sh @@ -115,11 +115,12 @@ rm -rf ./downloaded-basic-cli BASIC_CLI_PACKAGE_DIR="www/build/packages/basic-cli" mkdir -p $BASIC_CLI_PACKAGE_DIR -rm generated-docs/*.* # we already copied over the *.js and *.css files earlier, so just drop these. +mv generated-docs/index.html $BASIC_CLI_PACKAGE_DIR +rm generated-docs/*.* # we already copied over the *.js and *.css files earlier for the builtins, so just drop these. mv generated-docs/* $BASIC_CLI_PACKAGE_DIR # move all the folders to build/packages/basic-cli # set up docs for basic-cli 0.3.2 -BASIC_CLI_DIR_0_3_2=$BASIC_CLI_PACKAGE_DIR/0-3-2 +BASIC_CLI_DIR_0_3_2=$BASIC_CLI_PACKAGE_DIR/0.3.2 mkdir -p $BASIC_CLI_DIR_0_3_2 curl -fL --output $BASIC_CLI_DIR_0_3_2/docs.tar.gz https://github.com/roc-lang/basic-cli/releases/download/0.3.2/docs.tar.gz tar -xf $BASIC_CLI_DIR_0_3_2/docs.tar.gz -C $BASIC_CLI_DIR_0_3_2/ From 72c85efc832d82a7784dce1036920a3e51707cdd Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Sat, 29 Apr 2023 19:56:44 +0200 Subject: [PATCH 135/140] switch to rust 1.67 --- .github/workflows/windows_release_build.yml | 4 ++-- .github/workflows/windows_tests.yml | 4 ++-- crates/compiler/build/src/link.rs | 2 +- crates/compiler/mono/src/ir.rs | 4 ++-- devtools/flake.lock | 4 ++-- examples/platform-switching/rust-platform/rust-toolchain.toml | 2 +- rust-toolchain.toml | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/windows_release_build.yml b/.github/workflows/windows_release_build.yml index 86cca232e1f..a889900b0cf 100644 --- a/.github/workflows/windows_release_build.yml +++ b/.github/workflows/windows_release_build.yml @@ -32,8 +32,8 @@ jobs: - name: zig version run: zig version - - name: install rust nightly 1.66 - run: rustup install nightly-2022-10-30 + - name: install rust nightly 1.67 + run: rustup install nightly-2022-12-09 - name: set up llvm 13 run: | diff --git a/.github/workflows/windows_tests.yml b/.github/workflows/windows_tests.yml index 9ccf82d3ea7..2fe095b711b 100644 --- a/.github/workflows/windows_tests.yml +++ b/.github/workflows/windows_tests.yml @@ -36,8 +36,8 @@ jobs: - name: zig version run: zig version - - name: install rust nightly 1.66 - run: rustup install nightly-2022-10-30 + - name: install rust nightly 1.67 + run: rustup install nightly-2022-12-09 - name: set up llvm 13 run: | diff --git a/crates/compiler/build/src/link.rs b/crates/compiler/build/src/link.rs index a48e57c1732..575f88b4087 100644 --- a/crates/compiler/build/src/link.rs +++ b/crates/compiler/build/src/link.rs @@ -530,7 +530,7 @@ pub fn rebuild_host( // on windows, we need the nightly toolchain so we can use `-Z export-executable-symbols` // using `+nightly` only works when running cargo through rustup let mut cmd = rustup(); - cmd.args(["run", "nightly-2022-10-30", "cargo"]); + cmd.args(["run", "nightly-2022-12-09", "cargo"]); cmd } else { diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index 49e89196ac2..45686fae6c5 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -74,8 +74,8 @@ roc_error_macros::assert_sizeof_wasm!(Call, 44); roc_error_macros::assert_sizeof_wasm!(CallType, 36); roc_error_macros::assert_sizeof_non_wasm!(Literal, 3 * 8); -roc_error_macros::assert_sizeof_non_wasm!(Expr, 9 * 8); -roc_error_macros::assert_sizeof_non_wasm!(Stmt, 12 * 8); +roc_error_macros::assert_sizeof_non_wasm!(Expr, 10 * 8); +roc_error_macros::assert_sizeof_non_wasm!(Stmt, 13 * 8); roc_error_macros::assert_sizeof_non_wasm!(ProcLayout, 5 * 8); roc_error_macros::assert_sizeof_non_wasm!(Call, 9 * 8); roc_error_macros::assert_sizeof_non_wasm!(CallType, 7 * 8); diff --git a/devtools/flake.lock b/devtools/flake.lock index dd655bc0b49..beb73d08082 100644 --- a/devtools/flake.lock +++ b/devtools/flake.lock @@ -115,8 +115,8 @@ "rust-overlay": "rust-overlay" }, "locked": { - "lastModified": 1682761608, - "narHash": "sha256-+6tHbEK8GYDSCLasgawufSLegyJ0cqHV2nfmJICwzrk=", + "lastModified": 1682784625, + "narHash": "sha256-QUncKiwgpmHajo601NNHOjeUG2/vrGp1oMgxnPhq900=", "path": "/home/username/gitrepos/roc9/roc", "type": "path" }, diff --git a/examples/platform-switching/rust-platform/rust-toolchain.toml b/examples/platform-switching/rust-platform/rust-toolchain.toml index bfaab275a2a..9e80c038294 100644 --- a/examples/platform-switching/rust-platform/rust-toolchain.toml +++ b/examples/platform-switching/rust-platform/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "1.66.1" +channel = "1.67.1" profile = "default" diff --git a/rust-toolchain.toml b/rust-toolchain.toml index fd2c2a81d47..8a17faa5c3a 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -9,9 +9,9 @@ # - update nightly-OLD_DATE in .github/workflows/windows_release_build.yml # - update nightly-OLD_DATE in crates/compiler/build/src/link.rs -channel = "1.66.1" # check ^^^ when changing this +channel = "1.67.1" # check ^^^ when changing this # -# channel = "nightly-2022-10-30" # 1.66.0 nightly to be able to use unstable features +# channel = "nightly-2022-12-09" # 1.67.0 nightly to be able to use unstable features profile = "default" components = [ # for usages of rust-analyzer or similar tools inside `nix develop` From ef39bad7c61983f2329a11d2d23f7d038215c9d7 Mon Sep 17 00:00:00 2001 From: Folkert Date: Mon, 26 Jun 2023 20:42:50 +0200 Subject: [PATCH 136/140] auto clippy fixes --- crates/ast/src/ast_error.rs | 4 +- crates/ast/src/builtin_aliases.rs | 3 +- crates/ast/src/constrain.rs | 2 +- .../ast/src/lang/core/expr/expr2_to_string.rs | 4 +- .../ast/src/lang/core/expr/expr_to_expr2.rs | 16 +-- crates/ast/src/lang/core/str.rs | 2 +- crates/ast/src/lang/env.rs | 3 +- crates/ast/src/module.rs | 10 +- crates/cli/src/format.rs | 6 +- crates/cli/src/lib.rs | 20 ++-- crates/cli/src/main.rs | 6 +- crates/cli/tests/cli_run.rs | 22 ++-- crates/cli/tests/editor.rs | 2 +- crates/cli_utils/src/bench_utils.rs | 10 +- crates/cli_utils/src/helpers.rs | 6 +- crates/code_markup/src/markup/nodes.rs | 4 +- crates/code_markup/src/markup_error.rs | 2 +- crates/code_markup/src/slow_pool.rs | 6 +- crates/compiler/alias_analysis/src/lib.rs | 4 +- crates/compiler/build/src/link.rs | 14 +-- crates/compiler/build/src/program.rs | 34 +++--- crates/compiler/builtins/bitcode/bc/build.rs | 6 +- crates/compiler/builtins/bitcode/build.rs | 6 +- crates/compiler/can/src/abilities.rs | 3 +- crates/compiler/can/src/constraint.rs | 28 ++--- crates/compiler/can/src/copy.rs | 18 +-- crates/compiler/can/src/def.rs | 5 +- crates/compiler/can/src/derive.rs | 10 +- crates/compiler/can/src/effect_module.rs | 10 +- crates/compiler/can/src/env.rs | 3 +- crates/compiler/can/src/module.rs | 4 +- crates/compiler/can/src/num.rs | 3 +- crates/compiler/can/src/pattern.rs | 2 +- crates/compiler/can/tests/helpers/mod.rs | 3 +- crates/compiler/can/tests/test_can.rs | 2 +- crates/compiler/collections/src/all.rs | 2 +- .../collections/src/small_string_interner.rs | 6 +- crates/compiler/constrain/src/expr.rs | 3 +- crates/compiler/derive/src/hash.rs | 2 +- crates/compiler/derive/src/util.rs | 4 +- .../compiler/gen_dev/src/generic64/aarch64.rs | 2 +- .../compiler/gen_dev/src/generic64/x86_64.rs | 86 +++++++-------- crates/compiler/gen_dev/src/lib.rs | 2 +- crates/compiler/gen_dev/src/object_builder.rs | 2 +- crates/compiler/gen_llvm/src/llvm/bitcode.rs | 15 +-- crates/compiler/gen_llvm/src/llvm/build.rs | 65 +++++------ crates/compiler/gen_llvm/src/llvm/compare.rs | 5 +- crates/compiler/gen_llvm/src/llvm/lowlevel.rs | 2 +- .../compiler/gen_llvm/src/llvm/refcounting.rs | 4 +- crates/compiler/gen_llvm/src/llvm/scope.rs | 7 +- crates/compiler/gen_llvm/src/llvm/struct_.rs | 2 +- crates/compiler/gen_wasm/src/backend.rs | 8 +- crates/compiler/gen_wasm/src/code_builder.rs | 25 ++--- crates/compiler/gen_wasm/src/low_level.rs | 5 +- crates/compiler/late_solve/src/lib.rs | 2 +- crates/compiler/load_internal/src/file.rs | 46 +++----- crates/compiler/load_internal/src/work.rs | 9 +- .../compiler/load_internal/tests/test_load.rs | 23 ++-- crates/compiler/module/src/symbol.rs | 22 ++-- .../mono/src/code_gen_help/equality.rs | 16 +-- crates/compiler/mono/src/code_gen_help/mod.rs | 2 +- .../mono/src/code_gen_help/refcount.rs | 10 +- crates/compiler/mono/src/debug/report.rs | 2 +- .../compiler/mono/src/drop_specialization.rs | 12 +- crates/compiler/mono/src/ir.rs | 103 +++++++----------- crates/compiler/mono/src/ir/decision_tree.rs | 3 +- crates/compiler/mono/src/layout.rs | 26 ++--- crates/compiler/parse/src/ast.rs | 4 +- crates/compiler/parse/src/state.rs | 4 +- crates/compiler/parse/tests/test_parse.rs | 12 +- crates/compiler/problem/src/can.rs | 5 +- crates/compiler/region/src/all.rs | 5 +- crates/compiler/solve/src/ability.rs | 3 +- crates/compiler/solve/src/pools.rs | 4 +- crates/compiler/solve/src/solve.rs | 5 +- crates/compiler/solve/src/specialize.rs | 22 ++-- crates/compiler/solve/tests/solve_expr.rs | 13 +-- crates/compiler/test_derive/src/util.rs | 7 +- crates/compiler/test_gen/benches/list_map.rs | 2 +- crates/compiler/test_gen/benches/quicksort.rs | 2 +- crates/compiler/test_gen/build.rs | 14 +-- crates/compiler/test_gen/src/gen_list.rs | 6 +- crates/compiler/test_gen/src/helpers/llvm.rs | 26 ++--- crates/compiler/test_gen/src/helpers/mod.rs | 2 +- crates/compiler/test_mono/src/tests.rs | 6 +- .../compiler/test_syntax/src/test_helpers.rs | 10 +- crates/compiler/test_syntax/tests/test_fmt.rs | 16 +-- .../test_syntax/tests/test_snapshots.rs | 28 ++--- crates/compiler/types/src/pretty_print.rs | 2 +- crates/compiler/types/src/subs.rs | 54 ++++----- crates/compiler/types/src/types.rs | 70 ++++++------ crates/compiler/uitest/src/mono.rs | 8 +- crates/compiler/uitest/src/uitest.rs | 2 +- crates/compiler/unify/src/unify.rs | 3 +- crates/docs/src/lib.rs | 22 ++-- crates/editor/src/editor/code_lines.rs | 4 +- crates/editor/src/editor/ed_error.rs | 10 +- crates/editor/src/editor/grid_node_map.rs | 4 +- crates/editor/src/editor/main.rs | 29 ++--- crates/editor/src/editor/mvc/ed_model.rs | 13 +-- crates/editor/src/editor/mvc/int_update.rs | 2 +- crates/editor/src/editor/util.rs | 10 +- crates/editor/src/ui/text/big_text_area.rs | 2 +- crates/editor/src/ui/text/text_buffer.rs | 2 +- crates/editor/src/ui/ui_error.rs | 2 +- crates/glue/src/load.rs | 4 +- crates/glue/src/rust_glue.rs | 17 ++- crates/glue/src/types.rs | 12 +- crates/glue/tests/test_glue_cli.rs | 4 +- crates/highlight/src/lib.rs | 4 +- crates/linker/src/elf.rs | 84 ++++++-------- crates/linker/src/generate_dylib/macho.rs | 6 +- crates/linker/src/lib.rs | 28 ++--- crates/linker/src/macho.rs | 53 ++++----- crates/linker/src/pe.rs | 7 +- crates/repl_cli/src/cli_gen.rs | 2 +- crates/repl_cli/src/lib.rs | 6 +- crates/repl_eval/src/eval.rs | 2 +- crates/repl_expect/src/lib.rs | 2 +- crates/repl_expect/src/run.rs | 6 +- crates/repl_test/src/cli.rs | 8 +- crates/repl_wasm/build.rs | 10 +- crates/repl_wasm/src/repl.rs | 4 +- crates/reporting/src/cli.rs | 4 +- crates/reporting/src/error/canonicalize.rs | 2 +- crates/reporting/src/error/expect.rs | 4 +- crates/reporting/src/error/type.rs | 19 ++-- crates/reporting/src/report.rs | 4 +- crates/reporting/tests/test_reporting.rs | 10 +- crates/roc_std/tests/test_roc_std.rs | 10 +- crates/utils/command/src/lib.rs | 5 +- crates/utils/error/src/lib.rs | 10 +- crates/valgrind/src/lib.rs | 10 +- crates/vendor/morphic_lib/src/preprocess.rs | 16 +-- .../vendor/morphic_lib/src/render_api_ir.rs | 11 +- crates/wasi-libc-sys/build.rs | 2 +- crates/wasm_interp/src/instance.rs | 65 +++++------ crates/wasm_interp/src/lib.rs | 16 +-- crates/wasm_interp/src/main.rs | 8 +- crates/wasm_interp/src/tests/mod.rs | 2 +- crates/wasm_interp/src/tests/test_basics.rs | 8 +- crates/wasm_interp/src/value_store.rs | 2 +- crates/wasm_interp/src/wasi.rs | 7 +- crates/wasm_module/src/lib.rs | 5 +- crates/wasm_module/src/linking.rs | 21 ++-- crates/wasm_module/src/sections.rs | 14 +-- 146 files changed, 750 insertions(+), 1005 deletions(-) diff --git a/crates/ast/src/ast_error.rs b/crates/ast/src/ast_error.rs index c733ca0ca50..dd7dfe19a91 100644 --- a/crates/ast/src/ast_error.rs +++ b/crates/ast/src/ast_error.rs @@ -59,7 +59,7 @@ impl From for ASTError { impl From<(Region, Loc)> for ASTError { fn from(ident_exists_err: (Region, Loc)) -> Self { Self::IdentExistsError { - msg: format!("{:?}", ident_exists_err), + msg: format!("{ident_exists_err:?}"), } } } @@ -67,7 +67,7 @@ impl From<(Region, Loc)> for ASTError { impl<'a> From> for ASTError { fn from(syntax_err: SyntaxError) -> Self { Self::SyntaxErrorNoBacktrace { - msg: format!("{:?}", syntax_err), + msg: format!("{syntax_err:?}"), } } } diff --git a/crates/ast/src/builtin_aliases.rs b/crates/ast/src/builtin_aliases.rs index ebb95d304c3..1d70b867f8d 100644 --- a/crates/ast/src/builtin_aliases.rs +++ b/crates/ast/src/builtin_aliases.rs @@ -94,8 +94,7 @@ pub fn aliases() -> MutMap { let mut add_alias = |symbol, alias| { debug_assert!( !aliases.contains_key(&symbol), - "Duplicate alias definition for {:?}", - symbol + "Duplicate alias definition for {symbol:?}" ); // TODO instead of using Region::zero for all of these, diff --git a/crates/ast/src/constrain.rs b/crates/ast/src/constrain.rs index ae2ad75b9c4..c7467723bbc 100644 --- a/crates/ast/src/constrain.rs +++ b/crates/ast/src/constrain.rs @@ -2065,7 +2065,7 @@ pub mod test_constrain { assert_eq!(actual_str, expected_str); } - Err(e) => panic!("syntax error {:?}", e), + Err(e) => panic!("syntax error {e:?}"), } } diff --git a/crates/ast/src/lang/core/expr/expr2_to_string.rs b/crates/ast/src/lang/core/expr/expr2_to_string.rs index 2162ccc299f..cb94e8af716 100644 --- a/crates/ast/src/lang/core/expr/expr2_to_string.rs +++ b/crates/ast/src/lang/core/expr/expr2_to_string.rs @@ -130,7 +130,7 @@ fn expr2_to_string_helper( ); } Expr2::Call { .. } => { - let _ = write!(out_string, "Call({:?})", expr2); + let _ = write!(out_string, "Call({expr2:?})"); } Expr2::Closure { args, .. } => { out_string.push_str("Closure:\n"); @@ -148,7 +148,7 @@ fn expr2_to_string_helper( } } &Expr2::Var { .. } => { - let _ = write!(out_string, "{:?}", expr2); + let _ = write!(out_string, "{expr2:?}"); } Expr2::RuntimeError { .. } => { out_string.push_str("RuntimeError\n"); diff --git a/crates/ast/src/lang/core/expr/expr_to_expr2.rs b/crates/ast/src/lang/core/expr/expr_to_expr2.rs index c76375d478c..b494abfc7e4 100644 --- a/crates/ast/src/lang/core/expr/expr_to_expr2.rs +++ b/crates/ast/src/lang/core/expr/expr_to_expr2.rs @@ -671,27 +671,19 @@ pub fn expr_to_expr2<'a>( // operator desugaring should have removed them! bad_expr @ SpaceBefore(_, _) => { panic!( - "A SpaceBefore did not get removed during operator desugaring somehow: {:#?}", - bad_expr + "A SpaceBefore did not get removed during operator desugaring somehow: {bad_expr:#?}" ); } bad_expr @ SpaceAfter(_, _) => { panic!( - "A SpaceAfter did not get removed during operator desugaring somehow: {:#?}", - bad_expr + "A SpaceAfter did not get removed during operator desugaring somehow: {bad_expr:#?}" ); } bad_expr @ BinOps { .. } => { - panic!( - "A binary operator chain did not get desugared somehow: {:#?}", - bad_expr - ); + panic!("A binary operator chain did not get desugared somehow: {bad_expr:#?}"); } bad_expr @ UnaryOp(_, _) => { - panic!( - "A unary operator did not get desugared somehow: {:#?}", - bad_expr - ); + panic!("A unary operator did not get desugared somehow: {bad_expr:#?}"); } rest => todo!("not yet implemented {:?}", rest), diff --git a/crates/ast/src/lang/core/str.rs b/crates/ast/src/lang/core/str.rs index 9d5bb3e3d1e..c5e53b06910 100644 --- a/crates/ast/src/lang/core/str.rs +++ b/crates/ast/src/lang/core/str.rs @@ -227,7 +227,7 @@ pub fn update_str_expr( Expr2::Str(old_pool_str) => Either::OldPoolStr(*old_pool_str), other => UnexpectedASTNodeSnafu { required_node_type: "SmallStr or Str", - encountered_node_type: format!("{:?}", other), + encountered_node_type: format!("{other:?}"), } .fail()?, }; diff --git a/crates/ast/src/lang/env.rs b/crates/ast/src/lang/env.rs index c86b212c9af..8a40df3a7ee 100644 --- a/crates/ast/src/lang/env.rs +++ b/crates/ast/src/lang/env.rs @@ -102,8 +102,7 @@ impl<'a> Env<'a> { ) -> Result { debug_assert!( !module_name.is_empty(), - "Called env.qualified_lookup with an unqualified ident: {:?}", - ident + "Called env.qualified_lookup with an unqualified ident: {ident:?}" ); let module_name: ModuleName = module_name.into(); diff --git a/crates/ast/src/module.rs b/crates/ast/src/module.rs index 61352cd1eac..f88649ad7de 100644 --- a/crates/ast/src/module.rs +++ b/crates/ast/src/module.rs @@ -25,14 +25,8 @@ pub fn load_module( match loaded { Ok(x) => x, Err(roc_load::LoadingProblem::FormattedReport(report)) => { - panic!( - "Failed to load module from src_file: {:?}. Report: {}", - src_file, report - ); + panic!("Failed to load module from src_file: {src_file:?}. Report: {report}"); } - Err(e) => panic!( - "Failed to load module from src_file {:?}: {:?}", - src_file, e - ), + Err(e) => panic!("Failed to load module from src_file {src_file:?}: {e:?}"), } } diff --git a/crates/cli/src/format.rs b/crates/cli/src/format.rs index 7200109d618..6c62ef65846 100644 --- a/crates/cli/src/format.rs +++ b/crates/cli/src/format.rs @@ -93,18 +93,18 @@ pub fn format(files: std::vec::Vec, mode: FormatMode) -> Result<(), Str // the PartialEq implementation is returning `false` even when the Debug-formatted impl is exactly the same. // I don't have the patience to debug this right now, so let's leave it for another day... // TODO: fix PartialEq impl on ast types - if format!("{:?}", ast_normalized) != format!("{:?}", reparsed_ast_normalized) { + if format!("{ast_normalized:?}") != format!("{reparsed_ast_normalized:?}") { let mut fail_file = file.clone(); fail_file.set_extension("roc-format-failed"); std::fs::write(&fail_file, buf.as_str()).unwrap(); let mut before_file = file.clone(); before_file.set_extension("roc-format-failed-ast-before"); - std::fs::write(&before_file, format!("{:#?}\n", ast_normalized)).unwrap(); + std::fs::write(&before_file, format!("{ast_normalized:#?}\n")).unwrap(); let mut after_file = file.clone(); after_file.set_extension("roc-format-failed-ast-after"); - std::fs::write(&after_file, format!("{:#?}\n", reparsed_ast_normalized)).unwrap(); + std::fs::write(&after_file, format!("{reparsed_ast_normalized:#?}\n")).unwrap(); internal_error!( "Formatting bug; formatting didn't reparse as the same tree\n\n\ diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index 5fc5f88108a..e8ffb52f6fe 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -416,12 +416,10 @@ pub fn test(matches: &ArgMatches, triple: Triple) -> io::Result { match matches.value_source(ROC_FILE) { Some(ValueSource::DefaultValue) => { eprintln!( - "\nThe current directory ({}) does not contain a {} file to use as a default.\n\nYou can run `roc help` for more information on how to provide a .roc file.\n", - current_dir_string, - DEFAULT_ROC_FILENAME + "\nThe current directory ({current_dir_string}) does not contain a {DEFAULT_ROC_FILENAME} file to use as a default.\n\nYou can run `roc help` for more information on how to provide a .roc file.\n" ) } - _ => eprintln!("\nThis file was not found: {}\n\nYou can run `roc help` for more information on how to provide a .roc file.\n", expected_file_path_string), + _ => eprintln!("\nThis file was not found: {expected_file_path_string}\n\nYou can run `roc help` for more information on how to provide a .roc file.\n"), } process::exit(1); @@ -565,16 +563,13 @@ pub fn build( match matches.value_source(ROC_FILE) { Some(ValueSource::DefaultValue) => { eprintln!( - "\nThe current directory ({}) does not contain a {} file to use as a default.\n\nYou can run `roc help` for more information on how to provide a .roc file.\n", - current_dir_string, - DEFAULT_ROC_FILENAME + "\nThe current directory ({current_dir_string}) does not contain a {DEFAULT_ROC_FILENAME} file to use as a default.\n\nYou can run `roc help` for more information on how to provide a .roc file.\n" ) } _ => { let mut error_lines = Vec::new(); error_lines.push(format!( - "This file was not found: {}", - expected_file_path_string + "This file was not found: {expected_file_path_string}" )); // Add some additional hints if run as `roc [FILENAME]`. if matches.subcommand().is_none() { @@ -584,8 +579,7 @@ pub fn build( nearest_match(possible_typo, subcommands) { error_lines.push(format!( - "Did you mean to use the {} subcommand?", - nearest_command + "Did you mean to use the {nearest_command} subcommand?" )); } } @@ -1144,7 +1138,7 @@ fn roc_run_executable_file_path(binary_bytes: &[u8]) -> std::io::Result Ok(Target::Linux64), "windows64" => Ok(Target::Windows64), "wasm32" => Ok(Target::Wasm32), - _ => Err(format!("Roc does not know how to compile to {}", string)), + _ => Err(format!("Roc does not know how to compile to {string}")), } } } diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 93fb5750d7f..9ed115ad0dc 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -200,12 +200,12 @@ fn main() -> io::Result<()> { } Err(LoadingProblem::FormattedReport(report)) => { - print!("{}", report); + print!("{report}"); Ok(1) } Err(other) => { - panic!("build_file failed with error:\n{:?}", other); + panic!("build_file failed with error:\n{other:?}"); } } } @@ -272,7 +272,7 @@ fn main() -> io::Result<()> { let format_exit_code = match format(roc_files, format_mode) { Ok(_) => 0, Err(message) => { - eprintln!("{}", message); + eprintln!("{message}"); 1 } }; diff --git a/crates/cli/tests/cli_run.rs b/crates/cli/tests/cli_run.rs index 826c8c146b4..e187a218f47 100644 --- a/crates/cli/tests/cli_run.rs +++ b/crates/cli/tests/cli_run.rs @@ -90,7 +90,7 @@ mod cli_run { // e.g. "1 error and 0 warnings found in 123 ms." let (before_first_digit, _) = err.split_at(err.rfind("found in ").unwrap()); - let err = format!("{}found in ms.", before_first_digit); + let err = format!("{before_first_digit}found in ms."); // make paths consistent let err = err.replace('\\', "/"); @@ -230,7 +230,7 @@ mod cli_run { what: _, xwhat, } = error; - println!("Valgrind Error: {}\n", kind); + println!("Valgrind Error: {kind}\n"); if let Some(ValgrindErrorXWhat { text, @@ -238,14 +238,14 @@ mod cli_run { leakedblocks: _, }) = xwhat { - println!(" {}", text); + println!(" {text}"); } } panic!("Valgrind reported memory errors"); } } else { let exit_code = match valgrind_out.status.code() { - Some(code) => format!("exit code {}", code), + Some(code) => format!("exit code {code}"), None => "no exit code".to_string(), }; @@ -301,7 +301,7 @@ mod cli_run { // e.g. "1 failed and 0 passed in 123 ms." if let Some(split) = actual.rfind("passed in ") { let (before_first_digit, _) = actual.split_at(split); - actual = format!("{}passed in ms.", before_first_digit); + actual = format!("{before_first_digit}passed in ms."); } let self_path = file.display().to_string(); @@ -397,8 +397,7 @@ mod cli_run { "swiftui" | "rocLovesSwift" => { if cfg!(not(target_os = "macos")) { eprintln!( - "WARNING: skipping testing example {} because it only works on MacOS.", - roc_filename + "WARNING: skipping testing example {roc_filename} because it only works on MacOS." ); return; } else { @@ -409,8 +408,7 @@ mod cli_run { "rocLovesWebAssembly" => { // this is a web assembly example, but we don't test with JS at the moment eprintln!( - "WARNING: skipping testing example {} because it only works in a browser!", - roc_filename + "WARNING: skipping testing example {roc_filename} because it only works in a browser!" ); return; } @@ -965,16 +963,14 @@ mod cli_run { match roc_filename { "QuicksortApp.roc" => { eprintln!( - "WARNING: skipping testing benchmark {} because the test is broken right now!", - roc_filename + "WARNING: skipping testing benchmark {roc_filename} because the test is broken right now!" ); return; } "TestAStar.roc" => { if cfg!(feature = "wasm32-cli-run") { eprintln!( - "WARNING: skipping testing benchmark {} because it currently does not work on wasm32 due to dictionaries.", - roc_filename + "WARNING: skipping testing benchmark {roc_filename} because it currently does not work on wasm32 due to dictionaries." ); return; } diff --git a/crates/cli/tests/editor.rs b/crates/cli/tests/editor.rs index f6ec81e579d..8680e5de6aa 100644 --- a/crates/cli/tests/editor.rs +++ b/crates/cli/tests/editor.rs @@ -30,7 +30,7 @@ mod editor_launch_test { // The editor expects to be run from the root of the repo, so it can find the cli-platform to init a new project folder. env::set_current_dir(&root_dir) - .unwrap_or_else(|_| panic!("Failed to set current dir to {:?}", root_dir)); + .unwrap_or_else(|_| panic!("Failed to set current dir to {root_dir:?}")); let roc_binary_path = build_roc_bin(&["--features", "editor"]); diff --git a/crates/cli_utils/src/bench_utils.rs b/crates/cli_utils/src/bench_utils.rs index 31da15a8e78..ddac5232bff 100644 --- a/crates/cli_utils/src/bench_utils.rs +++ b/crates/cli_utils/src/bench_utils.rs @@ -25,8 +25,7 @@ fn exec_bench_w_input( assert!( compile_out.status.success(), - "build ended with bad status {:?}", - compile_out + "build ended with bad status {compile_out:?}" ); check_cmd_output(file, stdin_str, executable_filename, expected_ending); @@ -58,10 +57,7 @@ fn check_cmd_output( }; if !&out.stdout.ends_with(expected_ending) { - panic!( - "expected output to end with {:?} but instead got {:#?}", - expected_ending, out - ); + panic!("expected output to end with {expected_ending:?} but instead got {out:#?}"); } assert!(out.status.success()); } @@ -96,7 +92,7 @@ fn bench_cmd( } if let Some(bench_group) = bench_group_opt { - bench_group.bench_function(&format!("Benchmarking {:?}", executable_filename), |b| { + bench_group.bench_function(&format!("Benchmarking {executable_filename:?}"), |b| { b.iter(|| run_cmd(black_box(&cmd_str), black_box([stdin_str]), &[], [])) }); } else { diff --git a/crates/cli_utils/src/helpers.rs b/crates/cli_utils/src/helpers.rs index dbc28659f34..1239e0bcbd4 100644 --- a/crates/cli_utils/src/helpers.rs +++ b/crates/cli_utils/src/helpers.rs @@ -216,7 +216,7 @@ pub fn build_roc_bin(extra_args: &[&str]) -> PathBuf { cargo_cmd.current_dir(root_project_dir).args(&args); - let cargo_cmd_str = format!("{:?}", cargo_cmd); + let cargo_cmd_str = format!("{cargo_cmd:?}"); let cargo_output = cargo_cmd.output().unwrap(); @@ -255,7 +255,7 @@ pub fn run_cmd<'a, I: IntoIterator, E: IntoIterator, E: IntoIterator St let node = mark_node_pool.get(root_node_id); - writeln!(full_string, "{} mn_id {}\n", node, root_node_id).unwrap(); + writeln!(full_string, "{node} mn_id {root_node_id}\n").unwrap(); tree_as_string_helper(node, 1, &mut full_string, mark_node_pool); @@ -399,7 +399,7 @@ fn tree_as_string_helper( .join("") .to_owned(); - writeln!(full_str, "{} mn_id {}", child_str, child_id).unwrap(); + writeln!(full_str, "{child_str} mn_id {child_id}").unwrap(); tree_string.push_str(&full_str); diff --git a/crates/code_markup/src/markup_error.rs b/crates/code_markup/src/markup_error.rs index 5e888652d24..80abf3d004e 100644 --- a/crates/code_markup/src/markup_error.rs +++ b/crates/code_markup/src/markup_error.rs @@ -56,7 +56,7 @@ pub type MarkResult = std::result::Result; impl From for MarkError { fn from(util_err: UtilError) -> Self { - let msg = format!("{}", util_err); + let msg = format!("{util_err}"); // hack to handle MarkError derive let dummy_res: Result<(), NoneError> = Err(NoneError {}); diff --git a/crates/code_markup/src/slow_pool.rs b/crates/code_markup/src/slow_pool.rs index 9699e8dc9df..a5526eca134 100644 --- a/crates/code_markup/src/slow_pool.rs +++ b/crates/code_markup/src/slow_pool.rs @@ -39,8 +39,8 @@ impl SlowPool { for (mark_node_id, node) in self.nodes.iter().enumerate() { let ast_node_id_str = match mark_id_ast_id_map.get(mark_node_id) { - Ok(ast_id) => format!("{:?}", ast_id), - Err(err) => format!("{:?}", err), + Ok(ast_id) => format!("{ast_id:?}"), + Err(err) => format!("{err:?}"), }; let ast_node_id: String = ast_node_id_str .chars() @@ -52,7 +52,7 @@ impl SlowPool { let node_children = node.get_children_ids(); if !node_children.is_empty() { - child_str = format!("children: {:?}", node_children); + child_str = format!("children: {node_children:?}"); } write!( diff --git a/crates/compiler/alias_analysis/src/lib.rs b/crates/compiler/alias_analysis/src/lib.rs index 920371944c4..d6d843cf2f4 100644 --- a/crates/compiler/alias_analysis/src/lib.rs +++ b/crates/compiler/alias_analysis/src/lib.rs @@ -117,7 +117,7 @@ where } if debug() { - for (i, c) in (format!("{:?}", symbol)).chars().take(25).enumerate() { + for (i, c) in (format!("{symbol:?}")).chars().take(25).enumerate() { name_bytes[25 + i] = c as u8; } } @@ -131,7 +131,7 @@ fn bytes_as_ascii(bytes: &[u8]) -> String { let mut buf = String::new(); for byte in bytes { - write!(buf, "{:02X}", byte).unwrap(); + write!(buf, "{byte:02X}").unwrap(); } buf diff --git a/crates/compiler/build/src/link.rs b/crates/compiler/build/src/link.rs index 575f88b4087..519b88bca83 100644 --- a/crates/compiler/build/src/link.rs +++ b/crates/compiler/build/src/link.rs @@ -161,7 +161,7 @@ pub fn build_zig_host_native( zig_cmd.args([ zig_host_src, - &format!("-femit-bin={}", emit_bin), + &format!("-femit-bin={emit_bin}"), "--pkg-begin", "glue", find_zig_glue_path().to_str().unwrap(), @@ -399,7 +399,7 @@ pub fn build_swift_host_native( match arch { Architecture::Aarch64(_) => command.arg("-arm64"), - _ => command.arg(format!("-{}", arch)), + _ => command.arg(format!("-{arch}")), }; command @@ -928,7 +928,7 @@ fn link_linux( .map(|segments| segments.join("/")) .collect::>() .join("\n"); - eprintln!("We looked in the following directories:\n{}", dirs); + eprintln!("We looked in the following directories:\n{dirs}"); process::exit(1); } }; @@ -1085,8 +1085,8 @@ fn link_macos( let sdk_path = "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib"; if Path::new(sdk_path).exists() { - ld_command.arg(format!("-L{}", sdk_path)); - ld_command.arg(format!("-L{}/swift", sdk_path)); + ld_command.arg(format!("-L{sdk_path}")); + ld_command.arg(format!("-L{sdk_path}/swift")); }; let roc_link_flags = match env::var("ROC_LINK_FLAGS") { @@ -1288,9 +1288,7 @@ pub fn llvm_module_to_dylib( assert!( exit_status.success(), - "\n___________\nLinking command failed with status {:?}:\n\n {:?}\n___________\n", - exit_status, - child + "\n___________\nLinking command failed with status {exit_status:?}:\n\n {child:?}\n___________\n" ); // Load the dylib diff --git a/crates/compiler/build/src/program.rs b/crates/compiler/build/src/program.rs index 6b183d093f6..083b07cbbab 100644 --- a/crates/compiler/build/src/program.rs +++ b/crates/compiler/build/src/program.rs @@ -320,10 +320,10 @@ fn gen_from_mono_module_llvm<'a>( if !unrecognized.is_empty() { let out = unrecognized .iter() - .map(|x| format!("{:?}", x)) + .map(|x| format!("{x:?}")) .collect::>() .join(", "); - eprintln!("Unrecognized sanitizer: {}\nSupported options are \"address\", \"memory\", \"thread\", \"cargo-fuzz\", and \"afl.rs\".", out); + eprintln!("Unrecognized sanitizer: {out}\nSupported options are \"address\", \"memory\", \"thread\", \"cargo-fuzz\", and \"afl.rs\"."); eprintln!("Note: \"cargo-fuzz\" and \"afl.rs\" both enable sanitizer coverage for fuzzing. They just use different parameters to match the respective libraries.") } @@ -340,7 +340,7 @@ fn gen_from_mono_module_llvm<'a>( } let opt = opt.output().unwrap(); - assert!(opt.stderr.is_empty(), "{:#?}", opt); + assert!(opt.stderr.is_empty(), "{opt:#?}"); // write the .o file. Note that this builds the .o for the local machine, // and ignores the `target_machine` entirely. @@ -358,7 +358,7 @@ fn gen_from_mono_module_llvm<'a>( .output() .unwrap(); - assert!(bc_to_object.status.success(), "{:#?}", bc_to_object); + assert!(bc_to_object.status.success(), "{bc_to_object:#?}"); MemoryBuffer::create_from_file(&app_o_file).expect("memory buffer creation works") } else if emit_debug_info { @@ -414,7 +414,7 @@ fn gen_from_mono_module_llvm<'a>( .output() .unwrap(); - assert!(ll_to_object.stderr.is_empty(), "{:#?}", ll_to_object); + assert!(ll_to_object.stderr.is_empty(), "{ll_to_object:#?}"); } _ => unreachable!(), } @@ -716,13 +716,13 @@ pub fn handle_error_module( pub fn handle_loading_problem(problem: LoadingProblem) -> std::io::Result { match problem { LoadingProblem::FormattedReport(report) => { - print!("{}", report); + print!("{report}"); Ok(1) } _ => { // TODO: tighten up the types here, we should always end up with a // formatted report from load. - print!("Failed with error: {:?}", problem); + print!("Failed with error: {problem:?}"); Ok(1) } } @@ -889,7 +889,7 @@ fn build_loaded_file<'a>( buf.push('\n'); use std::fmt::Write; - write!(buf, "{}", module_timing).unwrap(); + write!(buf, "{module_timing}").unwrap(); if it.peek().is_some() { buf.push('\n'); @@ -914,10 +914,7 @@ fn build_loaded_file<'a>( .expect("Failed to (re)build platform."); if emit_timings && !is_platform_prebuilt { - println!( - "Finished rebuilding the platform in {} ms\n", - rebuild_duration - ); + println!("Finished rebuilding the platform in {rebuild_duration} ms\n"); } Some(HostRebuildTiming::BeforeApp(rebuild_duration)) @@ -957,8 +954,7 @@ fn build_loaded_file<'a>( if emit_timings { println!( - "\n\nCompilation finished!\n\nHere's how long each module took to compile:\n\n{}", - buf + "\n\nCompilation finished!\n\nHere's how long each module took to compile:\n\n{buf}" ); println!( @@ -972,10 +968,7 @@ fn build_loaded_file<'a>( let rebuild_duration = thread.join().expect("Failed to (re)build platform."); if emit_timings && !is_platform_prebuilt { - println!( - "Finished rebuilding the platform in {} ms\n", - rebuild_duration - ); + println!("Finished rebuilding the platform in {rebuild_duration} ms\n"); } } @@ -1007,7 +1000,7 @@ fn build_loaded_file<'a>( }; let app_o_file = tempfile::Builder::new() .prefix("roc_app") - .suffix(&format!(".{}", extension)) + .suffix(&format!(".{extension}")) .tempfile() .map_err(|err| todo!("TODO Gracefully handle tempfile creation error {:?}", err))?; let app_o_file = app_o_file.path(); @@ -1257,8 +1250,7 @@ pub fn check_file<'a>( if emit_timings { println!( - "\n\nCompilation finished!\n\nHere's how long each module took to compile:\n\n{}", - buf + "\n\nCompilation finished!\n\nHere's how long each module took to compile:\n\n{buf}" ); println!("Finished checking in {} ms\n", compilation_end.as_millis(),); diff --git a/crates/compiler/builtins/bitcode/bc/build.rs b/crates/compiler/builtins/bitcode/bc/build.rs index 0d50904a8c3..0fa207a9238 100644 --- a/crates/compiler/builtins/bitcode/bc/build.rs +++ b/crates/compiler/builtins/bitcode/bc/build.rs @@ -61,12 +61,12 @@ fn generate_bc_file(bitcode_path: &Path, zig_object: &str, file_name: &str) { ll_path.set_extension("ll"); let dest_ir_host = ll_path.to_str().expect("Invalid dest ir path"); - println!("Compiling host ir to: {}", dest_ir_host); + println!("Compiling host ir to: {dest_ir_host}"); let mut bc_path = bitcode_path.join(file_name); bc_path.set_extension("bc"); let dest_bc_64bit = bc_path.to_str().expect("Invalid dest bc path"); - println!("Compiling 64-bit bitcode to: {}", dest_bc_64bit); + println!("Compiling 64-bit bitcode to: {dest_bc_64bit}"); // workaround for github.com/ziglang/zig/issues/9711 #[cfg(target_os = "macos")] @@ -104,7 +104,7 @@ fn run_command(mut command: Command, flaky_fail_counter: usize) { false => { let error_str = match str::from_utf8(&output.stderr) { Ok(stderr) => stderr.to_string(), - Err(_) => format!("Failed to run \"{}\"", command_str), + Err(_) => format!("Failed to run \"{command_str}\""), }; // Flaky test errors that only occur sometimes on MacOS ci server. diff --git a/crates/compiler/builtins/bitcode/build.rs b/crates/compiler/builtins/bitcode/build.rs index 3a55837ed36..d957ee0a8c8 100644 --- a/crates/compiler/builtins/bitcode/build.rs +++ b/crates/compiler/builtins/bitcode/build.rs @@ -66,7 +66,7 @@ fn generate_object_file(bitcode_path: &Path, zig_object: &str, object_file_name: let src_obj_path = bitcode_path.join(object_file_name); let src_obj = src_obj_path.to_str().expect("Invalid src object path"); - println!("Compiling zig object `{}` to: {}", zig_object, src_obj); + println!("Compiling zig object `{zig_object}` to: {src_obj}"); if !DEBUG { let mut zig_cmd = zig(); @@ -77,7 +77,7 @@ fn generate_object_file(bitcode_path: &Path, zig_object: &str, object_file_name: run_command(zig_cmd, 0); - println!("Moving zig object `{}` to: {}", zig_object, dest_obj); + println!("Moving zig object `{zig_object}` to: {dest_obj}"); // we store this .o file in rust's `target` folder (for wasm we need to leave a copy here too) fs::copy(src_obj, dest_obj).unwrap_or_else(|err| { @@ -167,7 +167,7 @@ fn run_command(mut command: Command, flaky_fail_counter: usize) { false => { let error_str = match str::from_utf8(&output.stderr) { Ok(stderr) => stderr.to_string(), - Err(_) => format!("Failed to run \"{}\"", command_str), + Err(_) => format!("Failed to run \"{command_str}\""), }; // Flaky test errors that only occur sometimes on MacOS ci server. diff --git a/crates/compiler/can/src/abilities.rs b/crates/compiler/can/src/abilities.rs index f5f056ebcb8..893702add13 100644 --- a/crates/compiler/can/src/abilities.rs +++ b/crates/compiler/can/src/abilities.rs @@ -469,8 +469,7 @@ impl IAbilitiesStore { debug_assert!( old_specialization.is_none(), - "Existing resolution: {:?}", - old_specialization + "Existing resolution: {old_specialization:?}" ); } diff --git a/crates/compiler/can/src/constraint.rs b/crates/compiler/can/src/constraint.rs index 4e9fc1a4c0d..26a3f8dbe36 100644 --- a/crates/compiler/can/src/constraint.rs +++ b/crates/compiler/can/src/constraint.rs @@ -196,7 +196,7 @@ impl Constraints { let mut buf = String::new(); - writeln!(buf, "Constraints statistics for module {:?}:", module_id)?; + writeln!(buf, "Constraints statistics for module {module_id:?}:")?; writeln!(buf, " constraints length: {}:", self.constraints.len())?; writeln!( @@ -853,16 +853,16 @@ impl std::fmt::Debug for Constraint { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Eq(Eq(arg0, arg1, arg2, arg3)) => { - write!(f, "Eq({:?}, {:?}, {:?}, {:?})", arg0, arg1, arg2, arg3) + write!(f, "Eq({arg0:?}, {arg1:?}, {arg2:?}, {arg3:?})") } Self::Store(arg0, arg1, arg2, arg3) => { - write!(f, "Store({:?}, {:?}, {:?}, {:?})", arg0, arg1, arg2, arg3) + write!(f, "Store({arg0:?}, {arg1:?}, {arg2:?}, {arg3:?})") } Self::Lookup(arg0, arg1, arg2) => { - write!(f, "Lookup({:?}, {:?}, {:?})", arg0, arg1, arg2) + write!(f, "Lookup({arg0:?}, {arg1:?}, {arg2:?})") } Self::Pattern(arg0, arg1, arg2, arg3) => { - write!(f, "Pattern({:?}, {:?}, {:?}, {:?})", arg0, arg1, arg2, arg3) + write!(f, "Pattern({arg0:?}, {arg1:?}, {arg2:?}, {arg3:?})") } Self::True => write!(f, "True"), Self::SaveTheEnvironment => write!(f, "SaveTheEnvironment"), @@ -871,27 +871,19 @@ impl std::fmt::Debug for Constraint { Self::IsOpenType(arg0) => f.debug_tuple("IsOpenType").field(arg0).finish(), Self::IncludesTag(arg0) => f.debug_tuple("IncludesTag").field(arg0).finish(), Self::PatternPresence(arg0, arg1, arg2, arg3) => { - write!( - f, - "PatternPresence({:?}, {:?}, {:?}, {:?})", - arg0, arg1, arg2, arg3 - ) + write!(f, "PatternPresence({arg0:?}, {arg1:?}, {arg2:?}, {arg3:?})") } Self::Exhaustive(arg0, arg1, arg2, arg3) => { - write!( - f, - "Exhaustive({:?}, {:?}, {:?}, {:?})", - arg0, arg1, arg2, arg3 - ) + write!(f, "Exhaustive({arg0:?}, {arg1:?}, {arg2:?}, {arg3:?})") } Self::Resolve(arg0) => { - write!(f, "Resolve({:?})", arg0) + write!(f, "Resolve({arg0:?})") } Self::CheckCycle(arg0, arg1) => { - write!(f, "CheckCycle({:?}, {:?})", arg0, arg1) + write!(f, "CheckCycle({arg0:?}, {arg1:?})") } Self::IngestedFile(arg0, arg1, arg2) => { - write!(f, "IngestedFile({:?}, {:?}, {:?})", arg0, arg1, arg2) + write!(f, "IngestedFile({arg0:?}, {arg1:?}, {arg2:?})") } } } diff --git a/crates/compiler/can/src/copy.rs b/crates/compiler/can/src/copy.rs index 94279debd07..847382fcc81 100644 --- a/crates/compiler/can/src/copy.rs +++ b/crates/compiler/can/src/copy.rs @@ -24,7 +24,7 @@ trait CopyEnv { if descriptor.copy.into_variable().is_some() { descriptor.copy = OptVariable::NONE; } else { - debug_assert!(false, "{:?} marked as copied but it wasn't", var); + debug_assert!(false, "{var:?} marked as copied but it wasn't"); } }) } @@ -1320,7 +1320,7 @@ mod test { FlexVar(Some(name)) => { assert_eq!(subs[*name].as_str(), "a"); } - it => panic!("{:?}", it), + it => panic!("{it:?}"), } assert_eq!(var, variant_var); assert!(matches!( @@ -1337,7 +1337,7 @@ mod test { FlexVar(Some(name)) => { assert_eq!(subs[*name].as_str(), "b"); } - it => panic!("{:?}", it), + it => panic!("{it:?}"), } match arg.value { @@ -1355,10 +1355,10 @@ mod test { assert_eq!(name.0.as_str(), "G"); assert_eq!(arguments.len(), 0); } - e => panic!("{:?}", e), + e => panic!("{e:?}"), } } - e => panic!("{:?}", e), + e => panic!("{e:?}"), } } @@ -1403,7 +1403,7 @@ mod test { FlexVar(Some(name)) => { assert_eq!(target[*name].as_str(), "a"); } - it => panic!("{:?}", it), + it => panic!("{it:?}"), } assert_eq!(var, variant_var); assert!(matches!( @@ -1418,7 +1418,7 @@ mod test { FlexVar(Some(name)) => { assert_eq!(target[*name].as_str(), "b"); } - it => panic!("{:?}", it), + it => panic!("{it:?}"), } match arg.value { @@ -1436,10 +1436,10 @@ mod test { assert_eq!(name.0.as_str(), "G"); assert_eq!(arguments.len(), 0); } - e => panic!("{:?}", e), + e => panic!("{e:?}"), } } - e => panic!("{:?}", e), + e => panic!("{e:?}"), } } diff --git a/crates/compiler/can/src/def.rs b/crates/compiler/can/src/def.rs index 29fcf69b5b2..7fecd6ccc21 100644 --- a/crates/compiler/can/src/def.rs +++ b/crates/compiler/can/src/def.rs @@ -1069,8 +1069,7 @@ fn canonicalize_value_defs<'a>( debug_assert_eq!(env.home, s.module_id()); debug_assert!( !symbol_to_index.iter().any(|(id, _)| *id == s.ident_id()), - "{:?}", - s + "{s:?}" ); symbol_to_index.push((s.ident_id(), def_index as u32)); @@ -1838,7 +1837,7 @@ pub(crate) fn sort_can_defs( ); let declaration = if def_ordering.references.get_row_col(index, index) { - debug_assert!(!is_specialization, "Self-recursive specializations can only be determined during solving - but it was determined for {:?} now, that's a bug!", def); + debug_assert!(!is_specialization, "Self-recursive specializations can only be determined during solving - but it was determined for {def:?} now, that's a bug!"); if is_initial && !def diff --git a/crates/compiler/can/src/derive.rs b/crates/compiler/can/src/derive.rs index a5e6e645f22..fd85aaa514b 100644 --- a/crates/compiler/can/src/derive.rs +++ b/crates/compiler/can/src/derive.rs @@ -222,16 +222,16 @@ pub(crate) fn synthesize_member_impl<'a>( ability_member: Symbol, ) -> (Symbol, Loc, &'a Loc>) { // @Opaq - let at_opaque = env.arena.alloc_str(&format!("@{}", opaque_name)); + let at_opaque = env.arena.alloc_str(&format!("@{opaque_name}")); let (impl_name, def_body): (String, ast::Expr<'a>) = match ability_member { Symbol::ENCODE_TO_ENCODER => ( - format!("#{}_toEncoder", opaque_name), + format!("#{opaque_name}_toEncoder"), to_encoder(env, at_opaque), ), - Symbol::DECODE_DECODER => (format!("#{}_decoder", opaque_name), decoder(env, at_opaque)), - Symbol::HASH_HASH => (format!("#{}_hash", opaque_name), hash(env, at_opaque)), - Symbol::BOOL_IS_EQ => (format!("#{}_isEq", opaque_name), is_eq(env, at_opaque)), + Symbol::DECODE_DECODER => (format!("#{opaque_name}_decoder"), decoder(env, at_opaque)), + Symbol::HASH_HASH => (format!("#{opaque_name}_hash"), hash(env, at_opaque)), + Symbol::BOOL_IS_EQ => (format!("#{opaque_name}_isEq"), is_eq(env, at_opaque)), other => internal_error!("{:?} is not a derivable ability member!", other), }; diff --git a/crates/compiler/can/src/effect_module.rs b/crates/compiler/can/src/effect_module.rs index 7c8629db24c..91fdb5dd728 100644 --- a/crates/compiler/can/src/effect_module.rs +++ b/crates/compiler/can/src/effect_module.rs @@ -1362,7 +1362,7 @@ pub fn build_host_exposed_def( match typ.shallow_structural_dealias() { Type::Function(args, _, _) => { for i in 0..args.len() { - let name = format!("closure_arg_{}_{}", ident, i); + let name = format!("closure_arg_{ident}_{i}"); let arg_symbol = { let ident = name.clone().into(); @@ -1381,7 +1381,7 @@ pub fn build_host_exposed_def( linked_symbol_arguments.push((arg_var, Expr::Var(arg_symbol, arg_var))); } - let foreign_symbol_name = format!("roc_fx_{}", ident); + let foreign_symbol_name = format!("roc_fx_{ident}"); let low_level_call = Expr::ForeignCall { foreign_symbol: foreign_symbol_name.into(), args: linked_symbol_arguments, @@ -1389,7 +1389,7 @@ pub fn build_host_exposed_def( }; let effect_closure_symbol = { - let name = format!("effect_closure_{}", ident); + let name = format!("effect_closure_{ident}"); let ident = name.into(); scope.introduce(ident, Region::zero()).unwrap() @@ -1435,7 +1435,7 @@ pub fn build_host_exposed_def( _ => { // not a function - let foreign_symbol_name = format!("roc_fx_{}", ident); + let foreign_symbol_name = format!("roc_fx_{ident}"); let low_level_call = Expr::ForeignCall { foreign_symbol: foreign_symbol_name.into(), args: linked_symbol_arguments, @@ -1443,7 +1443,7 @@ pub fn build_host_exposed_def( }; let effect_closure_symbol = { - let name = format!("effect_closure_{}", ident); + let name = format!("effect_closure_{ident}"); let ident = name.into(); scope.introduce(ident, Region::zero()).unwrap() diff --git a/crates/compiler/can/src/env.rs b/crates/compiler/can/src/env.rs index 5c052d2f071..38c26ec464b 100644 --- a/crates/compiler/can/src/env.rs +++ b/crates/compiler/can/src/env.rs @@ -67,8 +67,7 @@ impl<'a> Env<'a> { ) -> Result { debug_assert!( !module_name_str.is_empty(), - "Called env.qualified_lookup with an unqualified ident: {:?}", - ident + "Called env.qualified_lookup with an unqualified ident: {ident:?}" ); let module_name = ModuleName::from(module_name_str); diff --git a/crates/compiler/can/src/module.rs b/crates/compiler/can/src/module.rs index 8517d3c1df4..d0c36000741 100644 --- a/crates/compiler/can/src/module.rs +++ b/crates/compiler/can/src/module.rs @@ -347,9 +347,7 @@ pub fn canonicalize_module_defs<'a>( // the symbol should already be added to the scope when this module is canonicalized debug_assert!( scope.contains_alias(symbol) || scope.abilities_store.is_ability(symbol), - "The {:?} is not a type alias or ability known in {:?}", - symbol, - home + "The {symbol:?} is not a type alias or ability known in {home:?}" ); // but now we know this symbol by a different identifier, so we still need to add it to diff --git a/crates/compiler/can/src/num.rs b/crates/compiler/can/src/num.rs index 886de610278..6efa4d3805a 100644 --- a/crates/compiler/can/src/num.rs +++ b/crates/compiler/can/src/num.rs @@ -220,8 +220,7 @@ fn from_str_radix(src: &str, radix: u32) -> Result( use std::ops::Neg; let sign_str = if is_negative { "-" } else { "" }; - let int_str = format!("{}{}", sign_str, int).into_boxed_str(); + let int_str = format!("{sign_str}{int}").into_boxed_str(); let i = match int { // Safety: this is fine because I128::MAX = |I128::MIN| - 1 IntValue::I128(n) if is_negative => { diff --git a/crates/compiler/can/tests/helpers/mod.rs b/crates/compiler/can/tests/helpers/mod.rs index 5442135f926..d2f95267c68 100644 --- a/crates/compiler/can/tests/helpers/mod.rs +++ b/crates/compiler/can/tests/helpers/mod.rs @@ -37,8 +37,7 @@ pub struct CanExprOut { pub fn can_expr_with(arena: &Bump, home: ModuleId, expr_str: &str) -> CanExprOut { let loc_expr = roc_parse::test_helpers::parse_loc_with(arena, expr_str).unwrap_or_else(|e| { panic!( - "can_expr_with() got a parse error when attempting to canonicalize:\n\n{:?} {:?}", - expr_str, e + "can_expr_with() got a parse error when attempting to canonicalize:\n\n{expr_str:?} {e:?}" ) }); diff --git a/crates/compiler/can/tests/test_can.rs b/crates/compiler/can/tests/test_can.rs index 7086931de0e..2afe3eff297 100644 --- a/crates/compiler/can/tests/test_can.rs +++ b/crates/compiler/can/tests/test_can.rs @@ -422,7 +422,7 @@ mod test_can { let CanExprOut { problems, .. } = can_expr_with(&arena, test_home(), src); assert_eq!(problems.len(), 2); - println!("{:#?}", problems); + println!("{problems:#?}"); assert!(problems.iter().any(|problem| matches!( problem, Problem::RuntimeError(RuntimeError::Shadowing { .. }) diff --git a/crates/compiler/collections/src/all.rs b/crates/compiler/collections/src/all.rs index f0663930001..d42ec32f6c0 100644 --- a/crates/compiler/collections/src/all.rs +++ b/crates/compiler/collections/src/all.rs @@ -202,7 +202,7 @@ fn int_to_ordinal(number: usize) -> std::string::String { }, }; - format!("{}{}", number, ending) + format!("{number}{ending}") } #[macro_export] diff --git a/crates/compiler/collections/src/small_string_interner.rs b/crates/compiler/collections/src/small_string_interner.rs index db3124375a2..f9f009266c8 100644 --- a/crates/compiler/collections/src/small_string_interner.rs +++ b/crates/compiler/collections/src/small_string_interner.rs @@ -48,9 +48,9 @@ enum Kind { impl Debug for Kind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::Generated(arg0) => write!(f, "Generated({})", arg0), + Self::Generated(arg0) => write!(f, "Generated({arg0})"), Self::Empty => write!(f, "Empty"), - Self::Interned(arg0) => write!(f, "Interned({})", arg0), + Self::Interned(arg0) => write!(f, "Interned({arg0})"), } } } @@ -155,7 +155,7 @@ impl SmallStringInterner { let index = self.lengths.len(); let offset = self.buffer.len(); - write!(self.buffer, "{}", index).unwrap(); + write!(self.buffer, "{index}").unwrap(); // this is a generated name, so store it as a negative length let length = Length(-((self.buffer.len() - offset) as i16)); diff --git a/crates/compiler/constrain/src/expr.rs b/crates/compiler/constrain/src/expr.rs index 338dc64e29b..972797a7f6e 100644 --- a/crates/compiler/constrain/src/expr.rs +++ b/crates/compiler/constrain/src/expr.rs @@ -1044,8 +1044,7 @@ pub fn constrain_expr( debug_assert!( intersection.is_empty(), - "Two patterns introduce the same symbols - that's a bug!\n{:?}", - intersection + "Two patterns introduce the same symbols - that's a bug!\n{intersection:?}" ); } diff --git a/crates/compiler/derive/src/hash.rs b/crates/compiler/derive/src/hash.rs index f01a28eac21..a960fdf0c2d 100644 --- a/crates/compiler/derive/src/hash.rs +++ b/crates/compiler/derive/src/hash.rs @@ -298,7 +298,7 @@ fn hash_tag_union( Expr::Int( discr_num_var, discr_precision_var, - format!("{}", discr_n).into_boxed_str(), + format!("{discr_n}").into_boxed_str(), IntValue::I128((discr_n as i128).to_ne_bytes()), IntBound::Exact(discr_width), ), diff --git a/crates/compiler/derive/src/util.rs b/crates/compiler/derive/src/util.rs index 2319dd2e12f..4cc0f790f52 100644 --- a/crates/compiler/derive/src/util.rs +++ b/crates/compiler/derive/src/util.rs @@ -31,7 +31,7 @@ impl Env<'_> { let name = if i == 1 { hint.clone() } else { - format!("{}{}", hint, i) + format!("{hint}{i}") }; if self.derived_ident_ids.get_id(&name).is_none() { break name; @@ -151,7 +151,7 @@ impl Env<'_> { == self.subs.get_root_key_without_compacting(lambda_set) }); debug_assert!(belongs_to_specialized_lambda_sets, - "Did not expect derivers to need to specialize unspecialized lambda sets, but we got one: {:?} for {:?}", lambda_set, spec_var) + "Did not expect derivers to need to specialize unspecialized lambda sets, but we got one: {lambda_set:?} for {spec_var:?}") } } } diff --git a/crates/compiler/gen_dev/src/generic64/aarch64.rs b/crates/compiler/gen_dev/src/generic64/aarch64.rs index 24e09234adb..fb777b1f4be 100644 --- a/crates/compiler/gen_dev/src/generic64/aarch64.rs +++ b/crates/compiler/gen_dev/src/generic64/aarch64.rs @@ -3164,7 +3164,7 @@ mod tests { UsesZR => "xzr".to_owned(), UsesSP => "sp".to_owned(), }, - _ => format!("{}", self), + _ => format!("{self}"), } } } diff --git a/crates/compiler/gen_dev/src/generic64/x86_64.rs b/crates/compiler/gen_dev/src/generic64/x86_64.rs index 32299672035..f67f8771943 100644 --- a/crates/compiler/gen_dev/src/generic64/x86_64.rs +++ b/crates/compiler/gen_dev/src/generic64/x86_64.rs @@ -3612,7 +3612,7 @@ mod tests { fn test_add_reg64_imm32() { disassembler_test!( add_reg64_imm32, - |reg, imm| format!("add {}, 0x{:x}", reg, imm), + |reg, imm| format!("add {reg}, 0x{imm:x}"), ALL_GENERAL_REGS, [TEST_I32] ); @@ -3622,7 +3622,7 @@ mod tests { fn test_add_reg64_reg64() { disassembler_test!( add_reg64_reg64, - |reg1, reg2| format!("add {}, {}", reg1, reg2), + |reg1, reg2| format!("add {reg1}, {reg2}"), ALL_GENERAL_REGS, ALL_GENERAL_REGS ); @@ -3632,7 +3632,7 @@ mod tests { fn test_sub_reg64_reg64() { disassembler_test!( sub_reg64_reg64, - |reg1, reg2| format!("sub {}, {}", reg1, reg2), + |reg1, reg2| format!("sub {reg1}, {reg2}"), ALL_GENERAL_REGS, ALL_GENERAL_REGS ); @@ -3642,7 +3642,7 @@ mod tests { fn test_addsd_freg64_freg64() { disassembler_test!( addsd_freg64_freg64, - |reg1, reg2| format!("addsd {}, {}", reg1, reg2), + |reg1, reg2| format!("addsd {reg1}, {reg2}"), ALL_FLOAT_REGS, ALL_FLOAT_REGS ); @@ -3652,7 +3652,7 @@ mod tests { fn test_addss_freg32_freg32() { disassembler_test!( addss_freg32_freg32, - |reg1, reg2| format!("addss {}, {}", reg1, reg2), + |reg1, reg2| format!("addss {reg1}, {reg2}"), ALL_FLOAT_REGS, ALL_FLOAT_REGS ); @@ -3662,7 +3662,7 @@ mod tests { fn test_andpd_freg64_freg64() { disassembler_test!( andpd_freg64_freg64, - |reg1, reg2| format!("andpd {}, {}", reg1, reg2), + |reg1, reg2| format!("andpd {reg1}, {reg2}"), ALL_FLOAT_REGS, ALL_FLOAT_REGS ); @@ -3729,7 +3729,7 @@ mod tests { fn test_cmovl_reg64_reg64() { disassembler_test!( cmovl_reg64_reg64, - |reg1, reg2| format!("cmovl {}, {}", reg1, reg2), + |reg1, reg2| format!("cmovl {reg1}, {reg2}"), ALL_GENERAL_REGS, ALL_GENERAL_REGS ); @@ -3739,7 +3739,7 @@ mod tests { fn test_cmp_reg64_imm32() { disassembler_test!( cmp_reg64_imm32, - |reg, imm| format!("cmp {}, 0x{:x}", reg, imm), + |reg, imm| format!("cmp {reg}, 0x{imm:x}"), ALL_GENERAL_REGS, [TEST_I32] ); @@ -3749,7 +3749,7 @@ mod tests { fn test_imul_reg64_reg64() { disassembler_test!( imul_reg64_reg64, - |reg1, reg2| format!("imul {}, {}", reg1, reg2), + |reg1, reg2| format!("imul {reg1}, {reg2}"), ALL_GENERAL_REGS, ALL_GENERAL_REGS ); @@ -3759,7 +3759,7 @@ mod tests { fn test_mul_reg64_reg64() { disassembler_test!( mul_reg64_reg64, - |reg| format!("mul {}", reg), + |reg| format!("mul {reg}"), ALL_GENERAL_REGS ); } @@ -3768,7 +3768,7 @@ mod tests { fn test_mulsd_freg64_freg64() { disassembler_test!( mulsd_freg64_freg64, - |reg1, reg2| format!("mulsd {}, {}", reg1, reg2), + |reg1, reg2| format!("mulsd {reg1}, {reg2}"), ALL_FLOAT_REGS, ALL_FLOAT_REGS ); @@ -3778,7 +3778,7 @@ mod tests { fn test_mulss_freg32_freg32() { disassembler_test!( mulss_freg32_freg32, - |reg1, reg2| format!("mulss {}, {}", reg1, reg2), + |reg1, reg2| format!("mulss {reg1}, {reg2}"), ALL_FLOAT_REGS, ALL_FLOAT_REGS ); @@ -3788,7 +3788,7 @@ mod tests { fn test_idiv_reg64_reg64() { disassembler_test!( idiv_reg64_reg64, - |reg| format!("cqo\nidiv {}", reg), + |reg| format!("cqo\nidiv {reg}"), ALL_GENERAL_REGS ); } @@ -3797,7 +3797,7 @@ mod tests { fn test_div_reg64_reg64() { disassembler_test!( udiv_reg64_reg64, - |reg| format!("cqo\ndiv {}", reg), + |reg| format!("cqo\ndiv {reg}"), ALL_GENERAL_REGS ); } @@ -3806,7 +3806,7 @@ mod tests { fn test_divsd_freg64_freg64() { disassembler_test!( divsd_freg64_freg64, - |reg1, reg2| format!("divsd {}, {}", reg1, reg2), + |reg1, reg2| format!("divsd {reg1}, {reg2}"), ALL_FLOAT_REGS, ALL_FLOAT_REGS ); @@ -3816,7 +3816,7 @@ mod tests { fn test_divss_freg32_freg32() { disassembler_test!( divss_freg32_freg32, - |reg1, reg2| format!("divss {}, {}", reg1, reg2), + |reg1, reg2| format!("divss {reg1}, {reg2}"), ALL_FLOAT_REGS, ALL_FLOAT_REGS ); @@ -3846,7 +3846,7 @@ mod tests { fn test_mov_reg64_imm32() { disassembler_test!( mov_reg64_imm32, - |reg, imm| format!("mov {}, 0x{:x}", reg, imm), + |reg, imm| format!("mov {reg}, 0x{imm:x}"), ALL_GENERAL_REGS, [TEST_I32] ); @@ -3856,13 +3856,13 @@ mod tests { fn test_mov_reg64_imm64() { disassembler_test!( mov_reg64_imm64, - |reg, imm| format!("movabs {}, 0x{:x}", reg, imm), + |reg, imm| format!("movabs {reg}, 0x{imm:x}"), ALL_GENERAL_REGS, [TEST_I64] ); disassembler_test!( mov_reg64_imm64, - |reg, imm| format!("mov {}, 0x{:x}", reg, imm), + |reg, imm| format!("mov {reg}, 0x{imm:x}"), ALL_GENERAL_REGS, [TEST_I32 as i64] ); @@ -3872,7 +3872,7 @@ mod tests { fn test_lea_reg64() { disassembler_test!( lea_reg64, - |reg| format!("lea {}, [rip]", reg), + |reg| format!("lea {reg}, [rip]"), ALL_GENERAL_REGS ); } @@ -3898,7 +3898,7 @@ mod tests { X86_64GeneralReg::low_32bits_string(®1), X86_64GeneralReg::low_32bits_string(®2) ), - RegisterWidth::W64 => format!("mov {}, {}", reg1, reg2), + RegisterWidth::W64 => format!("mov {reg1}, {reg2}"), } }, ALL_REGISTER_WIDTHS, @@ -3967,7 +3967,7 @@ mod tests { fn test_movsd_freg64_base64_offset32() { disassembler_test!( movsd_freg64_base64_offset32, - |reg1, reg2, imm| format!("movsd {}, qword ptr [{} + 0x{:x}]", reg1, reg2, imm), + |reg1, reg2, imm| format!("movsd {reg1}, qword ptr [{reg2} + 0x{imm:x}]"), ALL_FLOAT_REGS, ALL_GENERAL_REGS, [TEST_I32] @@ -3978,7 +3978,7 @@ mod tests { fn test_movss_freg32_base32_offset32() { disassembler_test!( movss_freg32_base32_offset32, - |reg1, reg2, imm| format!("movss {}, dword ptr [{} + 0x{:x}]", reg1, reg2, imm), + |reg1, reg2, imm| format!("movss {reg1}, dword ptr [{reg2} + 0x{imm:x}]"), ALL_FLOAT_REGS, ALL_GENERAL_REGS, [TEST_I32] @@ -3989,7 +3989,7 @@ mod tests { fn test_movsd_base64_offset32_freg64() { disassembler_test!( movsd_base64_offset32_freg64, - |reg1, imm, reg2| format!("movsd qword ptr [{} + 0x{:x}], {}", reg1, imm, reg2), + |reg1, imm, reg2| format!("movsd qword ptr [{reg1} + 0x{imm:x}], {reg2}"), ALL_GENERAL_REGS, [TEST_I32], ALL_FLOAT_REGS @@ -4011,7 +4011,7 @@ mod tests { fn test_mov_reg64_base64_offset32() { disassembler_test!( mov_reg64_base64_offset32, - |reg1, reg2, imm| format!("mov {}, qword ptr [{} + 0x{:x}]", reg1, reg2, imm), + |reg1, reg2, imm| format!("mov {reg1}, qword ptr [{reg2} + 0x{imm:x}]"), ALL_GENERAL_REGS, ALL_GENERAL_REGS, [TEST_I32] @@ -4070,7 +4070,7 @@ mod tests { fn test_mov_base64_offset32_reg64() { disassembler_test!( mov_base64_offset32_reg64, - |reg1, imm, reg2| format!("mov qword ptr [{} + 0x{:x}], {}", reg1, imm, reg2), + |reg1, imm, reg2| format!("mov qword ptr [{reg1} + 0x{imm:x}], {reg2}"), ALL_GENERAL_REGS, [TEST_I32], ALL_GENERAL_REGS @@ -4129,7 +4129,7 @@ mod tests { fn test_movsx_reg64_base32_offset32() { disassembler_test!( movsx_reg64_base32_offset32, - |reg1, reg2, imm| format!("movsxd {}, dword ptr [{} + 0x{:x}]", reg1, reg2, imm), + |reg1, reg2, imm| format!("movsxd {reg1}, dword ptr [{reg2} + 0x{imm:x}]"), ALL_GENERAL_REGS, ALL_GENERAL_REGS, [TEST_I32] @@ -4140,7 +4140,7 @@ mod tests { fn test_movsx_reg64_base16_offset32() { disassembler_test!( movsx_reg64_base16_offset32, - |reg1, reg2, imm| format!("movsx {}, word ptr [{} + 0x{:x}]", reg1, reg2, imm), + |reg1, reg2, imm| format!("movsx {reg1}, word ptr [{reg2} + 0x{imm:x}]"), ALL_GENERAL_REGS, ALL_GENERAL_REGS, [TEST_I32] @@ -4151,7 +4151,7 @@ mod tests { fn test_movsx_reg64_base8_offset32() { disassembler_test!( movsx_reg64_base8_offset32, - |reg1, reg2, imm| format!("movsx {}, byte ptr [{} + 0x{:x}]", reg1, reg2, imm), + |reg1, reg2, imm| format!("movsx {reg1}, byte ptr [{reg2} + 0x{imm:x}]"), ALL_GENERAL_REGS, ALL_GENERAL_REGS, [TEST_I32] @@ -4162,7 +4162,7 @@ mod tests { fn test_movzx_reg64_base16_offset32() { disassembler_test!( movzx_reg64_base16_offset32, - |reg1, reg2, imm| format!("movzx {}, word ptr [{} + 0x{:x}]", reg1, reg2, imm), + |reg1, reg2, imm| format!("movzx {reg1}, word ptr [{reg2} + 0x{imm:x}]"), ALL_GENERAL_REGS, ALL_GENERAL_REGS, [TEST_I32] @@ -4173,7 +4173,7 @@ mod tests { fn test_movzx_reg64_base8_offset32() { disassembler_test!( movzx_reg64_base8_offset32, - |reg1, reg2, imm| format!("movzx {}, byte ptr [{} + 0x{:x}]", reg1, reg2, imm), + |reg1, reg2, imm| format!("movzx {reg1}, byte ptr [{reg2} + 0x{imm:x}]"), ALL_GENERAL_REGS, ALL_GENERAL_REGS, [TEST_I32] @@ -4194,7 +4194,7 @@ mod tests { fn test_movq_reg64_freg64() { disassembler_test!( movq_reg64_freg64, - |dst, src| format!("movq {}, {}", dst, src), + |dst, src| format!("movq {dst}, {src}"), ALL_GENERAL_REGS, ALL_FLOAT_REGS ); @@ -4204,7 +4204,7 @@ mod tests { fn test_movsd_freg64_freg64() { disassembler_test!( raw_movsd_freg64_freg64, - |reg1, reg2| format!("movsd {}, {}", reg1, reg2), + |reg1, reg2| format!("movsd {reg1}, {reg2}"), ALL_FLOAT_REGS, ALL_FLOAT_REGS ); @@ -4214,7 +4214,7 @@ mod tests { fn test_movss_freg32_freg32() { disassembler_test!( raw_movss_freg32_freg32, - |reg1, reg2| format!("movss {}, {}", reg1, reg2), + |reg1, reg2| format!("movss {reg1}, {reg2}"), ALL_FLOAT_REGS, ALL_FLOAT_REGS ); @@ -4224,7 +4224,7 @@ mod tests { fn test_movss_freg32_rip_offset32() { disassembler_test!( movss_freg32_rip_offset32, - |reg, imm| format!("movss {}, dword ptr [rip + 0x{:x}]", reg, imm), + |reg, imm| format!("movss {reg}, dword ptr [rip + 0x{imm:x}]"), ALL_FLOAT_REGS, [TEST_I32 as u32] ); @@ -4234,7 +4234,7 @@ mod tests { fn test_movsd_freg64_rip_offset32() { disassembler_test!( movsd_freg64_rip_offset32, - |reg, imm| format!("movsd {}, qword ptr [rip + 0x{:x}]", reg, imm), + |reg, imm| format!("movsd {reg}, qword ptr [rip + 0x{imm:x}]"), ALL_FLOAT_REGS, [TEST_I32 as u32] ); @@ -4242,7 +4242,7 @@ mod tests { #[test] fn test_neg_reg64() { - disassembler_test!(neg_reg64, |reg| format!("neg {}", reg), ALL_GENERAL_REGS); + disassembler_test!(neg_reg64, |reg| format!("neg {reg}"), ALL_GENERAL_REGS); } #[test] @@ -4251,13 +4251,13 @@ mod tests { const CVTTSS2SI_CODE: u8 = 0x2C; disassembler_test!( |buf, r1, r2| cvtsi2_help(buf, 0xF3, CVTSI2SS_CODE, r1, r2), - |reg1, reg2| format!("cvtsi2ss {}, {}", reg1, reg2), + |reg1, reg2| format!("cvtsi2ss {reg1}, {reg2}"), ALL_FLOAT_REGS, ALL_GENERAL_REGS ); disassembler_test!( |buf, r1, r2| cvtsi2_help(buf, 0xF3, CVTTSS2SI_CODE, r1, r2), - |reg1, reg2| format!("cvttss2si {}, {}", reg1, reg2), + |reg1, reg2| format!("cvttss2si {reg1}, {reg2}"), ALL_GENERAL_REGS, ALL_FLOAT_REGS ); @@ -4268,7 +4268,7 @@ mod tests { const CVTSS2SD_CODE: u8 = 0x5A; disassembler_test!( |buf, r1, r2| cvtsi2_help(buf, 0xF3, CVTSS2SD_CODE, r1, r2), - |reg1, reg2| format!("cvtss2sd {}, {}", reg1, reg2), + |reg1, reg2| format!("cvtss2sd {reg1}, {reg2}"), ALL_FLOAT_REGS, ALL_FLOAT_REGS ); @@ -4292,7 +4292,7 @@ mod tests { fn test_sub_reg64_imm32() { disassembler_test!( sub_reg64_imm32, - |reg, imm| format!("sub {}, 0x{:x}", reg, imm), + |reg, imm| format!("sub {reg}, 0x{imm:x}"), ALL_GENERAL_REGS, [TEST_I32] ); @@ -4300,12 +4300,12 @@ mod tests { #[test] fn test_pop_reg64() { - disassembler_test!(pop_reg64, |reg| format!("pop {}", reg), ALL_GENERAL_REGS); + disassembler_test!(pop_reg64, |reg| format!("pop {reg}"), ALL_GENERAL_REGS); } #[test] fn test_push_reg64() { - disassembler_test!(push_reg64, |reg| format!("push {}", reg), ALL_GENERAL_REGS); + disassembler_test!(push_reg64, |reg| format!("push {reg}"), ALL_GENERAL_REGS); } #[test] diff --git a/crates/compiler/gen_dev/src/lib.rs b/crates/compiler/gen_dev/src/lib.rs index e8c1182ba28..be508b6669a 100644 --- a/crates/compiler/gen_dev/src/lib.rs +++ b/crates/compiler/gen_dev/src/lib.rs @@ -351,7 +351,7 @@ trait Backend<'a> { // the functions from the generates #help module (refcounting, equality) is always suffixed // with 1. That is fine, they are always unique anyway. if ident_string.contains("#help") { - format!("{}_{}_1", module_string, ident_string) + format!("{module_string}_{ident_string}_1") } else { format!("{}_{}_{}", module_string, ident_string, state.finish()) } diff --git a/crates/compiler/gen_dev/src/object_builder.rs b/crates/compiler/gen_dev/src/object_builder.rs index 991e1ddcbf0..3cf0a0e2b96 100644 --- a/crates/compiler/gen_dev/src/object_builder.rs +++ b/crates/compiler/gen_dev/src/object_builder.rs @@ -605,7 +605,7 @@ fn build_proc<'a, B: Backend<'a>>( let elfreloc = match reloc { Relocation::LocalData { offset, data } => { let data_symbol = write::Symbol { - name: format!("{}.data{}", fn_name, local_data_index) + name: format!("{fn_name}.data{local_data_index}") .as_bytes() .to_vec(), value: 0, diff --git a/crates/compiler/gen_llvm/src/llvm/bitcode.rs b/crates/compiler/gen_llvm/src/llvm/bitcode.rs index 64dac3814e0..af4f7cd1d1e 100644 --- a/crates/compiler/gen_llvm/src/llvm/bitcode.rs +++ b/crates/compiler/gen_llvm/src/llvm/bitcode.rs @@ -34,10 +34,7 @@ pub fn call_bitcode_fn<'ctx>( .try_as_basic_value() .left() .unwrap_or_else(|| { - panic!( - "LLVM error: Did not get return value from bitcode function {:?}", - fn_name - ) + panic!("LLVM error: Did not get return value from bitcode function {fn_name:?}") }) } @@ -49,7 +46,7 @@ pub fn call_void_bitcode_fn<'ctx>( call_bitcode_fn_help(env, args, fn_name) .try_as_basic_value() .right() - .unwrap_or_else(|| panic!("LLVM error: Tried to call void bitcode function, but got return value from bitcode function, {:?}", fn_name)) + .unwrap_or_else(|| panic!("LLVM error: Tried to call void bitcode function, but got return value from bitcode function, {fn_name:?}")) } fn call_bitcode_fn_help<'ctx>( @@ -63,7 +60,7 @@ fn call_bitcode_fn_help<'ctx>( let fn_val = env .module .get_function(fn_name) - .unwrap_or_else(|| panic!("Unrecognized builtin function: {:?} - if you're working on the Roc compiler, do you need to rebuild the bitcode? See compiler/builtins/bitcode/README.md", fn_name)); + .unwrap_or_else(|| panic!("Unrecognized builtin function: {fn_name:?} - if you're working on the Roc compiler, do you need to rebuild the bitcode? See compiler/builtins/bitcode/README.md")); let call = env.builder.build_call(fn_val, &arguments, "call_builtin"); @@ -378,9 +375,9 @@ fn build_rc_wrapper<'a, 'ctx>( .to_symbol_string(symbol, &env.interns); let fn_name = match rc_operation { - Mode::IncN => format!("{}_inc_n", fn_name), - Mode::Inc => format!("{}_inc", fn_name), - Mode::Dec => format!("{}_dec", fn_name), + Mode::IncN => format!("{fn_name}_inc_n"), + Mode::Inc => format!("{fn_name}_inc"), + Mode::Dec => format!("{fn_name}_dec"), }; let function_value = match env.module.get_function(fn_name.as_str()) { diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index ae92d4dc486..1add30678ee 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -263,7 +263,7 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> { let fn_val = self .module .get_function(intrinsic_name) - .unwrap_or_else(|| panic!("Unrecognized intrinsic function: {}", intrinsic_name)); + .unwrap_or_else(|| panic!("Unrecognized intrinsic function: {intrinsic_name}")); let mut arg_vals: Vec = Vec::with_capacity_in(args.len(), self.arena); @@ -289,10 +289,7 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> { let call = self.build_intrinsic_call(intrinsic_name, args); call.try_as_basic_value().left().unwrap_or_else(|| { - panic!( - "LLVM error: Invalid call by name for intrinsic {}", - intrinsic_name - ) + panic!("LLVM error: Invalid call by name for intrinsic {intrinsic_name}") }) } @@ -498,17 +495,14 @@ pub fn module_from_builtins<'ctx>( } => { include_bytes!("../../../builtins/bitcode/builtins-windows-x86_64.bc") } - _ => panic!( - "The zig builtins are not currently built for this target: {:?}", - target - ), + _ => panic!("The zig builtins are not currently built for this target: {target:?}"), } }; let memory_buffer = MemoryBuffer::create_from_memory_range(bitcode_bytes, module_name); let module = Module::parse_bitcode_from_buffer(&memory_buffer, ctx) - .unwrap_or_else(|err| panic!("Unable to import builtins bitcode. LLVM error: {:?}", err)); + .unwrap_or_else(|err| panic!("Unable to import builtins bitcode. LLVM error: {err:?}")); // Add LLVM intrinsics. add_intrinsics(ctx, &module); @@ -766,7 +760,7 @@ pub fn build_exp_literal<'a, 'ctx>( LayoutRepr::Builtin(Builtin::Int(int_width)) => { int_with_precision(env, i128::from_ne_bytes(*bytes), int_width).into() } - _ => panic!("Invalid layout for int literal = {:?}", layout), + _ => panic!("Invalid layout for int literal = {layout:?}"), }, U128(bytes) => const_u128(env, u128::from_ne_bytes(*bytes)).into(), @@ -775,7 +769,7 @@ pub fn build_exp_literal<'a, 'ctx>( LayoutRepr::Builtin(Builtin::Float(float_width)) => { float_with_precision(env, *float, float_width) } - _ => panic!("Invalid layout for float literal = {:?}", layout), + _ => panic!("Invalid layout for float literal = {layout:?}"), }, Decimal(bytes) => { @@ -2056,7 +2050,7 @@ pub fn get_tag_id<'a, 'ctx>( match union_layout { UnionLayout::NonRecursive(_) => { - debug_assert!(argument.is_pointer_value(), "{:?}", argument); + debug_assert!(argument.is_pointer_value(), "{argument:?}"); let argument_ptr = argument.into_pointer_value(); get_tag_id_wrapped(env, layout_interner, *union_layout, argument_ptr) @@ -3514,10 +3508,7 @@ fn build_switch_ir<'a, 'ctx>( layout_interner, layout_interner.get_repr(stored_layout) ), - "This switch matches on {:?}, but the matched-on symbol {:?} has layout {:?}", - cond_layout, - cond_symbol, - stored_layout + "This switch matches on {cond_layout:?}, but the matched-on symbol {cond_symbol:?} has layout {stored_layout:?}" ); let cont_block = context.append_basic_block(parent, "cont"); @@ -3623,7 +3614,7 @@ fn build_switch_ir<'a, 'ctx>( condition_int_type.const_int(*int, false) }; - let block = context.append_basic_block(parent, format!("branch{}", int).as_str()); + let block = context.append_basic_block(parent, format!("branch{int}").as_str()); cases.push((int_val, block)); } @@ -4032,7 +4023,7 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx>( &[], ); - let size_function_name: String = format!("roc__{}_size", ident_string); + let size_function_name: String = format!("roc__{ident_string}_size"); let size_function = add_func( env.context, @@ -4332,7 +4323,7 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx>( roc_function, arguments, return_layout, - &format!("{}_generic", c_function_name), + &format!("{c_function_name}_generic"), ); let c_function = expose_function_to_host_help_c_abi_v2( @@ -4351,7 +4342,7 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx>( Some(env.context.i64_type().as_basic_type_enum()), &[], ); - let size_function_name: String = format!("{}_size", c_function_name); + let size_function_name: String = format!("{c_function_name}_size"); let size_function = add_func( env.context, @@ -4998,7 +4989,7 @@ pub fn build_procedures_expose_expects<'a>( let mut it = func_solutions.specs(); let func_spec = match it.next() { Some(spec) => spec, - None => panic!("no specialization for expect {}", symbol), + None => panic!("no specialization for expect {symbol}"), }; debug_assert!( @@ -5012,7 +5003,7 @@ pub fn build_procedures_expose_expects<'a>( let name = roc_main_fn.get_name().to_str().unwrap(); - let expect_name = &format!("Expect_{}", name); + let expect_name = &format!("Expect_{name}"); let expect_name = env.arena.alloc_str(expect_name); expect_names.push(&*expect_name); @@ -5024,7 +5015,7 @@ pub fn build_procedures_expose_expects<'a>( roc_main_fn, top_level.arguments, top_level.result, - &format!("Expect_{}", name), + &format!("Expect_{name}"), ); } @@ -5051,7 +5042,7 @@ fn build_procedures_help<'a>( entry_point, it, ) { - Err(e) => panic!("Error in alias analysis: {}", e), + Err(e) => panic!("Error in alias analysis: {e}"), Ok(solutions) => solutions, }; @@ -5147,10 +5138,10 @@ fn func_spec_name<'a>( let ident_string = symbol.as_str(interns); let module_string = interns.module_ids.get_name(symbol.module_id()).unwrap(); - write!(buf, "{}_{}_", module_string, ident_string).unwrap(); + write!(buf, "{module_string}_{ident_string}_").unwrap(); for byte in func_spec.0.iter() { - write!(buf, "{:x?}", byte).unwrap(); + write!(buf, "{byte:x?}").unwrap(); } buf @@ -5355,7 +5346,7 @@ fn build_closure_caller<'a, 'ctx>( // STEP 1: build function header // e.g. `roc__mainForHost_0_caller` (def_name is `mainForHost_0`) - let function_name = format!("roc__{}_caller", def_name); + let function_name = format!("roc__{def_name}_caller"); let function_spec = FunctionSpec::cconv(env, CCReturn::Void, None, &argument_types); @@ -5467,9 +5458,9 @@ fn build_host_exposed_alias_size_help<'a, 'ctx>( let i64 = env.context.i64_type().as_basic_type_enum(); let size_function_spec = FunctionSpec::cconv(env, CCReturn::Return, Some(i64), &[]); let size_function_name: String = if let Some(label) = opt_label { - format!("roc__{}_{}_size", def_name, label) + format!("roc__{def_name}_{label}_size") } else { - format!("roc__{}_size", def_name,) + format!("roc__{def_name}_size",) }; let size_function = add_func( @@ -5604,10 +5595,7 @@ fn function_value_by_name_help<'a, 'ctx>( ); eprintln!("Is the function defined? If so, maybe there is a problem with the layout"); - panic!( - "Unrecognized builtin function: {:?} (symbol: {:?})", - fn_name, symbol, - ) + panic!("Unrecognized builtin function: {fn_name:?} (symbol: {symbol:?})",) } else { // Unrecognized non-builtin function: eprintln!( @@ -5618,10 +5606,7 @@ fn function_value_by_name_help<'a, 'ctx>( ); eprintln!("Is the function defined? If so, maybe there is a problem with the layout"); - panic!( - "Unrecognized non-builtin function: {:?} (symbol: {:?})", - fn_name, symbol, - ) + panic!("Unrecognized non-builtin function: {fn_name:?} (symbol: {symbol:?})",) } }) } @@ -6282,7 +6267,7 @@ fn define_global_str_literal<'ctx>( message.hash(&mut hasher); let hash = hasher.finish(); - format!("_str_literal_{}", hash) + format!("_str_literal_{hash}") }; match module.get_global(&name) { @@ -6383,7 +6368,7 @@ pub fn add_func<'ctx>( ) -> FunctionValue<'ctx> { if cfg!(debug_assertions) { if let Some(func) = module.get_function(name) { - panic!("Attempting to redefine LLVM function {}, which was already defined in this module as:\n\n{:#?}", name, func); + panic!("Attempting to redefine LLVM function {name}, which was already defined in this module as:\n\n{func:#?}"); } } diff --git a/crates/compiler/gen_llvm/src/llvm/compare.rs b/crates/compiler/gen_llvm/src/llvm/compare.rs index abb94462872..e8572d30cd1 100644 --- a/crates/compiler/gen_llvm/src/llvm/compare.rs +++ b/crates/compiler/gen_llvm/src/llvm/compare.rs @@ -329,8 +329,7 @@ fn build_neq<'a, 'ctx>( ) -> BasicValueEnum<'ctx> { if lhs_layout != rhs_layout { panic!( - "Inequality of different layouts; did you have a type mismatch?\n{:?} != {:?}", - lhs_layout, rhs_layout + "Inequality of different layouts; did you have a type mismatch?\n{lhs_layout:?} != {rhs_layout:?}" ); } @@ -789,7 +788,7 @@ fn build_struct_eq_help<'a, 'ctx>( .into_int_value() }; - current = ctx.append_basic_block(parent, &format!("eq_step_{}", index)); + current = ctx.append_basic_block(parent, &format!("eq_step_{index}")); env.builder .build_conditional_branch(are_equal, current, return_false); diff --git a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs index eae0f438584..0eb198349bc 100644 --- a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs +++ b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs @@ -2892,6 +2892,6 @@ fn load_symbol_and_lambda_set<'a, 'ctx>( let (ptr, layout) = scope.load_symbol_and_layout(symbol); match layout_interner.get_repr(layout) { LayoutRepr::LambdaSet(lambda_set) => (ptr, lambda_set), - other => panic!("Not a lambda set: {:?}, {:?}", other, ptr), + other => panic!("Not a lambda set: {other:?}, {ptr:?}"), } } diff --git a/crates/compiler/gen_llvm/src/llvm/refcounting.rs b/crates/compiler/gen_llvm/src/llvm/refcounting.rs index 90ec11107dc..64749f4a03e 100644 --- a/crates/compiler/gen_llvm/src/llvm/refcounting.rs +++ b/crates/compiler/gen_llvm/src/llvm/refcounting.rs @@ -132,7 +132,7 @@ impl<'ctx> PointerToRefcount<'ctx> { let block = env.builder.get_insert_block().expect("to be in a function"); let di_location = env.builder.get_current_debug_location().unwrap(); - let fn_name = &format!("decrement_refcounted_ptr_{}", alignment); + let fn_name = &format!("decrement_refcounted_ptr_{alignment}"); let function = match env.module.get_function(fn_name) { Some(function_value) => function_value, @@ -1398,7 +1398,7 @@ pub fn build_reset<'a, 'ctx>( let union_layout_repr = LayoutRepr::Union(union_layout); let layout_id = layout_ids.get(Symbol::DEC, &union_layout_repr); let fn_name = layout_id.to_symbol_string(Symbol::DEC, &env.interns); - let fn_name = format!("{}_reset", fn_name); + let fn_name = format!("{fn_name}_reset"); let dec_function = build_rec_union(env, layout_interner, layout_ids, Mode::Dec, union_layout); diff --git a/crates/compiler/gen_llvm/src/llvm/scope.rs b/crates/compiler/gen_llvm/src/llvm/scope.rs index 3261977bc86..a771700e66d 100644 --- a/crates/compiler/gen_llvm/src/llvm/scope.rs +++ b/crates/compiler/gen_llvm/src/llvm/scope.rs @@ -28,17 +28,14 @@ impl<'a, 'ctx> Scope<'a, 'ctx> { match self.symbols.get(symbol) { Some((_, ptr)) => *ptr, - None => panic!( - "There was no entry for {:?} {} in scope {:?}", - symbol, symbol, self - ), + None => panic!("There was no entry for {symbol:?} {symbol} in scope {self:?}"), } } pub fn load_symbol_and_layout(&self, symbol: &Symbol) -> (BasicValueEnum<'ctx>, InLayout<'a>) { match self.symbols.get(symbol) { Some((layout, ptr)) => (*ptr, *layout), - None => panic!("There was no entry for {:?} in scope {:?}", symbol, self), + None => panic!("There was no entry for {symbol:?} in scope {self:?}"), } } diff --git a/crates/compiler/gen_llvm/src/llvm/struct_.rs b/crates/compiler/gen_llvm/src/llvm/struct_.rs index 64226445868..b9ed4ecc9a2 100644 --- a/crates/compiler/gen_llvm/src/llvm/struct_.rs +++ b/crates/compiler/gen_llvm/src/llvm/struct_.rs @@ -126,7 +126,7 @@ fn index_struct_value<'a, 'ctx>( argument, index as _, env.arena - .alloc(format!("struct_field_access_record_{}", index)), + .alloc(format!("struct_field_access_record_{index}")), ); let field_layout = field_layouts[index as usize]; diff --git a/crates/compiler/gen_wasm/src/backend.rs b/crates/compiler/gen_wasm/src/backend.rs index 0d989d5eec4..0a87f5d098b 100644 --- a/crates/compiler/gen_wasm/src/backend.rs +++ b/crates/compiler/gen_wasm/src/backend.rs @@ -313,7 +313,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> { if let Ok(sym_index) = self.module.linking.find_internal_symbol(START) { let fn_index = match self.module.linking.symbol_table[sym_index] { SymInfo::Function(WasmObjectSymbol::ExplicitlyNamed { index, .. }) => index, - _ => panic!("linker symbol `{}` is not a function", START), + _ => panic!("linker symbol `{START}` is not a function"), }; self.module.export.append(Export { name: START, @@ -463,7 +463,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> { if DEBUG_SETTINGS.storage_map { println!("\nStorage:"); for (sym, storage) in self.storage.symbol_storage_map.iter() { - println!("{:?} => {:?}", sym, storage); + println!("{sym:?} => {storage:?}"); } } } @@ -1424,7 +1424,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> { .host_lookup .iter() .find(|(fn_name, _)| *fn_name == name) - .unwrap_or_else(|| panic!("The Roc app tries to call `{}` but I can't find it!", name)); + .unwrap_or_else(|| panic!("The Roc app tries to call `{name}` but I can't find it!")); self.called_fns.set(*fn_index as usize, true); @@ -1614,7 +1614,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> { ListLiteralElement::Literal(lit) => { // This has no Symbol but our storage methods expect one. // Let's just pretend it was defined in a `Let`. - let debug_name = format!("{:?}_{}", sym, i); + let debug_name = format!("{sym:?}_{i}"); let elem_sym = self.create_symbol(&debug_name); let expr = Expr::Literal(*lit); diff --git a/crates/compiler/gen_wasm/src/code_builder.rs b/crates/compiler/gen_wasm/src/code_builder.rs index 92912f0d012..ac20dc7dbed 100644 --- a/crates/compiler/gen_wasm/src/code_builder.rs +++ b/crates/compiler/gen_wasm/src/code_builder.rs @@ -322,10 +322,7 @@ impl<'a> CodeBuilder<'a> { self.add_insertion(pushed_at, SETLOCAL, local_id.0); } else { if DEBUG_SETTINGS.instructions { - println!( - "{:?} has been popped implicitly. Leaving it on the stack.", - symbol - ); + println!("{symbol:?} has been popped implicitly. Leaving it on the stack."); } self.add_insertion(pushed_at, TEELOCAL, local_id.0); } @@ -501,9 +498,7 @@ impl<'a> CodeBuilder<'a> { debug_assert!( stack_size >= pops, - "Wasm value stack underflow. Tried to pop {} but only {} available", - pops, - stack_size + "Wasm value stack underflow. Tried to pop {pops} but only {stack_size} available" ); let new_len = stack_size - pops; @@ -517,11 +512,7 @@ impl<'a> CodeBuilder<'a> { /// Plain instruction without any immediates fn inst(&mut self, opcode: OpCode, pops: usize, push: bool) { self.inst_base(opcode, pops, push); - log_instruction!( - "{:10}\t\t{:?}", - format!("{:?}", opcode), - self.vm_block_stack - ); + log_instruction!("{:10}\t\t{:?}", format!("{opcode:?}"), self.vm_block_stack); } /// Block instruction @@ -538,7 +529,7 @@ impl<'a> CodeBuilder<'a> { value_stack: Vec::with_capacity_in(8, self.arena), }); - log_instruction!("{:10}\t{:?}", format!("{:?}", opcode), &self.vm_block_stack); + log_instruction!("{:10}\t{:?}", format!("{opcode:?}"), &self.vm_block_stack); } fn inst_imm32(&mut self, opcode: OpCode, pops: usize, push: bool, immediate: u32) { @@ -546,7 +537,7 @@ impl<'a> CodeBuilder<'a> { self.code.encode_u32(immediate); log_instruction!( "{:10}\t{}\t{:?}", - format!("{:?}", opcode), + format!("{opcode:?}"), immediate, self.vm_block_stack ); @@ -558,7 +549,7 @@ impl<'a> CodeBuilder<'a> { self.code.encode_u32(offset); log_instruction!( "{:10} {:?} {}\t{:?}", - format!("{:?}", opcode), + format!("{opcode:?}"), align, offset, self.vm_block_stack @@ -654,7 +645,7 @@ impl<'a> CodeBuilder<'a> { log_instruction!( "{:10}\t{}\t{:?}", - format!("{:?}", CALL), + format!("{CALL:?}"), function_index, self.vm_block_stack ); @@ -725,7 +716,7 @@ impl<'a> CodeBuilder<'a> { { log_instruction!( "{:10}\t{}\t{:?}", - format!("{:?}", opcode), + format!("{opcode:?}"), x, self.vm_block_stack ); diff --git a/crates/compiler/gen_wasm/src/low_level.rs b/crates/compiler/gen_wasm/src/low_level.rs index 44d79484944..3ab828f5bef 100644 --- a/crates/compiler/gen_wasm/src/low_level.rs +++ b/crates/compiler/gen_wasm/src/low_level.rs @@ -2063,8 +2063,7 @@ impl<'a> LowLevelCall<'a> { .runtime_representation(backend.storage.symbol_layouts[&self.arguments[1]]); debug_assert_eq!( arg_layout_raw, other_arg_layout, - "Cannot do `==` comparison on different types: {:?} vs {:?}", - arg_layout, other_arg_layout + "Cannot do `==` comparison on different types: {arg_layout:?} vs {other_arg_layout:?}" ); let invert_result = matches!(self.lowlevel, LowLevel::NotEq); @@ -2502,7 +2501,7 @@ pub fn call_higher_order_lowlevel<'a>( } } }; - let wrapper_sym = backend.create_symbol(&format!("#wrap#{:?}", fn_name)); + let wrapper_sym = backend.create_symbol(&format!("#wrap#{fn_name:?}")); let wrapper_layout = { let mut wrapper_arg_layouts: Vec> = Vec::with_capacity_in(argument_layouts.len() + 1, backend.env.arena); diff --git a/crates/compiler/late_solve/src/lib.rs b/crates/compiler/late_solve/src/lib.rs index 96afef7d067..5e5a5ceb64a 100644 --- a/crates/compiler/late_solve/src/lib.rs +++ b/crates/compiler/late_solve/src/lib.rs @@ -52,7 +52,7 @@ impl WorldAbilities { .unwrap() .insert(module, (store, exposed_types)); - debug_assert!(old_store.is_none(), "{:?} abilities not new", module); + debug_assert!(old_store.is_none(), "{module:?} abilities not new"); } #[inline(always)] diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index f219ae0a602..8f1a4437c12 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -175,7 +175,7 @@ fn start_phase<'a>( match opt_dep_name { None => { - panic!("Module {:?} is not in module_cache.module_names", module_id) + panic!("Module {module_id:?} is not in module_cache.module_names") } Some(dep_name) => { let module_name = dep_name.clone(); @@ -820,11 +820,11 @@ impl std::fmt::Display for ModuleTiming { let multiple_make_specializations_passes = module_timing.make_specializations.len() > 1; for (i, pass_time) in module_timing.make_specializations.iter().enumerate() { let suffix = if multiple_make_specializations_passes { - format!(" (Pass {})", i) + format!(" (Pass {i})") } else { String::new() }; - report_timing(f, &format!("Make Specializations{}", suffix), *pass_time)?; + report_timing(f, &format!("Make Specializations{suffix}"), *pass_time)?; } report_timing(f, "Other", module_timing.other())?; f.write_str("\n")?; @@ -1866,7 +1866,7 @@ fn worker_task<'a>( ">>> {}", match &task { BuildTask::LoadModule { module_name, .. } => { - format!("BuildTask::LoadModule({:?})", module_name) + format!("BuildTask::LoadModule({module_name:?})") } BuildTask::Parse { header } => { format!("BuildTask::Parse({})", header.module_path.display()) @@ -1879,10 +1879,10 @@ fn worker_task<'a>( format!("BuildTask::Solve({:?})", module.module_id) } BuildTask::BuildPendingSpecializations { module_id, .. } => { - format!("BuildTask::BuildPendingSpecializations({:?})", module_id) + format!("BuildTask::BuildPendingSpecializations({module_id:?})") } BuildTask::MakeSpecializations { module_id, .. } => { - format!("BuildTask::MakeSpecializations({:?})", module_id) + format!("BuildTask::MakeSpecializations({module_id:?})") } } ); @@ -3248,8 +3248,7 @@ fn load_package_from_disk<'a>( }, _parse_state, )) => Err(LoadingProblem::UnexpectedHeader(format!( - "expected platform/package module, got Interface with header\n{:?}", - header + "expected platform/package module, got Interface with header\n{header:?}" ))), Ok(( ast::Module { @@ -3258,8 +3257,7 @@ fn load_package_from_disk<'a>( }, _parse_state, )) => Err(LoadingProblem::UnexpectedHeader(format!( - "expected platform/package module, got Hosted module with header\n{:?}", - header + "expected platform/package module, got Hosted module with header\n{header:?}" ))), Ok(( ast::Module { @@ -3268,8 +3266,7 @@ fn load_package_from_disk<'a>( }, _parse_state, )) => Err(LoadingProblem::UnexpectedHeader(format!( - "expected platform/package module, got App with header\n{:?}", - header + "expected platform/package module, got App with header\n{header:?}" ))), Ok(( ast::Module { @@ -3402,10 +3399,7 @@ fn load_builtin_module_help<'a>( (info, parse_state) } Ok(_) => panic!("invalid header format for builtin module"), - Err(e) => panic!( - "Hit a parse error in the header of {:?}:\n{:?}", - filename, e - ), + Err(e) => panic!("Hit a parse error in the header of {filename:?}:\n{e:?}"), } } @@ -5583,8 +5577,7 @@ fn build_pending_specializations<'a>( } LayoutProblem::UnresolvedTypeVar(v) => { let message = format!( - "top level function has unresolved type variable {:?}", - v + "top level function has unresolved type variable {v:?}" ); procs_base .runtime_errors @@ -5664,8 +5657,7 @@ fn build_pending_specializations<'a>( } LayoutProblem::UnresolvedTypeVar(v) => { let message = format!( - "top level function has unresolved type variable {:?}", - v + "top level function has unresolved type variable {v:?}" ); procs_base .runtime_errors @@ -5702,14 +5694,13 @@ fn build_pending_specializations<'a>( use roc_can::pattern::Pattern; let symbol = match &loc_pattern.value { Pattern::Identifier(_) => { - debug_assert!(false, "identifier ended up in Destructure {:?}", symbol); + debug_assert!(false, "identifier ended up in Destructure {symbol:?}"); symbol } Pattern::AbilityMemberSpecialization { ident, specializes } => { debug_assert!( false, - "ability member ended up in Destructure {:?} specializes {:?}", - ident, specializes + "ability member ended up in Destructure {ident:?} specializes {specializes:?}" ); symbol } @@ -5741,8 +5732,7 @@ fn build_pending_specializations<'a>( } LayoutProblem::UnresolvedTypeVar(v) => { let message = format!( - "top level function has unresolved type variable {:?}", - v + "top level function has unresolved type variable {v:?}" ); procs_base .runtime_errors @@ -5808,8 +5798,7 @@ fn build_pending_specializations<'a>( } LayoutProblem::UnresolvedTypeVar(v) => { let message = format!( - "top level function has unresolved type variable {:?}", - v + "top level function has unresolved type variable {v:?}" ); procs_base .runtime_errors @@ -5881,8 +5870,7 @@ fn build_pending_specializations<'a>( } LayoutProblem::UnresolvedTypeVar(v) => { let message = format!( - "top level function has unresolved type variable {:?}", - v + "top level function has unresolved type variable {v:?}" ); procs_base .runtime_errors diff --git a/crates/compiler/load_internal/src/work.rs b/crates/compiler/load_internal/src/work.rs index 27712ebb983..fb443c7f035 100644 --- a/crates/compiler/load_internal/src/work.rs +++ b/crates/compiler/load_internal/src/work.rs @@ -67,8 +67,7 @@ impl MakeSpecializationsDependents { let entry = self.entry(module_id); debug_assert!( entry.succ.is_empty(), - "already added successors for module '{:?}'", - module_id + "already added successors for module '{module_id:?}'" ); entry.succ.extend(succ.into_iter()); @@ -516,8 +515,7 @@ impl<'a> Dependencies<'a> { debug_assert_eq!( make_specializations_dependents.0.len(), default_make_specializations_dependents_len, - "more modules were added to the graph: {:?}", - make_specializations_dependents + "more modules were added to the graph: {make_specializations_dependents:?}" ); output @@ -567,8 +565,7 @@ impl<'a> Dependencies<'a> { debug_assert_eq!( make_specializations_dependents.0.len(), default_make_specializations_dependents_len, - "more modules were added to the graph: {:?}", - make_specializations_dependents + "more modules were added to the graph: {make_specializations_dependents:?}" ); output diff --git a/crates/compiler/load_internal/tests/test_load.rs b/crates/compiler/load_internal/tests/test_load.rs index 39f570c2a24..f788e6aed8a 100644 --- a/crates/compiler/load_internal/tests/test_load.rs +++ b/crates/compiler/load_internal/tests/test_load.rs @@ -106,9 +106,9 @@ fn multiple_modules(subdir: &str, files: Vec<(&str, &str)>) -> Result panic!("IO trouble: {:?}", io_error), + Err(io_error) => panic!("IO trouble: {io_error:?}"), Ok(Err(LoadingProblem::FormattedReport(buf))) => Err(buf), - Ok(Err(loading_problem)) => Err(format!("{:?}", loading_problem)), + Ok(Err(loading_problem)) => Err(format!("{loading_problem:?}")), Ok(Ok(mut loaded_module)) => { let home = loaded_module.module_id; let (filepath, src) = loaded_module.sources.get(&home).unwrap(); @@ -148,7 +148,7 @@ fn multiple_modules_help<'a>( // Use a deterministic temporary directory. // We can't have all tests use "tmp" because tests run in parallel, // so append the test name to the tmp path. - let tmp = format!("tmp/{}", subdir); + let tmp = format!("tmp/{subdir}"); let dir = roc_test_utils::TmpDir::new(&tmp); let app_module = files.pop().unwrap(); @@ -162,7 +162,7 @@ fn multiple_modules_help<'a>( fs::create_dir_all(file_path.parent().unwrap())?; let mut file = File::create(file_path)?; - writeln!(file, "{}", source)?; + writeln!(file, "{source}")?; file_handles.push(file); } @@ -173,7 +173,7 @@ fn multiple_modules_help<'a>( let file_path = dir.path().join(filename); let full_file_path = file_path.clone(); let mut file = File::create(file_path)?; - writeln!(file, "{}", source)?; + writeln!(file, "{source}")?; file_handles.push(file); load_and_typecheck(arena, full_file_path, Default::default(), TARGET_INFO) @@ -188,16 +188,16 @@ fn load_fixture( subs_by_module: ExposedByModule, ) -> LoadedModule { let src_dir = fixtures_dir().join(dir_name); - let filename = src_dir.join(format!("{}.roc", module_name)); + let filename = src_dir.join(format!("{module_name}.roc")); let arena = Bump::new(); let loaded = load_and_typecheck(&arena, filename, subs_by_module, TARGET_INFO); let mut loaded_module = match loaded { Ok(x) => x, Err(roc_load_internal::file::LoadingProblem::FormattedReport(report)) => { - println!("{}", report); + println!("{report}"); panic!("{}", report); } - Err(e) => panic!("{:?}", e), + Err(e) => panic!("{e:?}"), }; let home = loaded_module.module_id; @@ -258,7 +258,7 @@ fn expect_types(mut loaded_module: LoadedModule, mut expected_types: HashMap<&st let expected_type = expected_types .remove(fully_qualified.as_str()) .unwrap_or_else(|| { - panic!("Defs included an unexpected symbol: {:?}", fully_qualified) + panic!("Defs included an unexpected symbol: {fully_qualified:?}") }); assert_eq!((&symbol, expected_type), (&symbol, actual_str.as_str())); @@ -273,7 +273,7 @@ fn expect_types(mut loaded_module: LoadedModule, mut expected_types: HashMap<&st let expected_type = expected_types .remove(fully_qualified.as_str()) .unwrap_or_else(|| { - panic!("Defs included an unexpected symbol: {:?}", fully_qualified) + panic!("Defs included an unexpected symbol: {fully_qualified:?}") }); assert_eq!((&symbol, expected_type), (&symbol, actual_str.as_str())); @@ -705,8 +705,7 @@ fn platform_does_not_exist() { // assert!(report.contains("FILE NOT FOUND"), "report=({})", report); assert!( report.contains("zzz-does-not-exist/main.roc"), - "report=({})", - report + "report=({report})" ); } Ok(_) => unreachable!("we expect failure here"), diff --git a/crates/compiler/module/src/symbol.rs b/crates/compiler/module/src/symbol.rs index 89acf366531..0ef28252777 100644 --- a/crates/compiler/module/src/symbol.rs +++ b/crates/compiler/module/src/symbol.rs @@ -172,7 +172,7 @@ impl Symbol { #[cfg(debug_assertions)] pub fn contains(self, needle: &str) -> bool { - format!("{:?}", self).contains(needle) + format!("{self:?}").contains(needle) } } @@ -194,7 +194,7 @@ impl fmt::Debug for Symbol { match DEBUG_IDENT_IDS_BY_MODULE_ID.lock() { Ok(names) => match &names.get(&(module_id.to_zero_indexed() as u32)) { Some(ident_ids) => match ident_ids.get_name(ident_id) { - Some(ident_str) => write!(f, "`{:?}.{}`", module_id, ident_str), + Some(ident_str) => write!(f, "`{module_id:?}.{ident_str}`"), None => fallback_debug_fmt(*self, f), }, None => fallback_debug_fmt(*self, f), @@ -207,7 +207,7 @@ impl fmt::Debug for Symbol { use std::io::Write; let mut stderr = std::io::stderr(); - writeln!(stderr, "DEBUG INFO: Failed to acquire lock for Debug reading from DEBUG_IDENT_IDS_BY_MODULE_ID, presumably because a thread panicked: {:?}", err).unwrap(); + writeln!(stderr, "DEBUG INFO: Failed to acquire lock for Debug reading from DEBUG_IDENT_IDS_BY_MODULE_ID, presumably because a thread panicked: {err:?}").unwrap(); fallback_debug_fmt(*self, f) } @@ -229,7 +229,7 @@ impl fmt::Display for Symbol { let ident_id = self.ident_id(); match ident_id { - IdentId(value) => write!(f, "{:?}.{:?}", module_id, value), + IdentId(value) => write!(f, "{module_id:?}.{value:?}"), } } } @@ -244,7 +244,7 @@ fn fallback_debug_fmt(symbol: Symbol, f: &mut fmt::Formatter) -> fmt::Result { let module_id = symbol.module_id(); let ident_id = symbol.ident_id(); - write!(f, "`{:?}.{:?}`", module_id, ident_id) + write!(f, "`{module_id:?}.{ident_id:?}`") } /// This is used in Debug builds only, to let us have a Debug instance @@ -312,8 +312,8 @@ pub fn get_module_ident_ids<'a>( all_ident_ids .get(module_id) .with_context(|| ModuleIdNotFoundSnafu { - module_id: format!("{:?}", module_id), - all_ident_ids: format!("{:?}", all_ident_ids), + module_id: format!("{module_id:?}"), + all_ident_ids: format!("{all_ident_ids:?}"), }) } @@ -324,7 +324,7 @@ pub fn get_module_ident_ids_mut<'a>( all_ident_ids .get_mut(module_id) .with_context(|| ModuleIdNotFoundSnafu { - module_id: format!("{:?}", module_id), + module_id: format!("{module_id:?}"), all_ident_ids: "I could not return all_ident_ids here because of borrowing issues.", }) } @@ -400,7 +400,7 @@ impl fmt::Debug for ModuleId { if PRETTY_PRINT_DEBUG_SYMBOLS { match names.try_get(self.to_zero_indexed()) { - Some(str_ref) => write!(f, "{}", str_ref), + Some(str_ref) => write!(f, "{str_ref}"), None => { internal_error!( "Could not find a Debug name for module ID {} in {:?}", @@ -645,7 +645,7 @@ impl IdentIds { pub fn update_key(&mut self, old_name: &str, new_name: &str) -> Result { match self.interner.find_and_update(old_name, new_name) { Some(index) => Ok(IdentId(index as u32)), - None => Err(format!("The identifier {:?} is not in IdentIds", old_name)), + None => Err(format!("The identifier {old_name:?} is not in IdentIds")), } } @@ -682,7 +682,7 @@ impl IdentIds { self.get_name(ident_id) .with_context(|| IdentIdNotFoundSnafu { ident_id, - ident_ids_str: format!("{:?}", self), + ident_ids_str: format!("{self:?}"), }) } diff --git a/crates/compiler/mono/src/code_gen_help/equality.rs b/crates/compiler/mono/src/code_gen_help/equality.rs index 71210b4b459..95ae8508636 100644 --- a/crates/compiler/mono/src/code_gen_help/equality.rs +++ b/crates/compiler/mono/src/code_gen_help/equality.rs @@ -138,7 +138,7 @@ fn eq_struct<'a>( ) -> Stmt<'a> { let mut else_stmt = Stmt::Ret(Symbol::BOOL_TRUE); for (i, layout) in field_layouts.iter().enumerate().rev() { - let field1_sym = root.create_symbol(ident_ids, &format!("field_1_{}", i)); + let field1_sym = root.create_symbol(ident_ids, &format!("field_1_{i}")); let field1_expr = Expr::StructAtIndex { index: i as u64, field_layouts, @@ -146,7 +146,7 @@ fn eq_struct<'a>( }; let field1_stmt = |next| Stmt::Let(field1_sym, field1_expr, *layout, next); - let field2_sym = root.create_symbol(ident_ids, &format!("field_2_{}", i)); + let field2_sym = root.create_symbol(ident_ids, &format!("field_2_{i}")); let field2_expr = Expr::StructAtIndex { index: i as u64, field_layouts, @@ -164,7 +164,7 @@ fn eq_struct<'a>( ) .unwrap(); - let eq_call_name = format!("eq_call_{}", i); + let eq_call_name = format!("eq_call_{i}"); let eq_call_sym = root.create_symbol(ident_ids, &eq_call_name); let eq_call_stmt = |next| Stmt::Let(eq_call_sym, eq_call_expr, LAYOUT_BOOL, next); @@ -488,8 +488,8 @@ fn eq_tag_fields<'a>( Some(i) => { // Implement tail recursion on this RecursivePointer, // in the innermost `else` clause after all other fields have been checked - let field1_sym = root.create_symbol(ident_ids, &format!("field_1_{}_{}", tag_id, i)); - let field2_sym = root.create_symbol(ident_ids, &format!("field_2_{}_{}", tag_id, i)); + let field1_sym = root.create_symbol(ident_ids, &format!("field_1_{tag_id}_{i}")); + let field2_sym = root.create_symbol(ident_ids, &format!("field_2_{tag_id}_{i}")); let field1_expr = Expr::UnionAtIndex { union_layout, @@ -533,8 +533,8 @@ fn eq_tag_fields<'a>( continue; // the tail-recursive field is handled elsewhere } - let field1_sym = root.create_symbol(ident_ids, &format!("field_1_{}_{}", tag_id, i)); - let field2_sym = root.create_symbol(ident_ids, &format!("field_2_{}_{}", tag_id, i)); + let field1_sym = root.create_symbol(ident_ids, &format!("field_1_{tag_id}_{i}")); + let field2_sym = root.create_symbol(ident_ids, &format!("field_2_{tag_id}_{i}")); let field1_expr = Expr::UnionAtIndex { union_layout, @@ -560,7 +560,7 @@ fn eq_tag_fields<'a>( ) .unwrap(); - let eq_call_name = format!("eq_call_{}", i); + let eq_call_name = format!("eq_call_{i}"); let eq_call_sym = root.create_symbol(ident_ids, &eq_call_name); stmt = Stmt::Let( diff --git a/crates/compiler/mono/src/code_gen_help/mod.rs b/crates/compiler/mono/src/code_gen_help/mod.rs index cf80c5e5324..30cc8ad5e60 100644 --- a/crates/compiler/mono/src/code_gen_help/mod.rs +++ b/crates/compiler/mono/src/code_gen_help/mod.rs @@ -783,7 +783,7 @@ impl<'a> CallerProc<'a> { .pretty(80) .to_string(); - println!("{}", doc); + println!("{doc}"); } Self { diff --git a/crates/compiler/mono/src/code_gen_help/refcount.rs b/crates/compiler/mono/src/code_gen_help/refcount.rs index 20d9bd58bf6..3f5b90c7fc9 100644 --- a/crates/compiler/mono/src/code_gen_help/refcount.rs +++ b/crates/compiler/mono/src/code_gen_help/refcount.rs @@ -1276,7 +1276,7 @@ fn refcount_struct<'a>( for (i, field_layout) in field_layouts.iter().enumerate().rev() { if layout_interner.contains_refcounted(*field_layout) { - let field_val = root.create_symbol(ident_ids, &format!("field_val_{}", i)); + let field_val = root.create_symbol(ident_ids, &format!("field_val_{i}")); let field_val_expr = Expr::StructAtIndex { index: i as u64, field_layouts, @@ -1284,7 +1284,7 @@ fn refcount_struct<'a>( }; let field_val_stmt = |next| Stmt::Let(field_val, field_val_expr, *field_layout, next); - let mod_unit = root.create_symbol(ident_ids, &format!("mod_field_{}", i)); + let mod_unit = root.create_symbol(ident_ids, &format!("mod_field_{i}")); let mod_args = refcount_args(root, ctx, field_val); let mod_expr = root .call_specialized_op(ident_ids, ctx, layout_interner, *field_layout, mod_args) @@ -1758,7 +1758,7 @@ fn refcount_union_tailrec<'a>( filtered.push((i, *field)); } else { let field_val = - root.create_symbol(ident_ids, &format!("field_{}_{}", tag_id, i)); + root.create_symbol(ident_ids, &format!("field_{tag_id}_{i}")); let field_val_expr = Expr::UnionAtIndex { union_layout, tag_id, @@ -1896,7 +1896,7 @@ fn refcount_tag_fields<'a>( for (i, field_layout) in field_layouts.iter().rev() { if layout_interner.contains_refcounted(*field_layout) { - let field_val = root.create_symbol(ident_ids, &format!("field_{}_{}", tag_id, i)); + let field_val = root.create_symbol(ident_ids, &format!("field_{tag_id}_{i}")); let field_val_expr = Expr::UnionAtIndex { union_layout, tag_id, @@ -1905,7 +1905,7 @@ fn refcount_tag_fields<'a>( }; let field_val_stmt = |next| Stmt::Let(field_val, field_val_expr, *field_layout, next); - let mod_unit = root.create_symbol(ident_ids, &format!("mod_field_{}_{}", tag_id, i)); + let mod_unit = root.create_symbol(ident_ids, &format!("mod_field_{tag_id}_{i}")); let mod_args = refcount_args(root, ctx, field_val); let mod_expr = root .call_specialized_op(ident_ids, ctx, layout_interner, *field_layout, mod_args) diff --git a/crates/compiler/mono/src/debug/report.rs b/crates/compiler/mono/src/debug/report.rs index 1f7dd578352..dfc5558a43f 100644 --- a/crates/compiler/mono/src/debug/report.rs +++ b/crates/compiler/mono/src/debug/report.rs @@ -62,7 +62,7 @@ where .pretty(80) .to_string(); - eprintln!("Full source: {}", src); + eprintln!("Full source: {src}"); let interpolated_docs = stack( f, diff --git a/crates/compiler/mono/src/drop_specialization.rs b/crates/compiler/mono/src/drop_specialization.rs index be2edd43d3f..3079f24a323 100644 --- a/crates/compiler/mono/src/drop_specialization.rs +++ b/crates/compiler/mono/src/drop_specialization.rs @@ -806,7 +806,7 @@ fn specialize_struct<'a, 'i>( // This value has not been index before, create a new symbol. None => { let field_symbol = - environment.create_symbol(ident_ids, &format!("field_val_{}", i)); + environment.create_symbol(ident_ids, &format!("field_val_{i}")); let field_val_expr = Expr::StructAtIndex { index: i as u64, @@ -945,7 +945,7 @@ fn specialize_union<'a, 'i>( Some(rc) => { let field_symbol = environment.create_symbol( ident_ids, - &format!("field_val_{}", i), + &format!("field_val_{i}"), ); let field_val_expr = Expr::UnionAtIndex { @@ -1134,11 +1134,11 @@ fn specialize_list<'a, 'i>( // If the symbol is unknown, we have to get the value from the list. // Should only happen when list elements are discarded. None => { - let field_symbol = environment - .create_symbol(ident_ids, &format!("field_val_{}", i)); + let field_symbol = + environment.create_symbol(ident_ids, &format!("field_val_{i}")); - let index_symbol = environment - .create_symbol(ident_ids, &format!("index_val_{}", i)); + let index_symbol = + environment.create_symbol(ident_ids, &format!("index_val_{i}")); let dec = arena.alloc(Stmt::Refcounting( ModifyRc::Dec(field_symbol), diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index 45686fae6c5..4d8b4182b61 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -181,8 +181,7 @@ impl<'a> PartialProcs<'a> { pub fn insert(&mut self, symbol: Symbol, partial_proc: PartialProc<'a>) -> PartialProcId { debug_assert!( !self.contains_key(symbol), - "The {:?} is inserted as a partial proc twice: that's a bug!", - symbol, + "The {symbol:?} is inserted as a partial proc twice: that's a bug!", ); let id = PartialProcId(self.symbols.len()); @@ -675,7 +674,7 @@ impl<'a> Specialized<'a> { } else { match in_progress { InProgressProc::InProgress => { - panic!("Function {:?} ({:?}) is not done specializing", s, l) + panic!("Function {s:?} ({l:?}) is not done specializing") } InProgressProc::Done(proc) => Some((s, l, proc)), } @@ -838,11 +837,7 @@ impl<'a> SymbolSpecializations<'a> { /// Only those bound to number literals can be compiled polymorphically. fn mark_eligible(&mut self, symbol: Symbol) { let _old = self.0.insert(symbol, VecMap::with_capacity(1)); - debug_assert!( - _old.is_none(), - "overwriting specializations for {:?}", - symbol - ); + debug_assert!(_old.is_none(), "overwriting specializations for {symbol:?}"); } /// Removes all specializations for a symbol, returning the type and symbol of each specialization. @@ -945,8 +940,7 @@ impl<'a> Procs<'a> { .expect("specialization stack is empty"); debug_assert_eq!( popped, specialization, - "incorrect popped specialization: passed {:?}, but was {:?}", - specialization, popped + "incorrect popped specialization: passed {specialization:?}, but was {popped:?}" ); } @@ -1026,7 +1020,7 @@ impl<'a> Procs<'a> { ) -> Result, RuntimeError> { let raw_layout = layout_cache .raw_from_var(env.arena, annotation, env.subs) - .unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {:?}", err)); + .unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {err:?}")); let top_level = ProcLayout::from_raw_named(env.arena, name, raw_layout); @@ -1054,7 +1048,7 @@ impl<'a> Procs<'a> { // if we've already specialized this one, no further work is needed. if !already_specialized { if self.is_module_thunk(name.name()) { - debug_assert!(layout.arguments.is_empty(), "{:?}", name); + debug_assert!(layout.arguments.is_empty(), "{name:?}"); } let needs_suspended_specialization = @@ -1145,7 +1139,7 @@ impl<'a> Procs<'a> { ); } Err(error) => { - panic!("TODO generate a RuntimeError message for {:?}", error); + panic!("TODO generate a RuntimeError message for {error:?}"); } } } @@ -1234,7 +1228,7 @@ impl<'a> Procs<'a> { .insert_specialized(proc_name.name(), proc_layout, proc); } Err(error) => { - panic!("TODO generate a RuntimeError message for {:?}", error); + panic!("TODO generate a RuntimeError message for {error:?}"); } } } @@ -1918,13 +1912,13 @@ pub(crate) fn symbol_to_doc_string(symbol: Symbol, force_pretty: bool) -> String use roc_module::ident::ModuleName; if pretty_print_ir_symbols() || force_pretty { - format!("{:?}", symbol) + format!("{symbol:?}") } else { - let text = format!("{}", symbol); + let text = format!("{symbol}"); if text.starts_with(ModuleName::APP) { let name: String = text.trim_start_matches(ModuleName::APP).into(); - format!("Test{}", name) + format!("Test{name}") } else { text } @@ -2016,7 +2010,7 @@ impl<'a> Expr<'a> { .text("Reset { symbol: ") .append(symbol_to_doc(alloc, *symbol, pretty)) .append(", id: ") - .append(format!("{:?}", update_mode)) + .append(format!("{update_mode:?}")) .append(" }"), ResetRef { symbol, @@ -2025,7 +2019,7 @@ impl<'a> Expr<'a> { .text("ResetRef { symbol: ") .append(symbol_to_doc(alloc, *symbol, pretty)) .append(", id: ") - .append(format!("{:?}", update_mode)) + .append(format!("{update_mode:?}")) .append(" }"), Struct(args) => { let it = args.iter().map(|s| symbol_to_doc(alloc, *s, pretty)); @@ -3036,7 +3030,7 @@ fn specialize_external_help<'a>( let partial_proc_id = match procs.partial_procs.symbol_to_id(name.name()) { Some(v) => v, None => { - panic!("Cannot find a partial proc for {:?}", name); + panic!("Cannot find a partial proc for {name:?}"); } }; @@ -3765,8 +3759,7 @@ fn build_specialized_proc<'a>( debug_assert_eq!( pattern_layouts_len + 1, pattern_symbols.len(), - "Tried to zip two vecs with different lengths in {:?}!", - proc_name, + "Tried to zip two vecs with different lengths in {proc_name:?}!", ); let proc_args = proc_args.into_bump_slice(); @@ -3806,14 +3799,12 @@ fn build_specialized_proc<'a>( // so far, the problem when hitting this branch was always somewhere else // I think this branch should not be reachable in a bugfree compiler panic!( - "more arguments (according to the layout) than argument symbols for {:?}", - proc_name + "more arguments (according to the layout) than argument symbols for {proc_name:?}" ) } } Ordering::Less => panic!( - "more argument symbols than arguments (according to the layout) for {:?}", - proc_name + "more argument symbols than arguments (according to the layout) for {proc_name:?}" ), } } @@ -3845,14 +3836,12 @@ fn build_specialized_proc<'a>( // so far, the problem when hitting this branch was always somewhere else // I think this branch should not be reachable in a bugfree compiler panic!( - "more arguments (according to the layout) than argument symbols for {:?}", - proc_name + "more arguments (according to the layout) than argument symbols for {proc_name:?}" ) } } Ordering::Less => panic!( - "more argument symbols than arguments (according to the layout) for {:?}", - proc_name + "more argument symbols than arguments (according to the layout) for {proc_name:?}" ), } } @@ -3881,7 +3870,7 @@ fn specialize_variable<'a>( // TODO: can we get rid of raw entirely? let raw = layout_cache .raw_from_var(env.arena, fn_var, env.subs) - .unwrap_or_else(|err| panic!("TODO handle invalid function {:?}", err)); + .unwrap_or_else(|err| panic!("TODO handle invalid function {err:?}")); let raw = if procs.is_module_thunk(proc_name.name()) { match raw { @@ -4043,7 +4032,7 @@ fn specialize_naked_symbol<'a>( return result; } else if env.is_imported_symbol(symbol) { match layout_cache.from_var(env.arena, variable, env.subs) { - Err(e) => panic!("invalid layout {:?}", e), + Err(e) => panic!("invalid layout {e:?}"), Ok(_) => { // this is a 0-arity thunk let result = call_by_name( @@ -4573,7 +4562,7 @@ pub fn with_hole<'a>( let layout = layout_cache .from_var(env.arena, branch_var, env.subs) .unwrap_or_else(|err| { - panic!("TODO turn fn_var into a RuntimeError {:?}", err) + panic!("TODO turn fn_var into a RuntimeError {err:?}") }); let param = Param { @@ -4639,7 +4628,7 @@ pub fn with_hole<'a>( let layout = layout_cache .from_var(env.arena, expr_var, env.subs) - .unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {:?}", err)); + .unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {err:?}")); let param = Param { symbol: assigned, @@ -4692,7 +4681,7 @@ pub fn with_hole<'a>( let elem_layout = layout_cache .from_var(env.arena, elem_var, env.subs) - .unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {:?}", err)); + .unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {err:?}")); for arg_expr in loc_elems.into_iter() { if let Some(literal) = @@ -5033,7 +5022,7 @@ pub fn with_hole<'a>( let record_layout = layout_cache .from_var(env.arena, record_var, env.subs) - .unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {:?}", err)); + .unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {err:?}")); let field_layouts = match layout_cache.get_repr(record_layout) { LayoutRepr::Struct(field_layouts) => field_layouts, @@ -5181,7 +5170,7 @@ pub fn with_hole<'a>( if let Err(e) = inserted { return runtime_error( env, - env.arena.alloc(format!("RuntimeError: {:?}", e,)), + env.arena.alloc(format!("RuntimeError: {e:?}",)), ); } else { drop(inserted); @@ -5754,7 +5743,7 @@ fn compile_struct_like_access<'a>( let layout = layout_cache .from_var(env.arena, elem_var, env.subs) - .unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {:?}", err)); + .unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {err:?}")); Stmt::Let(assigned, expr, layout, hole) } @@ -6197,7 +6186,7 @@ fn convert_tag_union<'a>( // Layout will unpack this unwrapped tack if it only has one (non-zero-sized) field let layout = layout_cache .from_var(env.arena, variant_var, env.subs) - .unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {:?}", err)); + .unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {err:?}")); // even though this was originally a Tag, we treat it as a Struct from now on let stmt = if let [only_field] = field_symbols { @@ -6231,7 +6220,7 @@ fn convert_tag_union<'a>( // Layout will unpack this unwrapped tack if it only has one (non-zero-sized) field let layout = layout_cache .from_var(env.arena, variant_var, env.subs) - .unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {:?}", err)); + .unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {err:?}")); // even though this was originally a Tag, we treat it as a Struct from now on let stmt = if let [only_field] = field_symbols { @@ -6496,8 +6485,7 @@ fn tag_union_to_function<'a>( Err(e) => runtime_error( env, env.arena.alloc(format!( - "Could not produce tag function due to a runtime error: {:?}", - e, + "Could not produce tag function due to a runtime error: {e:?}", )), ), } @@ -8284,17 +8272,13 @@ fn call_by_name<'a>( match layout_cache.raw_from_var(env.arena, fn_var, env.subs) { Err(LayoutProblem::UnresolvedTypeVar(var)) => { let msg = format!( - "Hit an unresolved type variable {:?} when creating a layout for {:?} (var {:?})", - var, proc_name, fn_var + "Hit an unresolved type variable {var:?} when creating a layout for {proc_name:?} (var {fn_var:?})" ); evaluate_arguments_then_runtime_error(env, procs, layout_cache, msg, loc_args) } Err(LayoutProblem::Erroneous) => { - let msg = format!( - "Hit an erroneous type when creating a layout for {:?}", - proc_name - ); + let msg = format!("Hit an erroneous type when creating a layout for {proc_name:?}"); evaluate_arguments_then_runtime_error(env, procs, layout_cache, msg, loc_args) } @@ -8446,9 +8430,7 @@ fn call_by_name_help<'a>( Some(name) => { debug_assert!( iter_lambda_names.next().is_none(), - "Somehow, call by name for {:?} has multiple capture niches: {:?}", - proc_name, - lambda_set + "Somehow, call by name for {proc_name:?} has multiple capture niches: {lambda_set:?}" ); name } @@ -8487,8 +8469,7 @@ fn call_by_name_help<'a>( debug_assert_eq!( argument_layouts.len(), field_symbols.len(), - "see call_by_name for background (scroll down a bit), function is {:?}", - proc_name, + "see call_by_name for background (scroll down a bit), function is {proc_name:?}", ); call_specialized_proc( env, @@ -8539,8 +8520,7 @@ fn call_by_name_help<'a>( debug_assert_eq!( argument_layouts.len(), field_symbols.len(), - "see call_by_name for background (scroll down a bit), function is {:?}", - proc_name, + "see call_by_name for background (scroll down a bit), function is {proc_name:?}", ); let field_symbols = field_symbols.into_bump_slice(); @@ -8592,8 +8572,7 @@ fn call_by_name_help<'a>( debug_assert_eq!( argument_layouts.len(), field_symbols.len(), - "see call_by_name for background (scroll down a bit), function is {:?}", - proc_name, + "see call_by_name for background (scroll down a bit), function is {proc_name:?}", ); let field_symbols = field_symbols.into_bump_slice(); @@ -8784,8 +8763,7 @@ fn call_by_name_module_thunk<'a>( Ok((proc, raw_layout)) => { debug_assert!( raw_layout.is_zero_argument_thunk(), - "but actually {:?}", - raw_layout + "but actually {raw_layout:?}" ); let was_present = procs @@ -9044,10 +9022,9 @@ where } None => { eprintln!( - "a function passed to `{:?}` LowLevel call has an empty lambda set! + "a function passed to `{op:?}` LowLevel call has an empty lambda set! The most likely reason is that some symbol you use is not in scope. - ", - op + " ); hole.clone() @@ -10073,7 +10050,7 @@ fn unique_glue_symbol( use std::fmt::Write; let mut string = bumpalo::collections::String::with_capacity_in(32, arena); - let _result = write!(&mut string, "roc__getter_{}_{}", module_name, unique_id); + let _result = write!(&mut string, "roc__getter_{module_name}_{unique_id}"); debug_assert_eq!(_result, Ok(())); // This should never fail, but doesn't hurt to debug-check! let bump_string = string.into_bump_str(); diff --git a/crates/compiler/mono/src/ir/decision_tree.rs b/crates/compiler/mono/src/ir/decision_tree.rs index b34141e618f..76ba8e6a795 100644 --- a/crates/compiler/mono/src/ir/decision_tree.rs +++ b/crates/compiler/mono/src/ir/decision_tree.rs @@ -775,8 +775,7 @@ fn to_relevant_branch<'a>( // if there is no test, the pattern should not require any debug_assert!( matches!(pattern, Pattern::Identifier(_) | Pattern::Underscore,), - "{:?}", - pattern, + "{pattern:?}", ); Some(branch.clone()) diff --git a/crates/compiler/mono/src/layout.rs b/crates/compiler/mono/src/layout.rs index d6ffe895106..dbf9704f7d2 100644 --- a/crates/compiler/mono/src/layout.rs +++ b/crates/compiler/mono/src/layout.rs @@ -165,8 +165,7 @@ impl<'a> LayoutCache<'a> { let Cacheable(value, criteria) = Layout::from_var(&mut env, var); debug_assert!( criteria.is_cacheable(), - "{:?} not cacheable as top-level", - value + "{value:?} not cacheable as top-level" ); value } @@ -192,8 +191,7 @@ impl<'a> LayoutCache<'a> { let Cacheable(value, criteria) = RawFunctionLayout::from_var(&mut env, var); debug_assert!( criteria.is_cacheable(), - "{:?} not cacheable as top-level", - value + "{value:?} not cacheable as top-level" ); value } @@ -1485,9 +1483,7 @@ impl<'a> LambdaSet<'a> { { debug_assert!( self.contains(function_symbol), - "function symbol {:?} not in set {:?}", - function_symbol, - self + "function symbol {function_symbol:?} not in set {self:?}" ); let comparator = |other_name: Symbol, other_captures_layouts: &[InLayout<'a>]| { @@ -3210,10 +3206,7 @@ fn layout_from_flat_type<'a>( Cacheable(Ok(boxed_layout), criteria) } _ => { - panic!( - "TODO layout_from_flat_type for Apply({:?}, {:?})", - symbol, args - ); + panic!("TODO layout_from_flat_type for Apply({symbol:?}, {args:?})"); } } } @@ -3664,7 +3657,7 @@ pub fn union_sorted_tags<'a>( Error => return Err(LayoutProblem::Erroneous), - other => panic!("invalid content in tag union variable: {:?}", other), + other => panic!("invalid content in tag union variable: {other:?}"), } } }; @@ -4387,7 +4380,7 @@ pub fn ext_var_is_empty_tag_union(subs: &Subs, tag_ext: TagExt) -> bool { } // So that we can continue compiling in the presence of errors Error => ext_fields.is_empty(), - _ => panic!("invalid content in ext_var: {:?}", content), + _ => panic!("invalid content in ext_var: {content:?}"), } } } @@ -4442,17 +4435,14 @@ fn layout_from_num_content<'a>( Symbol::NUM_DEC => Ok(Layout::DEC), _ => { - panic!( - "Invalid Num.Num type application: Apply({:?}, {:?})", - symbol, args - ); + panic!("Invalid Num.Num type application: Apply({symbol:?}, {args:?})"); } }, Alias(_, _, _, _) => { todo!("TODO recursively resolve type aliases in num_from_content"); } Structure(_) | RangedNumber(..) | LambdaSet(_) => { - panic!("Invalid Num.Num type application: {:?}", content); + panic!("Invalid Num.Num type application: {content:?}"); } Error => Err(LayoutProblem::Erroneous), }; diff --git a/crates/compiler/parse/src/ast.rs b/crates/compiler/parse/src/ast.rs index c0d35d67c0e..f1d6729c336 100644 --- a/crates/compiler/parse/src/ast.rs +++ b/crates/compiler/parse/src/ast.rs @@ -743,8 +743,8 @@ impl<'a> CommentOrNewline<'a> { use CommentOrNewline::*; match self { Newline => "\n".to_owned(), - LineComment(comment_str) => format!("#{}", comment_str), - DocComment(comment_str) => format!("##{}", comment_str), + LineComment(comment_str) => format!("#{comment_str}"), + DocComment(comment_str) => format!("##{comment_str}"), } } diff --git a/crates/compiler/parse/src/state.rs b/crates/compiler/parse/src/state.rs index 03e29519eb3..7e4207584f4 100644 --- a/crates/compiler/parse/src/state.rs +++ b/crates/compiler/parse/src/state.rs @@ -136,7 +136,7 @@ impl<'a> fmt::Debug for State<'a> { write!(f, "State {{")?; match std::str::from_utf8(self.bytes()) { - Ok(string) => write!(f, "\n\tbytes: [utf8] {:?}", string)?, + Ok(string) => write!(f, "\n\tbytes: [utf8] {string:?}")?, Err(_) => write!(f, "\n\tbytes: [invalid utf8] {:?}", self.bytes())?, } @@ -151,5 +151,5 @@ fn state_size() { // cache line. let state_size = std::mem::size_of::(); let maximum = std::mem::size_of::() * 8; - assert!(state_size <= maximum, "{:?} <= {:?}", state_size, maximum); + assert!(state_size <= maximum, "{state_size:?} <= {maximum:?}"); } diff --git a/crates/compiler/parse/tests/test_parse.rs b/crates/compiler/parse/tests/test_parse.rs index b22b7d7aa5b..b55e1ad269a 100644 --- a/crates/compiler/parse/tests/test_parse.rs +++ b/crates/compiler/parse/tests/test_parse.rs @@ -81,7 +81,7 @@ mod test_parse { #[test] fn string_with_escaped_char_at_end() { parses_with_escaped_char( - |esc| format!(r#""abcd{}""#, esc), + |esc| format!(r#""abcd{esc}""#), |esc, arena| bumpalo::vec![in arena; Plaintext("abcd"), EscapedChar(esc)], ); } @@ -89,7 +89,7 @@ mod test_parse { #[test] fn string_with_escaped_char_in_front() { parses_with_escaped_char( - |esc| format!(r#""{}abcd""#, esc), + |esc| format!(r#""{esc}abcd""#), |esc, arena| bumpalo::vec![in arena; EscapedChar(esc), Plaintext("abcd")], ); } @@ -97,7 +97,7 @@ mod test_parse { #[test] fn string_with_escaped_char_in_middle() { parses_with_escaped_char( - |esc| format!(r#""ab{}cd""#, esc), + |esc| format!(r#""ab{esc}cd""#), |esc, arena| bumpalo::vec![in arena; Plaintext("ab"), EscapedChar(esc), Plaintext("cd")], ); } @@ -105,7 +105,7 @@ mod test_parse { #[test] fn string_with_multiple_escaped_chars() { parses_with_escaped_char( - |esc| format!(r#""{}abc{}de{}fghi{}""#, esc, esc, esc, esc), + |esc| format!(r#""{esc}abc{esc}de{esc}fghi{esc}""#), |esc, arena| bumpalo::vec![in arena; EscapedChar(esc), Plaintext("abc"), EscapedChar(esc), Plaintext("de"), EscapedChar(esc), Plaintext("fghi"), EscapedChar(esc)], ); } @@ -247,7 +247,7 @@ mod test_parse { // These can potentially be whole numbers. `Display` omits the decimal point for those, // causing them to no longer be parsed as fractional numbers by Roc. // Using `Debug` instead of `Display` ensures they always have a decimal point. - let float_string = format!("{:?}", num); + let float_string = format!("{num:?}"); assert_parses_to(float_string.as_str(), Float(float_string.as_str())); } @@ -284,7 +284,7 @@ mod test_parse { // It should occur twice in the debug output - once for the pattern, // and then again for the lookup. - let occurrences = format!("{:?}", actual).split("isTest").count() - 1; + let occurrences = format!("{actual:?}").split("isTest").count() - 1; assert_eq!(occurrences, 2); } diff --git a/crates/compiler/problem/src/can.rs b/crates/compiler/problem/src/can.rs index fdeb251f338..2a9d97f31c8 100644 --- a/crates/compiler/problem/src/can.rs +++ b/crates/compiler/problem/src/can.rs @@ -613,11 +613,10 @@ impl RuntimeError { match self { DegenerateBranch(region) => { format!( - "Hit a branch pattern that does not bind all symbols its body needs, at {:?}", - region + "Hit a branch pattern that does not bind all symbols its body needs, at {region:?}" ) } - err => format!("{:?}", err), + err => format!("{err:?}"), } } } diff --git a/crates/compiler/region/src/all.rs b/crates/compiler/region/src/all.rs index 9b556b76b45..ce13c1131bc 100644 --- a/crates/compiler/region/src/all.rs +++ b/crates/compiler/region/src/all.rs @@ -434,10 +434,7 @@ fn test_line_info() { } else { "\n" // HACK! pretend there's an extra newline on the end, strictly so we can do the comparison }; - println!( - "checking {:?} {:?}, expecting {:?}", - input, offset, expected - ); + println!("checking {input:?} {offset:?}, expecting {expected:?}"); let line_column = info.convert_offset(offset as u32); assert!( Some(line_column) > last, diff --git a/crates/compiler/solve/src/ability.rs b/crates/compiler/solve/src/ability.rs index c5ab1f60333..fa93bf1f2ff 100644 --- a/crates/compiler/solve/src/ability.rs +++ b/crates/compiler/solve/src/ability.rs @@ -1322,8 +1322,7 @@ pub fn type_implementing_specialization( .filter(|mia| mia.ability == ability) .count() } < 2, - "Multiple variables bound to an ability - this is ambiguous and should have been caught in canonicalization: {:?}", - specialization_must_implement_constraints + "Multiple variables bound to an ability - this is ambiguous and should have been caught in canonicalization: {specialization_must_implement_constraints:?}" ); specialization_must_implement_constraints diff --git a/crates/compiler/solve/src/pools.rs b/crates/compiler/solve/src/pools.rs index e3e86c20472..877ebbec796 100644 --- a/crates/compiler/solve/src/pools.rs +++ b/crates/compiler/solve/src/pools.rs @@ -27,14 +27,14 @@ impl Pools { pub fn get_mut(&mut self, rank: Rank) -> &mut Vec { match self.0.get_mut(rank.into_usize()) { Some(reference) => reference, - None => panic!("Compiler bug: could not find pool at rank {}", rank), + None => panic!("Compiler bug: could not find pool at rank {rank}"), } } pub fn get(&self, rank: Rank) -> &Vec { match self.0.get(rank.into_usize()) { Some(reference) => reference, - None => panic!("Compiler bug: could not find pool at rank {}", rank), + None => panic!("Compiler bug: could not find pool at rank {rank}"), } } diff --git a/crates/compiler/solve/src/solve.rs b/crates/compiler/solve/src/solve.rs index ea36ca5391b..ed55fa86155 100644 --- a/crates/compiler/solve/src/solve.rs +++ b/crates/compiler/solve/src/solve.rs @@ -404,7 +404,7 @@ fn solve( if it.peek().is_some() { let failing: Vec<_> = it.collect(); println!("Rigids {:?}", &rigid_vars); - println!("Failing {:?}", failing); + println!("Failing {failing:?}"); debug_assert!(false); } }); @@ -1739,8 +1739,7 @@ fn check_ability_specialization( ); debug_assert!( !awaiting_specializations.waiting_for(impl_key), - "still have lambda sets waiting for {:?}, but it was just resolved", - impl_key + "still have lambda sets waiting for {impl_key:?}, but it was just resolved" ); } } diff --git a/crates/compiler/solve/src/specialize.rs b/crates/compiler/solve/src/specialize.rs index 1ea79cff59a..36c17ad2018 100644 --- a/crates/compiler/solve/src/specialize.rs +++ b/crates/compiler/solve/src/specialize.rs @@ -187,9 +187,9 @@ fn trace_compaction_step_1(subs: &Subs, c_a: Variable, uls_a: &[Variable]) { .collect::>() .join(","); eprintln!("===lambda set compaction==="); - eprintln!(" concrete type: {:?}", c_a); + eprintln!(" concrete type: {c_a:?}"); eprintln!(" step 1:"); - eprintln!(" uls_a = {{ {} }}", uls_a); + eprintln!(" uls_a = {{ {uls_a} }}"); } #[cfg(debug_assertions)] @@ -205,7 +205,7 @@ fn trace_compaction_step_2(subs: &Subs, uls_a: &[Variable]) { .collect::>() .join(","); eprintln!(" step 2:"); - eprintln!(" uls_a' = {{ {} }}", uls_a); + eprintln!(" uls_a' = {{ {uls_a} }}"); } #[cfg(debug_assertions)] @@ -226,9 +226,9 @@ fn trace_compaction_step_3iter_start( ); let t_f1 = roc_types::subs::SubsFmtContent(subs.get_content_without_compacting(t_f1), subs); let t_f2 = roc_types::subs::SubsFmtContent(subs.get_content_without_compacting(t_f2), subs); - eprintln!(" - iteration: {:?}", iteration_lambda_set); - eprintln!(" {:?}", t_f1); - eprintln!(" ~ {:?}", t_f2); + eprintln!(" - iteration: {iteration_lambda_set:?}"); + eprintln!(" {t_f1:?}"); + eprintln!(" ~ {t_f2:?}"); } #[cfg(debug_assertions)] @@ -239,7 +239,7 @@ fn trace_compaction_step_3iter_end(subs: &Subs, t_f_result: Variable, skipped: b if skipped { eprintln!(" SKIP"); } - eprintln!(" = {:?}\n", t_f_result); + eprintln!(" = {t_f_result:?}\n"); } macro_rules! trace_compact { @@ -536,7 +536,7 @@ fn compact_lambda_set( Err(()) => { // Do nothing other than to remove the concrete lambda to drop from the lambda set, // which we already did in 1b above. - trace_compact!(3iter_end_skipped. env.subs, t_f1); + trace_compact!(3iter_end_skipped.env.subs, t_f1); return OneCompactionResult::Compacted { new_obligations: Default::default(), new_lambda_sets_to_specialize: Default::default(), @@ -559,7 +559,7 @@ fn compact_lambda_set( Err(()) => { // Do nothing other than to remove the concrete lambda to drop from the lambda set, // which we already did in 1b above. - trace_compact!(3iter_end_skipped. env.subs, t_f1); + trace_compact!(3iter_end_skipped.env.subs, t_f1); return OneCompactionResult::Compacted { new_obligations: Default::default(), new_lambda_sets_to_specialize: Default::default(), @@ -572,7 +572,7 @@ fn compact_lambda_set( let t_f2 = deep_copy_var_in(env, target_rank, t_f2, env.arena); // 3. Unify `t_f1 ~ t_f2`. - trace_compact!(3iter_start. env.subs, this_lambda_set, t_f1, t_f2); + trace_compact!(3iter_start.env.subs, this_lambda_set, t_f1, t_f2); let (vars, new_obligations, new_lambda_sets_to_specialize, _meta) = unify( &mut env.uenv(), t_f1, @@ -581,7 +581,7 @@ fn compact_lambda_set( Polarity::Pos, ) .expect_success("ambient functions don't unify"); - trace_compact!(3iter_end. env.subs, t_f1); + trace_compact!(3iter_end.env.subs, t_f1); env.introduce(target_rank, &vars); diff --git a/crates/compiler/solve/tests/solve_expr.rs b/crates/compiler/solve/tests/solve_expr.rs index 45dfa9f7b82..98392e80f42 100644 --- a/crates/compiler/solve/tests/solve_expr.rs +++ b/crates/compiler/solve/tests/solve_expr.rs @@ -49,7 +49,7 @@ mod solve_expr { exposed_to_host.retain(|s, _| !abilities_store.is_specialization_name(*s)); - debug_assert!(exposed_to_host.len() == 1, "{:?}", exposed_to_host); + debug_assert!(exposed_to_host.len() == 1, "{exposed_to_host:?}"); let (_symbol, variable) = exposed_to_host.into_iter().next().unwrap(); let actual_str = name_and_print_var(variable, subs, home, &interns, DebugPrint::NOTHING); @@ -61,8 +61,7 @@ mod solve_expr { assert!( can_problems.is_empty(), - "Canonicalization problems: {}", - can_problems + "Canonicalization problems: {can_problems}" ); assert_eq!(actual, expected.to_string()); @@ -73,17 +72,13 @@ mod solve_expr { assert!( can_problems.is_empty(), - "Canonicalization problems: {}", - can_problems + "Canonicalization problems: {can_problems}" ); if !type_problems.is_empty() { // fail with an assert, but print the problems normally so rust doesn't try to diff // an empty vec with the problems. - panic!( - "expected:\n{:?}\ninferred:\n{:?}\nproblems:\n{}", - expected, actual, type_problems, - ); + panic!("expected:\n{expected:?}\ninferred:\n{actual:?}\nproblems:\n{type_problems}",); } assert_eq!(actual, expected.to_string()); } diff --git a/crates/compiler/test_derive/src/util.rs b/crates/compiler/test_derive/src/util.rs index 26d4b6040ce..d6e8d5fa10f 100644 --- a/crates/compiler/test_derive/src/util.rs +++ b/crates/compiler/test_derive/src/util.rs @@ -335,7 +335,7 @@ fn assemble_derived_golden( specialization_lsets.sort_by_key(|(region, _)| *region); for (region, var) in specialization_lsets { let pretty_lset = print_var(var, false); - let _ = writeln!(pretty_buf, "# @<{}>: {}", region, pretty_lset); + let _ = writeln!(pretty_buf, "# @<{region}>: {pretty_lset}"); } pretty_buf.push_str(derived_source); @@ -476,10 +476,7 @@ fn check_derived_typechecks_and_golden( .render_raw(80, &mut roc_reporting::report::CiWrite::new(&mut buf)) .unwrap(); - panic!( - "Derived does not typecheck:\n{}\nDerived def:\n{}", - buf, derived_program - ); + panic!("Derived does not typecheck:\n{buf}\nDerived def:\n{derived_program}"); } let golden = assemble_derived_golden( diff --git a/crates/compiler/test_gen/benches/list_map.rs b/crates/compiler/test_gen/benches/list_map.rs index 665f6f3cb44..877957322b0 100644 --- a/crates/compiler/test_gen/benches/list_map.rs +++ b/crates/compiler/test_gen/benches/list_map.rs @@ -65,7 +65,7 @@ fn roc_function<'a, 'b>( let (main_fn_name, errors, lib) = helpers::llvm::helper(arena, config, source, arena.alloc(context)); - assert!(errors.is_empty(), "Encountered errors:\n{}", errors); + assert!(errors.is_empty(), "Encountered errors:\n{errors}"); run_roc_dylib!(arena.alloc(lib), main_fn_name, &Input, Output) } diff --git a/crates/compiler/test_gen/benches/quicksort.rs b/crates/compiler/test_gen/benches/quicksort.rs index 6c4dcf910f4..2c02646b492 100644 --- a/crates/compiler/test_gen/benches/quicksort.rs +++ b/crates/compiler/test_gen/benches/quicksort.rs @@ -94,7 +94,7 @@ fn roc_function<'a>( let (main_fn_name, errors, lib) = helpers::llvm::helper(arena, config, source, arena.alloc(context)); - assert!(errors.is_empty(), "Encountered errors:\n{}", errors); + assert!(errors.is_empty(), "Encountered errors:\n{errors}"); run_roc_dylib!(arena.alloc(lib), main_fn_name, *mut Input, Output) } diff --git a/crates/compiler/test_gen/build.rs b/crates/compiler/test_gen/build.rs index a9abb28f13d..2cd8f9cb45b 100644 --- a/crates/compiler/test_gen/build.rs +++ b/crates/compiler/test_gen/build.rs @@ -41,8 +41,8 @@ fn build_wasm_linking_test_host() { let host_wasm: &str = host_wasm_path.to_str().unwrap(); let host_native: &str = host_native_path.to_str().unwrap(); - println!("cargo:rerun-if-changed={}", host_source); - println!("cargo:rerun-if-changed={}", import_source); + println!("cargo:rerun-if-changed={host_source}"); + println!("cargo:rerun-if-changed={import_source}"); if !Path::new("build").exists() { fs::create_dir("build").unwrap(); @@ -57,7 +57,7 @@ fn build_wasm_linking_test_host() { "-target", "wasm32-freestanding-musl", host_source, - &format!("-femit-bin={}", host_wasm), + &format!("-femit-bin={host_wasm}"), ]); let mut import_obj_path = PathBuf::from("build").join("wasm_linking_host_imports"); @@ -73,7 +73,7 @@ fn build_wasm_linking_test_host() { "build-exe", host_source, import_obj, - &format!("-femit-bin={}", host_native), + &format!("-femit-bin={host_native}"), #[cfg(windows)] "--subsystem", #[cfg(windows)] @@ -148,7 +148,7 @@ fn run_zig(args: &[&str]) { let mut zig_cmd = zig(); let full_zig_cmd = zig_cmd.args(args); - println!("{:?}", full_zig_cmd); + println!("{full_zig_cmd:?}"); let zig_cmd_output = full_zig_cmd.output().unwrap(); @@ -164,6 +164,6 @@ fn run_zig(args: &[&str]) { panic!("zig call failed with status {:?}", zig_cmd_output.status); } - assert!(zig_cmd_output.stdout.is_empty(), "{:#?}", zig_cmd_output); - assert!(zig_cmd_output.stderr.is_empty(), "{:#?}", zig_cmd_output); + assert!(zig_cmd_output.stdout.is_empty(), "{zig_cmd_output:#?}"); + assert!(zig_cmd_output.stderr.is_empty(), "{zig_cmd_output:#?}"); } diff --git a/crates/compiler/test_gen/src/gen_list.rs b/crates/compiler/test_gen/src/gen_list.rs index 5a29e47d2f1..af7ededf091 100644 --- a/crates/compiler/test_gen/src/gen_list.rs +++ b/crates/compiler/test_gen/src/gen_list.rs @@ -1776,14 +1776,14 @@ fn assert_concat_worked(num_elems1: i64, num_elems2: i64) { let vec2: Vec = (0..num_elems2) .map(|i| 54321 % (i + num_elems1 + num_elems2 + 1)) .collect(); - let slice_str1 = format!("{:?}", vec1); - let slice_str2 = format!("{:?}", vec2); + let slice_str1 = format!("{vec1:?}"); + let slice_str2 = format!("{vec2:?}"); let mut expected = vec1; expected.extend(vec2); assert_evals_to!( - &format!("List.concat {} {}", slice_str1, slice_str2), + &format!("List.concat {slice_str1} {slice_str2}"), RocList::from_slice(&expected), RocList ); diff --git a/crates/compiler/test_gen/src/helpers/llvm.rs b/crates/compiler/test_gen/src/helpers/llvm.rs index 6ad7cc29a37..ad1a7bcd0ad 100644 --- a/crates/compiler/test_gen/src/helpers/llvm.rs +++ b/crates/compiler/test_gen/src/helpers/llvm.rs @@ -89,10 +89,10 @@ fn create_llvm_module<'a>( Err(LoadMonomorphizedError::LoadingProblem(roc_load::LoadingProblem::FormattedReport( report, ))) => { - println!("{}", report); + println!("{report}"); panic!(); } - Err(e) => panic!("{:?}", e), + Err(e) => panic!("{e:?}"), }; use roc_load::MonomorphizedModule; @@ -283,8 +283,7 @@ fn create_llvm_module<'a>( let path = std::env::temp_dir().join("test.ll"); env.module.print_to_file(&path).unwrap(); panic!( - "Errors defining module:\n\n{}\n\nI have written the full module to `{:?}`", - errors, path + "Errors defining module:\n\n{errors}\n\nI have written the full module to `{path:?}`" ); }; @@ -374,7 +373,7 @@ fn annotate_with_debug_info<'ctx>( ErrorKind::NotFound => panic!( r"I could not find the `debugir` tool on the PATH, install it from https://github.com/vaivaswatha/debugir" ), - _ => panic!("{:?}", error), + _ => panic!("{error:?}"), } } } @@ -495,17 +494,14 @@ fn llvm_module_to_wasm_file( let msg = String::from_utf8_lossy(&output.stderr); if msg.contains("wasm-ld: error: unknown file type") { - panic!( - "{}\nThis can happen if multiple tests have the same input string", - msg - ); + panic!("{msg}\nThis can happen if multiple tests have the same input string"); } else { panic!("{}", msg); } } - assert!(output.status.success(), "{:#?}", output); - assert!(output.stdout.is_empty(), "{:#?}", output); + assert!(output.status.success(), "{output:#?}"); + assert!(output.stdout.is_empty(), "{output:#?}"); test_wasm_path } @@ -570,7 +566,7 @@ pub fn try_run_lib_function( let main: libloading::Symbol)> = lib .get(main_fn_name.as_bytes()) .ok() - .ok_or(format!("Unable to JIT compile `{}`", main_fn_name)) + .ok_or(format!("Unable to JIT compile `{main_fn_name}`")) .expect("errored"); let mut main_result = MaybeUninit::uninit(); @@ -607,7 +603,7 @@ where match result { Ok(raw) => { // only if there are no exceptions thrown, check for errors - assert!(errors.is_empty(), "Encountered errors:\n{}", errors); + assert!(errors.is_empty(), "Encountered errors:\n{errors}"); #[allow(clippy::redundant_closure_call)] let given = transform(raw); @@ -618,8 +614,8 @@ where std::mem::forget(given); } Err((msg, tag)) => match tag { - CrashTag::Roc => panic!(r#"Roc failed with message: "{}""#, msg), - CrashTag::User => panic!(r#"User crash with message: "{}""#, msg), + CrashTag::Roc => panic!(r#"Roc failed with message: "{msg}""#), + CrashTag::User => panic!(r#"User crash with message: "{msg}""#), }, } } diff --git a/crates/compiler/test_gen/src/helpers/mod.rs b/crates/compiler/test_gen/src/helpers/mod.rs index ed49fa04ed5..2d530993013 100644 --- a/crates/compiler/test_gen/src/helpers/mod.rs +++ b/crates/compiler/test_gen/src/helpers/mod.rs @@ -24,7 +24,7 @@ pub(crate) fn src_hash(src: &str) -> u64 { pub(crate) fn save_wasm_file(app_module_bytes: &[u8], build_dir_hash: u64) { use std::path::Path; - let debug_dir_str = format!("/tmp/roc/gen_wasm/{:016x}", build_dir_hash); + let debug_dir_str = format!("/tmp/roc/gen_wasm/{build_dir_hash:016x}"); let debug_dir_path = Path::new(&debug_dir_str); let final_wasm_file = debug_dir_path.join("final.wasm"); diff --git a/crates/compiler/test_mono/src/tests.rs b/crates/compiler/test_mono/src/tests.rs index da86d734310..80c8ad48c65 100644 --- a/crates/compiler/test_mono/src/tests.rs +++ b/crates/compiler/test_mono/src/tests.rs @@ -123,10 +123,10 @@ fn compiles_to_ir(test_name: &str, src: &str, mode: &str, allow_type_errors: boo Err(LoadMonomorphizedError::LoadingProblem(roc_load::LoadingProblem::FormattedReport( report, ))) => { - println!("{}", report); + println!("{report}"); panic!(); } - Err(e) => panic!("{:?}", e), + Err(e) => panic!("{e:?}"), }; use roc_load::MonomorphizedModule; @@ -201,7 +201,7 @@ fn verify_procedures<'a>( let result = procs_string.join("\n"); - let path = format!("generated/{}.txt", test_name); + let path = format!("generated/{test_name}.txt"); std::fs::create_dir_all("generated").unwrap(); std::fs::write(&path, result).unwrap(); diff --git a/crates/compiler/test_syntax/src/test_helpers.rs b/crates/compiler/test_syntax/src/test_helpers.rs index e0038c57055..e5bfe854d6a 100644 --- a/crates/compiler/test_syntax/src/test_helpers.rs +++ b/crates/compiler/test_syntax/src/test_helpers.rs @@ -96,10 +96,10 @@ impl<'a> Output<'a> { pub fn debug_format_inner(&self) -> String { match self { - Output::Header(header) => format!("{:#?}\n", header), - Output::ModuleDefs(defs) => format!("{:#?}\n", defs), - Output::Expr(expr) => format!("{:#?}\n", expr), - Output::Full { .. } => format!("{:#?}\n", self), + Output::Header(header) => format!("{header:#?}\n"), + Output::ModuleDefs(defs) => format!("{defs:#?}\n"), + Output::Expr(expr) => format!("{expr:#?}\n"), + Output::Full { .. } => format!("{self:#?}\n"), } } } @@ -224,7 +224,7 @@ impl<'a> Input<'a> { // the PartialEq implementation is returning `false` even when the Debug-formatted impl is exactly the same. // I don't have the patience to debug this right now, so let's leave it for another day... // TODO: fix PartialEq impl on ast types - if format!("{:?}", ast_normalized) != format!("{:?}", reparsed_ast_normalized) { + if format!("{ast_normalized:?}") != format!("{reparsed_ast_normalized:?}") { panic!( "Formatting bug; formatting didn't reparse to the same AST (after removing spaces)\n\n\ * * * Source code before formatting:\n{}\n\n\ diff --git a/crates/compiler/test_syntax/tests/test_fmt.rs b/crates/compiler/test_syntax/tests/test_fmt.rs index ff7cb5dd04d..847832782f0 100644 --- a/crates/compiler/test_syntax/tests/test_fmt.rs +++ b/crates/compiler/test_syntax/tests/test_fmt.rs @@ -43,8 +43,7 @@ mod test_fmt { fmt_defs(buf, &loc_defs, 0); } Err(error) => panic!( - r"Unexpected parse failure when parsing this for defs formatting:\n\n{:?}\n\nParse error was:\n\n{:?}\n\n", - src, error + r"Unexpected parse failure when parsing this for defs formatting:\n\n{src:?}\n\nParse error was:\n\n{error:?}\n\n" ), } } @@ -67,8 +66,7 @@ mod test_fmt { let (reparsed_ast, state) = module::parse_header(&arena, State::new(output.as_bytes())).unwrap_or_else(|err| { panic!( - "After formatting, the source code no longer parsed!\n\nParse error was: {:?}\n\nThe code that failed to parse:\n\n{}\n\n", - err, output + "After formatting, the source code no longer parsed!\n\nParse error was: {err:?}\n\nThe code that failed to parse:\n\n{output}\n\n" ); }); @@ -80,13 +78,11 @@ mod test_fmt { // the PartialEq implementation is returning `false` even when the Debug-formatted impl is exactly the same. // I don't have the patience to debug this right now, so let's leave it for another day... // TODO: fix PartialEq impl on ast types - if format!("{:?}", ast_normalized) != format!("{:?}", reparsed_ast_normalized) { + if format!("{ast_normalized:?}") != format!("{reparsed_ast_normalized:?}") { panic!( "Formatting bug; formatting didn't reparse to the same AST (after removing spaces)\n\n\ - * * * Source code before formatting:\n{}\n\n\ - * * * Source code after formatting:\n{}\n\n", - src, - output + * * * Source code before formatting:\n{src}\n\n\ + * * * Source code after formatting:\n{output}\n\n" ); } @@ -111,7 +107,7 @@ mod test_fmt { // those more than we want to know that the expectation failed! assert_multiline_str_eq!(expected, output); } - Err(error) => panic!("Unexpected parse failure when parsing this for module header formatting:\n\n{:?}\n\nParse error was:\n\n{:?}\n\n", src, error) + Err(error) => panic!("Unexpected parse failure when parsing this for module header formatting:\n\n{src:?}\n\nParse error was:\n\n{error:?}\n\n") }; } diff --git a/crates/compiler/test_syntax/tests/test_snapshots.rs b/crates/compiler/test_syntax/tests/test_snapshots.rs index 92ab0e6c790..e51d67cf165 100644 --- a/crates/compiler/test_syntax/tests/test_snapshots.rs +++ b/crates/compiler/test_syntax/tests/test_snapshots.rs @@ -526,14 +526,13 @@ mod test_snapshots { // Expect file to be missing assert!( !result_path.exists(), - "Expected {:?} to be missing. \ + "Expected {result_path:?} to be missing. \ This is how we represent a 'default' result (i.e. a test that \ formats to the same thing as the input). \ Consider running the tests with:\n\ `env ROC_SNAPSHOT_TEST_OVERWRITE=1 cargo test ...`\n\ (which will delete the file for you),\n\ - and commiting the delete.", - result_path + and commiting the delete." ); } } @@ -545,15 +544,12 @@ mod test_snapshots { let mut parent = std::path::PathBuf::from("tests"); parent.push("snapshots"); parent.push(expect.to_dir_name()); - let input_path = parent.join(format!("{}.{}.roc", name, ty)); - let result_path = parent.join(format!("{}.{}.result-ast", name, ty)); - let formatted_path = parent.join(format!("{}.{}.formatted.roc", name, ty)); + let input_path = parent.join(format!("{name}.{ty}.roc")); + let result_path = parent.join(format!("{name}.{ty}.result-ast")); + let formatted_path = parent.join(format!("{name}.{ty}.formatted.roc")); let source = std::fs::read_to_string(&input_path).unwrap_or_else(|err| { - panic!( - "Could not find a snapshot test result at {:?} - {:?}", - input_path, err - ) + panic!("Could not find a snapshot test result at {input_path:?} - {err:?}") }); let input = func(&source); @@ -566,14 +562,14 @@ mod test_snapshots { } Ok(ast.debug_format_inner()) } - Err(err) => Err(format!("{:?}", err)), + Err(err) => Err(format!("{err:?}")), }; if expect == TestExpectation::Pass { let tokens = roc_parse::highlight::highlight(&source); for token in tokens { if token.value == roc_parse::highlight::Token::Error { - panic!("Found an error highlight token in the input: {:?}", token); + panic!("Found an error highlight token in the input: {token:?}"); } } } @@ -653,7 +649,7 @@ mod test_snapshots { #[test] fn string_with_escaped_char_at_end() { parses_with_escaped_char( - |esc| format!(r#""abcd{}""#, esc), + |esc| format!(r#""abcd{esc}""#), |esc, arena| bumpalo::vec![in arena; Plaintext("abcd"), EscapedChar(esc)], ); } @@ -661,7 +657,7 @@ mod test_snapshots { #[test] fn string_with_escaped_char_in_front() { parses_with_escaped_char( - |esc| format!(r#""{}abcd""#, esc), + |esc| format!(r#""{esc}abcd""#), |esc, arena| bumpalo::vec![in arena; EscapedChar(esc), Plaintext("abcd")], ); } @@ -669,7 +665,7 @@ mod test_snapshots { #[test] fn string_with_escaped_char_in_middle() { parses_with_escaped_char( - |esc| format!(r#""ab{}cd""#, esc), + |esc| format!(r#""ab{esc}cd""#), |esc, arena| bumpalo::vec![in arena; Plaintext("ab"), EscapedChar(esc), Plaintext("cd")], ); } @@ -677,7 +673,7 @@ mod test_snapshots { #[test] fn string_with_multiple_escaped_chars() { parses_with_escaped_char( - |esc| format!(r#""{}abc{}de{}fghi{}""#, esc, esc, esc, esc), + |esc| format!(r#""{esc}abc{esc}de{esc}fghi{esc}""#), |esc, arena| bumpalo::vec![in arena; EscapedChar(esc), Plaintext("abc"), EscapedChar(esc), Plaintext("de"), EscapedChar(esc), Plaintext("fghi"), EscapedChar(esc)], ); } diff --git a/crates/compiler/types/src/pretty_print.rs b/crates/compiler/types/src/pretty_print.rs index 77bbbb4da18..2b235b43aa8 100644 --- a/crates/compiler/types/src/pretty_print.rs +++ b/crates/compiler/types/src/pretty_print.rs @@ -820,7 +820,7 @@ fn write_content<'a>( "".to_string() }; if env.home == symbol.module_id() { - format!("{}{}", ident_str, disambiguation,) + format!("{ident_str}{disambiguation}",) } else { format!( "{}.{}{}", diff --git a/crates/compiler/types/src/subs.rs b/crates/compiler/types/src/subs.rs index 3eb40deb754..c1126f84434 100644 --- a/crates/compiler/types/src/subs.rs +++ b/crates/compiler/types/src/subs.rs @@ -774,11 +774,11 @@ impl fmt::Debug for Subs { let root = self.get_root_key_without_compacting(var); if var == root { - write!(f, "{} => ", i)?; + write!(f, "{i} => ")?; subs_fmt_desc(&desc, self, f)?; } else { - write!(f, "{} => <{:?}>", i, root)?; + write!(f, "{i} => <{root:?}>")?; } writeln!(f)?; @@ -811,7 +811,7 @@ fn subs_fmt_content(this: &Content, subs: &Subs, f: &mut fmt::Formatter) -> fmt: Some(index) => subs[*index].as_str(), None => "_", }; - write!(f, "Flex({})", name) + write!(f, "Flex({name})") } Content::FlexAbleVar(name, symbols) => { let name = match name { @@ -827,7 +827,7 @@ fn subs_fmt_content(this: &Content, subs: &Subs, f: &mut fmt::Formatter) -> fmt: Content::RecursionVar { structure, opt_name, - } => write!(f, "Recursion({:?}, {:?})", structure, opt_name), + } => write!(f, "Recursion({structure:?}, {opt_name:?})"), Content::Structure(flat_type) => subs_fmt_flat_type(flat_type, subs, f), Content::Alias(name, arguments, actual, kind) => { let slice = subs.get_subs_slice(arguments.all_variables()); @@ -855,7 +855,7 @@ fn subs_fmt_content(this: &Content, subs: &Subs, f: &mut fmt::Formatter) -> fmt: write!(f, "LambdaSet([")?; for (name, slice) in solved.iter_from_subs(subs) { - write!(f, "{:?} ", name)?; + write!(f, "{name:?} ")?; for var in slice { write!( f, @@ -869,7 +869,7 @@ fn subs_fmt_content(this: &Content, subs: &Subs, f: &mut fmt::Formatter) -> fmt: write!(f, "]")?; if let Some(rec_var) = recursion_var.into_variable() { - write!(f, " as <{:?}>", rec_var)?; + write!(f, " as <{rec_var:?}>")?; } for Uls(var, member, region) in subs.get_subs_slice(*unspecialized) { write!( @@ -881,10 +881,10 @@ fn subs_fmt_content(this: &Content, subs: &Subs, f: &mut fmt::Formatter) -> fmt: region )?; } - write!(f, ", ^<{:?}>)", ambient_function_var) + write!(f, ", ^<{ambient_function_var:?}>)") } Content::RangedNumber(range) => { - write!(f, "RangedNumber( {:?})", range) + write!(f, "RangedNumber( {range:?})") } Content::Error => write!(f, "Error"), } @@ -903,7 +903,7 @@ fn subs_fmt_flat_type(this: &FlatType, subs: &Subs, f: &mut fmt::Formatter) -> f FlatType::Apply(name, arguments) => { let slice = subs.get_subs_slice(*arguments); - write!(f, "Apply({:?}, {:?})", name, slice) + write!(f, "Apply({name:?}, {slice:?})") } FlatType::Func(arguments, lambda_set, result) => { let slice = subs.get_subs_slice(*arguments); @@ -948,7 +948,7 @@ fn subs_fmt_flat_type(this: &FlatType, subs: &Subs, f: &mut fmt::Formatter) -> f )?; } - write!(f, "}}<{:?}>", new_ext) + write!(f, "}}<{new_ext:?}>") } FlatType::Tuple(elems, ext) => { write!(f, "( ")?; @@ -962,14 +962,14 @@ fn subs_fmt_flat_type(this: &FlatType, subs: &Subs, f: &mut fmt::Formatter) -> f )?; } - write!(f, ")<{:?}>", new_ext) + write!(f, ")<{new_ext:?}>") } FlatType::TagUnion(tags, ext) => { write!(f, "[")?; let (it, new_ext) = tags.sorted_iterator_and_ext(subs, *ext); for (name, slice) in it { - write!(f, "{:?} ", name)?; + write!(f, "{name:?} ")?; for var in slice { write!( f, @@ -981,26 +981,22 @@ fn subs_fmt_flat_type(this: &FlatType, subs: &Subs, f: &mut fmt::Formatter) -> f write!(f, ", ")?; } - write!(f, "]<{:?}>", new_ext) + write!(f, "]<{new_ext:?}>") } FlatType::FunctionOrTagUnion(tagnames, symbol, ext) => { let tagnames: &[TagName] = subs.get_subs_slice(*tagnames); - write!( - f, - "FunctionOrTagUnion({:?}, {:?}, {:?})", - tagnames, symbol, ext - ) + write!(f, "FunctionOrTagUnion({tagnames:?}, {symbol:?}, {ext:?})") } FlatType::RecursiveTagUnion(rec, tags, ext) => { write!(f, "[")?; let (it, new_ext) = tags.sorted_iterator_and_ext(subs, *ext); for (name, slice) in it { - write!(f, "{:?} {:?}, ", name, slice)?; + write!(f, "{name:?} {slice:?}, ")?; } - write!(f, "]<{:?}> as <{:?}>", new_ext, rec) + write!(f, "]<{new_ext:?}> as <{rec:?}>") } FlatType::EmptyRecord => write!(f, "EmptyRecord"), FlatType::EmptyTuple => write!(f, "EmptyTuple"), @@ -1016,7 +1012,7 @@ impl std::fmt::Debug for DebugUtable<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str("UnificationTable {\n")?; for v in 0..self.0.utable.len() { - f.write_fmt(format_args!(" {} => ", v))?; + f.write_fmt(format_args!(" {v} => "))?; let var = unsafe { Variable::from_index(v as u32) }; let root = self.0.utable.root_key_without_compacting(var); if root == var { @@ -2820,9 +2816,7 @@ where debug_assert_eq!( labels.len(), variables.len(), - "tag name len != variables len: {:?} {:?}", - labels, - variables, + "tag name len != variables len: {labels:?} {variables:?}", ); Self { @@ -4025,7 +4019,7 @@ where } else { // TODO is this the proper use of index here, or should we be // doing something else like turning it into an ASCII letter? - Lowercase::from(format!("{}{}", given_name, index)) + Lowercase::from(format!("{given_name}{index}")) }; match taken_names.get(&indexed_name) { @@ -4335,7 +4329,7 @@ fn flat_type_to_err_type( ErrorType::Error => ErrorType::Record(err_fields, TypeExt::Closed), other => - panic!("Tried to convert a record extension to an error, but the record extension had the ErrorType of {:?}", other) + panic!("Tried to convert a record extension to an error, but the record extension had the ErrorType of {other:?}") } } @@ -4367,7 +4361,7 @@ fn flat_type_to_err_type( ErrorType::Error => ErrorType::Tuple(err_elems, TypeExt::Closed), other => - panic!("Tried to convert a record extension to an error, but the record extension had the ErrorType of {:?}", other) + panic!("Tried to convert a record extension to an error, but the record extension had the ErrorType of {other:?}") } } @@ -4393,7 +4387,7 @@ fn flat_type_to_err_type( ErrorType::Error => ErrorType::TagUnion(err_tags, TypeExt::Closed, pol), other => - panic!("Tried to convert a tag union extension to an error, but the tag union extension had the ErrorType of {:?}", other) + panic!("Tried to convert a tag union extension to an error, but the tag union extension had the ErrorType of {other:?}") } } @@ -4423,7 +4417,7 @@ fn flat_type_to_err_type( ErrorType::Error => ErrorType::TagUnion(err_tags, TypeExt::Closed, pol), other => - panic!("Tried to convert a tag union extension to an error, but the tag union extension had the ErrorType of {:?}", other) + panic!("Tried to convert a tag union extension to an error, but the tag union extension had the ErrorType of {other:?}") } } @@ -4455,7 +4449,7 @@ fn flat_type_to_err_type( ErrorType::Error => ErrorType::RecursiveTagUnion(rec_error_type, err_tags, TypeExt::Closed, pol), other => - panic!("Tried to convert a recursive tag union extension to an error, but the tag union extension had the ErrorType of {:?}", other) + panic!("Tried to convert a recursive tag union extension to an error, but the tag union extension had the ErrorType of {other:?}") } } } diff --git a/crates/compiler/types/src/types.rs b/crates/compiler/types/src/types.rs index 00eb2b0098d..a8d69888402 100644 --- a/crates/compiler/types/src/types.rs +++ b/crates/compiler/types/src/types.rs @@ -55,11 +55,11 @@ impl fmt::Debug for RecordField { use RecordField::*; match self { - Optional(typ) => write!(f, "Optional({:?})", typ), - Required(typ) => write!(f, "Required({:?})", typ), - Demanded(typ) => write!(f, "Demanded({:?})", typ), - RigidRequired(typ) => write!(f, "RigidRequired({:?})", typ), - RigidOptional(typ) => write!(f, "RigidOptional({:?})", typ), + Optional(typ) => write!(f, "Optional({typ:?})"), + Required(typ) => write!(f, "Required({typ:?})"), + Demanded(typ) => write!(f, "Demanded({typ:?})"), + RigidRequired(typ) => write!(f, "RigidRequired({typ:?})"), + RigidOptional(typ) => write!(f, "RigidOptional({typ:?})"), } } } @@ -1949,10 +1949,10 @@ fn write_tags<'a>( let mut it = tags.peekable(); while let Some((label, arguments)) = it.next() { - write!(f, "{:?}", label)?; + write!(f, "{label:?}")?; for argument in arguments { - write!(f, " {:?}", argument)?; + write!(f, " {argument:?}")?; } if it.peek().is_some() { @@ -1976,23 +1976,23 @@ impl fmt::Debug for Type { write!(f, ", ")?; } - write!(f, "{:?}", arg)?; + write!(f, "{arg:?}")?; } - write!(f, " |{:?}|", closure)?; + write!(f, " |{closure:?}|")?; write!(f, " -> ")?; ret.fmt(f)?; write!(f, ")") } - Type::Variable(var) => write!(f, "<{:?}>", var), + Type::Variable(var) => write!(f, "<{var:?}>"), Type::Apply(symbol, args, _) => { - write!(f, "({:?}", symbol)?; + write!(f, "({symbol:?}")?; for arg in args { - write!(f, " {:?}", arg)?; + write!(f, " {arg:?}")?; } write!(f, ")") @@ -2004,10 +2004,10 @@ impl fmt::Debug for Type { lambda_set_variables, infer_ext_in_output_types, }) => { - write!(f, "(DelayedAlias {:?}", symbol)?; + write!(f, "(DelayedAlias {symbol:?}")?; for arg in type_arguments { - write!(f, " {:?}", arg)?; + write!(f, " {arg:?}")?; } for (lambda_set, greek_letter) in @@ -2017,7 +2017,7 @@ impl fmt::Debug for Type { } for (i, infer_ext) in infer_ext_in_output_types.iter().enumerate() { - write!(f, " `{}@{:?}", i, infer_ext)?; + write!(f, " `{i}@{infer_ext:?}")?; } write!(f, ")")?; @@ -2032,12 +2032,12 @@ impl fmt::Debug for Type { actual: _actual, .. } => { - write!(f, "(Alias {:?}", symbol)?; + write!(f, "(Alias {symbol:?}")?; for arg in type_arguments { write!(f, " {:?}", &arg.typ)?; if let Some(abs) = &arg.opt_abilities { - write!(f, ":{:?}", abs)?; + write!(f, ":{abs:?}")?; } } @@ -2048,7 +2048,7 @@ impl fmt::Debug for Type { } // Sometimes it's useful to see the expansion of the alias - write!(f, "[ but actually {:?} ]", _actual)?; + write!(f, "[ but actually {_actual:?} ]")?; write!(f, ")")?; @@ -2059,10 +2059,10 @@ impl fmt::Debug for Type { type_arguments: arguments, .. } => { - write!(f, "HostExposedAlias {:?}", name)?; + write!(f, "HostExposedAlias {name:?}")?; for arg in arguments { - write!(f, " {:?}", arg)?; + write!(f, " {arg:?}")?; } // Sometimes it's useful to see the expansion of the alias @@ -2082,13 +2082,11 @@ impl fmt::Debug for Type { for (label, field_type) in fields { match field_type { RecordField::Optional(_) | RecordField::RigidOptional(_) => { - write!(f, "{:?} ? {:?}", label, field_type)? + write!(f, "{label:?} ? {field_type:?}")? } RecordField::Required(_) | RecordField::Demanded(_) - | RecordField::RigidRequired(_) => { - write!(f, "{:?} : {:?}", label, field_type)? - } + | RecordField::RigidRequired(_) => write!(f, "{label:?} : {field_type:?}")?, } if any_written_yet { @@ -2129,7 +2127,7 @@ impl fmt::Debug for Type { let mut any_written_yet = false; for (_, field_type) in elems.iter() { - write!(f, "{:?}", field_type)?; + write!(f, "{field_type:?}")?; if any_written_yet { write!(f, ", ")?; @@ -2179,7 +2177,7 @@ impl fmt::Debug for Type { } Type::FunctionOrTagUnion(tag_name, _, ext) => { write!(f, "[")?; - write!(f, "{:?}", tag_name)?; + write!(f, "{tag_name:?}")?; write!(f, "]")?; match ext { @@ -2204,9 +2202,9 @@ impl fmt::Debug for Type { } => { write!(f, "ClosureTag(")?; - write!(f, "{:?}, ", name)?; + write!(f, "{name:?}, ")?; for capture in captures { - write!(f, "{:?}, ", capture)?; + write!(f, "{capture:?}, ")?; } write!(f, ")") @@ -2229,13 +2227,13 @@ impl fmt::Debug for Type { } }?; - write!(f, " as <{:?}>", rec) + write!(f, " as <{rec:?}>") } Type::RangedNumber(range_vars) => { - write!(f, "Ranged({:?})", range_vars) + write!(f, "Ranged({range_vars:?})") } Type::UnspecializedLambdaSet { unspecialized } => { - write!(f, "{:?}", unspecialized) + write!(f, "{unspecialized:?}") } } } @@ -4005,7 +4003,7 @@ fn write_debug_error_type_help(error_type: ErrorType, buf: &mut String, parens: buf.push('('); } buf.push_str(name.as_str()); - write!(buf, "has {:?}", symbol).unwrap(); + write!(buf, "has {symbol:?}").unwrap(); if write_parens { buf.push(')'); } @@ -4016,7 +4014,7 @@ fn write_debug_error_type_help(error_type: ErrorType, buf: &mut String, parens: if write_parens { buf.push('('); } - write!(buf, "{:?}", symbol).unwrap(); + write!(buf, "{symbol:?}").unwrap(); for arg in arguments { buf.push(' '); @@ -4061,7 +4059,7 @@ fn write_debug_error_type_help(error_type: ErrorType, buf: &mut String, parens: if write_parens { buf.push('('); } - write!(buf, "{:?}", symbol).unwrap(); + write!(buf, "{symbol:?}").unwrap(); for arg in arguments { buf.push(' '); @@ -4146,7 +4144,7 @@ fn write_debug_error_type_help(error_type: ErrorType, buf: &mut String, parens: let mut it = tags.into_iter().peekable(); while let Some((tag, args)) = it.next() { - write!(buf, "{:?}", tag).unwrap(); + write!(buf, "{tag:?}").unwrap(); for arg in args { buf.push(' '); write_debug_error_type_help(arg, buf, Parens::InTypeParam); @@ -4165,7 +4163,7 @@ fn write_debug_error_type_help(error_type: ErrorType, buf: &mut String, parens: let mut it = tags.into_iter().peekable(); while let Some((tag, args)) = it.next() { - write!(buf, "{:?}", tag).unwrap(); + write!(buf, "{tag:?}").unwrap(); for arg in args { buf.push(' '); write_debug_error_type_help(arg, buf, Parens::Unnecessary); diff --git a/crates/compiler/uitest/src/mono.rs b/crates/compiler/uitest/src/mono.rs index 423197c0384..06f4f421965 100644 --- a/crates/compiler/uitest/src/mono.rs +++ b/crates/compiler/uitest/src/mono.rs @@ -60,10 +60,10 @@ pub fn write_compiled_ir<'a>( Err(LoadMonomorphizedError::LoadingProblem(roc_load::LoadingProblem::FormattedReport( report, ))) => { - println!("{}", report); + println!("{report}"); panic!(); } - Err(e) => panic!("{:?}", e), + Err(e) => panic!("{e:?}"), }; use roc_load::MonomorphizedModule; @@ -146,9 +146,9 @@ fn write_procedures<'a>( let mut procs = procs_strings.iter().peekable(); while let Some(proc) = procs.next() { if procs.peek().is_some() { - writeln!(writer, "{}", proc)?; + writeln!(writer, "{proc}")?; } else { - write!(writer, "{}", proc)?; + write!(writer, "{proc}")?; } } diff --git a/crates/compiler/uitest/src/uitest.rs b/crates/compiler/uitest/src/uitest.rs index b9fb9c8dca6..3ed55f6bd25 100644 --- a/crates/compiler/uitest/src/uitest.rs +++ b/crates/compiler/uitest/src/uitest.rs @@ -337,7 +337,7 @@ fn assemble_query_output( for (module, source) in other_modules.iter() { writeln!(writer, "## module {module}")?; - writeln!(writer, "{}\n", source)?; + writeln!(writer, "{source}\n")?; } if !other_modules.is_empty() { diff --git a/crates/compiler/unify/src/unify.rs b/crates/compiler/unify/src/unify.rs index 383197a8056..37b991cb7b1 100644 --- a/crates/compiler/unify/src/unify.rs +++ b/crates/compiler/unify/src/unify.rs @@ -1853,8 +1853,7 @@ fn unify_unspecialized_lambdas( debug_assert!( is_sorted_unspecialized_lamba_set_list(env.subs, &merged_uls), - "merging of unspecialized lambda sets does not preserve sort! {:?}", - merged_uls + "merging of unspecialized lambda sets does not preserve sort! {merged_uls:?}" ); Ok(( diff --git a/crates/docs/src/lib.rs b/crates/docs/src/lib.rs index 756c23a7afa..ff911aa92aa 100644 --- a/crates/docs/src/lib.rs +++ b/crates/docs/src/lib.rs @@ -151,10 +151,7 @@ pub fn generate_docs_html(root_file: PathBuf) { ); fs::write(build_dir.join("index.html"), rendered_package).unwrap_or_else(|error| { - panic!( - "Attempted to write index.html but failed with this error: {}", - error - ) + panic!("Attempted to write index.html but failed with this error: {error}") }); } @@ -470,10 +467,10 @@ pub fn load_module_for_docs(filename: PathBuf) -> LoadedModule { ) { Ok(loaded) => loaded, Err(LoadingProblem::FormattedReport(report)) => { - eprintln!("{}", report); + eprintln!("{report}"); std::process::exit(1); } - Err(e) => panic!("{:?}", e), + Err(e) => panic!("{e:?}"), } } @@ -796,8 +793,7 @@ fn doc_url<'a>( Err(_) => { // TODO return Err here panic!( - "Tried to generate an automatic link in docs for symbol `{}`, but that symbol was not in scope in this module.", - ident + "Tried to generate an automatic link in docs for symbol `{ident}`, but that symbol was not in scope in this module." ); } } @@ -819,8 +815,7 @@ fn doc_url<'a>( else if !all_exposed_symbols.contains(&symbol) { // TODO return Err here panic!( - "Tried to generate an automatic link in docs for `{}.{}`, but `{}` does not expose `{}`.", - module_name, ident, module_name, ident); + "Tried to generate an automatic link in docs for `{module_name}.{ident}`, but `{module_name}` does not expose `{ident}`."); } // This is a valid symbol for this dependency, @@ -831,7 +826,7 @@ fn doc_url<'a>( } None => { // TODO return Err here - panic!("Tried to generate a doc link for `{}.{}` but the `{}` module was not imported!", module_name, ident, module_name); + panic!("Tried to generate a doc link for `{module_name}.{ident}` but the `{module_name}` module was not imported!"); } } } @@ -847,7 +842,7 @@ fn doc_url<'a>( DocUrl { url, - title: format!("Docs for {}.{}", module_name, ident), + title: format!("Docs for {module_name}.{ident}"), } } @@ -935,8 +930,7 @@ fn markdown_to_html( for event in parser { match event { Event::Code(code_str) => { - let inline_code = - pulldown_cmark::CowStr::from(format!("{}", code_str)); + let inline_code = pulldown_cmark::CowStr::from(format!("{code_str}")); docs_parser.push(pulldown_cmark::Event::Html(inline_code)); } Event::End(Link(LinkType::ShortcutUnknown, ref _url, ref _title)) => { diff --git a/crates/editor/src/editor/code_lines.rs b/crates/editor/src/editor/code_lines.rs index 521686e6e07..38e6aac66d3 100644 --- a/crates/editor/src/editor/code_lines.rs +++ b/crates/editor/src/editor/code_lines.rs @@ -66,13 +66,13 @@ impl fmt::Display for CodeLines { for row in &self.lines { let row_str = row .chars() - .map(|code_char| format!("{}", code_char)) + .map(|code_char| format!("{code_char}")) .collect::>() .join(" "); let escaped_row_str = row_str.replace('\n', "\\n"); - write!(f, "\n{}", escaped_row_str)?; + write!(f, "\n{escaped_row_str}")?; } writeln!(f, " (code_lines, {:?} lines)", self.lines.len())?; diff --git a/crates/editor/src/editor/ed_error.rs b/crates/editor/src/editor/ed_error.rs index e1409896694..732b7873fc8 100644 --- a/crates/editor/src/editor/ed_error.rs +++ b/crates/editor/src/editor/ed_error.rs @@ -278,7 +278,7 @@ pub enum EdError { pub type EdResult = std::result::Result; pub fn print_err(err: &EdError) { - eprintln!("{}", format!("{}", err).truecolor(255, 0, 0)); + eprintln!("{}", format!("{err}").truecolor(255, 0, 0)); if let Some(backtrace) = ErrorCompat::backtrace(err) { eprintln!("{}", color_backtrace(backtrace)); @@ -286,7 +286,7 @@ pub fn print_err(err: &EdError) { } fn color_backtrace(backtrace: &snafu::Backtrace) -> String { - let backtrace_str = format!("{}", backtrace); + let backtrace_str = format!("{backtrace}"); let backtrace_split = backtrace_str.split('\n'); let irrelevant_src = vec![".cargo", "registry", ".rustup", "rustc"]; @@ -301,10 +301,10 @@ fn color_backtrace(backtrace: &snafu::Backtrace) -> String { } format!("{}\n", line.truecolor(255, 100, 100)) } else { - format!("{}\n", line) + format!("{line}\n") } } else { - format!("{}\n", line) + format!("{line}\n") }; if let Some(prev_line) = prev_line_opt { @@ -328,7 +328,7 @@ fn contains_one_of(main_str: &str, contain_slice: &[&str]) -> bool { impl From for String { fn from(ed_error: EdError) -> Self { - format!("{}", ed_error) + format!("{ed_error}") } } diff --git a/crates/editor/src/editor/grid_node_map.rs b/crates/editor/src/editor/grid_node_map.rs index 3d3c1f239ae..87907276dcc 100644 --- a/crates/editor/src/editor/grid_node_map.rs +++ b/crates/editor/src/editor/grid_node_map.rs @@ -429,11 +429,11 @@ impl fmt::Display for GridNodeMap { for row in &self.lines { let row_str = row .iter() - .map(|mark_node_id| format!(" {} ", mark_node_id)) + .map(|mark_node_id| format!(" {mark_node_id} ")) .collect::>() .join(", "); - writeln!(f, "{}", row_str)?; + writeln!(f, "{row_str}")?; } writeln!(f, "(grid_node_map, {:?} lines)", self.lines.len())?; diff --git a/crates/editor/src/editor/main.rs b/crates/editor/src/editor/main.rs index 3bb28ef4079..9ac83cd0f29 100644 --- a/crates/editor/src/editor/main.rs +++ b/crates/editor/src/editor/main.rs @@ -92,7 +92,7 @@ fn run_event_loop(project_path_opt: Option<&Path>) -> Result<(), Box> ) }) .unwrap_or_else(|err| { - panic!("Failed to request device: `{}`", err); + panic!("Failed to request device: `{err}`"); }) .await }); @@ -125,7 +125,7 @@ fn run_event_loop(project_path_opt: Option<&Path>) -> Result<(), Box> let code_arena = Bump::new(); let (file_path_buf, code_str) = read_main_roc_file(project_path_opt); - println!("Loading file {:?}...", file_path_buf); + println!("Loading file {file_path_buf:?}..."); let file_path = Path::new(&file_path_buf); let loaded_module = load_module( @@ -237,7 +237,7 @@ fn run_event_loop(project_path_opt: Option<&Path>) -> Result<(), Box> if let Err(e) = input_outcome_res { print_err(&e) } else if let Ok(InputOutcome::Ignored) = input_outcome_res { - println!("\nInput '{}' ignored!", ch); + println!("\nInput '{ch}' ignored!"); } else { window.request_redraw() } @@ -507,10 +507,7 @@ fn read_main_roc_file(project_path_opt: Option<&Path>) -> (PathBuf, String) { let dir_items = ls(project_path, &ls_config) .unwrap_or_else(|err| { - panic!( - "Failed to list items in project directory; error: {:?}", - err - ) + panic!("Failed to list items in project directory; error: {err:?}") }) .items; @@ -574,15 +571,13 @@ fn init_new_roc_project(project_dir_path: &Path) -> (PathBuf, String) { fn create_roc_file_if_not_exists(project_dir_path: &Path, roc_file_path: &Path) -> String { if !roc_file_path.exists() { let mut roc_file = File::create(roc_file_path).unwrap_or_else(|err| { - panic!("No roc file path was passed to the editor, so I wanted to create a new roc project with the file {:?}, but it failed: {}", roc_file_path, err) + panic!("No roc file path was passed to the editor, so I wanted to create a new roc project with the file {roc_file_path:?}, but it failed: {err}") }); - write!(roc_file, "{}", HELLO_WORLD).unwrap_or_else(|err| { + write!(roc_file, "{HELLO_WORLD}").unwrap_or_else(|err| { panic!( - r#"No roc file path was passed to the editor, so I created a new roc project with the file {:?} - I wanted to write roc hello world to that file, but it failed: {:?}"#, - roc_file_path, - err + r#"No roc file path was passed to the editor, so I created a new roc project with the file {roc_file_path:?} + I wanted to write roc hello world to that file, but it failed: {err:?}"# ) }); @@ -590,8 +585,7 @@ fn create_roc_file_if_not_exists(project_dir_path: &Path, roc_file_path: &Path) } else { std::fs::read_to_string(roc_file_path).unwrap_or_else(|err| { panic!( - "I detected an existing {:?} inside {:?}, but I failed to read from it: {}", - roc_file_path, project_dir_path, err + "I detected an existing {roc_file_path:?} inside {project_dir_path:?}, but I failed to read from it: {err}" ) }) } @@ -613,10 +607,7 @@ fn copy_roc_platform_if_not_exists( } else if !project_platform_path.exists() { copy(orig_platform_path, project_dir_path, &CopyOptions::new()).unwrap_or_else(|err|{ panic!(r#"No roc file path was passed to the editor, so I wanted to create a new roc project and roc projects require a platform, - I tried to copy the platform at {:?} to {:?} but it failed: {}"#, - orig_platform_path, - project_platform_path, - err + I tried to copy the platform at {orig_platform_path:?} to {project_platform_path:?} but it failed: {err}"# ) }); } diff --git a/crates/editor/src/editor/mvc/ed_model.rs b/crates/editor/src/editor/mvc/ed_model.rs index 549ce688e2b..ab7f131aeaa 100644 --- a/crates/editor/src/editor/mvc/ed_model.rs +++ b/crates/editor/src/editor/mvc/ed_model.rs @@ -206,7 +206,7 @@ impl<'a> EdModule<'a> { match parse_res { Ok(ast) => Ok(EdModule { env, ast }), Err(err) => SrcParseSnafu { - syntax_err: format!("{:?}", err), + syntax_err: format!("{err:?}"), } .fail(), } @@ -315,20 +315,17 @@ pub mod test_ed_model { let platform_module_path = platform_dir.join("main.roc"); let mut platform_module_file = File::create(platform_module_path).expect("Failed to create main.roc"); - writeln!(platform_module_file, "{}", PLATFORM_STR).expect("Failed to write to main.roc"); + writeln!(platform_module_file, "{PLATFORM_STR}").expect("Failed to write to main.roc"); let temp_file_path_buf = PathBuf::from([Uuid::new_v4().to_string(), ".roc".to_string()].join("")); let temp_file_full_path = temp_dir.path().join(temp_file_path_buf); let mut file = File::create(temp_file_full_path.clone()).unwrap_or_else(|_| { - panic!( - "Failed to create temporary file for path {:?}", - temp_file_full_path - ) + panic!("Failed to create temporary file for path {temp_file_full_path:?}") }); - writeln!(file, "{}", clean_code_str) - .unwrap_or_else(|_| panic!("Failed to write {:?} to file: {:?}", clean_code_str, file)); + writeln!(file, "{clean_code_str}") + .unwrap_or_else(|_| panic!("Failed to write {clean_code_str:?} to file: {file:?}")); let loaded_module = load_module( &temp_file_full_path, diff --git a/crates/editor/src/editor/mvc/int_update.rs b/crates/editor/src/editor/mvc/int_update.rs index 39cfb119955..7796d237e58 100644 --- a/crates/editor/src/editor/mvc/int_update.rs +++ b/crates/editor/src/editor/mvc/int_update.rs @@ -126,7 +126,7 @@ fn check_parse_res(parse_res: Result) -> EdResult Ok(some_type), Err(parse_err) => StringParseSnafu { - msg: format!("{:?}", parse_err), + msg: format!("{parse_err:?}"), } .fail(), } diff --git a/crates/editor/src/editor/util.rs b/crates/editor/src/editor/util.rs index bea115b11a2..b5266c0ced7 100644 --- a/crates/editor/src/editor/util.rs +++ b/crates/editor/src/editor/util.rs @@ -9,7 +9,7 @@ pub fn map_get<'a, K: ::std::fmt::Debug + std::hash::Hash + std::cmp::Eq, V>( key: &K, ) -> EdResult<&'a V> { let value = hash_map.get(key).context(KeyNotFoundSnafu { - key_str: format!("{:?}", key), + key_str: format!("{key:?}"), })?; Ok(value) @@ -20,8 +20,8 @@ pub fn index_of(elt: T, slice: &[T]) -> EdR .iter() .position(|slice_elt| *slice_elt == elt) .with_context(|| { - let elt_str = format!("{:?}", elt); - let collection_str = format!("{:?}", slice); + let elt_str = format!("{elt:?}"); + let collection_str = format!("{slice:?}"); IndexOfFailedSnafu { elt_str, @@ -56,8 +56,8 @@ pub fn first_last_index_of( if let (Some(first_index), Some(last_index)) = (first_index_opt, last_index_opt) { Ok((first_index, last_index)) } else { - let elt_str = format!("{:?}", elt); - let collection_str = format!("{:?}", slice); + let elt_str = format!("{elt:?}"); + let collection_str = format!("{slice:?}"); IndexOfFailedSnafu { elt_str, diff --git a/crates/editor/src/ui/text/big_text_area.rs b/crates/editor/src/ui/text/big_text_area.rs index fee3119d6e4..178882376ab 100644 --- a/crates/editor/src/ui/text/big_text_area.rs +++ b/crates/editor/src/ui/text/big_text_area.rs @@ -596,7 +596,7 @@ pub mod test_big_sel_text { assert_eq!(expected_post_lines, post_lines); Ok(()) } - Err(e) => Err(format!("{:?}", e)), + Err(e) => Err(format!("{e:?}")), } } diff --git a/crates/editor/src/ui/text/text_buffer.rs b/crates/editor/src/ui/text/text_buffer.rs index cbd6a424912..faa455e1b68 100644 --- a/crates/editor/src/ui/text/text_buffer.rs +++ b/crates/editor/src/ui/text/text_buffer.rs @@ -91,7 +91,7 @@ impl TextBuffer { txt_pos.column <= line_len, OutOfBoundsSnafu { index: txt_pos.column, - collection_name: format!("Line in TextBuffer: {}", line_ref), + collection_name: format!("Line in TextBuffer: {line_ref}"), len: line_len, } ); diff --git a/crates/editor/src/ui/ui_error.rs b/crates/editor/src/ui/ui_error.rs index 9f4d1a96b08..af4f34fd747 100644 --- a/crates/editor/src/ui/ui_error.rs +++ b/crates/editor/src/ui/ui_error.rs @@ -64,6 +64,6 @@ pub type UIResult = std::result::Result; impl From for String { fn from(ui_error: UIError) -> Self { - format!("{}", ui_error) + format!("{ui_error}") } } diff --git a/crates/glue/src/load.rs b/crates/glue/src/load.rs index 466ca17eb88..aa58bf5edd2 100644 --- a/crates/glue/src/load.rs +++ b/crates/glue/src/load.rs @@ -138,7 +138,7 @@ pub fn generate( let files: Result, roc_std::RocStr> = files.into(); let files = files.unwrap_or_else(|err| { - eprintln!("Glue generation failed: {}", err); + eprintln!("Glue generation failed: {err}"); process::exit(1); }); @@ -358,7 +358,7 @@ pub fn load_types( ) .unwrap_or_else(|problem| match problem { LoadingProblem::FormattedReport(report) => { - eprintln!("{}", report); + eprintln!("{report}"); process::exit(1); } diff --git a/crates/glue/src/rust_glue.rs b/crates/glue/src/rust_glue.rs index 5a27609cac0..5d13bb0ff05 100644 --- a/crates/glue/src/rust_glue.rs +++ b/crates/glue/src/rust_glue.rs @@ -999,7 +999,7 @@ pub struct {name} {{ | RocType::RocResult(_, _) | RocType::RecursivePointer { .. } => { owned_ret_type = type_name(*payload_id, types); - borrowed_ret_type = format!("&{}", owned_ret_type); + borrowed_ret_type = format!("&{owned_ret_type}"); owned_ret = "payload".to_string(); borrowed_ret = format!("&{owned_ret}"); payload_args = format!("arg: {owned_ret_type}"); @@ -1119,7 +1119,7 @@ pub struct {name} {{ // TODO revise these - they're all copy/pasted from somewhere else owned_ret_type = type_name(*payload_id, types); - borrowed_ret_type = format!("&{}", owned_ret_type); + borrowed_ret_type = format!("&{owned_ret_type}"); owned_ret = "payload".to_string(); borrowed_ret = format!("&{owned_ret}"); payload_args = format!("arg: {owned_ret_type}"); @@ -1658,7 +1658,7 @@ pub struct {name} {{ }},"# ) } else { - format!("{},", hash_tag) + format!("{hash_tag},") } }, ); @@ -2255,7 +2255,7 @@ pub struct {name} {{ | RocType::TagUnion(_) | RocType::RecursivePointer { .. } => { owned_ret_type = type_name(non_null_payload, types); - borrowed_ret_type = format!("&{}", owned_ret_type); + borrowed_ret_type = format!("&{owned_ret_type}"); payload_args = format!("arg: {owned_ret_type}"); args_to_payload = "arg".to_string(); owned_ret = "payload".to_string(); @@ -2631,7 +2631,7 @@ fn tag_union_struct_help( let label = if is_tag_union_payload { // Tag union payload fields need "f" prefix // because they're numbers - format!("f{}", label) + format!("f{label}") } else { escape_kw(label.to_string()) }; @@ -2671,12 +2671,9 @@ fn tag_union_struct_help( if cannot_derive_copy(types.get_type(payload_id), types) { format!( - "core::mem::ManuallyDrop::new({payload_type_name} {{\n{}\n{INDENT}{INDENT}{INDENT}{INDENT}}})",prefixed_fields) + "core::mem::ManuallyDrop::new({payload_type_name} {{\n{prefixed_fields}\n{INDENT}{INDENT}{INDENT}{INDENT}}})") } else { - format!( - "{payload_type_name} {{\n{}\n{INDENT}{INDENT}{INDENT}{INDENT}}}", - prefixed_fields - ) + format!("{payload_type_name} {{\n{prefixed_fields}\n{INDENT}{INDENT}{INDENT}{INDENT}}}") } } else { "core::mem::ManuallyDrop::new(arg0)".to_string() diff --git a/crates/glue/src/types.rs b/crates/glue/src/types.rs index 86d8bbacad8..2933a0d35af 100644 --- a/crates/glue/src/types.rs +++ b/crates/glue/src/types.rs @@ -521,8 +521,7 @@ impl Types { } else { // TODO report this gracefully! panic!( - "Duplicate name detected - {:?} could refer to either {:?} or {:?}", - name, existing_type, typ + "Duplicate name detected - {name:?} could refer to either {existing_type:?} or {typ:?}" ); } } else { @@ -1213,8 +1212,7 @@ impl<'a> Env<'a> { debug_assert!( matches!(types.get_type(type_id), RocType::RecursivePointer(TypeId::PENDING)), - "The TypeId {:?} was registered as a pending recursive pointer, but was not stored in Types as one.", - type_id + "The TypeId {type_id:?} was registered as a pending recursive pointer, but was not stored in Types as one." ); // size and alignment shouldn't change; this is still @@ -1267,7 +1265,7 @@ fn add_function_type<'a>( let args = env.subs.get_subs_slice(*args); let mut arg_type_ids = Vec::with_capacity(args.len()); - let name = format!("RocFunction_{:?}", closure_var); + let name = format!("RocFunction_{closure_var:?}"); let id = env.lambda_set_ids.get(&closure_var).unwrap(); let extern_name = format!("roc__mainForHost_{}_caller", id.0); @@ -1851,7 +1849,7 @@ where getter: getter.clone(), }; - (format!("{}", label), type_id, accessors) + (format!("{label}"), type_id, accessors) }) .collect(); @@ -1865,7 +1863,7 @@ where .map(|(label, field_var, field_layout)| { let type_id = add_type_help(env, field_layout, field_var, None, types); - (format!("{}", label), type_id) + (format!("{label}"), type_id) }) .collect(); diff --git a/crates/glue/tests/test_glue_cli.rs b/crates/glue/tests/test_glue_cli.rs index c1f54d1aa93..6397c28369c 100644 --- a/crates/glue/tests/test_glue_cli.rs +++ b/crates/glue/tests/test_glue_cli.rs @@ -220,7 +220,7 @@ mod glue_cli_run { ); } - assert!(glue_out.status.success(), "bad status {:?}", glue_out); + assert!(glue_out.status.success(), "bad status {glue_out:?}"); glue_out } @@ -243,7 +243,7 @@ mod glue_cli_run { ); } - assert!(compile_out.status.success(), "bad status {:?}", compile_out); + assert!(compile_out.status.success(), "bad status {compile_out:?}"); compile_out } diff --git a/crates/highlight/src/lib.rs b/crates/highlight/src/lib.rs index 8929824f4cb..2002b4c8fc6 100644 --- a/crates/highlight/src/lib.rs +++ b/crates/highlight/src/lib.rs @@ -102,7 +102,7 @@ fn push_html_span(mut buf: Vec, curr: &str, class: &str) -> Vec // html escape strings from source code let escaped = html_escape::encode_text(curr); - buf.push(format!("{}", class, escaped)); + buf.push(format!("{escaped}")); buf } @@ -111,7 +111,7 @@ fn push_html(mut buf: Vec, curr: &str) -> Vec { // html escape strings from source code let escaped = html_escape::encode_text(curr); - buf.push(format!("{}", escaped)); + buf.push(format!("{escaped}")); buf } diff --git a/crates/linker/src/elf.rs b/crates/linker/src/elf.rs index 40b2c8948d0..7ddf0dafd41 100644 --- a/crates/linker/src/elf.rs +++ b/crates/linker/src/elf.rs @@ -202,7 +202,7 @@ impl<'a> Surgeries<'a> { println!(); println!("Text Sections"); for sec in text_sections.iter() { - println!("{:+x?}", sec); + println!("{sec:+x?}"); } } @@ -285,8 +285,7 @@ impl<'a> Surgeries<'a> { let offset = inst.next_ip() - op_size as u64 - sec.address() + file_offset; if verbose { println!( - "\tNeed to surgically replace {} bytes at file offset {:+x}", - op_size, offset, + "\tNeed to surgically replace {op_size} bytes at file offset {offset:+x}", ); println!( "\tIts current value is {:+x?}", @@ -373,13 +372,13 @@ pub(crate) fn preprocess_elf( other.sort_by_key(|t| t.1); for (name, vaddr) in other.iter() { - println!("\t{:#08x}: {}", vaddr, name); + println!("\t{vaddr:#08x}: {name}"); } println!("Of which {} are builtins", builtins.len(),); for (name, vaddr) in builtins.iter() { - println!("\t{:#08x}: {}", vaddr, name); + println!("\t{vaddr:#08x}: {name}"); } } @@ -410,8 +409,8 @@ pub(crate) fn preprocess_elf( } }; if verbose { - println!("PLT Address: {:+x}", plt_address); - println!("PLT File Offset: {:+x}", plt_offset); + println!("PLT Address: {plt_address:+x}"); + println!("PLT File Offset: {plt_offset:+x}"); } let app_syms: Vec<_> = exec_obj @@ -467,7 +466,7 @@ pub(crate) fn preprocess_elf( } println!(); - println!("App Function Address Map: {:+x?}", app_func_addresses); + println!("App Function Address Map: {app_func_addresses:+x?}"); } let symbol_and_plt_processing_duration = symbol_and_plt_processing_start.elapsed(); @@ -526,7 +525,7 @@ pub(crate) fn preprocess_elf( if verbose { println!(); - println!("{:+x?}", md); + println!("{md:+x?}"); } let saving_metadata_start = Instant::now(); @@ -593,12 +592,12 @@ fn gen_elf_le( if verbose { println!(); - println!("PH Offset: {:+x}", ph_offset); - println!("PH Entry Size: {}", ph_ent_size); - println!("PH Entry Count: {}", ph_num); - println!("SH Offset: {:+x}", sh_offset); - println!("SH Entry Size: {}", sh_ent_size); - println!("SH Entry Count: {}", sh_num); + println!("PH Offset: {ph_offset:+x}"); + println!("PH Entry Size: {ph_ent_size}"); + println!("PH Entry Count: {ph_num}"); + println!("SH Offset: {sh_offset:+x}"); + println!("SH Entry Size: {sh_ent_size}"); + println!("SH Entry Count: {sh_num}"); } // Copy header and shift everything to enable more program sections. @@ -633,10 +632,7 @@ fn gen_elf_le( user_error!("Executable does not load any data at 0x00000000\nProbably input the wrong file as the executable"); } if verbose { - println!( - "Shifting all data after: {:+x}({:+x})", - physical_shift_start, virtual_shift_start - ); + println!("Shifting all data after: {physical_shift_start:+x}({virtual_shift_start:+x})"); } // Shift all of the program headers. @@ -998,7 +994,7 @@ fn scan_elf_dynamic_deps( let dynstr_data = match dynstr_sec.uncompressed_data() { Ok(data) => data, Err(err) => { - panic!("Failed to load dynstr section: {}", err); + panic!("Failed to load dynstr section: {err}"); } }; @@ -1028,10 +1024,7 @@ fn scan_elf_dynamic_deps( if Path::new(c_str).file_name() == shared_lib_filename { shared_lib_index = Some(dyn_lib_index); if verbose { - println!( - "Found shared lib in dynamic table at index: {}", - dyn_lib_index - ); + println!("Found shared lib in dynamic table at index: {dyn_lib_index}"); } } } @@ -1260,14 +1253,14 @@ fn surgery_elf_help( if verbose { println!(); - println!("Is Elf64: {}", elf64); - println!("Is Little Endian: {}", litte_endian); - println!("PH Offset: {:+x}", ph_offset); - println!("PH Entry Size: {}", ph_ent_size); - println!("PH Entry Count: {}", ph_num); - println!("SH Offset: {:+x}", sh_offset); - println!("SH Entry Size: {}", sh_ent_size); - println!("SH Entry Count: {}", sh_num); + println!("Is Elf64: {elf64}"); + println!("Is Little Endian: {litte_endian}"); + println!("PH Offset: {ph_offset:+x}"); + println!("PH Entry Size: {ph_ent_size}"); + println!("PH Entry Count: {ph_num}"); + println!("SH Offset: {sh_offset:+x}"); + println!("SH Entry Size: {sh_ent_size}"); + println!("SH Entry Count: {sh_num}"); } // Backup section header table. @@ -1360,8 +1353,8 @@ fn surgery_elf_help( } } if verbose { - println!("Data Relocation Offsets: {:+x?}", symbol_vaddr_map); - println!("Found App Function Symbols: {:+x?}", app_func_vaddr_map); + println!("Data Relocation Offsets: {symbol_vaddr_map:+x?}"); + println!("Found App Function Symbols: {app_func_vaddr_map:+x?}"); } let (new_text_section_offset, new_text_section_vaddr) = text_sections @@ -1427,22 +1420,18 @@ fn surgery_elf_help( if verbose { println!(); println!( - "Processing Relocations for Section: 0x{:+x?} @ {:+x} (virt: {:+x})", - sec, section_offset, section_virtual_offset + "Processing Relocations for Section: 0x{sec:+x?} @ {section_offset:+x} (virt: {section_virtual_offset:+x})" ); } for rel in sec.relocations() { if verbose { - println!("\tFound Relocation: {:+x?}", rel); + println!("\tFound Relocation: {rel:+x?}"); } match rel.1.target() { RelocationTarget::Symbol(index) => { let target_offset = if let Some(target_offset) = symbol_vaddr_map.get(&index) { if verbose { - println!( - "\t\tRelocation targets symbol in app at: {:+x}", - target_offset - ); + println!("\t\tRelocation targets symbol in app at: {target_offset:+x}"); } Some(*target_offset as i64) } else { @@ -1455,8 +1444,7 @@ fn surgery_elf_help( let vaddr = (*address + md.added_byte_count) as i64; if verbose { println!( - "\t\tRelocation targets symbol in host: {} @ {:+x}", - name, vaddr + "\t\tRelocation targets symbol in host: {name} @ {vaddr:+x}" ); } vaddr @@ -1660,7 +1648,7 @@ fn surgery_elf_help( for s in md.surgeries.get(func_name).unwrap_or(&vec![]) { if verbose { - println!("\tPerforming surgery: {:+x?}", s); + println!("\tPerforming surgery: {s:+x?}"); } let surgery_virt_offset = match s.virtual_offset { VirtualOffset::Relative(vs) => (vs + md.added_byte_count) as i64, @@ -1670,7 +1658,7 @@ fn surgery_elf_help( 4 => { let target = (func_virt_offset as i64 - surgery_virt_offset) as i32; if verbose { - println!("\tTarget Jump: {:+x}", target); + println!("\tTarget Jump: {target:+x}"); } let data = target.to_le_bytes(); exec_mmap[(s.file_offset + md.added_byte_count) as usize..][..4] @@ -1679,7 +1667,7 @@ fn surgery_elf_help( 8 => { let target = func_virt_offset as i64 - surgery_virt_offset; if verbose { - println!("\tTarget Jump: {:+x}", target); + println!("\tTarget Jump: {target:+x}"); } let data = target.to_le_bytes(); exec_mmap[(s.file_offset + md.added_byte_count) as usize..][..8] @@ -1700,8 +1688,8 @@ fn surgery_elf_help( let target = (func_virt_offset as i64 - (plt_vaddr as i64 + jmp_inst_len as i64)) as i32; if verbose { - println!("\tPLT: {:+x}, {:+x}", plt_off, plt_vaddr); - println!("\tTarget Jump: {:+x}", target); + println!("\tPLT: {plt_off:+x}, {plt_vaddr:+x}"); + println!("\tTarget Jump: {target:+x}"); } let data = target.to_le_bytes(); exec_mmap[plt_off] = 0xE9; diff --git a/crates/linker/src/generate_dylib/macho.rs b/crates/linker/src/generate_dylib/macho.rs index 697b9187d04..6c5d2bc04d5 100644 --- a/crates/linker/src/generate_dylib/macho.rs +++ b/crates/linker/src/generate_dylib/macho.rs @@ -82,12 +82,10 @@ pub fn create_dylib_macho( if !output.status.success() { match std::str::from_utf8(&output.stderr) { Ok(stderr) => panic!( - "Failed to link dummy shared library - stderr of the `ld` command was:\n{}", - stderr + "Failed to link dummy shared library - stderr of the `ld` command was:\n{stderr}" ), Err(utf8_err) => panic!( - "Failed to link dummy shared library - stderr of the `ld` command was invalid utf8 ({:?})", - utf8_err + "Failed to link dummy shared library - stderr of the `ld` command was invalid utf8 ({utf8_err:?})" ), } } diff --git a/crates/linker/src/lib.rs b/crates/linker/src/lib.rs index b92ae67965c..9f53ac42b41 100644 --- a/crates/linker/src/lib.rs +++ b/crates/linker/src/lib.rs @@ -64,7 +64,7 @@ pub fn supported(link_type: LinkType, target: &Triple) -> bool { pub const PRECOMPILED_HOST_EXT: &str = "rh"; // Short for "roc host" pub fn preprocessed_host_filename(target: &Triple) -> Option { - roc_target::get_target_triple_str(target).map(|x| format!("{}.{}", x, PRECOMPILED_HOST_EXT)) + roc_target::get_target_triple_str(target).map(|x| format!("{x}.{PRECOMPILED_HOST_EXT}")) } fn metadata_file_name(target: &Triple) -> String { @@ -181,9 +181,9 @@ impl ExposedSymbols { let sym = x.as_str(interns); custom_names.extend([ - format!("roc__{}_1_exposed", sym), - format!("roc__{}_1_exposed_generic", sym), - format!("roc__{}_1_exposed_size", sym), + format!("roc__{sym}_1_exposed"), + format!("roc__{sym}_1_exposed_generic"), + format!("roc__{sym}_1_exposed_size"), ]); let exported_closure_types = exposed_to_host @@ -193,9 +193,9 @@ impl ExposedSymbols { for (i, _) in exported_closure_types.enumerate() { custom_names.extend([ - format!("roc__{}_{i}_caller", sym), - format!("roc__{}_{i}_size", sym), - format!("roc__{}_{i}_result_size", sym), + format!("roc__{sym}_{i}_caller"), + format!("roc__{sym}_{i}_size"), + format!("roc__{sym}_{i}_result_size"), ]); } } @@ -227,16 +227,16 @@ impl ExposedSymbols { for sym in &self.top_level_values { custom_names.extend([ - format!("roc__{}_1_exposed", sym), - format!("roc__{}_1_exposed_generic", sym), - format!("roc__{}_size", sym), + format!("roc__{sym}_1_exposed"), + format!("roc__{sym}_1_exposed_generic"), + format!("roc__{sym}_size"), ]); for closure_type in &self.exported_closure_types { custom_names.extend([ - format!("roc__{}_1_{}_caller", sym, closure_type), - format!("roc__{}_1_{}_size", sym, closure_type), - format!("roc__{}_1_{}_result_size", sym, closure_type), + format!("roc__{sym}_1_{closure_type}_caller"), + format!("roc__{sym}_1_{closure_type}_size"), + format!("roc__{sym}_1_{closure_type}_result_size"), ]); } } @@ -421,7 +421,7 @@ fn preprocess( time: bool, ) { if verbose { - println!("Targeting: {}", target); + println!("Targeting: {target}"); } let endianness = target diff --git a/crates/linker/src/macho.rs b/crates/linker/src/macho.rs index c64cd350cef..ce4e8a24d11 100644 --- a/crates/linker/src/macho.rs +++ b/crates/linker/src/macho.rs @@ -192,7 +192,7 @@ impl<'a> Surgeries<'a> { println!(); println!("Text Sections"); for sec in text_sections.iter() { - println!("{:+x?}", sec); + println!("{sec:+x?}"); } } @@ -275,8 +275,7 @@ impl<'a> Surgeries<'a> { let offset = inst.next_ip() - op_size as u64 - sec.address() + file_offset; if verbose { println!( - "\tNeed to surgically replace {} bytes at file offset {:+x}", - op_size, offset, + "\tNeed to surgically replace {op_size} bytes at file offset {offset:+x}", ); println!( "\tIts current value is {:+x?}", @@ -382,8 +381,8 @@ pub(crate) fn preprocess_macho( } }; if verbose { - println!("PLT Address: {:+x}", plt_address); - println!("PLT File Offset: {:+x}", plt_offset); + println!("PLT Address: {plt_address:+x}"); + println!("PLT File Offset: {plt_offset:+x}"); } let app_syms: Vec<_> = exec_obj.symbols().filter(is_roc_undefined).collect(); @@ -532,7 +531,7 @@ pub(crate) fn preprocess_macho( } println!(); - println!("App Function Address Map: {:+x?}", app_func_addresses); + println!("App Function Address Map: {app_func_addresses:+x?}"); } let symbol_and_plt_processing_duration = symbol_and_plt_processing_start.elapsed(); @@ -603,7 +602,7 @@ pub(crate) fn preprocess_macho( if verbose { println!(); - println!("{:+x?}", md); + println!("{md:+x?}"); } let saving_metadata_start = Instant::now(); @@ -1101,8 +1100,7 @@ fn gen_macho_le( } cmd => { eprintln!( - "- - - Unrecognized Mach-O command during linker preprocessing: 0x{:x?}", - cmd + "- - - Unrecognized Mach-O command during linker preprocessing: 0x{cmd:x?}" ); // panic!( // "Unrecognized Mach-O command during linker preprocessing: 0x{:x?}", @@ -1237,10 +1235,7 @@ fn surgery_macho_help( let new_rodata_section_vaddr = virt_offset; if verbose { println!(); - println!( - "New Virtual Rodata Section Address: {:+x?}", - new_rodata_section_vaddr - ); + println!("New Virtual Rodata Section Address: {new_rodata_section_vaddr:+x?}"); } // First decide on sections locations and then recode every exact symbol locations. @@ -1320,8 +1315,8 @@ fn surgery_macho_help( } } if verbose { - println!("Data Relocation Offsets: {:+x?}", symbol_vaddr_map); - println!("Found App Function Symbols: {:+x?}", app_func_vaddr_map); + println!("Data Relocation Offsets: {symbol_vaddr_map:+x?}"); + println!("Found App Function Symbols: {app_func_vaddr_map:+x?}"); } // let (new_text_section_offset, new_text_section_vaddr) = text_sections @@ -1356,22 +1351,18 @@ fn surgery_macho_help( if verbose { println!(); println!( - "Processing Relocations for Section: 0x{:+x?} @ {:+x} (virt: {:+x})", - sec, section_offset, section_virtual_offset + "Processing Relocations for Section: 0x{sec:+x?} @ {section_offset:+x} (virt: {section_virtual_offset:+x})" ); } for rel in sec.relocations() { if verbose { - println!("\tFound Relocation: {:+x?}", rel); + println!("\tFound Relocation: {rel:+x?}"); } match rel.1.target() { RelocationTarget::Symbol(index) => { let target_offset = if let Some(target_offset) = symbol_vaddr_map.get(&index) { if verbose { - println!( - "\t\tRelocation targets symbol in app at: {:+x}", - target_offset - ); + println!("\t\tRelocation targets symbol in app at: {target_offset:+x}"); } Some(*target_offset as i64) } else { @@ -1384,8 +1375,7 @@ fn surgery_macho_help( let vaddr = (*address + md.added_byte_count) as i64; if verbose { println!( - "\t\tRelocation targets symbol in host: {} @ {:+x}", - name, vaddr + "\t\tRelocation targets symbol in host: {name} @ {vaddr:+x}" ); } vaddr @@ -1406,10 +1396,9 @@ fn surgery_macho_help( }; if verbose { println!( - "\t\tRelocation base location: {:+x} (virt: {:+x})", - base, virt_base + "\t\tRelocation base location: {base:+x} (virt: {virt_base:+x})" ); - println!("\t\tFinal relocation target offset: {:+x}", target); + println!("\t\tFinal relocation target offset: {target:+x}"); } match rel.1.size() { 32 => { @@ -1560,7 +1549,7 @@ fn surgery_macho_help( for s in md.surgeries.get(func_name).unwrap_or(&vec![]) { if verbose { - println!("\tPerforming surgery: {:+x?}", s); + println!("\tPerforming surgery: {s:+x?}"); } let surgery_virt_offset = match s.virtual_offset { VirtualOffset::Relative(vs) => (vs + md.added_byte_count) as i64, @@ -1570,7 +1559,7 @@ fn surgery_macho_help( 4 => { let target = (func_virt_offset as i64 - surgery_virt_offset) as i32; if verbose { - println!("\tTarget Jump: {:+x}", target); + println!("\tTarget Jump: {target:+x}"); } let data = target.to_le_bytes(); exec_mmap[(s.file_offset + md.added_byte_count) as usize @@ -1580,7 +1569,7 @@ fn surgery_macho_help( 8 => { let target = func_virt_offset as i64 - surgery_virt_offset; if verbose { - println!("\tTarget Jump: {:+x}", target); + println!("\tTarget Jump: {target:+x}"); } let data = target.to_le_bytes(); exec_mmap[(s.file_offset + md.added_byte_count) as usize @@ -1602,8 +1591,8 @@ fn surgery_macho_help( let target = (func_virt_offset as i64 - (plt_vaddr as i64 + jmp_inst_len as i64)) as i32; if verbose { - println!("\tPLT: {:+x}, {:+x}", plt_off, plt_vaddr); - println!("\tTarget Jump: {:+x}", target); + println!("\tPLT: {plt_off:+x}, {plt_vaddr:+x}"); + println!("\tTarget Jump: {target:+x}"); } let data = target.to_le_bytes(); exec_mmap[plt_off] = 0xE9; diff --git a/crates/linker/src/pe.rs b/crates/linker/src/pe.rs index 8848172e1d9..34a9f295147 100644 --- a/crates/linker/src/pe.rs +++ b/crates/linker/src/pe.rs @@ -450,8 +450,7 @@ pub(crate) fn surgery_pe(executable_path: &Path, metadata_path: &Path, roc_app_b .contains(&name.as_str()); if *address == 0 && !name.starts_with("roc") && !is_ingested_compiler_rt { eprintln!( - "I don't know the address of the {} function! this may cause segfaults", - name + "I don't know the address of the {name} function! this may cause segfaults" ); } @@ -1718,7 +1717,7 @@ mod test { std::io::stdout().write_all(&output.stdout).unwrap(); std::io::stderr().write_all(&output.stderr).unwrap(); - panic!("zig build-exe failed: {}", command_str); + panic!("zig build-exe failed: {command_str}"); } let preprocessed_host_filename = @@ -1939,7 +1938,7 @@ mod test { std::io::stdout().write_all(&output.stdout).unwrap(); std::io::stderr().write_all(&output.stderr).unwrap(); - panic!("zig build-exe failed: {}", command_str); + panic!("zig build-exe failed: {command_str}"); } let host_bytes = std::fs::read(dir.join("host.exe")).unwrap(); diff --git a/crates/repl_cli/src/cli_gen.rs b/crates/repl_cli/src/cli_gen.rs index 1045c2c2639..95236209aba 100644 --- a/crates/repl_cli/src/cli_gen.rs +++ b/crates/repl_cli/src/cli_gen.rs @@ -264,7 +264,7 @@ fn mono_module_to_dylib<'a>( if main_fn.verify(true) { function_pass.run_on(&main_fn); } else { - internal_error!("Main function {} failed LLVM verification in build. Uncomment things nearby to see more details.", main_fn_name); + internal_error!("Main function {main_fn_name} failed LLVM verification in build. Uncomment things nearby to see more details.", ); } module_pass.run_on(env.module); diff --git a/crates/repl_cli/src/lib.rs b/crates/repl_cli/src/lib.rs index 336bb2b53ac..2b700750710 100644 --- a/crates/repl_cli/src/lib.rs +++ b/crates/repl_cli/src/lib.rs @@ -32,7 +32,7 @@ pub fn main() -> i32 { // To debug rustyline: // env_logger::init(); // RUST_LOG=rustyline=debug cargo run repl 2> debug.log - print!("{}{}", WELCOME_MESSAGE, SHORT_INSTRUCTIONS); + print!("{WELCOME_MESSAGE}{SHORT_INSTRUCTIONS}"); let mut editor = Editor::::new(); let repl_helper = ReplState::new(); @@ -51,7 +51,7 @@ pub fn main() -> i32 { // If there was no output, don't print a blank line! // (This happens for something like a type annotation.) if !output.is_empty() { - println!("{}", output); + println!("{output}"); } } Err(exit_code) => return exit_code, @@ -70,7 +70,7 @@ pub fn main() -> i32 { return 1; } Err(err) => { - eprintln!("REPL error: {:?}", err); + eprintln!("REPL error: {err:?}"); return 1; } } diff --git a/crates/repl_eval/src/eval.rs b/crates/repl_eval/src/eval.rs index 31d2f3b2d07..c5372b8ffe7 100644 --- a/crates/repl_eval/src/eval.rs +++ b/crates/repl_eval/src/eval.rs @@ -1457,6 +1457,6 @@ fn number_literal_to_ast(arena: &Bump, num: T) -> Expr<'_> use std::fmt::Write; let mut string = bumpalo::collections::String::with_capacity_in(64, arena); - write!(string, "{}", num).unwrap(); + write!(string, "{num}").unwrap(); Expr::Num(string.into_bump_str()) } diff --git a/crates/repl_expect/src/lib.rs b/crates/repl_expect/src/lib.rs index 9332a2a3913..e08a23d7ad2 100644 --- a/crates/repl_expect/src/lib.rs +++ b/crates/repl_expect/src/lib.rs @@ -200,7 +200,7 @@ mod test { let expected = expected.trim_end(); if x != expected { - println!("{}", x); + println!("{x}"); } assert_eq!(expected, x); diff --git a/crates/repl_expect/src/run.rs b/crates/repl_expect/src/run.rs index d4f2ecfc1df..413a6e7a161 100644 --- a/crates/repl_expect/src/run.rs +++ b/crates/repl_expect/src/run.rs @@ -327,7 +327,7 @@ fn run_expect_fx<'a, W: std::io::Write>( try_run_jit_function!(lib, expect.name, (), |v: ()| v); if let Err((msg, _)) = result { - internal_error!("roc panic {}", msg); + internal_error!("roc panic {msg}"); } if sequence.count_failures() > 0 { @@ -386,7 +386,7 @@ fn run_expect_fx<'a, W: std::io::Write>( ExpectSequence::START_OFFSET, )?; } - _ => println!("received signal {}", sig), + _ => println!("received signal {sig}"), } } @@ -638,7 +638,7 @@ impl ExpectSequence { 0 => std::hint::spin_loop(), 1 => break ChildProcessMsg::Expect, 2 => break ChildProcessMsg::Dbg, - n => internal_error!("invalid atomic value set by the child: {:#x}", n), + n => internal_error!("invalid atomic value set by the child: {n:#x}"), } } } diff --git a/crates/repl_test/src/cli.rs b/crates/repl_test/src/cli.rs index 8aa71cd9418..314d31ad868 100644 --- a/crates/repl_test/src/cli.rs +++ b/crates/repl_test/src/cli.rs @@ -75,13 +75,12 @@ pub fn repl_eval(input: &str) -> Out { // Remove the initial instructions from the output. - let expected_instructions = format!("{}{}", WELCOME_MESSAGE, SHORT_INSTRUCTIONS); + let expected_instructions = format!("{WELCOME_MESSAGE}{SHORT_INSTRUCTIONS}"); let stdout = String::from_utf8(output.stdout).unwrap(); assert!( stdout.starts_with(&expected_instructions), - "Unexpected repl output: {}", - stdout + "Unexpected repl output: {stdout}" ); let (_, answer) = stdout.split_at(expected_instructions.len()); @@ -101,8 +100,7 @@ pub fn repl_eval(input: &str) -> Out { assert!( answer.ends_with(&expected_after_answer), - "Unexpected repl output after answer: {}", - answer + "Unexpected repl output after answer: {answer}" ); // Use [1..] to trim the leading '\n' diff --git a/crates/repl_wasm/build.rs b/crates/repl_wasm/build.rs index 7cb3d021498..150eb81c4e2 100644 --- a/crates/repl_wasm/build.rs +++ b/crates/repl_wasm/build.rs @@ -14,8 +14,8 @@ const OBJECT_EXTENSION: &str = "obj"; fn main() { println!("cargo:rerun-if-changed=build.rs"); - let source_path = format!("src/{}.c", PLATFORM_FILENAME); - println!("cargo:rerun-if-changed={}", source_path); + let source_path = format!("src/{PLATFORM_FILENAME}.c"); + println!("cargo:rerun-if-changed={source_path}"); // Zig can produce *either* an object containing relocations OR an object containing libc code // But we want both, so we have to compile twice with different flags, then link them @@ -51,9 +51,9 @@ fn main() { // (and thus deleted) before the Zig process is done using it! let _ = builtins_host_tempfile; - assert!(output.status.success(), "{:#?}", output); - assert!(output.stdout.is_empty(), "{:#?}", output); - assert!(output.stderr.is_empty(), "{:#?}", output); + assert!(output.status.success(), "{output:#?}"); + assert!(output.stdout.is_empty(), "{output:#?}"); + assert!(output.stderr.is_empty(), "{output:#?}"); } fn zig_executable() -> String { diff --git a/crates/repl_wasm/src/repl.rs b/crates/repl_wasm/src/repl.rs index 8108e4a9e82..b1703985d6b 100644 --- a/crates/repl_wasm/src/repl.rs +++ b/crates/repl_wasm/src/repl.rs @@ -233,7 +233,7 @@ pub async fn entrypoint_from_js(src: String) -> Result { let (_, main_fn_layout) = match procedures.keys().find(|(s, _)| *s == main_fn_symbol) { Some(layout) => *layout, - None => return Ok(format!(" : {}", expr_type_str)), + None => return Ok(format!(" : {expr_type_str}")), }; let app_module_bytes = { @@ -280,7 +280,7 @@ pub async fn entrypoint_from_js(src: String) -> Result { // Send the compiled binary out to JS and create an executable instance from it js_create_app(&app_module_bytes) .await - .map_err(|js| format!("{:?}", js))?; + .map_err(|js| format!("{js:?}"))?; let mut app = WasmReplApp { arena }; diff --git a/crates/reporting/src/cli.rs b/crates/reporting/src/cli.rs index 22bd527da0e..a31533f35fe 100644 --- a/crates/reporting/src/cli.rs +++ b/crates/reporting/src/cli.rs @@ -133,13 +133,13 @@ pub fn report_problems( problems_reported = warnings.len(); for warning in warnings.iter() { - println!("\n{}\n", warning); + println!("\n{warning}\n"); } } else { problems_reported = errors.len(); for error in errors.iter() { - println!("\n{}\n", error); + println!("\n{error}\n"); } } diff --git a/crates/reporting/src/error/canonicalize.rs b/crates/reporting/src/error/canonicalize.rs index c0be61e751f..faa2556af82 100644 --- a/crates/reporting/src/error/canonicalize.rs +++ b/crates/reporting/src/error/canonicalize.rs @@ -843,7 +843,7 @@ pub fn can_problem<'b>( alloc.reflow("An implementation of "), alloc.symbol_unqualified(member), alloc.reflow(" could not be found in this scope:"), ]), alloc.region(lines.convert_region(region)), - alloc.tip().append(alloc.concat([alloc.reflow("consider adding a value of name "), alloc.symbol_unqualified(member), alloc.reflow(" in this scope, or using another variable that implements this ability member, like "), alloc.type_str(&format!("{{ {}: my{} }}", member_str, member_str))])) + alloc.tip().append(alloc.concat([alloc.reflow("consider adding a value of name "), alloc.symbol_unqualified(member), alloc.reflow(" in this scope, or using another variable that implements this ability member, like "), alloc.type_str(&format!("{{ {member_str}: my{member_str} }}"))])) ]); title = IMPLEMENTATION_NOT_FOUND.to_string(); } diff --git a/crates/reporting/src/error/expect.rs b/crates/reporting/src/error/expect.rs index 4da494eece3..8b5eaa1b20a 100644 --- a/crates/reporting/src/error/expect.rs +++ b/crates/reporting/src/error/expect.rs @@ -167,7 +167,7 @@ impl<'a> Renderer<'a> { &crate::report::DEFAULT_PALETTE, ); - write!(writer, "{}", buf) + write!(writer, "{buf}") } #[allow(clippy::too_many_arguments)] @@ -238,6 +238,6 @@ impl<'a> Renderer<'a> { &crate::report::DEFAULT_PALETTE, ); - write!(writer, "{}", buf) + write!(writer, "{buf}") } } diff --git a/crates/reporting/src/error/type.rs b/crates/reporting/src/error/type.rs index ea2b56d9d82..44df8197316 100644 --- a/crates/reporting/src/error/type.rs +++ b/crates/reporting/src/error/type.rs @@ -1047,7 +1047,7 @@ fn to_expr_report<'b>( region, Some(expr_region), alloc.reflow("This list contains elements with different types:"), - alloc.string(format!("Its {} element is", ith)), + alloc.string(format!("Its {ith} element is")), alloc.reflow(prev_elems_msg), Some(alloc.reflow("Every element in a list must have the same type!")), ) @@ -1180,7 +1180,7 @@ fn to_expr_report<'b>( if arity == 1 { "1 argument".into() } else { - format!("{} arguments", arity) + format!("{arity} arguments") } )), ]), @@ -1227,7 +1227,7 @@ fn to_expr_report<'b>( if n == 1 { "1 argument".into() } else { - format!("{} arguments", n) + format!("{n} arguments") }, arity )), @@ -1251,7 +1251,7 @@ fn to_expr_report<'b>( if n == 1 { "1 argument".into() } else { - format!("{} arguments", n) + format!("{n} arguments") }, arity )), @@ -1865,10 +1865,7 @@ fn format_category<'b>( ), CallResult(None, _) => (this_is, alloc.text(":")), LowLevelOpResult(op) => { - panic!( - "Compiler bug: invalid return type from low-level op {:?}", - op - ); + panic!("Compiler bug: invalid return type from low-level op {op:?}"); } ForeignCall => { panic!("Compiler bug: invalid return type from foreign call",); @@ -4372,8 +4369,8 @@ fn type_problem_to_pretty<'b>( match suggestions.get(0) { None => alloc.nil(), Some(nearest) => { - let typo_str = format!("{}", typo); - let nearest_str = format!("{}", nearest); + let typo_str = format!("{typo}"); + let nearest_str = format!("{nearest}"); let found = alloc.text(typo_str).annotate(Annotation::Typo); let suggestion = alloc.text(nearest_str).annotate(Annotation::TypoSuggestion); @@ -4424,7 +4421,7 @@ fn type_problem_to_pretty<'b>( match suggestions.get(0) { None => alloc.nil(), Some(nearest) => { - let nearest_str = format!("{}", nearest); + let nearest_str = format!("{nearest}"); let found = alloc.text(typo_str).annotate(Annotation::Typo); let suggestion = alloc.text(nearest_str).annotate(Annotation::TypoSuggestion); diff --git a/crates/reporting/src/report.rs b/crates/reporting/src/report.rs index 81fcb990165..504c563635f 100644 --- a/crates/reporting/src/report.rs +++ b/crates/reporting/src/report.rs @@ -438,7 +438,7 @@ impl<'a> RocDocAllocator<'a> { } pub fn wrapped_opaque_name(&'a self, opaque: Symbol) -> DocBuilder<'a, Self, Annotation> { - debug_assert_eq!(opaque.module_id(), self.home, "Opaque wrappings can only be defined in the same module they're defined in, but this one is defined elsewhere: {:?}", opaque); + debug_assert_eq!(opaque.module_id(), self.home, "Opaque wrappings can only be defined in the same module they're defined in, but this one is defined elsewhere: {opaque:?}"); text!(self, "@{}", opaque.as_str(self.interns)).annotate(Annotation::Opaque) } @@ -1612,7 +1612,7 @@ pub fn to_file_problem_report<'b>( } _ => { let error = std::io::Error::from(error); - let formatted = format!("{}", error); + let formatted = format!("{error}"); let doc = alloc.stack([ alloc.reflow(r"I tried to read this file:"), alloc.string(filename).annotate(Annotation::Error).indent(4), diff --git a/crates/reporting/tests/test_reporting.rs b/crates/reporting/tests/test_reporting.rs index 9a4d66e4b7f..46702abcace 100644 --- a/crates/reporting/tests/test_reporting.rs +++ b/crates/reporting/tests/test_reporting.rs @@ -86,7 +86,7 @@ mod test_reporting { path.push("snapshots"); path.push("fail"); let kind = if is_expr { "expr" } else { "header" }; - path.push(format!("{}.{}.roc", test_name, kind)); + path.push(format!("{test_name}.{kind}.roc")); std::fs::write(path, src).unwrap(); } @@ -113,14 +113,14 @@ mod test_reporting { // Use a deterministic temporary directory. // We can't have all tests use "tmp" because tests run in parallel, // so append the test name to the tmp path. - let tmp = format!("tmp/{}", subdir); + let tmp = format!("tmp/{subdir}"); let dir = roc_test_utils::TmpDir::new(&tmp); let filename = PathBuf::from("Test.roc"); let file_path = dir.path().join(filename); let full_file_path = file_path.clone(); let mut file = File::create(file_path).unwrap(); - writeln!(file, "{}", module_src).unwrap(); + writeln!(file, "{module_src}").unwrap(); let load_config = LoadConfig { target_info: roc_target::TargetInfo::default_x86_64(), render: RenderTarget::Generic, @@ -218,7 +218,7 @@ mod test_reporting { buf } Err(other) => { - panic!("failed to load: {:?}", other); + panic!("failed to load: {other:?}"); } } } @@ -389,7 +389,7 @@ mod test_reporting { // convenient to copy-paste the generated message if buf != expected_rendering { for line in buf.split('\n') { - println!(" {}", line); + println!(" {line}"); } } diff --git a/crates/roc_std/tests/test_roc_std.rs b/crates/roc_std/tests/test_roc_std.rs index c868acdfb72..6a41552c698 100644 --- a/crates/roc_std/tests/test_roc_std.rs +++ b/crates/roc_std/tests/test_roc_std.rs @@ -39,7 +39,7 @@ pub unsafe extern "C" fn roc_panic(c_ptr: *mut c_void, tag_id: u32) { 0 => { let c_str = CStr::from_ptr(c_ptr as *const c_char); let string = c_str.to_str().unwrap(); - panic!("roc_panic during test: {}", string); + panic!("roc_panic during test: {string}"); } _ => todo!(), } @@ -282,16 +282,16 @@ mod test_roc_std { ); let half = RocDec::from_str("0.5").unwrap(); - assert_eq!(format!("{}", half), "0.5"); + assert_eq!(format!("{half}"), "0.5"); let ten = RocDec::from_str("10").unwrap(); - assert_eq!(format!("{}", ten), "10"); + assert_eq!(format!("{ten}"), "10"); let example = RocDec::from_str("1234.5678").unwrap(); - assert_eq!(format!("{}", example), "1234.5678"); + assert_eq!(format!("{example}"), "1234.5678"); let example = RocDec::from_str("1_000.5678").unwrap(); - assert_eq!(format!("{}", example), "1000.5678"); + assert_eq!(format!("{example}"), "1000.5678"); } #[test] diff --git a/crates/utils/command/src/lib.rs b/crates/utils/command/src/lib.rs index 4bdb87fb23d..80b43baf498 100644 --- a/crates/utils/command/src/lib.rs +++ b/crates/utils/command/src/lib.rs @@ -112,12 +112,11 @@ fn check_command_available(command_name: &str) -> bool { cmd.args([command_name]); - let cmd_str = format!("{:?}", cmd); + let cmd_str = format!("{cmd:?}"); let cmd_out = cmd.output().unwrap_or_else(|err| { panic!( - "Failed to execute `{}` to check if {} is available:\n {}", - cmd_str, command_name, err + "Failed to execute `{cmd_str}` to check if {command_name} is available:\n {err}" ) }); diff --git a/crates/utils/error/src/lib.rs b/crates/utils/error/src/lib.rs index 9b63f1307ca..d6b3584512e 100644 --- a/crates/utils/error/src/lib.rs +++ b/crates/utils/error/src/lib.rs @@ -42,7 +42,7 @@ pub fn map_get<'a, K: ::std::fmt::Debug + std::hash::Hash + std::cmp::Eq, V>( key: &K, ) -> UtilResult<&'a V> { let value = hash_map.get(key).context(KeyNotFoundSnafu { - key_str: format!("{:?}", key), + key_str: format!("{key:?}"), })?; Ok(value) @@ -53,8 +53,8 @@ pub fn index_of(elt: T, slice: &[T]) -> Uti .iter() .position(|slice_elt| *slice_elt == elt) .with_context(|| { - let elt_str = format!("{:?}", elt); - let collection_str = format!("{:?}", slice); + let elt_str = format!("{elt:?}"); + let collection_str = format!("{slice:?}"); IndexOfFailedSnafu { elt_str, @@ -115,8 +115,8 @@ pub fn first_last_index_of( if let (Some(first_index), Some(last_index)) = (first_index_opt, last_index_opt) { Ok((first_index, last_index)) } else { - let elt_str = format!("{:?}", elt); - let collection_str = format!("{:?}", slice); + let elt_str = format!("{elt:?}"); + let collection_str = format!("{slice:?}"); IndexOfFailedSnafu { elt_str, diff --git a/crates/valgrind/src/lib.rs b/crates/valgrind/src/lib.rs index a7ca1ee2b33..8633f53176a 100644 --- a/crates/valgrind/src/lib.rs +++ b/crates/valgrind/src/lib.rs @@ -122,10 +122,10 @@ fn valgrind_test_linux(source: &str) { Err(roc_build::program::BuildFileError::LoadingProblem( roc_load::LoadingProblem::FormattedReport(report), )) => { - eprintln!("{}", report); + eprintln!("{report}"); panic!(""); } - Err(e) => panic!("{:?}", e), + Err(e) => panic!("{e:?}"), } drop(temp_dir) @@ -180,7 +180,7 @@ fn run_with_valgrind(binary_path: &std::path::Path) { what: _, xwhat, } = error; - println!("Valgrind Error: {}\n", kind); + println!("Valgrind Error: {kind}\n"); if let Some(ValgrindErrorXWhat { text, @@ -188,14 +188,14 @@ fn run_with_valgrind(binary_path: &std::path::Path) { leakedblocks: _, }) = xwhat { - println!(" {}", text); + println!(" {text}"); } } panic!("Valgrind found memory errors"); } } else { let exit_code = match valgrind_out.status.code() { - Some(code) => format!("exit code {}", code), + Some(code) => format!("exit code {code}"), None => "no exit code".to_string(), }; diff --git a/crates/vendor/morphic_lib/src/preprocess.rs b/crates/vendor/morphic_lib/src/preprocess.rs index e4eee2c6f01..bd1f9e21f94 100644 --- a/crates/vendor/morphic_lib/src/preprocess.rs +++ b/crates/vendor/morphic_lib/src/preprocess.rs @@ -160,23 +160,23 @@ impl std::fmt::Display for Error { if let Some(mod_) = &self.mod_ { loc_prefix(f)?; - write!(f, "module {:?}", mod_)?; + write!(f, "module {mod_:?}")?; } if let Some(def) = &self.def { loc_prefix(f)?; match def { DefName::Type(name) => { - write!(f, "named type definition {:?}", name)?; + write!(f, "named type definition {name:?}")?; } DefName::Func(name) => { - write!(f, "function definition {:?}", name)?; + write!(f, "function definition {name:?}")?; } DefName::Const(name) => { - write!(f, "constant definition {:?}", name)?; + write!(f, "constant definition {name:?}")?; } DefName::EntryPoint(name) => { - write!(f, "entry point definition {:?}", name)?; + write!(f, "entry point definition {name:?}")?; } } } @@ -185,13 +185,13 @@ impl std::fmt::Display for Error { loc_prefix(f)?; match binding { BindingLocation::Type(id) => { - write!(f, "definition of type binding {:?}", id)?; + write!(f, "definition of type binding {id:?}")?; } BindingLocation::Value(id) => { - write!(f, "definition of value binding {:?}", id)?; + write!(f, "definition of value binding {id:?}")?; } BindingLocation::Continuation(id) => { - write!(f, "definition of continuation binding {:?}", id)?; + write!(f, "definition of continuation binding {id:?}")?; } } } diff --git a/crates/vendor/morphic_lib/src/render_api_ir.rs b/crates/vendor/morphic_lib/src/render_api_ir.rs index dadbec892d0..f7db922b898 100644 --- a/crates/vendor/morphic_lib/src/render_api_ir.rs +++ b/crates/vendor/morphic_lib/src/render_api_ir.rs @@ -39,7 +39,7 @@ impl RenderContext { .extend((0..self.indent_level * self.spaces_per_level).map(|_| ' ')); self.pending_indent = false; } - write!(&mut self.content, "{}", to_write).expect("writing to string failed"); + write!(&mut self.content, "{to_write}").expect("writing to string failed"); } fn writeln(&mut self, to_write: impl std::fmt::Display) { @@ -146,8 +146,7 @@ fn render_op(builder: &ExprBuilder, ctx: &mut RenderContext, op: &Op) { match op { Op::Arg | Op::ContinuationArg | Op::DeclareContinuation { .. } => { ctx.write(format_args!( - "/* internal error: {:?} should not be rendered as a value */", - op + "/* internal error: {op:?} should not be rendered as a value */" )); } @@ -252,7 +251,7 @@ fn render_op(builder: &ExprBuilder, ctx: &mut RenderContext, op: &Op) { } Op::GetTupleField { field_idx } => { - ctx.write(format_args!("get_tuple_field {}", field_idx)); + ctx.write(format_args!("get_tuple_field {field_idx}")); } Op::MakeUnion { @@ -270,11 +269,11 @@ fn render_op(builder: &ExprBuilder, ctx: &mut RenderContext, op: &Op) { ctx.write(type_ident(*variant_type)); }, ); - ctx.write(format_args!("> {}", variant_idx)); + ctx.write(format_args!("> {variant_idx}")); } Op::UnwrapUnion { variant_idx } => { - ctx.write(format_args!("unwrap_union {}", variant_idx)); + ctx.write(format_args!("unwrap_union {variant_idx}")); } Op::MakeNamed { named_mod, named } => { diff --git a/crates/wasi-libc-sys/build.rs b/crates/wasi-libc-sys/build.rs index 74a2cd6a370..3f3031df098 100644 --- a/crates/wasi-libc-sys/build.rs +++ b/crates/wasi-libc-sys/build.rs @@ -24,7 +24,7 @@ fn main() { "--global-cache-dir", zig_cache_dir.to_str().unwrap(), "src/dummy.c", - &format!("-femit-bin={}/dummy.wasm", out_dir), + &format!("-femit-bin={out_dir}/dummy.wasm"), ]) .output() .unwrap(); diff --git a/crates/wasm_interp/src/instance.rs b/crates/wasm_interp/src/instance.rs index 4197365ea5e..2278a2d2552 100644 --- a/crates/wasm_interp/src/instance.rs +++ b/crates/wasm_interp/src/instance.rs @@ -105,7 +105,7 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> { is_debug_mode: bool, ) -> Result { let module = - WasmModule::preload(arena, module_bytes, false).map_err(|e| format!("{:?}", e))?; + WasmModule::preload(arena, module_bytes, false).map_err(|e| format!("{e:?}"))?; Self::for_module(arena, arena.alloc(module), import_dispatcher, is_debug_mode) } @@ -178,8 +178,7 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> { let actual_type = ValueType::from(value); if actual_type != expected_type { return Err(format!( - "Type mismatch on argument {} of {}. Expected {:?} but got {:?}", - i, fn_name, expected_type, value + "Type mismatch on argument {i} of {fn_name}. Expected {expected_type:?} but got {value:?}" )); } self.value_store.push(value); @@ -261,10 +260,7 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> { ) }) .ok_or_else(|| { - format!( - "I couldn't find a function '{}' in this WebAssembly module", - fn_name - ) + format!("I couldn't find a function '{fn_name}' in this WebAssembly module") })? as usize }; @@ -348,7 +344,7 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> { fn fetch_immediate_u32(&mut self, module: &WasmModule<'a>) -> u32 { let x = u32::parse((), &module.code.bytes, &mut self.program_counter).unwrap(); if let Some(debug_string) = self.debug_string.as_mut() { - write!(debug_string, "{} ", x).unwrap(); + write!(debug_string, "{x} ").unwrap(); } x } @@ -426,7 +422,7 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> { fn write_debug(&mut self, value: T) { if let Some(debug_string) = self.debug_string.as_mut() { - std::write!(debug_string, "{:?} ", value).unwrap(); + std::write!(debug_string, "{value:?} ").unwrap(); } } @@ -512,8 +508,7 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> { if let Some(expected) = expected_signature { assert_eq!( expected, signature_index, - "Indirect function call failed. Expected signature {} but found {}", - expected, signature_index, + "Indirect function call failed. Expected signature {expected} but found {signature_index}", ); } @@ -599,9 +594,9 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> { } else { write!(debug_string, ", ").unwrap(); } - write!(debug_string, "{:x?}", arg).unwrap(); + write!(debug_string, "{arg:x?}").unwrap(); } - writeln!(debug_string, "] return_type={:?}", return_type).unwrap(); + writeln!(debug_string, "] return_type={return_type:?}").unwrap(); } } @@ -747,15 +742,13 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> { // So far, all compilers seem to be emitting MVP-compatible code. (Rust, Zig, Roc...) assert_eq!( table_index, 0, - "Table index {} not supported at file offset {:#x}. This interpreter only supports Wasm MVP.", - table_index, file_offset + "Table index {table_index} not supported at file offset {file_offset:#x}. This interpreter only supports Wasm MVP." ); // Dereference the function pointer (look up the element index in the function table) let fn_index = module.element.lookup(element_index).unwrap_or_else(|| { panic!( - "Indirect function call failed. There is no function with element index {}", - element_index + "Indirect function call failed. There is no function with element index {element_index}" ) }); @@ -1613,28 +1606,28 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> { I32TRUNCSF32 => { let arg = self.value_store.pop_f32()?; if arg < i32::MIN as f32 || arg > i32::MAX as f32 { - panic!("Cannot truncate {} from F32 to I32", arg); + panic!("Cannot truncate {arg} from F32 to I32"); } self.value_store.push(Value::I32(arg as i32)); } I32TRUNCUF32 => { let arg = self.value_store.pop_f32()?; if arg < u32::MIN as f32 || arg > u32::MAX as f32 { - panic!("Cannot truncate {} from F32 to unsigned I32", arg); + panic!("Cannot truncate {arg} from F32 to unsigned I32"); } self.value_store.push(Value::from(arg as u32)); } I32TRUNCSF64 => { let arg = self.value_store.pop_f64()?; if arg < i32::MIN as f64 || arg > i32::MAX as f64 { - panic!("Cannot truncate {} from F64 to I32", arg); + panic!("Cannot truncate {arg} from F64 to I32"); } self.value_store.push(Value::I32(arg as i32)); } I32TRUNCUF64 => { let arg = self.value_store.pop_f64()?; if arg < u32::MIN as f64 || arg > u32::MAX as f64 { - panic!("Cannot truncate {} from F64 to unsigned I32", arg); + panic!("Cannot truncate {arg} from F64 to unsigned I32"); } self.value_store.push(Value::from(arg as u32)); } @@ -1649,28 +1642,28 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> { I64TRUNCSF32 => { let arg = self.value_store.pop_f32()?; if arg < i64::MIN as f32 || arg > i64::MAX as f32 { - panic!("Cannot truncate {} from F32 to I64", arg); + panic!("Cannot truncate {arg} from F32 to I64"); } self.value_store.push(Value::I64(arg as i64)); } I64TRUNCUF32 => { let arg = self.value_store.pop_f32()?; if arg < u64::MIN as f32 || arg > u64::MAX as f32 { - panic!("Cannot truncate {} from F32 to unsigned I64", arg); + panic!("Cannot truncate {arg} from F32 to unsigned I64"); } self.value_store.push(Value::from(arg as u64)); } I64TRUNCSF64 => { let arg = self.value_store.pop_f64()?; if arg < i64::MIN as f64 || arg > i64::MAX as f64 { - panic!("Cannot truncate {} from F64 to I64", arg); + panic!("Cannot truncate {arg} from F64 to I64"); } self.value_store.push(Value::I64(arg as i64)); } I64TRUNCUF64 => { let arg = self.value_store.pop_f64()?; if arg < u64::MIN as f64 || arg > u64::MAX as f64 { - panic!("Cannot truncate {} from F64 to unsigned I64", arg); + panic!("Cannot truncate {arg} from F64 to unsigned I64"); } self.value_store.push(Value::from(arg as u64)); } @@ -1739,12 +1732,12 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> { if let Some(debug_string) = &self.debug_string { if matches!(op_code, CALL | CALLINDIRECT) { - eprintln!("\n{:06x} {}", file_offset, debug_string); + eprintln!("\n{file_offset:06x} {debug_string}"); } else { // For calls, we print special debug stuff in do_call let base = self.current_frame.locals_start + self.current_frame.locals_count; let slice = self.value_store.get_slice(base); - eprintln!("{:06x} {:17} {:x?}", file_offset, debug_string, slice); + eprintln!("{file_offset:06x} {debug_string:17} {slice:x?}"); } let is_return = op_code == RETURN || (op_code == END && implicit_return); let is_program_end = self.program_counter == 0; @@ -1762,7 +1755,7 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> { #[allow(dead_code)] fn debug_values_and_blocks(&self, label: &str) { - eprintln!("\n========== {} ==========", label); + eprintln!("\n========== {label} =========="); let mut block_str = String::new(); let mut block_iter = self.blocks.iter().enumerate(); @@ -1774,17 +1767,17 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> { if *vstack > i { break; } - write!(block_str, "{}:{:?} ", b, ty).unwrap(); + write!(block_str, "{b}:{ty:?} ").unwrap(); block = block_iter.next(); } if !block_str.is_empty() { - eprintln!("--------------- {}", block_str); + eprintln!("--------------- {block_str}"); } }; for (i, v) in self.value_store.iter().enumerate() { print_blocks(i); - eprintln!("{:3} {:x?}", i, v); + eprintln!("{i:3} {v:x?}"); } print_blocks(self.value_store.depth()); @@ -1801,7 +1794,7 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> { /// -------------- fn debug_stack_trace(&self, buffer: &mut String) -> fmt::Result { let divider = "-------------------"; - writeln!(buffer, "{}", divider)?; + writeln!(buffer, "{divider}")?; let frames = self.previous_frames.iter().chain(once(&self.current_frame)); let next_frames = frames.clone().skip(1); @@ -1850,7 +1843,7 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> { .unwrap_or(""); // Function and address match wasm-objdump formatting, for easy copy & find - writeln!(buffer, "func[{}] {}", fn_index, fn_name)?; + writeln!(buffer, "func[{fn_index}] {fn_name}")?; writeln!(buffer, " address {:06x}", execution_addrs.next().unwrap())?; write!(buffer, " args ")?; @@ -1861,7 +1854,7 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> { } else if local_index != 0 { write!(buffer, ", ")?; } - write!(buffer, "{}: {:?}", local_index, value)?; + write!(buffer, "{local_index}: {value:?}")?; } write!(buffer, "\n stack [")?; @@ -1874,10 +1867,10 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> { if i != stack_start { write!(buffer, ", ")?; } - write!(buffer, "{:?}", value)?; + write!(buffer, "{value:?}")?; } writeln!(buffer, "]")?; - writeln!(buffer, "{}", divider)?; + writeln!(buffer, "{divider}")?; } Ok(()) diff --git a/crates/wasm_interp/src/lib.rs b/crates/wasm_interp/src/lib.rs index 09b81f95269..8cc98d3e399 100644 --- a/crates/wasm_interp/src/lib.rs +++ b/crates/wasm_interp/src/lib.rs @@ -53,10 +53,7 @@ impl<'a> ImportDispatcher for DefaultImportDispatcher<'a> { if module_name == wasi::MODULE_NAME { self.wasi.dispatch(function_name, arguments, memory) } else { - panic!( - "DefaultImportDispatcher does not implement {}.{}", - module_name, function_name - ); + panic!("DefaultImportDispatcher does not implement {module_name}.{function_name}"); } } } @@ -76,14 +73,12 @@ impl Error { match self { Error::Type(expected, actual) => { format!( - "ERROR: I found a type mismatch at file offset {:#x}. Expected {:?}, but found {:?}.\n", - file_offset, expected, actual + "ERROR: I found a type mismatch at file offset {file_offset:#x}. Expected {expected:?}, but found {actual:?}.\n" ) } Error::StackEmpty => { format!( - "ERROR: I tried to pop a value from the stack at file offset {:#x}, but it was empty.\n", - file_offset + "ERROR: I tried to pop a value from the stack at file offset {file_offset:#x}, but it was empty.\n" ) } Error::MemoryAccessOutOfBounds(addr, memory_size) => { @@ -93,10 +88,7 @@ impl Error { ) } Error::UnreachableOp => { - format!( - "WebAssembly `unreachable` instruction at file offset {:#x}.\n", - file_offset - ) + format!("WebAssembly `unreachable` instruction at file offset {file_offset:#x}.\n") } } } diff --git a/crates/wasm_interp/src/main.rs b/crates/wasm_interp/src/main.rs index b7b3a5dea1f..86bce0dc903 100644 --- a/crates/wasm_interp/src/main.rs +++ b/crates/wasm_interp/src/main.rs @@ -90,7 +90,7 @@ fn main() -> io::Result<()> { let dispatcher = DefaultImportDispatcher::new(&wasi_argv); let mut inst = Instance::for_module(&arena, &module, dispatcher, is_debug_mode).unwrap_or_else(|e| { - eprintln!("{}", e); + eprintln!("{e}"); process::exit(2); }); @@ -103,14 +103,14 @@ fn main() -> io::Result<()> { match result { Ok(Some(val)) => { if is_hex_format { - println!("{:#x?}", val) + println!("{val:#x?}") } else { - println!("{:?}", val) + println!("{val:?}") } } Ok(None) => {} Err(e) => { - eprintln!("{}", e); + eprintln!("{e}"); process::exit(3); } } diff --git a/crates/wasm_interp/src/tests/mod.rs b/crates/wasm_interp/src/tests/mod.rs index a78e4031ccf..9b83a81b98a 100644 --- a/crates/wasm_interp/src/tests/mod.rs +++ b/crates/wasm_interp/src/tests/mod.rs @@ -85,7 +85,7 @@ where // Dump the generated module to a file (this is mainly for debugging the test itself) if std::env::var("DEBUG_WASM_INTERP_TEST").is_ok() { - let filename = format!("/tmp/{:?}.wasm", op); + let filename = format!("/tmp/{op:?}.wasm"); println!("\nDumping test module to {}\n", &filename); let mut outfile_buf = Vec::new_in(&arena); module.serialize(&mut outfile_buf); diff --git a/crates/wasm_interp/src/tests/test_basics.rs b/crates/wasm_interp/src/tests/test_basics.rs index c0b56cec858..7ce3a11996e 100644 --- a/crates/wasm_interp/src/tests/test_basics.rs +++ b/crates/wasm_interp/src/tests/test_basics.rs @@ -563,7 +563,7 @@ fn test_call_import() { module.serialize(&mut buf); let filename = "/tmp/roc/call-return.wasm"; std::fs::write(filename, buf).unwrap(); - println!("Wrote to {}", filename); + println!("Wrote to {filename}"); } let mut inst = Instance::for_module(&arena, &module, import_dispatcher, true).unwrap(); @@ -631,7 +631,7 @@ fn test_call_return_no_args() { module.serialize(&mut buf); let filename = "/tmp/roc/call-return.wasm"; std::fs::write(filename, buf).unwrap(); - println!("Wrote to {}", filename); + println!("Wrote to {filename}"); } let mut inst = @@ -771,9 +771,9 @@ fn test_call_indirect_help(table_index: u32, elem_index: u32) -> Value { if false { let mut outfile_buf = Vec::new_in(&arena); module.serialize(&mut outfile_buf); - let filename = format!("/tmp/roc/call_indirect_{}_{}.wasm", table_index, elem_index); + let filename = format!("/tmp/roc/call_indirect_{table_index}_{elem_index}.wasm"); std::fs::write(&filename, outfile_buf).unwrap(); - println!("\nWrote to {}\n", filename); + println!("\nWrote to {filename}\n"); } let mut inst = Instance::for_module( diff --git a/crates/wasm_interp/src/value_store.rs b/crates/wasm_interp/src/value_store.rs index 5636a5d0be8..50287827c5e 100644 --- a/crates/wasm_interp/src/value_store.rs +++ b/crates/wasm_interp/src/value_store.rs @@ -158,6 +158,6 @@ mod tests { stack.push(val); } - assert_eq!(format!("{:?}", VALUES), format!("{:?}", stack)); + assert_eq!(format!("{VALUES:?}"), format!("{stack:?}")); } } diff --git a/crates/wasm_interp/src/wasi.rs b/crates/wasm_interp/src/wasi.rs index b6a9242ef3a..5b3d8f285a8 100644 --- a/crates/wasm_interp/src/wasi.rs +++ b/crates/wasm_interp/src/wasi.rs @@ -161,7 +161,7 @@ impl<'a> WasiDispatcher<'a> { if fd < self.files.len() { success_code } else { - println!("WASI warning: file descriptor {} does not exist", fd); + println!("WASI warning: file descriptor {fd} does not exist"); Some(Value::I32(Errno::Badf as i32)) } } @@ -291,8 +291,7 @@ impl<'a> WasiDispatcher<'a> { if negative_length_count > 0 { // Let's see if we ever get this message. If not, we can remove this negative-length stuff. eprintln!( - "WASI DEV INFO: found {} negative-length iovecs.", - negative_length_count + "WASI DEV INFO: found {negative_length_count} negative-length iovecs." ); } @@ -331,7 +330,7 @@ impl<'a> WasiDispatcher<'a> { "sock_recv" => todo!("WASI {}({:?})", function_name, arguments), "sock_send" => todo!("WASI {}({:?})", function_name, arguments), "sock_shutdown" => todo!("WASI {}({:?})", function_name, arguments), - _ => panic!("Unknown WASI function {}({:?})", function_name, arguments), + _ => panic!("Unknown WASI function {function_name}({arguments:?})"), } } } diff --git a/crates/wasm_module/src/lib.rs b/crates/wasm_module/src/lib.rs index 87b1183d6d6..73cbb92f7fd 100644 --- a/crates/wasm_module/src/lib.rs +++ b/crates/wasm_module/src/lib.rs @@ -183,10 +183,7 @@ impl<'a> WasmModule<'a> { module_errors, ) } else { - format!( - "I wasn't able to understand this WebAssembly file.\n{}", - module_errors, - ) + format!("I wasn't able to understand this WebAssembly file.\n{module_errors}",) }; return Err(ParseError { offset: 0, message }); } diff --git a/crates/wasm_module/src/linking.rs b/crates/wasm_module/src/linking.rs index 89235951808..d8432ebd65d 100644 --- a/crates/wasm_module/src/linking.rs +++ b/crates/wasm_module/src/linking.rs @@ -144,7 +144,7 @@ impl Parse<()> for RelocationEntry { Err(ParseError { offset: *cursor, - message: format!("Unknown relocation type 0x{:2x}", type_id_byte), + message: format!("Unknown relocation type 0x{type_id_byte:2x}"), }) } } @@ -491,7 +491,7 @@ impl Parse<()> for SymType { 5 => Ok(Self::Table), x => Err(ParseError { offset, - message: format!("Invalid symbol info type in linking section: {}", x), + message: format!("Invalid symbol info type in linking section: {x}"), }), } } @@ -536,7 +536,7 @@ impl Parse<()> for SubSectionId { 8 => Ok(Self::SymbolTable), x => Err(ParseError { offset, - message: format!("Invalid linking subsection ID {}", x), + message: format!("Invalid linking subsection ID {x}"), }), } } @@ -578,10 +578,7 @@ impl<'a> LinkingSection<'a> { .iter() .position(|sym| sym.name() == Some(target_name)) .ok_or_else(|| { - format!( - "Linking failed! Can't find `{}` in host symbol table", - target_name - ) + format!("Linking failed! Can't find `{target_name}` in host symbol table") }) } @@ -596,7 +593,7 @@ impl<'a> LinkingSection<'a> { _ => false, }) .map(|sym_index| sym_index as u32) - .ok_or_else(|| format!("Can't find fn #{} in host symbol table", fn_index)) + .ok_or_else(|| format!("Can't find fn #{fn_index} in host symbol table")) } pub fn find_and_reindex_imported_fn( @@ -619,10 +616,7 @@ impl<'a> LinkingSection<'a> { }) .map(|sym_index| sym_index as u32) .ok_or_else(|| { - format!( - "Linking failed! Can't find fn #{} in host symbol table", - old_fn_index - ) + format!("Linking failed! Can't find fn #{old_fn_index} in host symbol table") }) } } @@ -650,8 +644,7 @@ impl<'a> Parse<&'a Bump> for LinkingSection<'a> { return Err(ParseError { offset: *cursor, message: format!( - "This file uses version {} of Wasm linking data, but only version {} is supported.", - linking_version, LINKING_VERSION + "This file uses version {linking_version} of Wasm linking data, but only version {LINKING_VERSION} is supported." ), }); } diff --git a/crates/wasm_module/src/sections.rs b/crates/wasm_module/src/sections.rs index 6b6723f8363..99ef4db60ce 100644 --- a/crates/wasm_module/src/sections.rs +++ b/crates/wasm_module/src/sections.rs @@ -628,7 +628,7 @@ impl Parse<()> for RefType { 0x6f => Ok(Self::Extern), _ => Err(ParseError { offset: *cursor - 1, - message: format!("Invalid RefType 0x{:2x}", byte), + message: format!("Invalid RefType 0x{byte:2x}"), }), } } @@ -973,7 +973,7 @@ impl Parse<()> for ConstExpr { } _ => Err(ParseError { offset: *cursor, - message: format!("Unsupported opcode {:?} in constant expression.", opcode), + message: format!("Unsupported opcode {opcode:?} in constant expression."), }), }; @@ -1522,7 +1522,7 @@ impl Parse<()> for DataMode { } else { Err(ParseError { offset: *cursor - 1, - message: format!("Data section: invalid DataMode variant 0x{:x}", variant_id), + message: format!("Data section: invalid DataMode variant 0x{variant_id:x}"), }) } } @@ -1574,7 +1574,7 @@ impl<'a> DataSection<'a> { let mut cursor = 0; for _ in 0..self.count { let mode = - DataMode::parse((), &self.bytes, &mut cursor).map_err(|e| format!("{:?}", e))?; + DataMode::parse((), &self.bytes, &mut cursor).map_err(|e| format!("{e:?}"))?; let start = match mode { DataMode::Active { offset: ConstExpr::I32(addr), @@ -1583,12 +1583,12 @@ impl<'a> DataSection<'a> { continue; } }; - let len32 = u32::parse((), &self.bytes, &mut cursor).map_err(|e| format!("{:?}", e))?; + let len32 = u32::parse((), &self.bytes, &mut cursor).map_err(|e| format!("{e:?}"))?; let len = len32 as usize; let mut target_slice = &mut memory[start..][..len]; target_slice .write(&self.bytes[cursor..][..len]) - .map_err(|e| format!("{:?}", e))?; + .map_err(|e| format!("{e:?}"))?; cursor += len; } Ok(()) @@ -1859,7 +1859,7 @@ impl<'a> Debug for NameSection<'a> { writeln!(f, "NameSection")?; for (index, name) in self.function_names.iter() { - writeln!(f, " {:4}: {}", index, name)?; + writeln!(f, " {index:4}: {name}")?; } Ok(()) From 2d616d1fe948b920d71ac53868918566b9027411 Mon Sep 17 00:00:00 2001 From: Folkert Date: Mon, 26 Jun 2023 20:45:39 +0200 Subject: [PATCH 137/140] manual clippy fixes --- crates/compiler/gen_llvm/src/llvm/convert.rs | 4 ++-- crates/compiler/gen_llvm/src/llvm/lowlevel.rs | 2 +- crates/compiler/gen_llvm/src/llvm/struct_.rs | 2 +- crates/compiler/mono/src/drop_specialization.rs | 2 +- crates/compiler/mono/src/reset_reuse.rs | 4 ++-- crates/compiler/mono/src/tail_recursion.rs | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/compiler/gen_llvm/src/llvm/convert.rs b/crates/compiler/gen_llvm/src/llvm/convert.rs index e0042c4c461..1b0a3d12478 100644 --- a/crates/compiler/gen_llvm/src/llvm/convert.rs +++ b/crates/compiler/gen_llvm/src/llvm/convert.rs @@ -14,8 +14,8 @@ use roc_target::TargetInfo; use super::struct_::RocStruct; -pub fn basic_type_from_layout<'a, 'ctx, 'env>( - env: &Env<'a, 'ctx, 'env>, +pub fn basic_type_from_layout<'a, 'ctx>( + env: &Env<'a, 'ctx, '_>, layout_interner: &STLayoutInterner<'a>, layout: LayoutRepr<'_>, ) -> BasicTypeEnum<'ctx> { diff --git a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs index 0eb198349bc..22115d79cb3 100644 --- a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs +++ b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs @@ -1832,7 +1832,7 @@ fn throw_on_overflow<'ctx>( .unwrap() } -fn throw_because_overflow<'ctx>(env: &Env<'_, 'ctx, '_>, message: &str) { +fn throw_because_overflow(env: &Env<'_, '_, '_>, message: &str) { let block = env.builder.get_insert_block().expect("to be in a function"); let di_location = env.builder.get_current_debug_location().unwrap(); diff --git a/crates/compiler/gen_llvm/src/llvm/struct_.rs b/crates/compiler/gen_llvm/src/llvm/struct_.rs index b9ed4ecc9a2..5f26b0ec0a9 100644 --- a/crates/compiler/gen_llvm/src/llvm/struct_.rs +++ b/crates/compiler/gen_llvm/src/llvm/struct_.rs @@ -153,7 +153,7 @@ fn index_struct_ptr<'a, 'ctx>( let field_layout = field_layouts[index as usize]; let field_repr = layout_interner.get_repr(field_layout); - let name = format!("struct_field_access_record_{}", index); + let name = format!("struct_field_access_record_{index}"); let field_value = env .builder .new_build_struct_gep(struct_type, ptr, index as u32, &name) diff --git a/crates/compiler/mono/src/drop_specialization.rs b/crates/compiler/mono/src/drop_specialization.rs index 3079f24a323..19f8bbb10d9 100644 --- a/crates/compiler/mono/src/drop_specialization.rs +++ b/crates/compiler/mono/src/drop_specialization.rs @@ -1427,7 +1427,7 @@ impl<'a> DropSpecializationEnvironment<'a> { } } - fn create_symbol<'i>(&self, ident_ids: &'i mut IdentIds, debug_name: &str) -> Symbol { + fn create_symbol(&self, ident_ids: &mut IdentIds, debug_name: &str) -> Symbol { let ident_id = ident_ids.add_str(debug_name); Symbol::new(self.home, ident_id) } diff --git a/crates/compiler/mono/src/reset_reuse.rs b/crates/compiler/mono/src/reset_reuse.rs index d51e522fa0b..f68da9279b7 100644 --- a/crates/compiler/mono/src/reset_reuse.rs +++ b/crates/compiler/mono/src/reset_reuse.rs @@ -1404,8 +1404,8 @@ fn drop_unused_reuse_tokens<'a>( }) } -fn get_reuse_layout_info<'a, 'i>( - layout_interner: &'i STLayoutInterner<'a>, +fn get_reuse_layout_info<'a>( + layout_interner: &STLayoutInterner<'a>, union_layout: UnionLayout<'a>, ) -> TokenLayout { let (size, alignment) = union_layout.data_size_and_alignment(layout_interner); diff --git a/crates/compiler/mono/src/tail_recursion.rs b/crates/compiler/mono/src/tail_recursion.rs index 7b7bb793903..9517eb9ef85 100644 --- a/crates/compiler/mono/src/tail_recursion.rs +++ b/crates/compiler/mono/src/tail_recursion.rs @@ -501,9 +501,9 @@ where candidate_set } -fn trmc_candidates_help<'a>( +fn trmc_candidates_help( function_name: LambdaName, - stmt: &'_ Stmt<'a>, + stmt: &'_ Stmt<'_>, candidates: &mut TrmcCandidateSet, ) { // if this stmt is the literal tail tag application and return, then this is a TRMC opportunity From 03c517dcfcc6555e462447c2d57aa016d15c470e Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Mon, 10 Jul 2023 18:46:41 +0200 Subject: [PATCH 138/140] resurrecting previous nix changes --- default.nix | 166 ++++++++++++++++++++++++++++------------------------ flake.nix | 4 +- 2 files changed, 93 insertions(+), 77 deletions(-) diff --git a/default.nix b/default.nix index 5c8e8cbeea9..c4839e99d51 100644 --- a/default.nix +++ b/default.nix @@ -10,91 +10,107 @@ let rustPlatform = pkgs.rustPlatform; + desiredRustVersion = (builtins.fromTOML (builtins.readFile (./rust-toolchain.toml))).toolchain.channel; + actualRustVersion = rustPlatform.rust.rustc; + rustVersionsMatch = pkgs.lib.strings.hasSuffix desiredRustVersion actualRustVersion; + llvmPkgs = pkgs.llvmPackages_13; # nix does not store libs in /usr/lib or /lib nixGlibcPath = if pkgs.stdenv.isLinux then "${pkgs.glibc.out}/lib" else ""; in -rustPlatform.buildRustPackage { - pname = "roc"; - version = "0.0.1"; - src = pkgs.nix-gitignore.gitignoreSource [ ] ./.; + assert pkgs.lib.assertMsg rustVersionsMatch '' + The rust version changed in rust-toolchain.toml but the rev(commit) in nixpkgs.url in flake.nix was not updated. + 1. clone the nixpkgs repo: `git clone --depth 60000 git@github.com:NixOS/nixpkgs.git` + 2. `cd nixpkgs` + 3. `git log --oneline | rg -A 1 "rustc: "` + 4. Copy the short SHA from the line **after** the commit with the message of for example `rustc: 1.67.1 -> 1.68.0` + 5. Find the long SHA by executing `git rev-parse ` + 6. Copy the long SHA + 7. Paste it in place of the old SHA(rev) in flake.nix:inputs:nixpkgs.url + ''; - cargoLock = { - lockFile = ./Cargo.lock; - outputHashes = { - "criterion-0.3.5" = "sha256-+FibPQGiR45g28xCHcM0pMN+C+Q8gO8206Wb5fiTy+k="; - "inkwell-0.1.0" = "sha256-1kpvY3naS33B99nuu5ZYhb7mdddAyG+DkbUl/RG1Ptg="; - "plotters-0.3.1" = "sha256-noy/RSjoEPZZbOJTZw1yxGcX5S+2q/7mxnUrzDyxOFw="; - "rustyline-9.1.1" = "sha256-aqQqz6nSp+Qn44gm3jXmmQUO6/fYTx7iLph2tbA24Bs="; - }; - }; + rustPlatform.buildRustPackage { + pname = "roc"; + version = "0.0.1"; + + src = pkgs.nix-gitignore.gitignoreSource [ ] ./.; - LLVM_SYS_130_PREFIX = "${llvmPkgs.llvm.dev}"; + cargoLock = { + lockFile = ./Cargo.lock; + outputHashes = { + "criterion-0.3.5" = "sha256-+FibPQGiR45g28xCHcM0pMN+C+Q8gO8206Wb5fiTy+k="; + "inkwell-0.1.0" = "sha256-1kpvY3naS33B99nuu5ZYhb7mdddAyG+DkbUl/RG1Ptg="; + "plotters-0.3.1" = "sha256-noy/RSjoEPZZbOJTZw1yxGcX5S+2q/7mxnUrzDyxOFw="; + "rustyline-9.1.1" = "sha256-aqQqz6nSp+Qn44gm3jXmmQUO6/fYTx7iLph2tbA24Bs="; + }; + }; - # required for zig - XDG_CACHE_HOME = - "xdg_cache"; # prevents zig AccessDenied error github.com/ziglang/zig/issues/6810 - # want to see backtrace in case of failure - RUST_BACKTRACE = 1; + LLVM_SYS_130_PREFIX = "${llvmPkgs.llvm.dev}"; - # skip running rust tests, problems: - # building of example platforms requires network: Could not resolve host - # zig AccessDenied error github.com/ziglang/zig/issues/6810 - # Once instance has previously been poisoned ?? - doCheck = false; + # required for zig + XDG_CACHE_HOME = + "xdg_cache"; # prevents zig AccessDenied error github.com/ziglang/zig/issues/6810 + # want to see backtrace in case of failure + RUST_BACKTRACE = 1; - nativeBuildInputs = (with pkgs; [ - cmake - git - pkg-config - python3 - llvmPkgs.clang - llvmPkgs.llvm.dev - zig - ]); + # skip running rust tests, problems: + # building of example platforms requires network: Could not resolve host + # zig AccessDenied error github.com/ziglang/zig/issues/6810 + # Once instance has previously been poisoned ?? + doCheck = false; - buildInputs = (with pkgs; - [ - libffi - libiconv - libxkbcommon - libxml2 - ncurses - zlib - cargo - makeWrapper # necessary for postBuild wrapProgram - ] ++ lib.optionals pkgs.stdenv.isLinux [ - valgrind - vulkan-headers - vulkan-loader - vulkan-tools - vulkan-validation-layers - xorg.libX11 - xorg.libXcursor - xorg.libXi - xorg.libXrandr - xorg.libxcb - ] ++ lib.optionals pkgs.stdenv.isDarwin [ - pkgs.darwin.apple_sdk.frameworks.AppKit - pkgs.darwin.apple_sdk.frameworks.CoreFoundation - pkgs.darwin.apple_sdk.frameworks.CoreServices - pkgs.darwin.apple_sdk.frameworks.CoreVideo - pkgs.darwin.apple_sdk.frameworks.Foundation - pkgs.darwin.apple_sdk.frameworks.Metal - pkgs.darwin.apple_sdk.frameworks.Security + nativeBuildInputs = (with pkgs; [ + cmake + git + pkg-config + python3 + llvmPkgs.clang + llvmPkgs.llvm.dev + zig_0_9 ]); - # cp: to copy str.zig,list.zig... - # wrapProgram pkgs.stdenv.cc: to make ld available for compiler/build/src/link.rs - postInstall = - if pkgs.stdenv.isLinux then '' - wrapProgram $out/bin/roc --set NIX_GLIBC_PATH ${nixGlibcPath} --prefix PATH : ${ - pkgs.lib.makeBinPath [ pkgs.stdenv.cc ] - } - '' else '' - wrapProgram $out/bin/roc --prefix PATH : ${ - pkgs.lib.makeBinPath [ pkgs.stdenv.cc ] - } - ''; -} + buildInputs = (with pkgs; + [ + libffi + libiconv + libxkbcommon + libxml2 + ncurses + zlib + cargo + makeWrapper # necessary for postBuild wrapProgram + ] ++ lib.optionals pkgs.stdenv.isLinux [ + valgrind + vulkan-headers + vulkan-loader + vulkan-tools + vulkan-validation-layers + xorg.libX11 + xorg.libXcursor + xorg.libXi + xorg.libXrandr + xorg.libxcb + ] ++ lib.optionals pkgs.stdenv.isDarwin [ + pkgs.darwin.apple_sdk.frameworks.AppKit + pkgs.darwin.apple_sdk.frameworks.CoreFoundation + pkgs.darwin.apple_sdk.frameworks.CoreServices + pkgs.darwin.apple_sdk.frameworks.CoreVideo + pkgs.darwin.apple_sdk.frameworks.Foundation + pkgs.darwin.apple_sdk.frameworks.Metal + pkgs.darwin.apple_sdk.frameworks.Security + ]); + + # cp: to copy str.zig,list.zig... + # wrapProgram pkgs.stdenv.cc: to make ld available for compiler/build/src/link.rs + postInstall = + if pkgs.stdenv.isLinux then '' + wrapProgram $out/bin/roc --set NIX_GLIBC_PATH ${nixGlibcPath} --prefix PATH : ${ + pkgs.lib.makeBinPath [ pkgs.stdenv.cc ] + } + '' else '' + wrapProgram $out/bin/roc --prefix PATH : ${ + pkgs.lib.makeBinPath [ pkgs.stdenv.cc ] + } + ''; + } diff --git a/flake.nix b/flake.nix index d5ead805997..52fa26c8346 100644 --- a/flake.nix +++ b/flake.nix @@ -2,7 +2,7 @@ description = "Roc flake"; inputs = { - nixpkgs.url = "github:nixos/nixpkgs?rev=9f4346eac544cc0db5eb7d889e71eac0f9c8b9eb"; + nixpkgs.url = "github:nixos/nixpkgs?rev=d7887373fe0731719365831cd254c1e5948307d3"; # rust from nixpkgs has some libc problems, this is patched in the rust-overlay rust-overlay = { @@ -90,7 +90,7 @@ llvmPkgs.clang libxkbcommon pkg-config - zig # roc builtins are implemented in zig, see compiler/builtins/bitcode/ + zig_0_9 # roc builtins are implemented in zig, see compiler/builtins/bitcode/ # lib deps libffi From ac8cf9bbd438665b58d3e6fd91dde453155622c9 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Mon, 10 Jul 2023 19:41:14 +0200 Subject: [PATCH 139/140] update flake.lock --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index ff6fc7a2072..e8b6934018e 100644 --- a/flake.lock +++ b/flake.lock @@ -74,17 +74,17 @@ }, "nixpkgs": { "locked": { - "lastModified": 1674860021, - "narHash": "sha256-ES4XUf/AlPp8RetKR6WlWgYEZ7bLWI7k6reHp2q9rqY=", + "lastModified": 1679868513, + "narHash": "sha256-uRGLALUmieyMVqVt3mXEv0a+g9ouFOCmsv7V/01efEc=", "owner": "nixos", "repo": "nixpkgs", - "rev": "9f4346eac544cc0db5eb7d889e71eac0f9c8b9eb", + "rev": "d7887373fe0731719365831cd254c1e5948307d3", "type": "github" }, "original": { "owner": "nixos", "repo": "nixpkgs", - "rev": "9f4346eac544cc0db5eb7d889e71eac0f9c8b9eb", + "rev": "d7887373fe0731719365831cd254c1e5948307d3", "type": "github" } }, From b92bc4922e191bd128bc61eaabff3707d2844cd8 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Tue, 11 Jul 2023 16:18:22 +0200 Subject: [PATCH 140/140] segfault codemodel workaround --- crates/compiler/build/src/target.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/compiler/build/src/target.rs b/crates/compiler/build/src/target.rs index 9a62421c166..1719e8e7917 100644 --- a/crates/compiler/build/src/target.rs +++ b/crates/compiler/build/src/target.rs @@ -149,13 +149,20 @@ pub fn target_machine( init_arch(target); + // workaround for issue: + #[cfg(all(target_arch = "aarch64", target_os = "macos"))] + let code_model = CodeModel::Large; + + #[cfg(not(all(target_arch = "aarch64", target_os = "macos")))] + let code_model = CodeModel::Default; + Target::from_name(arch).unwrap().create_target_machine( &TargetTriple::create(target_triple_str(target)), "generic", "", opt, reloc, - CodeModel::Default, + code_model, ) }