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/cli/src/format.rs b/cli/src/format.rs index 399d562e29..ef2e853867 100644 --- a/cli/src/format.rs +++ b/cli/src/format.rs @@ -25,7 +25,49 @@ use roc_parse::{ }; use roc_region::all::{Loc, Region}; +fn flatten_directories(files: std::vec::Vec) -> std::vec::Vec { + let mut to_flatten = files; + let mut files = 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 + ), + } + } + } + + Err(error) => internal_error!( + "There was an error while trying to read the contents of a directory: {:?}", + error + ), + } + } else { + files.push(path) + } + } + + files +} + pub fn format(files: std::vec::Vec, mode: FormatMode) -> Result<(), String> { + let files = flatten_directories(files); + for file in files { let arena = Bump::new(); 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/cli/tests/cli_run.rs b/cli/tests/cli_run.rs index 45a32eecd9..ea5bd4f33d 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, + 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; @@ -884,6 +884,15 @@ mod cli_run { fn format_check_reformatting_needed() { check_format_check_as_expected(&fixture_file("format", "NotFormatted.roc"), false); } + + #[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); + } } #[allow(dead_code)] diff --git a/cli/tests/fixtures/format/formatted_directory/Formatted.roc b/cli/tests/fixtures/format/formatted_directory/Formatted.roc new file mode 100644 index 0000000000..b62c494e66 --- /dev/null +++ b/cli/tests/fixtures/format/formatted_directory/Formatted.roc @@ -0,0 +1,6 @@ +app "formatted" + packages { pf: "platform" } imports [] + provides [ main ] to pf + +main : Str +main = Dep1.value1 {} 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(); 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 64a7a32176..7a503fade0 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, } 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/compiler/test_gen/src/gen_list.rs b/compiler/test_gen/src/gen_list.rs index 333bdb4a63..8a6f142c64 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,10 +202,14 @@ 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 ); - assert_evals_to!("List.takeLast [] 1", RocList::from_slice(&[]), RocList); assert_evals_to!( "List.takeLast [1,2] 5", RocList::from_slice(&[1, 2]), @@ -233,17 +237,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 +265,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 +284,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 +315,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 +340,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 +370,7 @@ fn list_intersperse() { List.intersperse [] 1 "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -380,7 +409,7 @@ fn list_drop_if_empty_list_of_int() { List.dropIf empty \_ -> True "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -397,7 +426,7 @@ fn list_drop_if_empty_list() { List.dropIf [] alwaysTrue "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -425,7 +454,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 +495,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 +537,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 +829,7 @@ fn list_keep_if_empty_list_of_int() { List.keepIf empty \_ -> True "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -799,7 +848,7 @@ fn list_keep_if_empty_list() { List.keepIf [] alwaysTrue "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -839,7 +888,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 +938,7 @@ fn list_map_on_empty_list_with_int_layout() { List.map empty (\x -> x) "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -1000,7 +1049,7 @@ fn list_map_all_inline() { List.map [] (\x -> x > 0) "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -1126,7 +1175,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 +1261,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 +1299,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> ); @@ -1260,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> ); @@ -1300,7 +1353,7 @@ fn list_reverse_empty_list_of_int() { List.reverse emptyList "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -1308,7 +1361,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 +1385,7 @@ fn list_concat() { List.concat firstList secondList "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -1336,7 +1393,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 +1417,7 @@ fn list_concat_two_empty_lists_of_int() { List.concat firstList secondList "# ), - RocList::from_slice(&[]), + RocList::::from_slice(&[]), RocList ); } @@ -2386,7 +2447,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 +2465,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 +2483,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 +2498,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 ); } 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 = []