From c327681ebc0a651a9409822cf46b332b91658e2e Mon Sep 17 00:00:00 2001 From: Brendan Hansknecht Date: Thu, 24 Feb 2022 10:31:21 -0800 Subject: [PATCH 01/14] Wasmer: use cranelift for non-x86_64 since singlepass is not supported --- Cargo.lock | 117 ++++++++++++++++++++++++++++++++++- cli/Cargo.toml | 17 ++++- compiler/test_gen/Cargo.toml | 8 ++- repl_test/Cargo.toml | 8 ++- 4 files changed, 144 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 69d526c6f6..bbaa9d4ce2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,7 +24,7 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" dependencies = [ - "gimli", + "gimli 0.26.1", ] [[package]] @@ -739,6 +739,66 @@ dependencies = [ "libc", ] +[[package]] +name = "cranelift-bforest" +version = "0.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ca3560686e7c9c7ed7e0fe77469f2410ba5d7781b1acaa9adc8d8deea28e3e" +dependencies = [ + "cranelift-entity", +] + +[[package]] +name = "cranelift-codegen" +version = "0.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf9bf1ffffb6ce3d2e5ebc83549bd2436426c99b31cc550d521364cbe35d276" +dependencies = [ + "cranelift-bforest", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-entity", + "gimli 0.24.0", + "log", + "regalloc", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cc21936a5a6d07e23849ffe83e5c1f6f50305c074f4b2970ca50c13bf55b821" +dependencies = [ + "cranelift-codegen-shared", + "cranelift-entity", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca5b6ffaa87560bebe69a5446449da18090b126037920b0c1c6d5945f72faf6b" + +[[package]] +name = "cranelift-entity" +version = "0.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d6b4a8bef04f82e4296782646f733c641d09497df2fabf791323fefaa44c64c" + +[[package]] +name = "cranelift-frontend" +version = "0.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b783b351f966fce33e3c03498cb116d16d97a8f9978164a60920bd0d3a99c" +dependencies = [ + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", +] + [[package]] name = "crc32fast" version = "1.2.1" @@ -1252,6 +1312,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + [[package]] name = "fd-lock" version = "3.0.2" @@ -1471,6 +1537,17 @@ dependencies = [ "syn", ] +[[package]] +name = "gimli" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4075386626662786ddb0ec9081e7c7eeb1ba31951f447ca780ef9f5d568189" +dependencies = [ + "fallible-iterator", + "indexmap", + "stable_deref_trait", +] + [[package]] name = "gimli" version = "0.26.1" @@ -3079,6 +3156,17 @@ dependencies = [ "redox_syscall", ] +[[package]] +name = "regalloc" +version = "0.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "571f7f397d61c4755285cd37853fe8e03271c243424a907415909379659381c5" +dependencies = [ + "log", + "rustc-hash", + "smallvec", +] + [[package]] name = "regex" version = "1.5.4" @@ -4165,6 +4253,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_assertions" version = "1.1.0" @@ -4692,6 +4786,7 @@ dependencies = [ "target-lexicon", "thiserror", "wasmer-compiler", + "wasmer-compiler-cranelift", "wasmer-compiler-singlepass", "wasmer-derive", "wasmer-engine", @@ -4721,6 +4816,26 @@ dependencies = [ "wasmparser", ] +[[package]] +name = "wasmer-compiler-cranelift" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a570746cbec434179e2d53357973a34dfdb208043104e8fac3b7b0023015cf6" +dependencies = [ + "cranelift-codegen", + "cranelift-entity", + "cranelift-frontend", + "gimli 0.24.0", + "loupe", + "more-asserts", + "rayon", + "smallvec", + "tracing", + "wasmer-compiler", + "wasmer-types", + "wasmer-vm", +] + [[package]] name = "wasmer-compiler-singlepass" version = "2.0.0" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index d47d8cce8a..8890ba8076 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -65,12 +65,16 @@ mimalloc = { version = "0.1.26", default-features = false } target-lexicon = "0.12.2" tempfile = "3.2.0" - -wasmer = { version = "2.0.0", optional = true, default-features = false, features = ["default-singlepass", "default-universal"] } wasmer-wasi = { version = "2.0.0", optional = true } +# Wasmer singlepass compiler only works on x86_64. +[target.'cfg(target_arch = "x86_64")'.dependencies] +wasmer = { version = "2.0.0", optional = true, default-features = false, features = ["default-singlepass", "default-universal"] } + +[target.'cfg(not(target_arch = "x86_64"))'.dependencies] +wasmer = { version = "2.0.0", optional = true, default-features = false, features = ["default-cranelift", "default-universal"] } + [dev-dependencies] -wasmer = { version = "2.0.0", default-features = false, features = ["default-singlepass", "default-universal"] } wasmer-wasi = "2.0.0" pretty_assertions = "1.0.0" roc_test_utils = { path = "../test_utils" } @@ -79,6 +83,13 @@ serial_test = "0.5.1" criterion = { git = "https://github.com/Anton-4/criterion.rs"} cli_utils = { path = "../cli_utils" } +# Wasmer singlepass compiler only works on x86_64. +[target.'cfg(target_arch = "x86_64")'.dev-dependencies] +wasmer = { version = "2.0.0", default-features = false, features = ["default-singlepass", "default-universal"] } + +[target.'cfg(not(target_arch = "x86_64"))'.dev-dependencies] +wasmer = { version = "2.0.0", default-features = false, features = ["default-cranelift", "default-universal"] } + [[bench]] name = "time_bench" harness = false diff --git a/compiler/test_gen/Cargo.toml b/compiler/test_gen/Cargo.toml index 53e7e968c0..67421a073d 100644 --- a/compiler/test_gen/Cargo.toml +++ b/compiler/test_gen/Cargo.toml @@ -39,11 +39,17 @@ libc = "0.2.106" inkwell = { path = "../../vendor/inkwell" } target-lexicon = "0.12.2" libloading = "0.7.1" -wasmer = { version = "2.0.0", default-features = false, features = ["default-singlepass", "default-universal"] } wasmer-wasi = "2.0.0" tempfile = "3.2.0" indoc = "1.0.3" +# Wasmer singlepass compiler only works on x86_64. +[target.'cfg(target_arch = "x86_64")'.dev-dependencies] +wasmer = { version = "2.0.0", default-features = false, features = ["default-singlepass", "default-universal"] } + +[target.'cfg(not(target_arch = "x86_64"))'.dev-dependencies] +wasmer = { version = "2.0.0", default-features = false, features = ["default-cranelift", "default-universal"] } + [features] default = ["gen-llvm"] gen-llvm = [] diff --git a/repl_test/Cargo.toml b/repl_test/Cargo.toml index 4bd8992b6d..736276ba9b 100644 --- a/repl_test/Cargo.toml +++ b/repl_test/Cargo.toml @@ -13,11 +13,17 @@ roc_cli = {path = "../cli"} [dev-dependencies] indoc = "1.0.3" strip-ansi-escapes = "0.1.1" -wasmer = {version = "2.0.0", default-features = false, features = ["default-singlepass", "default-universal"]} wasmer-wasi = "2.0.0" roc_repl_cli = {path = "../repl_cli"} roc_test_utils = {path = "../test_utils"} +# Wasmer singlepass compiler only works on x86_64. +[target.'cfg(target_arch = "x86_64")'.dev-dependencies] +wasmer = { version = "2.0.0", default-features = false, features = ["default-singlepass", "default-universal"] } + +[target.'cfg(not(target_arch = "x86_64"))'.dev-dependencies] +wasmer = { version = "2.0.0", default-features = false, features = ["default-cranelift", "default-universal"] } + [features] wasm = [] From 8bafbf3bebb8c1f474abdc5870c53df2f799f242 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Thu, 24 Feb 2022 17:33:53 -0300 Subject: [PATCH 02/14] extracts .roc files from folders before formatting --- cli/src/format.rs | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/cli/src/format.rs b/cli/src/format.rs index fdc1d2bd6f..348f16bbd3 100644 --- a/cli/src/format.rs +++ b/cli/src/format.rs @@ -25,7 +25,45 @@ use roc_parse::{ }; use roc_region::all::{Loc, Region}; +fn flatten_folders(files: std::vec::Vec) -> std::vec::Vec { + files.into_iter().flat_map(|file| { + if file.is_dir() { + match file.read_dir() { + Ok(directory) => directory + .flat_map(|result| match result { + Ok(file) => { + let path = file.path(); + + if path.is_dir() { + flatten_folders(vec![path]) + } else if path.ends_with(".roc") { + vec![path] + } else { + vec![] + } + } + Err(error) => internal_error!( + "There was an error while trying to read a file from a folder: {:?}", + error + ), + }) + .collect(), + Err(error) => { + internal_error!( + "There was an error while trying to read the contents of a directory: {:?}", + error + ); + } + } + } else { + vec![file] + } + }).collect() +} + pub fn format(files: std::vec::Vec, mode: FormatMode) -> Result<(), String> { + let files = flatten_folders(files); + for file in files { let arena = Bump::new(); From 797605cd72bd8f88f0eb043d6e7e71ad08a18c15 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Thu, 24 Feb 2022 17:56:48 -0300 Subject: [PATCH 03/14] uses the word 'folder' consistently --- cli/src/format.rs | 51 +++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/cli/src/format.rs b/cli/src/format.rs index 348f16bbd3..98c31faaa0 100644 --- a/cli/src/format.rs +++ b/cli/src/format.rs @@ -26,39 +26,42 @@ use roc_parse::{ use roc_region::all::{Loc, Region}; fn flatten_folders(files: std::vec::Vec) -> std::vec::Vec { - files.into_iter().flat_map(|file| { - if file.is_dir() { - match file.read_dir() { - Ok(directory) => directory - .flat_map(|result| match result { - Ok(file) => { - let path = file.path(); + files + .into_iter() + .flat_map(|file| { + if file.is_dir() { + match file.read_dir() { + Ok(folder) => folder + .flat_map(|result| match result { + Ok(file) => { + let path = file.path(); - if path.is_dir() { - flatten_folders(vec![path]) - } else if path.ends_with(".roc") { - vec![path] - } else { - vec![] + if path.is_dir() { + flatten_folders(vec![path]) + } else if path.ends_with(".roc") { + vec![path] + } else { + vec![] + } } - } - Err(error) => internal_error!( + Err(error) => internal_error!( "There was an error while trying to read a file from a folder: {:?}", error ), - }) - .collect(), - Err(error) => { - internal_error!( - "There was an error while trying to read the contents of a directory: {:?}", + }) + .collect(), + Err(error) => { + internal_error!( + "There was an error while trying to read the contents of a folder: {:?}", error ); + } } + } else { + vec![file] } - } else { - vec![file] - } - }).collect() + }) + .collect() } pub fn format(files: std::vec::Vec, mode: FormatMode) -> Result<(), String> { From 9d487a4a95483ee6c53e0421b43ee1bec967b156 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Thu, 24 Feb 2022 18:06:42 -0300 Subject: [PATCH 04/14] adds tests --- cli/tests/cli_run.rs | 8 +++++++- cli/tests/fixtures/format/formatted_folder/Formatted.roc | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 cli/tests/fixtures/format/formatted_folder/Formatted.roc diff --git a/cli/tests/cli_run.rs b/cli/tests/cli_run.rs index 45a32eecd9..b29890cfff 100644 --- a/cli/tests/cli_run.rs +++ b/cli/tests/cli_run.rs @@ -13,7 +13,7 @@ extern crate indoc; mod cli_run { use cli_utils::helpers::{ example_file, examples_dir, extract_valgrind_errors, fixture_file, known_bad_file, run_cmd, - run_roc, run_with_valgrind, ValgrindError, ValgrindErrorXWhat, + run_roc, run_with_valgrind, ValgrindError, ValgrindErrorXWhat, fixtures_dir, }; use roc_test_utils::assert_multiline_str_eq; use serial_test::serial; @@ -884,6 +884,12 @@ mod cli_run { fn format_check_reformatting_needed() { check_format_check_as_expected(&fixture_file("format", "NotFormatted.roc"), false); } + + #[test] + fn format_check_folders() { + check_format_check_as_expected(&fixtures_dir("format"), false); + check_format_check_as_expected(&fixtures_dir("format/formatted_folder"), true); + } } #[allow(dead_code)] diff --git a/cli/tests/fixtures/format/formatted_folder/Formatted.roc b/cli/tests/fixtures/format/formatted_folder/Formatted.roc new file mode 100644 index 0000000000..b62c494e66 --- /dev/null +++ b/cli/tests/fixtures/format/formatted_folder/Formatted.roc @@ -0,0 +1,6 @@ +app "formatted" + packages { pf: "platform" } imports [] + provides [ main ] to pf + +main : Str +main = Dep1.value1 {} From 214d4e025b31457a9a0d16785db652710745164f Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Thu, 24 Feb 2022 18:10:39 -0300 Subject: [PATCH 05/14] changes wording from 'folder' to 'directory' --- cli/src/format.rs | 12 ++++++------ cli/tests/cli_run.rs | 2 +- .../Formatted.roc | 0 3 files changed, 7 insertions(+), 7 deletions(-) rename cli/tests/fixtures/format/{formatted_folder => formatted_directory}/Formatted.roc (100%) diff --git a/cli/src/format.rs b/cli/src/format.rs index 98c31faaa0..f334c3ca69 100644 --- a/cli/src/format.rs +++ b/cli/src/format.rs @@ -25,19 +25,19 @@ use roc_parse::{ }; use roc_region::all::{Loc, Region}; -fn flatten_folders(files: std::vec::Vec) -> std::vec::Vec { +fn flatten_directories(files: std::vec::Vec) -> std::vec::Vec { files .into_iter() .flat_map(|file| { if file.is_dir() { match file.read_dir() { - Ok(folder) => folder + Ok(directory) => directory .flat_map(|result| match result { Ok(file) => { let path = file.path(); if path.is_dir() { - flatten_folders(vec![path]) + flatten_directories(vec![path]) } else if path.ends_with(".roc") { vec![path] } else { @@ -45,14 +45,14 @@ fn flatten_folders(files: std::vec::Vec) -> std::vec::Vec { } } Err(error) => internal_error!( - "There was an error while trying to read a file from a folder: {:?}", + "There was an error while trying to read a file from a directory: {:?}", error ), }) .collect(), Err(error) => { internal_error!( - "There was an error while trying to read the contents of a folder: {:?}", + "There was an error while trying to read the contents of a directory: {:?}", error ); } @@ -65,7 +65,7 @@ fn flatten_folders(files: std::vec::Vec) -> std::vec::Vec { } pub fn format(files: std::vec::Vec, mode: FormatMode) -> Result<(), String> { - let files = flatten_folders(files); + let files = flatten_directories(files); for file in files { let arena = Bump::new(); diff --git a/cli/tests/cli_run.rs b/cli/tests/cli_run.rs index b29890cfff..2e6f21e020 100644 --- a/cli/tests/cli_run.rs +++ b/cli/tests/cli_run.rs @@ -888,7 +888,7 @@ mod cli_run { #[test] fn format_check_folders() { check_format_check_as_expected(&fixtures_dir("format"), false); - check_format_check_as_expected(&fixtures_dir("format/formatted_folder"), true); + check_format_check_as_expected(&fixtures_dir("format/formatted_directory"), true); } } diff --git a/cli/tests/fixtures/format/formatted_folder/Formatted.roc b/cli/tests/fixtures/format/formatted_directory/Formatted.roc similarity index 100% rename from cli/tests/fixtures/format/formatted_folder/Formatted.roc rename to cli/tests/fixtures/format/formatted_directory/Formatted.roc From 7f186249a1a7a83def1cd1cc911052b709e119c7 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Thu, 24 Feb 2022 18:11:57 -0300 Subject: [PATCH 06/14] formats cli test file --- cli/tests/cli_run.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/tests/cli_run.rs b/cli/tests/cli_run.rs index 2e6f21e020..3f3c507dfb 100644 --- a/cli/tests/cli_run.rs +++ b/cli/tests/cli_run.rs @@ -12,8 +12,8 @@ extern crate indoc; #[cfg(test)] mod cli_run { use cli_utils::helpers::{ - example_file, examples_dir, extract_valgrind_errors, fixture_file, known_bad_file, run_cmd, - run_roc, run_with_valgrind, ValgrindError, ValgrindErrorXWhat, fixtures_dir, + example_file, examples_dir, extract_valgrind_errors, fixture_file, fixtures_dir, + known_bad_file, run_cmd, run_roc, run_with_valgrind, ValgrindError, ValgrindErrorXWhat, }; use roc_test_utils::assert_multiline_str_eq; use serial_test::serial; From c0709a91f3a5f5d2332e41b1d24a17b40b78d6ca Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Thu, 24 Feb 2022 19:57:58 -0300 Subject: [PATCH 07/14] adds comments to format_check_folders test --- cli/tests/cli_run.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cli/tests/cli_run.rs b/cli/tests/cli_run.rs index 3f3c507dfb..ea5bd4f33d 100644 --- a/cli/tests/cli_run.rs +++ b/cli/tests/cli_run.rs @@ -887,7 +887,10 @@ mod cli_run { #[test] fn format_check_folders() { + // This fails, because "NotFormatted.roc" is present in this folder check_format_check_as_expected(&fixtures_dir("format"), false); + + // This doesn't fail, since only "Formatted.roc" is present in this folder check_format_check_as_expected(&fixtures_dir("format/formatted_directory"), true); } } From 36dffc8c5f360f7477c34cd23e9935a297802e19 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Thu, 24 Feb 2022 19:58:20 -0300 Subject: [PATCH 08/14] changes implementation of folder flattening --- cli/src/format.rs | 53 +++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/cli/src/format.rs b/cli/src/format.rs index f334c3ca69..157254293f 100644 --- a/cli/src/format.rs +++ b/cli/src/format.rs @@ -26,42 +26,41 @@ use roc_parse::{ use roc_region::all::{Loc, Region}; fn flatten_directories(files: std::vec::Vec) -> std::vec::Vec { - files - .into_iter() - .flat_map(|file| { - if file.is_dir() { - match file.read_dir() { - Ok(directory) => directory - .flat_map(|result| match result { - Ok(file) => { - let path = file.path(); + let mut to_flatten = files; + let mut files = vec![]; - if path.is_dir() { - flatten_directories(vec![path]) - } else if path.ends_with(".roc") { - vec![path] - } else { - vec![] + while let Some(path) = to_flatten.pop() { + if path.is_dir() { + match path.read_dir() { + Ok(directory) => { + for item in directory { + match item { + Ok(file) => { + let file_path = file.path(); + if file_path.is_dir() { + to_flatten.push(file_path); + } else if file_path.ends_with(".roc") { + files.push(file_path); } } + Err(error) => internal_error!( "There was an error while trying to read a file from a directory: {:?}", error - ), - }) - .collect(), - Err(error) => { - internal_error!( - "There was an error while trying to read the contents of a directory: {:?}", - error - ); + ), + } } } - } else { - vec![file] + + Err(error) => internal_error!( + "There was an error while trying to read the contents of a directory: {:?}", + error + ), } - }) - .collect() + } else { + files.push(path) + } + } } pub fn format(files: std::vec::Vec, mode: FormatMode) -> Result<(), String> { From 98f3f1498492924d282ecb60315d35c904f468ec Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Thu, 24 Feb 2022 20:00:29 -0300 Subject: [PATCH 09/14] fixes compiling error on directory flattening --- cli/src/format.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cli/src/format.rs b/cli/src/format.rs index 157254293f..9950ca2a62 100644 --- a/cli/src/format.rs +++ b/cli/src/format.rs @@ -61,6 +61,8 @@ fn flatten_directories(files: std::vec::Vec) -> std::vec::Vec files.push(path) } } + + files } pub fn format(files: std::vec::Vec, mode: FormatMode) -> Result<(), String> { From 98eb359dade5061d8fbf0bba105d0553eb08699f Mon Sep 17 00:00:00 2001 From: celso Date: Thu, 24 Feb 2022 20:07:03 -0300 Subject: [PATCH 10/14] fixes identation on flatten_directories Co-authored-by: hafiz <20735482+ayazhafiz@users.noreply.github.com> --- cli/src/format.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/src/format.rs b/cli/src/format.rs index 9950ca2a62..5504cf8e6d 100644 --- a/cli/src/format.rs +++ b/cli/src/format.rs @@ -45,8 +45,8 @@ fn flatten_directories(files: std::vec::Vec) -> std::vec::Vec } Err(error) => internal_error!( - "There was an error while trying to read a file from a directory: {:?}", - error + "There was an error while trying to read a file from a directory: {:?}", + error ), } } From 69b4e78ac74efa58225a194f201a4a22d8998794 Mon Sep 17 00:00:00 2001 From: Brendan Hansknecht Date: Thu, 24 Feb 2022 15:39:50 -0800 Subject: [PATCH 11/14] Add --opt-size and compiling smaller binaries --- cli/src/lib.rs | 36 ++++++++++++++------ compiler/build/src/program.rs | 2 +- compiler/build/src/target.rs | 2 ++ compiler/gen_llvm/src/llvm/build.rs | 52 +++++++++++++++++------------ compiler/mono/src/alias_analysis.rs | 2 +- compiler/mono/src/ir.rs | 1 + 6 files changed, 61 insertions(+), 34 deletions(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index e3027927ea..b790552538 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -5,6 +5,7 @@ use build::{BuildOutcome, BuiltFile}; use bumpalo::Bump; use clap::{App, AppSettings, Arg, ArgMatches}; use roc_build::link::LinkType; +use roc_error_macros::user_error; use roc_load::file::LoadingProblem; use roc_mono::ir::OptLevel; use std::env; @@ -31,6 +32,7 @@ pub const CMD_FORMAT: &str = "format"; pub const FLAG_DEBUG: &str = "debug"; pub const FLAG_DEV: &str = "dev"; pub const FLAG_OPTIMIZE: &str = "optimize"; +pub const FLAG_OPT_SIZE: &str = "opt-size"; pub const FLAG_LIB: &str = "lib"; pub const FLAG_BACKEND: &str = "backend"; pub const FLAG_TIME: &str = "time"; @@ -61,6 +63,12 @@ pub fn build_app<'a>() -> App<'a> { .about("Optimize your compiled Roc program to run faster. (Optimization takes time to complete.)") .required(false), ) + .arg( + Arg::new(FLAG_OPT_SIZE) + .long(FLAG_OPT_SIZE) + .about("Optimize your compiled Roc program to have a small binary size. (Optimization takes time to complete.)") + .required(false), + ) .arg( Arg::new(FLAG_DEV) .long(FLAG_DEV) @@ -166,12 +174,18 @@ pub fn build_app<'a>() -> App<'a> { .requires(ROC_FILE) .required(false), ) - .arg( - Arg::new(FLAG_DEV) - .long(FLAG_DEV) - .about("Make compilation as fast as possible. (Runtime performance may suffer)") - .required(false), - ) + .arg( + Arg::new(FLAG_OPT_SIZE) + .long(FLAG_OPT_SIZE) + .about("Optimize your compiled Roc program to have a small binary size. (Optimization takes time to complete.)") + .required(false), + ) + .arg( + Arg::new(FLAG_DEV) + .long(FLAG_DEV) + .about("Make compilation as fast as possible. (Runtime performance may suffer)") + .required(false), + ) .arg( Arg::new(FLAG_DEBUG) .long(FLAG_DEBUG) @@ -272,12 +286,14 @@ pub fn build(matches: &ArgMatches, config: BuildConfig) -> io::Result { let original_cwd = std::env::current_dir()?; let opt_level = match ( matches.is_present(FLAG_OPTIMIZE), + matches.is_present(FLAG_OPT_SIZE), matches.is_present(FLAG_DEV), ) { - (true, false) => OptLevel::Optimize, - (true, true) => panic!("development cannot be optimized!"), - (false, true) => OptLevel::Development, - (false, false) => OptLevel::Normal, + (true, false, false) => OptLevel::Optimize, + (false, true, false) => OptLevel::Size, + (false, false, true) => OptLevel::Development, + (false, false, false) => OptLevel::Normal, + _ => user_error!("build can be only one of `--dev`, `--optimize`, or `--opt-size`"), }; let emit_debug_info = matches.is_present(FLAG_DEBUG); let emit_timings = matches.is_present(FLAG_TIME); diff --git a/compiler/build/src/program.rs b/compiler/build/src/program.rs index 933e8f9e7a..53b74ae8b1 100644 --- a/compiler/build/src/program.rs +++ b/compiler/build/src/program.rs @@ -199,7 +199,7 @@ pub fn gen_from_mono_module( emit_debug_info: bool, ) -> CodeGenTiming { match opt_level { - OptLevel::Normal | OptLevel::Optimize => gen_from_mono_module_llvm( + OptLevel::Normal | OptLevel::Size | OptLevel::Optimize => gen_from_mono_module_llvm( arena, loaded, roc_file_path, diff --git a/compiler/build/src/target.rs b/compiler/build/src/target.rs index 6064e58428..a49aff892b 100644 --- a/compiler/build/src/target.rs +++ b/compiler/build/src/target.rs @@ -114,6 +114,8 @@ pub fn target_machine( pub fn convert_opt_level(level: OptLevel) -> OptimizationLevel { match level { OptLevel::Development | OptLevel::Normal => OptimizationLevel::None, + // Default is O2/Os. If we want Oz, we have to explicitly turn of loop vectorization as well. + OptLevel::Size => OptimizationLevel::Default, OptLevel::Optimize => OptimizationLevel::Aggressive, } } diff --git a/compiler/gen_llvm/src/llvm/build.rs b/compiler/gen_llvm/src/llvm/build.rs index af42090989..7058b1c635 100644 --- a/compiler/gen_llvm/src/llvm/build.rs +++ b/compiler/gen_llvm/src/llvm/build.rs @@ -657,35 +657,43 @@ pub fn construct_optimization_passes<'a>( OptLevel::Development | OptLevel::Normal => { pmb.set_optimization_level(OptimizationLevel::None); } + OptLevel::Size => { + pmb.set_optimization_level(OptimizationLevel::Default); + // TODO: For some usecase, like embedded, it is useful to expose this and tune it. + pmb.set_inliner_with_threshold(50); + } OptLevel::Optimize => { pmb.set_optimization_level(OptimizationLevel::Aggressive); // this threshold seems to do what we want pmb.set_inliner_with_threshold(275); - - // TODO figure out which of these actually help - - // function passes - - fpm.add_cfg_simplification_pass(); - mpm.add_cfg_simplification_pass(); - - fpm.add_jump_threading_pass(); - mpm.add_jump_threading_pass(); - - fpm.add_memcpy_optimize_pass(); // this one is very important - - fpm.add_licm_pass(); - - // turn invoke into call - mpm.add_prune_eh_pass(); - - // remove unused global values (often the `_wrapper` can be removed) - mpm.add_global_dce_pass(); - - mpm.add_function_inlining_pass(); } } + // Add optimization passes for Size and Optimize. + if matches!(opt_level, OptLevel::Size | OptLevel::Optimize) { + // TODO figure out which of these actually help + + // function passes + + fpm.add_cfg_simplification_pass(); + mpm.add_cfg_simplification_pass(); + + fpm.add_jump_threading_pass(); + mpm.add_jump_threading_pass(); + + fpm.add_memcpy_optimize_pass(); // this one is very important + + fpm.add_licm_pass(); + + // turn invoke into call + mpm.add_prune_eh_pass(); + + // remove unused global values (often the `_wrapper` can be removed) + mpm.add_global_dce_pass(); + + mpm.add_function_inlining_pass(); + } + pmb.populate_module_pass_manager(&mpm); pmb.populate_function_pass_manager(&fpm); diff --git a/compiler/mono/src/alias_analysis.rs b/compiler/mono/src/alias_analysis.rs index 810e3c3595..f25e3e3b08 100644 --- a/compiler/mono/src/alias_analysis.rs +++ b/compiler/mono/src/alias_analysis.rs @@ -245,7 +245,7 @@ where match opt_level { OptLevel::Development | OptLevel::Normal => morphic_lib::solve_trivial(program), - OptLevel::Optimize => morphic_lib::solve(program), + OptLevel::Optimize | OptLevel::Size => morphic_lib::solve(program), } } diff --git a/compiler/mono/src/ir.rs b/compiler/mono/src/ir.rs index 300c4272ef..3aed213fd3 100644 --- a/compiler/mono/src/ir.rs +++ b/compiler/mono/src/ir.rs @@ -90,6 +90,7 @@ macro_rules! return_on_layout_error_help { pub enum OptLevel { Development, Normal, + Size, Optimize, } From ec411b7a62d609de21f65fed6492bd4302da5a3e Mon Sep 17 00:00:00 2001 From: Brendan Hansknecht Date: Thu, 24 Feb 2022 16:21:12 -0800 Subject: [PATCH 12/14] Also build host for size when using --opt-size --- compiler/build/src/link.rs | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/compiler/build/src/link.rs b/compiler/build/src/link.rs index 21ea8da01a..27ef1cc7ca 100644 --- a/compiler/build/src/link.rs +++ b/compiler/build/src/link.rs @@ -137,6 +137,8 @@ pub fn build_zig_host_native( if matches!(opt_level, OptLevel::Optimize) { command.args(&["-O", "ReleaseSafe"]); + } else if matches!(opt_level, OptLevel::Size) { + command.args(&["-O", "ReleaseSmall"]); } command.output().unwrap() } @@ -231,6 +233,8 @@ pub fn build_zig_host_native( ]); if matches!(opt_level, OptLevel::Optimize) { command.args(&["-O", "ReleaseSafe"]); + } else if matches!(opt_level, OptLevel::Size) { + command.args(&["-O", "ReleaseSmall"]); } command.output().unwrap() } @@ -282,6 +286,8 @@ pub fn build_zig_host_wasm32( ]); if matches!(opt_level, OptLevel::Optimize) { command.args(&["-O", "ReleaseSafe"]); + } else if matches!(opt_level, OptLevel::Size) { + command.args(&["-O", "ReleaseSmall"]); } command.output().unwrap() } @@ -317,7 +323,9 @@ pub fn build_c_host_native( command.args(&["-fPIC", "-c"]); } if matches!(opt_level, OptLevel::Optimize) { - command.arg("-O2"); + command.arg("-O3"); + } else if matches!(opt_level, OptLevel::Size) { + command.arg("-Os"); } command.output().unwrap() } @@ -351,6 +359,8 @@ pub fn build_swift_host_native( if matches!(opt_level, OptLevel::Optimize) { command.arg("-O"); + } else if matches!(opt_level, OptLevel::Size) { + command.arg("-Osize"); } command.output().unwrap() @@ -456,18 +466,18 @@ pub fn rebuild_host( } else if cargo_host_src.exists() { // Compile and link Cargo.toml, if it exists let cargo_dir = host_input_path.parent().unwrap(); - let cargo_out_dir = - cargo_dir - .join("target") - .join(if matches!(opt_level, OptLevel::Optimize) { - "release" - } else { - "debug" - }); + let cargo_out_dir = cargo_dir.join("target").join( + if matches!(opt_level, OptLevel::Optimize | OptLevel::Size) { + "release" + } else { + "debug" + }, + ); let mut command = Command::new("cargo"); command.arg("build").current_dir(cargo_dir); - if matches!(opt_level, OptLevel::Optimize) { + // Rust doesn't expose size without editing the cargo.toml. Instead just use release. + if matches!(opt_level, OptLevel::Optimize | OptLevel::Size) { command.arg("--release"); } let source_file = if shared_lib_path.is_some() { @@ -533,6 +543,8 @@ pub fn rebuild_host( ]); if matches!(opt_level, OptLevel::Optimize) { command.arg("-O"); + } else if matches!(opt_level, OptLevel::Size) { + command.arg("-C opt-level=s"); } let output = command.output().unwrap(); From 868316abb81f77c0badaf4016b863a7cea5f9bc3 Mon Sep 17 00:00:00 2001 From: Tom Dohrmann Date: Fri, 25 Feb 2022 13:02:11 +0100 Subject: [PATCH 13/14] make types more explicit --- compiler/test_gen/src/gen_list.rs | 153 ++++++++++++++++++++++-------- compiler/test_gen/src/gen_set.rs | 4 +- 2 files changed, 113 insertions(+), 44 deletions(-) diff --git a/compiler/test_gen/src/gen_list.rs b/compiler/test_gen/src/gen_list.rs index 333bdb4a63..19cef4ebc5 100644 --- a/compiler/test_gen/src/gen_list.rs +++ b/compiler/test_gen/src/gen_list.rs @@ -28,7 +28,7 @@ fn roc_list_construction() { #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] fn empty_list_literal() { - assert_evals_to!("[]", RocList::from_slice(&[]), RocList); + assert_evals_to!("[]", RocList::::from_slice(&[]), RocList); } #[test] @@ -136,7 +136,7 @@ fn bool_list_literal() { #[test] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] fn variously_sized_list_literals() { - assert_evals_to!("[]", RocList::from_slice(&[]), RocList); + assert_evals_to!("[]", RocList::::from_slice(&[]), RocList); assert_evals_to!("[1]", RocList::from_slice(&[1]), RocList); assert_evals_to!("[1, 2]", RocList::from_slice(&[1, 2]), RocList); assert_evals_to!("[1, 2, 3]", RocList::from_slice(&[1, 2, 3]), RocList); @@ -177,12 +177,12 @@ fn list_take_first() { ); assert_evals_to!( "List.takeFirst [1, 2, 3] 0", - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); assert_evals_to!( "List.takeFirst [] 1", - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); assert_evals_to!( @@ -202,7 +202,7 @@ fn list_take_last() { ); assert_evals_to!( "List.takeLast [1, 2, 3] 0", - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); assert_evals_to!("List.takeLast [] 1", RocList::from_slice(&[]), RocList); @@ -233,17 +233,17 @@ fn list_sublist() { ); assert_evals_to!( "List.sublist [1, 2, 3] { start: 3 , len: 2 } ", - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); assert_evals_to!( "List.sublist [] { start: 1 , len: 1 } ", - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); assert_evals_to!( "List.sublist [1, 2, 3] { start: 1 , len: 0 } ", - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); assert_evals_to!( @@ -261,7 +261,7 @@ fn list_split() { list = List.split [1, 2, 3] 0 list.before "#, - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); assert_evals_to!( @@ -280,17 +280,26 @@ fn list_split() { ); assert_evals_to!( "List.split [1, 2, 3] 3", - (RocList::from_slice(&[1, 2, 3]), RocList::from_slice(&[]),), + ( + RocList::from_slice(&[1, 2, 3]), + RocList::::from_slice(&[]), + ), (RocList, RocList,) ); assert_evals_to!( "List.split [1, 2, 3] 4", - (RocList::from_slice(&[1, 2, 3]), RocList::from_slice(&[]),), + ( + RocList::from_slice(&[1, 2, 3]), + RocList::::from_slice(&[]), + ), (RocList, RocList,) ); assert_evals_to!( "List.split [] 1", - (RocList::from_slice(&[]), RocList::from_slice(&[]),), + ( + RocList::::from_slice(&[]), + RocList::::from_slice(&[]), + ), (RocList, RocList,) ); } @@ -302,8 +311,16 @@ fn list_drop() { RocList::from_slice(&[3]), RocList ); - assert_evals_to!("List.drop [] 1", RocList::from_slice(&[]), RocList); - assert_evals_to!("List.drop [1,2] 5", RocList::from_slice(&[]), RocList); + assert_evals_to!( + "List.drop [] 1", + RocList::::from_slice(&[]), + RocList + ); + assert_evals_to!( + "List.drop [1,2] 5", + RocList::::from_slice(&[]), + RocList + ); } #[test] @@ -319,8 +336,16 @@ fn list_drop_at() { RocList::from_slice(&[0, 0, 0]), RocList ); - assert_evals_to!("List.dropAt [] 1", RocList::from_slice(&[]), RocList); - assert_evals_to!("List.dropAt [0] 0", RocList::from_slice(&[]), RocList); + assert_evals_to!( + "List.dropAt [] 1", + RocList::::from_slice(&[]), + RocList + ); + assert_evals_to!( + "List.dropAt [0] 0", + RocList::::from_slice(&[]), + RocList + ); } #[test] @@ -341,7 +366,7 @@ fn list_intersperse() { List.intersperse [] 1 "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -380,7 +405,7 @@ fn list_drop_if_empty_list_of_int() { List.dropIf empty \_ -> True "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -397,7 +422,7 @@ fn list_drop_if_empty_list() { List.dropIf [] alwaysTrue "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -425,7 +450,7 @@ fn list_drop_if_always_true_for_non_empty_list() { List.dropIf [1,2,3,4,5,6,7,8] (\_ -> True) "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -466,8 +491,16 @@ fn list_drop_last() { RocList::from_slice(&[1, 2]), RocList ); - assert_evals_to!("List.dropLast []", RocList::from_slice(&[]), RocList); - assert_evals_to!("List.dropLast [0]", RocList::from_slice(&[]), RocList); + assert_evals_to!( + "List.dropLast []", + RocList::::from_slice(&[]), + RocList + ); + assert_evals_to!( + "List.dropLast [0]", + RocList::::from_slice(&[]), + RocList + ); } #[test] @@ -500,14 +533,26 @@ fn list_drop_first() { RocList::from_slice(&[2, 3]), RocList ); - assert_evals_to!("List.dropFirst []", RocList::from_slice(&[]), RocList); - assert_evals_to!("List.dropFirst [0]", RocList::from_slice(&[]), RocList); + assert_evals_to!( + "List.dropFirst []", + RocList::::from_slice(&[]), + RocList + ); + assert_evals_to!( + "List.dropFirst [0]", + RocList::::from_slice(&[]), + RocList + ); } #[test] #[cfg(any(feature = "gen-llvm"))] fn list_swap() { - assert_evals_to!("List.swap [] 0 1", RocList::from_slice(&[]), RocList); + assert_evals_to!( + "List.swap [] 0 1", + RocList::::from_slice(&[]), + RocList + ); assert_evals_to!( "List.swap [ 0 ] 1 2", RocList::from_slice(&[0]), @@ -780,7 +825,7 @@ fn list_keep_if_empty_list_of_int() { List.keepIf empty \_ -> True "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -799,7 +844,7 @@ fn list_keep_if_empty_list() { List.keepIf [] alwaysTrue "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -839,7 +884,7 @@ fn list_keep_if_always_false_for_non_empty_list() { List.keepIf [1,2,3,4,5,6,7,8] alwaysFalse "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -889,7 +934,7 @@ fn list_map_on_empty_list_with_int_layout() { List.map empty (\x -> x) "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -1000,7 +1045,7 @@ fn list_map_all_inline() { List.map [] (\x -> x > 0) "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -1126,7 +1171,11 @@ fn list_map2_different_lengths() { #[test] #[cfg(any(feature = "gen-llvm"))] fn list_join_empty_list() { - assert_evals_to!("List.join []", RocList::from_slice(&[]), RocList); + assert_evals_to!( + "List.join []", + RocList::::from_slice(&[]), + RocList + ); } #[test] @@ -1208,7 +1257,7 @@ fn list_join_defined_empty_list() { fn list_join_all_empty_lists() { assert_evals_to!( "List.join [ [], [], [] ]", - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -1246,7 +1295,7 @@ fn list_repeat() { assert_evals_to!( "List.repeat [] 2", - RocList::from_slice(&[RocList::default(), RocList::default()]), + RocList::from_slice(&[RocList::::default(), RocList::default()]), RocList> ); @@ -1300,7 +1349,7 @@ fn list_reverse_empty_list_of_int() { List.reverse emptyList "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -1308,7 +1357,11 @@ fn list_reverse_empty_list_of_int() { #[test] #[cfg(any(feature = "gen-llvm"))] fn list_reverse_empty_list() { - assert_evals_to!("List.reverse []", RocList::from_slice(&[]), RocList); + assert_evals_to!( + "List.reverse []", + RocList::::from_slice(&[]), + RocList + ); } #[test] @@ -1328,7 +1381,7 @@ fn list_concat() { List.concat firstList secondList "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -1336,7 +1389,11 @@ fn list_concat() { #[test] #[cfg(any(feature = "gen-llvm"))] fn list_concat_two_empty_lists() { - assert_evals_to!("List.concat [] []", RocList::from_slice(&[]), RocList); + assert_evals_to!( + "List.concat [] []", + RocList::::from_slice(&[]), + RocList + ); } #[test] @@ -1356,7 +1413,7 @@ fn list_concat_two_empty_lists_of_int() { List.concat firstList secondList "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -2386,7 +2443,11 @@ fn cleanup_because_exception() { #[test] #[cfg(any(feature = "gen-llvm"))] fn list_range() { - assert_evals_to!("List.range 0 -1", RocList::from_slice(&[]), RocList); + assert_evals_to!( + "List.range 0 -1", + RocList::::from_slice(&[]), + RocList + ); assert_evals_to!("List.range 0 0", RocList::from_slice(&[0]), RocList); assert_evals_to!( "List.range 0 5", @@ -2400,7 +2461,7 @@ fn list_range() { fn list_sort_with() { assert_evals_to!( "List.sortWith [] Num.compare", - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); assert_evals_to!( @@ -2418,7 +2479,11 @@ fn list_sort_with() { #[test] #[cfg(any(feature = "gen-llvm"))] fn list_sort_asc() { - assert_evals_to!("List.sortAsc []", RocList::from_slice(&[]), RocList); + assert_evals_to!( + "List.sortAsc []", + RocList::::from_slice(&[]), + RocList + ); assert_evals_to!( "List.sortAsc [ 4,3,2,1 ]", RocList::from_slice(&[1, 2, 3, 4]), @@ -2429,7 +2494,11 @@ fn list_sort_asc() { #[test] #[cfg(any(feature = "gen-llvm"))] fn list_sort_desc() { - assert_evals_to!("List.sortDesc []", RocList::from_slice(&[]), RocList); + assert_evals_to!( + "List.sortDesc []", + RocList::::from_slice(&[]), + RocList + ); assert_evals_to!( "List.sortDesc [ 1,2,3,4 ]", RocList::from_slice(&[4, 3, 2, 1]), diff --git a/compiler/test_gen/src/gen_set.rs b/compiler/test_gen/src/gen_set.rs index 77503c105e..4a2f922f55 100644 --- a/compiler/test_gen/src/gen_set.rs +++ b/compiler/test_gen/src/gen_set.rs @@ -238,7 +238,7 @@ fn from_list() { |> Set.toList "# ), - RocList::default(), + RocList::::default(), RocList ); } @@ -254,7 +254,7 @@ fn from_list_void() { |> Set.toList "# ), - RocList::default(), + RocList::::default(), RocList ); } From 954064fa1e1356cceadbd792f1bfb5283a79dc2d Mon Sep 17 00:00:00 2001 From: Tom Dohrmann Date: Fri, 25 Feb 2022 13:58:07 +0100 Subject: [PATCH 14/14] make more types more explicit --- compiler/test_gen/src/gen_list.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/test_gen/src/gen_list.rs b/compiler/test_gen/src/gen_list.rs index 19cef4ebc5..8a6f142c64 100644 --- a/compiler/test_gen/src/gen_list.rs +++ b/compiler/test_gen/src/gen_list.rs @@ -205,7 +205,11 @@ fn list_take_last() { RocList::::from_slice(&[]), RocList ); - assert_evals_to!("List.takeLast [] 1", RocList::from_slice(&[]), RocList); + assert_evals_to!( + "List.takeLast [] 1", + RocList::::from_slice(&[]), + RocList + ); assert_evals_to!( "List.takeLast [1,2] 5", RocList::from_slice(&[1, 2]), @@ -1309,7 +1313,7 @@ fn list_repeat() { List.repeat noStrs 2 "# ), - RocList::from_slice(&[RocList::default(), RocList::default()]), + RocList::from_slice(&[RocList::::default(), RocList::default()]), RocList> );