#[allow(unused_imports)] use indoc::indoc; use roc_test_utils::assert_multiline_str_eq; #[cfg(not(feature = "wasm"))] use crate::cli::{expect_failure, expect_success, repl_eval}; #[cfg(feature = "wasm")] #[allow(unused_imports)] use crate::wasm::{expect_failure, expect_success}; #[test] fn literal_0() { expect_success("0", "0 : Num *"); } #[test] fn literal_42() { expect_success("42", "42 : Num *"); } #[test] fn literal_0x0() { expect_success("0x0", "0 : Int *"); } #[test] fn literal_0x42() { expect_success("0x42", "66 : Int *"); } #[test] fn literal_0point0() { expect_success("0.0", "0 : Float *"); } #[test] fn literal_4point2() { expect_success("4.2", "4.2 : Float *"); } #[test] fn num_addition() { expect_success("1 + 2", "3 : Num *"); } #[test] fn int_addition() { expect_success("0x1 + 2", "3 : Int *"); } #[test] fn float_addition() { expect_success("1.1 + 2", "3.1 : Float *"); } #[cfg(not(feature = "wasm"))] #[test] fn num_rem() { expect_success("299 % 10", "9 : Int *"); } #[cfg(not(feature = "wasm"))] #[test] fn num_floor_division() { expect_success("Num.divTrunc 4 3", "1 : Int *"); } #[cfg(not(feature = "wasm"))] #[test] fn num_floor_checked_division_success() { expect_success( "Num.divTruncChecked 4 3", "Ok 1 : Result (Int *) [DivByZero]", ); } #[cfg(not(feature = "wasm"))] #[test] fn num_floor_checked_division_divby_zero() { expect_success( "Num.divTruncChecked 4 0", "Err DivByZero : Result (Int *) [DivByZero]", ); } #[cfg(not(feature = "wasm"))] #[test] fn num_ceil_division() { expect_success("Num.divCeil 4 3", "2 : Int *") } #[cfg(not(feature = "wasm"))] #[test] fn num_ceil_checked_division_success() { expect_success( "Num.divCeilChecked 4 3", "Ok 2 : Result (Int *) [DivByZero]", ) } #[test] fn bool_in_record() { expect_success("{ x: 1 == 1 }", "{ x: Bool.true } : { x : Bool }"); expect_success( "{ z: { y: { x: 1 == 1 } } }", "{ z: { y: { x: Bool.true } } } : { z : { y : { x : Bool } } }", ); expect_success("{ x: 1 != 1 }", "{ x: Bool.false } : { x : Bool }"); expect_success( "{ x: 1 == 1, y: 1 != 1 }", "{ x: Bool.true, y: Bool.false } : { x : Bool, y : Bool }", ); } #[test] fn bool_basic_equality() { expect_success("1 == 1", "Bool.true : Bool"); expect_success("1 != 1", "Bool.false : Bool"); } #[test] fn bool_true() { expect_success( indoc!( r#" Bool.true "# ), r#"Bool.true : Bool"#, ); } #[test] fn bool_false() { expect_success( indoc!( r#" Bool.false "# ), r#"Bool.false : Bool"#, ); } #[test] fn arbitrary_tag_unions() { expect_success("if 1 == 1 then Red else Green", "Red : [Green, Red]"); expect_success("if 1 != 1 then Red else Green", "Green : [Green, Red]"); } #[test] fn tag_without_arguments() { expect_success("True", "True : [True]"); expect_success("False", "False : [False]"); } #[test] fn byte_tag_union() { expect_success( "if 1 == 1 then Red else if 1 == 1 then Green else Blue", "Red : [Blue, Green, Red]", ); expect_success( "{ y: { x: if 1 == 1 then Red else if 1 == 1 then Green else Blue } }", "{ y: { x: Red } } : { y : { x : [Blue, Green, Red] } }", ); } #[test] fn tag_in_record() { expect_success( "{ x: Foo 1 2 3, y : 4 }", "{ x: Foo 1 2 3, y: 4 } : { x : [Foo (Num *) (Num *) (Num *)], y : Num * }", ); expect_success( "{ x: Foo 1 2 3 }", "{ x: Foo 1 2 3 } : { x : [Foo (Num *) (Num *) (Num *)] }", ); expect_success("{ x: Unit }", "{ x: Unit } : { x : [Unit] }"); } #[test] fn single_element_tag_union() { expect_success("True 1", "True 1 : [True (Num *)]"); expect_success("Foo 1 3.14", "Foo 1 3.14 : [Foo (Num *) (Float *)]"); } #[test] fn newtype_of_unit() { expect_success("Foo Bar", "Foo Bar : [Foo [Bar]]"); } #[test] fn newtype_of_big_data() { expect_success( indoc!( r#" Either a b : [Left a, Right b] lefty : Either Str Str lefty = Left "loosey" A lefty"# ), r#"A (Left "loosey") : [A (Either Str Str)]"#, ) } #[test] fn newtype_nested() { expect_success( indoc!( r#" Either a b : [Left a, Right b] lefty : Either Str Str lefty = Left "loosey" A (B (C lefty))"# ), r#"A (B (C (Left "loosey"))) : [A [B [C (Either Str Str)]]]"#, ) } #[test] fn newtype_of_big_of_newtype() { expect_success( indoc!( r#" Big a : [Big a [Wrapper [Newtype a]]] big : Big Str big = Big "s" (Wrapper (Newtype "t")) A big"# ), r#"A (Big "s" (Wrapper (Newtype "t"))) : [A (Big Str)]"#, ) } #[test] fn tag_with_arguments() { expect_success("True 1", "True 1 : [True (Num *)]"); expect_success( "if 1 == 1 then True 3 else False 3.14", "True 3 : [False (Float *), True (Num *)]", ) } #[test] fn literal_empty_str() { expect_success("\"\"", "\"\" : Str"); } #[test] fn literal_ascii_str() { expect_success("\"Hello, World!\"", "\"Hello, World!\" : Str"); } #[test] fn literal_utf8_str() { expect_success("\"👩‍👩‍👦‍👦\"", "\"👩‍👩‍👦‍👦\" : Str"); } #[test] fn str_concat() { expect_success( "Str.concat \"Hello, \" \"World!\"", "\"Hello, World!\" : Str", ); } #[test] fn str_count_graphemes() { expect_success("Str.countGraphemes \"å🤔\"", "2 : Nat"); } #[test] fn literal_empty_list() { expect_success("[]", "[] : List *"); } #[cfg(not(feature = "wasm"))] #[test] fn literal_empty_list_empty_record() { expect_success("[{}]", "[{}] : List {}"); } #[test] fn literal_num_list() { expect_success("[1, 2, 3]", "[1, 2, 3] : List (Num *)"); } #[test] fn literal_int_list() { expect_success("[0x1, 0x2, 0x3]", "[1, 2, 3] : List (Int *)"); } #[test] fn literal_float_list() { expect_success("[1.1, 2.2, 3.3]", "[1.1, 2.2, 3.3] : List (Float *)"); } #[test] fn literal_string_list() { expect_success(r#"["a", "b", "cd"]"#, r#"["a", "b", "cd"] : List Str"#); } #[test] fn nested_string_list() { expect_success( r#"[[["a", "b", "cd"], ["y", "z"]], [[]], []]"#, r#"[[["a", "b", "cd"], ["y", "z"]], [[]], []] : List (List (List Str))"#, ); } #[test] fn nested_num_list() { expect_success( r#"[[[4, 3, 2], [1, 0]], [[]], []]"#, r#"[[[4, 3, 2], [1, 0]], [[]], []] : List (List (List (Num *)))"#, ); } #[test] fn nested_int_list() { expect_success( r#"[[[4, 3, 2], [1, 0x0]], [[]], []]"#, r#"[[[4, 3, 2], [1, 0]], [[]], []] : List (List (List (Int *)))"#, ); } #[test] fn nested_float_list() { expect_success( r#"[[[4, 3, 2], [1, 0.0]], [[]], []]"#, r#"[[[4, 3, 2], [1, 0]], [[]], []] : List (List (List (Float *)))"#, ); } #[test] fn num_bitwise_and() { expect_success("Num.bitwiseAnd 20 20", "20 : Int *"); expect_success("Num.bitwiseAnd 25 10", "8 : Int *"); expect_success("Num.bitwiseAnd 200 0", "0 : Int *") } #[test] fn num_bitwise_xor() { expect_success("Num.bitwiseXor 20 20", "0 : Int *"); expect_success("Num.bitwiseXor 15 14", "1 : Int *"); expect_success("Num.bitwiseXor 7 15", "8 : Int *"); expect_success("Num.bitwiseXor 200 0", "200 : Int *") } #[test] fn num_add_wrap() { expect_success("Num.addWrap Num.maxI64 1", "-9223372036854775808 : I64"); } #[test] fn num_sub_wrap() { expect_success("Num.subWrap Num.minI64 1", "9223372036854775807 : I64"); } #[test] fn num_mul_wrap() { expect_success("Num.mulWrap Num.maxI64 2", "-2 : I64"); } #[test] fn num_mul_saturated() { expect_success("Num.mulSaturated Num.maxI64 2", "9223372036854775807 : I64"); } #[cfg(not(feature = "wasm"))] #[test] fn num_add_checked() { expect_success("Num.addChecked 1 1", "Ok 2 : Result (Num *) [Overflow]"); expect_success( "Num.addChecked Num.maxI64 1", "Err Overflow : Result I64 [Overflow]", ); } #[cfg(not(feature = "wasm"))] #[test] fn num_sub_checked() { expect_success("Num.subChecked 1 1", "Ok 0 : Result (Num *) [Overflow]"); expect_success( "Num.subChecked Num.minI64 1", "Err Overflow : Result I64 [Overflow]", ); } #[cfg(not(feature = "wasm"))] #[test] fn num_mul_checked() { expect_success("Num.mulChecked 20 2", "Ok 40 : Result (Num *) [Overflow]"); expect_success( "Num.mulChecked Num.maxI64 2", "Err Overflow : Result I64 [Overflow]", ); } #[cfg(not(feature = "wasm"))] #[test] fn list_concat() { expect_success( "List.concat [1.1, 2.2] [3.3, 4.4, 5.5]", "[1.1, 2.2, 3.3, 4.4, 5.5] : List (Float *)", ); } #[cfg(not(feature = "wasm"))] #[test] fn list_contains() { expect_success("List.contains [] 0", "Bool.false : Bool"); expect_success("List.contains [1, 2, 3] 2", "Bool.true : Bool"); expect_success("List.contains [1, 2, 3] 4", "Bool.false : Bool"); } #[cfg(not(feature = "wasm"))] #[test] fn list_sum() { expect_success("List.sum []", "0 : Num a"); expect_success("List.sum [1, 2, 3]", "6 : Num *"); expect_success("List.sum [1.1, 2.2, 3.3]", "6.6 : Float *"); } #[cfg(not(feature = "wasm"))] #[test] fn list_first() { expect_success( "List.first [12, 9, 6, 3]", "Ok 12 : Result (Num *) [ListWasEmpty]", ); expect_success( "List.first []", "Err ListWasEmpty : Result a [ListWasEmpty]", ); } #[cfg(not(feature = "wasm"))] #[test] fn list_last() { expect_success( "List.last [12, 9, 6, 3]", "Ok 3 : Result (Num *) [ListWasEmpty]", ); expect_success("List.last []", "Err ListWasEmpty : Result a [ListWasEmpty]"); } #[test] fn empty_record() { expect_success("{}", "{} : {}"); } #[test] fn basic_1_field_i64_record() { // Even though this gets unwrapped at runtime, the repl should still // report it as a record expect_success("{ foo: 42 }", "{ foo: 42 } : { foo : Num * }"); } #[test] fn basic_1_field_f64_record() { // Even though this gets unwrapped at runtime, the repl should still // report it as a record expect_success("{ foo: 4.2 }", "{ foo: 4.2 } : { foo : Float * }"); } #[test] fn nested_1_field_i64_record() { // Even though this gets unwrapped at runtime, the repl should still // report it as a record expect_success( "{ foo: { bar: { baz: 42 } } }", "{ foo: { bar: { baz: 42 } } } : { foo : { bar : { baz : Num * } } }", ); } #[test] fn nested_1_field_f64_record() { // Even though this gets unwrapped at runtime, the repl should still // report it as a record expect_success( "{ foo: { bar: { baz: 4.2 } } }", "{ foo: { bar: { baz: 4.2 } } } : { foo : { bar : { baz : Float * } } }", ); } #[test] fn basic_2_field_i64_record() { expect_success( "{ foo: 0x4, bar: 0x2 }", "{ bar: 2, foo: 4 } : { bar : Int *, foo : Int * }", ); } #[test] fn basic_2_field_f64_record() { expect_success( "{ foo: 4.1, bar: 2.3 }", "{ bar: 2.3, foo: 4.1 } : { bar : Float *, foo : Float * }", ); } #[test] fn basic_2_field_mixed_record() { expect_success( "{ foo: 4.1, bar: 2 }", "{ bar: 2, foo: 4.1 } : { bar : Num *, foo : Float * }", ); } #[test] fn basic_3_field_record() { expect_success( "{ foo: 4.1, bar: 2, baz: 0x5 }", "{ bar: 2, baz: 5, foo: 4.1 } : { bar : Num *, baz : Int *, foo : Float * }", ); } #[test] fn list_of_1_field_records() { // Even though these get unwrapped at runtime, the repl should still // report them as records expect_success("[{ foo: 42 }]", "[{ foo: 42 }] : List { foo : Num * }"); } #[test] fn list_of_2_field_records() { expect_success( "[{ foo: 4.1, bar: 2 }]", "[{ bar: 2, foo: 4.1 }] : List { bar : Num *, foo : Float * }", ); } #[test] fn three_element_record() { // if this tests turns out to fail on 32-bit targets, look at jit_to_ast_help expect_success( "{ a: 1, b: 2, c: 3 }", "{ a: 1, b: 2, c: 3 } : { a : Num *, b : Num *, c : Num * }", ); } #[test] fn four_element_record() { // if this tests turns out to fail on 32-bit targets, look at jit_to_ast_help expect_success( "{ a: 1, b: 2, c: 3, d: 4 }", "{ a: 1, b: 2, c: 3, d: 4 } : { a : Num *, b : Num *, c : Num *, d : Num * }", ); } #[cfg(not(feature = "wasm"))] #[test] fn multiline_string_non_wasm() { // If a string contains newlines, format it as a multiline string in the output. // We can't use expect_success to test this, because it only looks at the last // line of output, and in this case we care about every line of output! let out = repl_eval(r#""\n\nhi!\n\n""#); let expected = indoc!( r#"""" hi! """ : Str"# ); assert_multiline_str_eq!("", out.stderr.as_str()); // Don't consider the auto variable name ("# val1") at the end. // The state.rs tests do that! assert_multiline_str_eq!(expected, out.stdout.replace("# val1", "").trim()); assert!(out.status.success()); } #[cfg(feature = "wasm")] #[test] fn multiline_string_wasm() { // If a string contains newlines, format it as a multiline string in the output expect_success( r#""\n\nhi!\n\n""#, indoc!( r#"""" hi! """ : Str"# ), ); } #[test] fn list_of_3_field_records() { expect_success( "[{ foo: 4.1, bar: 2, baz: 0x3 }]", "[{ bar: 2, baz: 3, foo: 4.1 }] : List { bar : Num *, baz : Int *, foo : Float * }", ); } #[test] fn identity_lambda() { expect_success("\\x -> x", " : a -> a"); } #[cfg(not(feature = "wasm"))] #[test] fn sum_lambda() { expect_success("\\x, y -> x + y", " : Num a, Num a -> Num a"); } #[cfg(not(feature = "wasm"))] #[test] fn stdlib_function() { expect_success("Num.abs", " : Num a -> Num a"); } #[cfg(not(feature = "wasm"))] // TODO: mismatch is due to terminal control codes! #[test] fn too_few_args() { expect_failure( "Num.add 2", indoc!( r#" ── TOO FEW ARGS ──────────────────────────────────────────────────────────────── The add function expects 2 arguments, but it got only 1: 4│ Num.add 2 ^^^^^^^ Roc does not allow functions to be partially applied. Use a closure to make partial application explicit. "# ), ); } #[cfg(not(feature = "wasm"))] // TODO: mismatch is due to terminal control codes! #[test] fn type_problem() { expect_failure( "1 + \"\"", indoc!( r#" ── TYPE MISMATCH ─────────────────────────────────────────────────────────────── This 2nd argument to add has an unexpected type: 4│ 1 + "" ^^ The argument is a string of type: Str But add needs its 2nd argument to be: Num * "# ), ); } #[test] fn issue_2149() { expect_success(r#"Str.toI8 "127""#, "Ok 127 : Result I8 [InvalidNumStr]"); expect_success( r#"Str.toI8 "128""#, "Err InvalidNumStr : Result I8 [InvalidNumStr]", ); expect_success( r#"Str.toI16 "32767""#, "Ok 32767 : Result I16 [InvalidNumStr]", ); expect_success( r#"Str.toI16 "32768""#, "Err InvalidNumStr : Result I16 [InvalidNumStr]", ); } #[test] fn multiline_input() { expect_success( indoc!( r#" a : Str a = "123" a "# ), r#""123" : Str"#, ) } #[test] fn recursive_tag_union_flat_variant() { expect_success( indoc!( r#" Expr : [Sym Str, Add Expr Expr] s : Expr s = Sym "levitating" s "# ), r#"Sym "levitating" : Expr"#, ) } #[test] fn large_recursive_tag_union_flat_variant() { expect_success( // > 7 variants so that to force tag storage alongside the data indoc!( r#" Item : [A Str, B Str, C Str, D Str, E Str, F Str, G Str, H Str, I Str, J Str, K Item] s : Item s = H "woo" s "# ), r#"H "woo" : Item"#, ) } #[test] fn recursive_tag_union_recursive_variant() { expect_success( indoc!( r#" Expr : [Sym Str, Add Expr Expr] s : Expr s = Add (Add (Sym "one") (Sym "two")) (Sym "four") s "# ), r#"Add (Add (Sym "one") (Sym "two")) (Sym "four") : Expr"#, ) } #[test] fn large_recursive_tag_union_recursive_variant() { expect_success( // > 7 variants so that to force tag storage alongside the data indoc!( r#" Item : [A Str, B Str, C Str, D Str, E Str, F Str, G Str, H Str, I Str, J Str, K Item, L Item] s : Item s = K (L (E "woo")) s "# ), r#"K (L (E "woo")) : Item"#, ) } #[test] fn recursive_tag_union_into_flat_tag_union() { expect_success( indoc!( r#" Item : [One [A Str, B Str], Deep Item] i : Item i = Deep (One (A "woo")) i "# ), r#"Deep (One (A "woo")) : Item"#, ) } #[test] fn non_nullable_unwrapped_tag_union() { expect_success( indoc!( r#" RoseTree a : [Tree a (List (RoseTree a))] e1 : RoseTree Str e1 = Tree "e1" [] e2 : RoseTree Str e2 = Tree "e2" [] combo : RoseTree Str combo = Tree "combo" [e1, e2] combo "# ), r#"Tree "combo" [Tree "e1" [], Tree "e2" []] : RoseTree Str"#, ) } #[test] fn nullable_unwrapped_tag_union() { expect_success( indoc!( r#" LinkedList a : [Nil, Cons a (LinkedList a)] c1 : LinkedList Str c1 = Cons "Red" Nil c2 : LinkedList Str c2 = Cons "Yellow" c1 c3 : LinkedList Str c3 = Cons "Green" c2 c3 "# ), r#"Cons "Green" (Cons "Yellow" (Cons "Red" Nil)) : LinkedList Str"#, ) } #[test] fn nullable_wrapped_tag_union() { expect_success( indoc!( r#" Container a : [Empty, Whole a, Halved (Container a) (Container a)] meats : Container Str meats = Halved (Whole "Brisket") (Whole "Ribs") sides : Container Str sides = Halved (Whole "Coleslaw") Empty bbqPlate : Container Str bbqPlate = Halved meats sides bbqPlate "# ), r#"Halved (Halved (Whole "Brisket") (Whole "Ribs")) (Halved (Whole "Coleslaw") Empty) : Container Str"#, ) } #[test] fn large_nullable_wrapped_tag_union() { // > 7 non-empty variants so that to force tag storage alongside the data expect_success( indoc!( r#" Cont a : [Empty, S1 a, S2 a, S3 a, S4 a, S5 a, S6 a, S7 a, Tup (Cont a) (Cont a)] fst : Cont Str fst = Tup (S1 "S1") (S2 "S2") snd : Cont Str snd = Tup (S5 "S5") Empty tup : Cont Str tup = Tup fst snd tup "# ), r#"Tup (Tup (S1 "S1") (S2 "S2")) (Tup (S5 "S5") Empty) : Cont Str"#, ) } #[cfg(not(feature = "wasm"))] #[test] fn issue_2300() { expect_success( r#"\Email str -> str == """#, r#" : [Email Str] -> Bool"#, ) } #[cfg(not(feature = "wasm"))] #[test] fn function_in_list() { expect_success( r#"[\x -> x + 1, \s -> s * 2]"#, r#"[, ] : List (Num a -> Num a)"#, ) } #[cfg(not(feature = "wasm"))] #[test] fn function_in_record() { expect_success( r#"{ n: 1, adder: \x -> x + 1 }"#, r#"{ adder: , n: 1 } : { adder : Num a -> Num a, n : Num * }"#, ) } #[cfg(not(feature = "wasm"))] #[test] fn function_in_unwrapped_record() { expect_success( r#"{ adder: \x -> x + 1 }"#, r#"{ adder: } : { adder : Num a -> Num a }"#, ) } #[cfg(not(feature = "wasm"))] #[test] fn function_in_tag() { expect_success( r#"Adder (\x -> x + 1)"#, r#"Adder : [Adder (Num a -> Num a)]"#, ) } #[test] fn newtype_of_record_of_tag_of_record_of_tag() { expect_success( r#"A {b: C {d: 1}}"#, r#"A { b: C { d: 1 } } : [A { b : [C { d : Num * }] }]"#, ) } #[test] fn print_u8s() { expect_success( indoc!( r#" x : U8 x = 129 x "# ), "129 : U8", ) } #[cfg(not(feature = "wasm"))] // TODO: mismatch is due to terminal control codes! #[test] fn parse_problem() { expect_failure( "add m n = m + n", indoc!( r#" ── ARGUMENTS BEFORE EQUALS ───────────────────────────────────────────────────── I am partway through parsing a definition, but I got stuck here: 1│ app "app" provides [replOutput] to "./platform" 2│ 3│ replOutput = 4│ add m n = m + n ^^^ Looks like you are trying to define a function. In roc, functions are always written as a lambda, like increment = \n -> n + 1. "# ), ); } #[ignore] // re-enable (and fix) after https://github.com/roc-lang/roc/issues/4425 is done! #[cfg(not(feature = "wasm"))] #[test] fn issue_2343_complete_mono_with_shadowed_vars() { expect_failure( indoc!( r#" b = False f = \b -> when b is True -> 5 False -> 15 f b "# ), indoc!( r#" ── DUPLICATE NAME ────────────────────────────────────────────────────────────── The b name is first defined here: 4│ b = False ^ But then it's defined a second time here: 5│ f = \b -> ^ Since these variables have the same name, it's easy to use the wrong one on accident. Give one of them a new name. "# ), ); } #[test] fn record_with_type_behind_alias() { expect_success( indoc!( r#" T : { a: Str } v : T v = { a: "value" } v "# ), r#"{ a: "value" } : T"#, ); } #[test] fn tag_with_type_behind_alias() { expect_success( indoc!( r#" T : [A Str] v : T v = A "value" v"# ), r#"A "value" : T"#, ); } #[cfg(not(feature = "wasm"))] #[test] fn issue_2588_record_with_function_and_nonfunction() { expect_success( indoc!( r#" x = 1 f = \n -> n * 2 { y: f x, f }"# ), r#"{ f: , y: 2 } : { f : Num a -> Num a, y : Num * }"#, ) } #[test] fn opaque_apply() { expect_success( indoc!( r#" Age := U32 @Age 23"# ), "@Age 23 : Age", ) } #[test] fn opaque_apply_polymorphic() { expect_success( indoc!( r#" F t u := [Package t u] @F (Package "" { a: "" })"# ), r#"@F (Package "" { a: "" }) : F Str { a : Str }"#, ) } #[test] fn opaque_pattern_and_call() { expect_success( indoc!( r#" F t u := [Package t u] f = \@F (Package A {}) -> @F (Package {} A) f (@F (Package A {}))"# ), r#"@F (Package {} A) : F {} [A]"#, ) } #[test] fn dec_in_repl() { expect_success( indoc!( r#" x: Dec x=1.23 x"# ), "1.23 : Dec", ) } #[test] fn print_i8_issue_2710() { expect_success( indoc!( r#" a : I8 a = -1 a"# ), r#"-1 : I8"#, ) } #[cfg(not(feature = "wasm"))] #[test] fn box_box() { expect_success( indoc!( r#" Box.box "container store""# ), r#"Box.box "container store" : Box Str"#, ) } #[cfg(not(feature = "wasm"))] #[test] fn box_box_type_alias() { expect_success( indoc!( r#" HeapStr : Box Str helloHeap : HeapStr helloHeap = Box.box "bye stacks" helloHeap"# ), r#"Box.box "bye stacks" : HeapStr"#, ) } #[test] #[cfg(not(feature = "wasm"))] fn issue_2582_specialize_result_value() { expect_success( r#"\x, list -> if x > 0 then List.first list else Ok """#, r" : Num *, List Str -> Result Str [ListWasEmpty]", ) } #[test] #[cfg(not(feature = "wasm"))] fn issue_2818() { expect_success( indoc!( r#" f : {} -> List Str f = \_ -> x = [] x"# ), r" : {} -> List Str", ) } #[test] fn issue_2810_recursive_layout_inside_nonrecursive() { expect_success( indoc!( r#" Command : [Command Tool] Job : [Job Command] Tool : [SystemTool, FromJob Job] a : Job a = Job (Command (FromJob (Job (Command SystemTool)))) a"# ), "Job (Command (FromJob (Job (Command SystemTool)))) : Job", ) } #[test] fn render_nullable_unwrapped_passing_through_alias() { expect_success( indoc!( r#" Deep : [L DeepList] DeepList : [Nil, Cons Deep] v : DeepList v = (Cons (L (Cons (L (Cons (L Nil)))))) v"# ), "Cons (L (Cons (L (Cons (L Nil))))) : DeepList", ) } #[test] fn opaque_wrap_function() { expect_success( indoc!( r#" A a := a List.map [1u8, 2u8, 3u8] @A"# ), "[@A 1, @A 2, @A 3] : List (A U8)", ); } #[test] fn dict_get_single() { expect_success( indoc!( r#" Dict.single 0 {a: 1, c: 2} |> Dict.get 0"# ), r#"Ok { a: 1, c: 2 } : Result { a : Num *, c : Num * } [KeyNotFound]"#, ) } #[test] fn record_of_poly_function() { expect_success( indoc!( r#" { a: \_ -> "a" }"# ), r#"{ a: } : { a : * -> Str }"#, ); } #[test] fn record_of_poly_function_and_string() { expect_success( indoc!( r#" { a: \_ -> "a", b: "b" }"# ), r#"{ a: , b: "b" } : { a : * -> Str, b : Str }"#, ); } #[test] fn newtype_by_void_is_wrapped() { expect_success( indoc!( r#" Result.try (Err 42) (\x -> Err (x+1))"# ), r#"Err 42 : Result b (Num *)"#, ); expect_success( indoc!( r#" Result.try (Ok 42) (\x -> Ok (x+1))"# ), r#"Ok 43 : Result (Num *) err"#, ); }