diff --git a/test/snapshots/fuzz_crash/fuzz_crash_027.md b/test/snapshots/fuzz_crash/fuzz_crash_027.md index df0fc2482b..f3dcd44752 100644 --- a/test/snapshots/fuzz_crash/fuzz_crash_027.md +++ b/test/snapshots/fuzz_crash/fuzz_crash_027.md @@ -229,6 +229,7 @@ INCOMPATIBLE MATCH PATTERNS - fuzz_crash_027.md:64:2:64:2 UNUSED VALUE - fuzz_crash_027.md:1:1:1:1 TYPE MISMATCH - fuzz_crash_027.md:111:2:113:3 UNUSED VALUE - fuzz_crash_027.md:111:2:113:3 +TYPE MISMATCH - fuzz_crash_027.md:143:2:147:3 # PROBLEMS **LEADING ZERO** Numbers cannot have leading zeros. @@ -948,6 +949,23 @@ This expression produces a value, but it's not being used: It has the type: __d_ +**TYPE MISMATCH** +This expression is used in an unexpected way: +**fuzz_crash_027.md:143:2:147:3:** +```roc + Stdoline!( + "How about ${ # + Num.toStr(number) # on expr + } as a", + ) +``` + +It has the type: + _[Stdoline!(Error)][Err(_d), Ok({ })]_ + +But the type annotation says it should have the type: + _Try({ }, _d)_ + # TOKENS ~~~zig KwApp,OpenSquare,LowerIdent,CloseSquare,OpenCurly,LowerIdent,OpColon,KwPlatform,StringStart,StringPart,StringEnd,CloseCurly, diff --git a/test/snapshots/lambda_multi_arg_mismatch.md b/test/snapshots/lambda_multi_arg_mismatch.md index e69de29bb2..1886d9dd25 100644 --- a/test/snapshots/lambda_multi_arg_mismatch.md +++ b/test/snapshots/lambda_multi_arg_mismatch.md @@ -0,0 +1,253 @@ +# META +~~~ini +description=Lambda with multiple non-consecutive argument type mismatches +type=snippet +~~~ +# SOURCE +~~~roc +# Function with 8 arguments where several types must match (a appears in positions 1, 3, 5, 7) +multi_arg_fn : a, b, a, c, a, d, a, e -> (a, b, c, d, e) +multi_arg_fn = |x1, x2, x3, x4, x5, x6, x7, x8| + (x1, x2, x4, x6, x8) + +# Call with mismatched types - args 1, 3, 5, and 7 should all be the same type 'a' +# but we're passing U64, Str, F64, Bool which are all different +result = multi_arg_fn( + 42, # x1: U64 (type 'a') + "hello", # x2: Str (type 'b') - correct + "world", # x3: Str (should be 'a' = U64) - MISMATCH + 1.5, # x4: F64 (type 'c') - correct + 3.14, # x5: F64 (should be 'a' = U64) - MISMATCH + [1, 2], # x6: List I64 (type 'd') - correct + True, # x7: Bool (should be 'a' = U64) - MISMATCH + "done", # x8: Str (type 'e') - correct +) +~~~ +# EXPECTED +UNUSED VARIABLE - lambda_multi_arg_mismatch.md:3:25:3:27 +UNUSED VARIABLE - lambda_multi_arg_mismatch.md:3:33:3:35 +UNUSED VARIABLE - lambda_multi_arg_mismatch.md:3:41:3:43 +TYPE MISMATCH - lambda_multi_arg_mismatch.md:9:5:9:5 +# PROBLEMS +**UNUSED VARIABLE** +Variable `x3` is not used anywhere in your code. + +If you don't need this variable, prefix it with an underscore like `_x3` to suppress this warning. +The unused variable is declared here: +**lambda_multi_arg_mismatch.md:3:25:3:27:** +```roc +multi_arg_fn = |x1, x2, x3, x4, x5, x6, x7, x8| +``` + ^^ + + +**UNUSED VARIABLE** +Variable `x5` is not used anywhere in your code. + +If you don't need this variable, prefix it with an underscore like `_x5` to suppress this warning. +The unused variable is declared here: +**lambda_multi_arg_mismatch.md:3:33:3:35:** +```roc +multi_arg_fn = |x1, x2, x3, x4, x5, x6, x7, x8| +``` + ^^ + + +**UNUSED VARIABLE** +Variable `x7` is not used anywhere in your code. + +If you don't need this variable, prefix it with an underscore like `_x7` to suppress this warning. +The unused variable is declared here: +**lambda_multi_arg_mismatch.md:3:41:3:43:** +```roc +multi_arg_fn = |x1, x2, x3, x4, x5, x6, x7, x8| +``` + ^^ + + +**TYPE MISMATCH** +The first and third arguments to `multi_arg_fn` must have compatible types, but they are incompatible in this call: +**lambda_multi_arg_mismatch.md:9:5:** +```roc + 42, # x1: U64 (type 'a') + "hello", # x2: Str (type 'b') - correct + "world", # x3: Str (should be 'a' = U64) - MISMATCH +``` + ^^ + ^^^^^^^ + +The first argument has the type: + _Num(_size)_ + +But the third argument has the type: + _Str_ + +`multi_arg_fn` needs these arguments to have compatible types. + +# TOKENS +~~~zig +LowerIdent,OpColon,LowerIdent,Comma,LowerIdent,Comma,LowerIdent,Comma,LowerIdent,Comma,LowerIdent,Comma,LowerIdent,Comma,LowerIdent,Comma,LowerIdent,OpArrow,OpenRound,LowerIdent,Comma,LowerIdent,Comma,LowerIdent,Comma,LowerIdent,Comma,LowerIdent,CloseRound, +LowerIdent,OpAssign,OpBar,LowerIdent,Comma,LowerIdent,Comma,LowerIdent,Comma,LowerIdent,Comma,LowerIdent,Comma,LowerIdent,Comma,LowerIdent,Comma,LowerIdent,OpBar, +OpenRound,LowerIdent,Comma,LowerIdent,Comma,LowerIdent,Comma,LowerIdent,Comma,LowerIdent,CloseRound, +LowerIdent,OpAssign,LowerIdent,NoSpaceOpenRound, +Int,Comma, +StringStart,StringPart,StringEnd,Comma, +StringStart,StringPart,StringEnd,Comma, +Float,Comma, +Float,Comma, +OpenSquare,Int,Comma,Int,CloseSquare,Comma, +UpperIdent,Comma, +StringStart,StringPart,StringEnd,Comma, +CloseRound, +EndOfFile, +~~~ +# PARSE +~~~clojure +(file + (type-module) + (statements + (s-type-anno (name "multi_arg_fn") + (ty-fn + (ty-var (raw "a")) + (ty-var (raw "b")) + (ty-var (raw "a")) + (ty-var (raw "c")) + (ty-var (raw "a")) + (ty-var (raw "d")) + (ty-var (raw "a")) + (ty-var (raw "e")) + (ty-tuple + (ty-var (raw "a")) + (ty-var (raw "b")) + (ty-var (raw "c")) + (ty-var (raw "d")) + (ty-var (raw "e"))))) + (s-decl + (p-ident (raw "multi_arg_fn")) + (e-lambda + (args + (p-ident (raw "x1")) + (p-ident (raw "x2")) + (p-ident (raw "x3")) + (p-ident (raw "x4")) + (p-ident (raw "x5")) + (p-ident (raw "x6")) + (p-ident (raw "x7")) + (p-ident (raw "x8"))) + (e-tuple + (e-ident (raw "x1")) + (e-ident (raw "x2")) + (e-ident (raw "x4")) + (e-ident (raw "x6")) + (e-ident (raw "x8"))))) + (s-decl + (p-ident (raw "result")) + (e-apply + (e-ident (raw "multi_arg_fn")) + (e-int (raw "42")) + (e-string + (e-string-part (raw "hello"))) + (e-string + (e-string-part (raw "world"))) + (e-frac (raw "1.5")) + (e-frac (raw "3.14")) + (e-list + (e-int (raw "1")) + (e-int (raw "2"))) + (e-tag (raw "True")) + (e-string + (e-string-part (raw "done"))))))) +~~~ +# FORMATTED +~~~roc +# Function with 8 arguments where several types must match (a appears in positions 1, 3, 5, 7) +multi_arg_fn : a, b, a, c, a, d, a, e -> (a, b, c, d, e) +multi_arg_fn = |x1, x2, x3, x4, x5, x6, x7, x8| + (x1, x2, x4, x6, x8) + +# Call with mismatched types - args 1, 3, 5, and 7 should all be the same type 'a' +# but we're passing U64, Str, F64, Bool which are all different +result = multi_arg_fn( + 42, # x1: U64 (type 'a') + "hello", # x2: Str (type 'b') - correct + "world", # x3: Str (should be 'a' = U64) - MISMATCH + 1.5, # x4: F64 (type 'c') - correct + 3.14, # x5: F64 (should be 'a' = U64) - MISMATCH + [1, 2], # x6: List I64 (type 'd') - correct + True, # x7: Bool (should be 'a' = U64) - MISMATCH + "done", # x8: Str (type 'e') - correct +) +~~~ +# CANONICALIZE +~~~clojure +(can-ir + (d-let + (p-assign (ident "multi_arg_fn")) + (e-lambda + (args + (p-assign (ident "x1")) + (p-assign (ident "x2")) + (p-assign (ident "x3")) + (p-assign (ident "x4")) + (p-assign (ident "x5")) + (p-assign (ident "x6")) + (p-assign (ident "x7")) + (p-assign (ident "x8"))) + (e-tuple + (elems + (e-lookup-local + (p-assign (ident "x1"))) + (e-lookup-local + (p-assign (ident "x2"))) + (e-lookup-local + (p-assign (ident "x4"))) + (e-lookup-local + (p-assign (ident "x6"))) + (e-lookup-local + (p-assign (ident "x8")))))) + (annotation + (ty-fn (effectful false) + (ty-rigid-var (name "a")) + (ty-rigid-var (name "b")) + (ty-rigid-var-lookup (ty-rigid-var (name "a"))) + (ty-rigid-var (name "c")) + (ty-rigid-var-lookup (ty-rigid-var (name "a"))) + (ty-rigid-var (name "d")) + (ty-rigid-var-lookup (ty-rigid-var (name "a"))) + (ty-rigid-var (name "e")) + (ty-tuple + (ty-rigid-var-lookup (ty-rigid-var (name "a"))) + (ty-rigid-var-lookup (ty-rigid-var (name "b"))) + (ty-rigid-var-lookup (ty-rigid-var (name "c"))) + (ty-rigid-var-lookup (ty-rigid-var (name "d"))) + (ty-rigid-var-lookup (ty-rigid-var (name "e"))))))) + (d-let + (p-assign (ident "result")) + (e-call + (e-lookup-local + (p-assign (ident "multi_arg_fn"))) + (e-num (value "42")) + (e-string + (e-literal (string "hello"))) + (e-string + (e-literal (string "world"))) + (e-dec-small (numerator "15") (denominator-power-of-ten "1") (value "1.5")) + (e-dec-small (numerator "314") (denominator-power-of-ten "2") (value "3.14")) + (e-list + (elems + (e-num (value "1")) + (e-num (value "2")))) + (e-tag (name "True")) + (e-string + (e-literal (string "done")))))) +~~~ +# TYPES +~~~clojure +(inferred-types + (defs + (patt (type "a, b, a, c, a, d, a, e -> (a, b, c, d, e)")) + (patt (type "Error"))) + (expressions + (expr (type "a, b, a, c, a, d, a, e -> (a, b, c, d, e)")) + (expr (type "Error")))) +~~~ diff --git a/test/snapshots/nominal/nominal_associated_lookup_in_containers.md b/test/snapshots/nominal/nominal_associated_lookup_in_containers.md index 3be419b287..0e44caa4b4 100644 --- a/test/snapshots/nominal/nominal_associated_lookup_in_containers.md +++ b/test/snapshots/nominal/nominal_associated_lookup_in_containers.md @@ -171,7 +171,7 @@ nested = { bar: A, count: 1 } (inferred-types (defs (patt (type "List(Foo.Bar)")) - (patt (type "Error")) + (patt (type "Try(Foo.Bar, Foo.Error)")) (patt (type "{ bar: Foo.Bar, count: Num(Int(Unsigned64)) }"))) (type_decls (nominal (type "Foo") @@ -182,6 +182,6 @@ nested = { bar: A, count: 1 } (ty-header (name "Foo.Error")))) (expressions (expr (type "List(Foo.Bar)")) - (expr (type "Error")) + (expr (type "Try(Foo.Bar, Foo.Error)")) (expr (type "{ bar: Foo.Bar, count: Num(Int(Unsigned64)) }")))) ~~~ diff --git a/test/snapshots/plume_package/Color.md b/test/snapshots/plume_package/Color.md index fd4ace4b83..58554dda70 100644 --- a/test/snapshots/plume_package/Color.md +++ b/test/snapshots/plume_package/Color.md @@ -96,6 +96,7 @@ TYPE DOES NOT HAVE METHODS - Color.md:37:21:37:45 TYPE DOES NOT HAVE METHODS - Color.md:38:21:38:45 TYPE DOES NOT HAVE METHODS - Color.md:39:21:39:45 TYPE DOES NOT HAVE METHODS - Color.md:40:21:40:45 +TYPE MISMATCH - Color.md:32:5:45:6 TYPE DOES NOT HAVE METHODS - Color.md:62:8:62:28 # PROBLEMS **MODULE HEADER DEPRECATED** @@ -313,6 +314,32 @@ This type doesn't support methods: +**TYPE MISMATCH** +This expression is used in an unexpected way: +**Color.md:32:5:45:6:** +```roc + match bytes { + ['#', a, b, c, d, e, f] => { + is_valid = + a.is_char_in_hex_range() + and b.is_char_in_hex_range() + and c.is_char_in_hex_range() + and d.is_char_in_hex_range() + and e.is_char_in_hex_range() + and f.is_char_in_hex_range() + + if is_valid Ok(Color.Hex(str)) else Err(InvalidHex("Expected Hex to be in the range 0-9, a-f, A-F, got ${str}")) + } + _ => Err(InvalidHex("Expected Hex must start with # and be 7 characters long, got ${str}")) + } +``` + +It has the type: + _[InvalidHex(Str), Err([InvalidHex(Str)]_others)][Ok(Color)]_others2_ + +But the type annotation says it should have the type: + _Try(Color, [InvalidHex(Str)])_ + **TYPE DOES NOT HAVE METHODS** You're calling the method `is_named_color` on a type that doesn't support methods: **Color.md:62:8:62:28:** @@ -1278,7 +1305,7 @@ is_named_color = |str| { (patt (type "Num(Int(Unsigned8)), Num(Int(Unsigned8)), Num(Int(Unsigned8)), Num(Int(Unsigned8)) -> Color")) (patt (type "Str -> Error")) (patt (type "Color -> Error")) - (patt (type "Str -> Error")) + (patt (type "Str -> Try(Color, [UnknownColor(Str)])")) (patt (type "_arg -> Error"))) (type_decls (nominal (type "Color") @@ -1288,6 +1315,6 @@ is_named_color = |str| { (expr (type "Num(Int(Unsigned8)), Num(Int(Unsigned8)), Num(Int(Unsigned8)), Num(Int(Unsigned8)) -> Color")) (expr (type "Str -> Error")) (expr (type "Color -> Error")) - (expr (type "Str -> Error")) + (expr (type "Str -> Try(Color, [UnknownColor(Str)])")) (expr (type "_arg -> Error")))) ~~~ diff --git a/test/snapshots/type_alias_parameterized.md b/test/snapshots/type_alias_parameterized.md index 65e02bfc7b..4ae6f136d0 100644 --- a/test/snapshots/type_alias_parameterized.md +++ b/test/snapshots/type_alias_parameterized.md @@ -1 +1,162 @@ -ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª \ No newline at end of file +# META +~~~ini +description=Parameterized type alias with type variables +type=file +~~~ +# SOURCE +~~~roc +app [main!] { pf: platform "../basic-cli/main.roc" } + +Pair(a, b) : (a, b) + +swapPair : Pair(a, b) -> Pair(b, a) +swapPair = |(x, y)| (y, x) + +main! = |_| swapPair(1, 2) +~~~ +# EXPECTED +TYPE MISMATCH - type_alias_parameterized.md:8:13:8:27 +# PROBLEMS +**TYPE MISMATCH** +This expression is used in an unexpected way: +**type_alias_parameterized.md:8:13:8:27:** +```roc +main! = |_| swapPair(1, 2) +``` + ^^^^^^^^^^^^^^ + +It has the type: + _Num(_size), Num(_size2) -> _ret_ + +But I expected it to be: + _Pair(a, b) -> Pair(b, a)_ + +# TOKENS +~~~zig +KwApp,OpenSquare,LowerIdent,CloseSquare,OpenCurly,LowerIdent,OpColon,KwPlatform,StringStart,StringPart,StringEnd,CloseCurly, +UpperIdent,NoSpaceOpenRound,LowerIdent,Comma,LowerIdent,CloseRound,OpColon,OpenRound,LowerIdent,Comma,LowerIdent,CloseRound, +LowerIdent,OpColon,UpperIdent,NoSpaceOpenRound,LowerIdent,Comma,LowerIdent,CloseRound,OpArrow,UpperIdent,NoSpaceOpenRound,LowerIdent,Comma,LowerIdent,CloseRound, +LowerIdent,OpAssign,OpBar,NoSpaceOpenRound,LowerIdent,Comma,LowerIdent,CloseRound,OpBar,OpenRound,LowerIdent,Comma,LowerIdent,CloseRound, +LowerIdent,OpAssign,OpBar,Underscore,OpBar,LowerIdent,NoSpaceOpenRound,Int,Comma,Int,CloseRound, +EndOfFile, +~~~ +# PARSE +~~~clojure +(file + (app + (provides + (exposed-lower-ident + (text "main!"))) + (record-field (name "pf") + (e-string + (e-string-part (raw "../basic-cli/main.roc")))) + (packages + (record-field (name "pf") + (e-string + (e-string-part (raw "../basic-cli/main.roc")))))) + (statements + (s-type-decl + (header (name "Pair") + (args + (ty-var (raw "a")) + (ty-var (raw "b")))) + (ty-tuple + (ty-var (raw "a")) + (ty-var (raw "b")))) + (s-type-anno (name "swapPair") + (ty-fn + (ty-apply + (ty (name "Pair")) + (ty-var (raw "a")) + (ty-var (raw "b"))) + (ty-apply + (ty (name "Pair")) + (ty-var (raw "b")) + (ty-var (raw "a"))))) + (s-decl + (p-ident (raw "swapPair")) + (e-lambda + (args + (p-tuple + (p-ident (raw "x")) + (p-ident (raw "y")))) + (e-tuple + (e-ident (raw "y")) + (e-ident (raw "x"))))) + (s-decl + (p-ident (raw "main!")) + (e-lambda + (args + (p-underscore)) + (e-apply + (e-ident (raw "swapPair")) + (e-int (raw "1")) + (e-int (raw "2"))))))) +~~~ +# FORMATTED +~~~roc +NO CHANGE +~~~ +# CANONICALIZE +~~~clojure +(can-ir + (d-let + (p-assign (ident "swapPair")) + (e-lambda + (args + (p-tuple + (patterns + (p-assign (ident "x")) + (p-assign (ident "y"))))) + (e-tuple + (elems + (e-lookup-local + (p-assign (ident "y"))) + (e-lookup-local + (p-assign (ident "x")))))) + (annotation + (ty-fn (effectful false) + (ty-apply (name "Pair") (local) + (ty-rigid-var (name "a")) + (ty-rigid-var (name "b"))) + (ty-apply (name "Pair") (local) + (ty-rigid-var-lookup (ty-rigid-var (name "b"))) + (ty-rigid-var-lookup (ty-rigid-var (name "a"))))))) + (d-let + (p-assign (ident "main!")) + (e-closure + (captures + (capture (ident "swapPair"))) + (e-lambda + (args + (p-underscore)) + (e-call + (e-lookup-local + (p-assign (ident "swapPair"))) + (e-num (value "1")) + (e-num (value "2")))))) + (s-alias-decl + (ty-header (name "Pair") + (ty-args + (ty-rigid-var (name "a")) + (ty-rigid-var (name "b")))) + (ty-tuple + (ty-rigid-var-lookup (ty-rigid-var (name "a"))) + (ty-rigid-var-lookup (ty-rigid-var (name "b")))))) +~~~ +# TYPES +~~~clojure +(inferred-types + (defs + (patt (type "Pair(a, b) -> Pair(b, a)")) + (patt (type "_arg -> _ret"))) + (type_decls + (alias (type "Pair(a, b)") + (ty-header (name "Pair") + (ty-args + (ty-rigid-var (name "a")) + (ty-rigid-var (name "b")))))) + (expressions + (expr (type "Pair(a, b) -> Pair(b, a)")) + (expr (type "_arg -> _ret")))) +~~~ diff --git a/test/snapshots/type_annotation_basic.md b/test/snapshots/type_annotation_basic.md index e69de29bb2..64e215498d 100644 --- a/test/snapshots/type_annotation_basic.md +++ b/test/snapshots/type_annotation_basic.md @@ -0,0 +1,284 @@ +# META +~~~ini +description=Basic type annotations with type variables and application +type=file +~~~ +# SOURCE +~~~roc +app [main!] { pf: platform "../basic-cli/main.roc" } + +# Test generic identity function +identity : a -> a +identity = |x| x + +# Test function with multiple type parameters +combine : a, b -> (a, b) +combine = |first, second| (first, second) + +# Test type application with concrete types +addOne : U64 -> U64 +addOne = |n| n + 1 + +main! = |_| { + # Test identity with different types + num = identity(42) + text = identity("hello") + + # Test combine function + pair = combine(num, text) + + # Test concrete function + result = addOne(5) + + result +} +~~~ +# EXPECTED +UNUSED VARIABLE - type_annotation_basic.md:21:5:21:9 +# PROBLEMS +**UNUSED VARIABLE** +Variable `pair` is not used anywhere in your code. + +If you don't need this variable, prefix it with an underscore like `_pair` to suppress this warning. +The unused variable is declared here: +**type_annotation_basic.md:21:5:21:9:** +```roc + pair = combine(num, text) +``` + ^^^^ + + +# TOKENS +~~~zig +KwApp,OpenSquare,LowerIdent,CloseSquare,OpenCurly,LowerIdent,OpColon,KwPlatform,StringStart,StringPart,StringEnd,CloseCurly, +LowerIdent,OpColon,LowerIdent,OpArrow,LowerIdent, +LowerIdent,OpAssign,OpBar,LowerIdent,OpBar,LowerIdent, +LowerIdent,OpColon,LowerIdent,Comma,LowerIdent,OpArrow,OpenRound,LowerIdent,Comma,LowerIdent,CloseRound, +LowerIdent,OpAssign,OpBar,LowerIdent,Comma,LowerIdent,OpBar,OpenRound,LowerIdent,Comma,LowerIdent,CloseRound, +LowerIdent,OpColon,UpperIdent,OpArrow,UpperIdent, +LowerIdent,OpAssign,OpBar,LowerIdent,OpBar,LowerIdent,OpPlus,Int, +LowerIdent,OpAssign,OpBar,Underscore,OpBar,OpenCurly, +LowerIdent,OpAssign,LowerIdent,NoSpaceOpenRound,Int,CloseRound, +LowerIdent,OpAssign,LowerIdent,NoSpaceOpenRound,StringStart,StringPart,StringEnd,CloseRound, +LowerIdent,OpAssign,LowerIdent,NoSpaceOpenRound,LowerIdent,Comma,LowerIdent,CloseRound, +LowerIdent,OpAssign,LowerIdent,NoSpaceOpenRound,Int,CloseRound, +LowerIdent, +CloseCurly, +EndOfFile, +~~~ +# PARSE +~~~clojure +(file + (app + (provides + (exposed-lower-ident + (text "main!"))) + (record-field (name "pf") + (e-string + (e-string-part (raw "../basic-cli/main.roc")))) + (packages + (record-field (name "pf") + (e-string + (e-string-part (raw "../basic-cli/main.roc")))))) + (statements + (s-type-anno (name "identity") + (ty-fn + (ty-var (raw "a")) + (ty-var (raw "a")))) + (s-decl + (p-ident (raw "identity")) + (e-lambda + (args + (p-ident (raw "x"))) + (e-ident (raw "x")))) + (s-type-anno (name "combine") + (ty-fn + (ty-var (raw "a")) + (ty-var (raw "b")) + (ty-tuple + (ty-var (raw "a")) + (ty-var (raw "b"))))) + (s-decl + (p-ident (raw "combine")) + (e-lambda + (args + (p-ident (raw "first")) + (p-ident (raw "second"))) + (e-tuple + (e-ident (raw "first")) + (e-ident (raw "second"))))) + (s-type-anno (name "addOne") + (ty-fn + (ty (name "U64")) + (ty (name "U64")))) + (s-decl + (p-ident (raw "addOne")) + (e-lambda + (args + (p-ident (raw "n"))) + (e-binop (op "+") + (e-ident (raw "n")) + (e-int (raw "1"))))) + (s-decl + (p-ident (raw "main!")) + (e-lambda + (args + (p-underscore)) + (e-block + (statements + (s-decl + (p-ident (raw "num")) + (e-apply + (e-ident (raw "identity")) + (e-int (raw "42")))) + (s-decl + (p-ident (raw "text")) + (e-apply + (e-ident (raw "identity")) + (e-string + (e-string-part (raw "hello"))))) + (s-decl + (p-ident (raw "pair")) + (e-apply + (e-ident (raw "combine")) + (e-ident (raw "num")) + (e-ident (raw "text")))) + (s-decl + (p-ident (raw "result")) + (e-apply + (e-ident (raw "addOne")) + (e-int (raw "5")))) + (e-ident (raw "result")))))))) +~~~ +# FORMATTED +~~~roc +app [main!] { pf: platform "../basic-cli/main.roc" } + +# Test generic identity function +identity : a -> a +identity = |x| x + +# Test function with multiple type parameters +combine : a, b -> (a, b) +combine = |first, second| (first, second) + +# Test type application with concrete types +addOne : U64 -> U64 +addOne = |n| n + 1 + +main! = |_| { + # Test identity with different types + num = identity(42) + text = identity("hello") + + # Test combine function + pair = combine(num, text) + + # Test concrete function + result = addOne(5) + + result +} +~~~ +# CANONICALIZE +~~~clojure +(can-ir + (d-let + (p-assign (ident "identity")) + (e-lambda + (args + (p-assign (ident "x"))) + (e-lookup-local + (p-assign (ident "x")))) + (annotation + (ty-fn (effectful false) + (ty-rigid-var (name "a")) + (ty-rigid-var-lookup (ty-rigid-var (name "a")))))) + (d-let + (p-assign (ident "combine")) + (e-lambda + (args + (p-assign (ident "first")) + (p-assign (ident "second"))) + (e-tuple + (elems + (e-lookup-local + (p-assign (ident "first"))) + (e-lookup-local + (p-assign (ident "second")))))) + (annotation + (ty-fn (effectful false) + (ty-rigid-var (name "a")) + (ty-rigid-var (name "b")) + (ty-tuple + (ty-rigid-var-lookup (ty-rigid-var (name "a"))) + (ty-rigid-var-lookup (ty-rigid-var (name "b"))))))) + (d-let + (p-assign (ident "addOne")) + (e-lambda + (args + (p-assign (ident "n"))) + (e-binop (op "add") + (e-lookup-local + (p-assign (ident "n"))) + (e-num (value "1")))) + (annotation + (ty-fn (effectful false) + (ty-lookup (name "U64") (builtin)) + (ty-lookup (name "U64") (builtin))))) + (d-let + (p-assign (ident "main!")) + (e-closure + (captures + (capture (ident "identity")) + (capture (ident "combine")) + (capture (ident "addOne"))) + (e-lambda + (args + (p-underscore)) + (e-block + (s-let + (p-assign (ident "num")) + (e-call + (e-lookup-local + (p-assign (ident "identity"))) + (e-num (value "42")))) + (s-let + (p-assign (ident "text")) + (e-call + (e-lookup-local + (p-assign (ident "identity"))) + (e-string + (e-literal (string "hello"))))) + (s-let + (p-assign (ident "pair")) + (e-call + (e-lookup-local + (p-assign (ident "combine"))) + (e-lookup-local + (p-assign (ident "num"))) + (e-lookup-local + (p-assign (ident "text"))))) + (s-let + (p-assign (ident "result")) + (e-call + (e-lookup-local + (p-assign (ident "addOne"))) + (e-num (value "5")))) + (e-lookup-local + (p-assign (ident "result")))))))) +~~~ +# TYPES +~~~clojure +(inferred-types + (defs + (patt (type "a -> a")) + (patt (type "a, b -> (a, b)")) + (patt (type "Num(Int(Unsigned64)) -> Num(Int(Unsigned64))")) + (patt (type "_arg -> Num(Int(Unsigned64))"))) + (expressions + (expr (type "a -> a")) + (expr (type "a, b -> (a, b)")) + (expr (type "Num(Int(Unsigned64)) -> Num(Int(Unsigned64))")) + (expr (type "_arg -> Num(Int(Unsigned64))")))) +~~~ diff --git a/test/snapshots/type_app_complex_nested.md b/test/snapshots/type_app_complex_nested.md index d61494df91..fb5be29fd5 100644 --- a/test/snapshots/type_app_complex_nested.md +++ b/test/snapshots/type_app_complex_nested.md @@ -33,6 +33,8 @@ UNDECLARED TYPE - type_app_complex_nested.md:4:27:4:32 UNDECLARED TYPE - type_app_complex_nested.md:4:48:4:53 UNUSED VARIABLE - type_app_complex_nested.md:7:12:7:21 UNDECLARED TYPE - type_app_complex_nested.md:12:14:12:19 +TOO MANY ARGS - type_app_complex_nested.md:18:41:18:60 +TOO MANY ARGS - type_app_complex_nested.md:4:38:4:58 # PROBLEMS **UNDECLARED TYPE** The type _Maybe_ is not declared in this scope. @@ -101,6 +103,26 @@ deepNested : Maybe(Try(List(Dict(Str, a)), _b)) -> a ^^^^^ +**TOO MANY ARGS** +The type _Dict_ expects argument, but got instead. +**type_app_complex_nested.md:18:41:18:60:** +```roc +ComplexType(a, b) : Try(List(Maybe(a)), Dict(Str, Error(b))) +``` + ^^^^^^^^^^^^^^^^^^^ + + + +**TOO MANY ARGS** +The type _Dict_ expects argument, but got instead. +**type_app_complex_nested.md:4:38:4:58:** +```roc +processComplex : Try(List(Maybe(a)), Dict(Str, Error(_b))) -> List(a) +``` + ^^^^^^^^^^^^^^^^^^^^ + + + # TOKENS ~~~zig KwApp,OpenSquare,LowerIdent,CloseSquare,OpenCurly,LowerIdent,OpColon,KwPlatform,StringStart,StringPart,StringEnd,CloseCurly, @@ -329,7 +351,7 @@ main! = |_| processComplex(Ok([Some(42), None])) ~~~clojure (inferred-types (defs - (patt (type "Error -> List(_c)")) + (patt (type "Try(List(Error), Error) -> List(_c)")) (patt (type "Error -> _ret")) (patt (type "_arg -> List(_c)"))) (type_decls @@ -339,7 +361,7 @@ main! = |_| processComplex(Ok([Some(42), None])) (ty-rigid-var (name "a")) (ty-rigid-var (name "b")))))) (expressions - (expr (type "Error -> List(_c)")) + (expr (type "Try(List(Error), Error) -> List(_c)")) (expr (type "Error -> _ret")) (expr (type "_arg -> List(_c)")))) ~~~ diff --git a/test/snapshots/type_app_multiple_args.md b/test/snapshots/type_app_multiple_args.md index 74c04d6d55..276befa98d 100644 --- a/test/snapshots/type_app_multiple_args.md +++ b/test/snapshots/type_app_multiple_args.md @@ -14,6 +14,7 @@ main! = |_| processDict(Dict.empty().insert("one", 1)) ~~~ # EXPECTED DOES NOT EXIST - type_app_multiple_args.md:6:25:6:35 +TOO MANY ARGS - type_app_multiple_args.md:3:15:3:29 # PROBLEMS **DOES NOT EXIST** `Dict.empty` does not exist. @@ -25,6 +26,16 @@ main! = |_| processDict(Dict.empty().insert("one", 1)) ^^^^^^^^^^ +**TOO MANY ARGS** +The type _Dict_ expects argument, but got instead. +**type_app_multiple_args.md:3:15:3:29:** +```roc +processDict : Dict(Str, U64) -> List(Str) +``` + ^^^^^^^^^^^^^^ + + + # TOKENS ~~~zig KwApp,OpenSquare,LowerIdent,CloseSquare,OpenCurly,LowerIdent,OpColon,KwPlatform,StringStart,StringPart,StringEnd,CloseCurly, diff --git a/test/snapshots/type_app_nested.md b/test/snapshots/type_app_nested.md index 807688f56a..23444c899d 100644 --- a/test/snapshots/type_app_nested.md +++ b/test/snapshots/type_app_nested.md @@ -127,9 +127,9 @@ main! = |_| processNested([]) ~~~clojure (inferred-types (defs - (patt (type "List(Error) -> List(Str)")) + (patt (type "List(Try(Str, Error)) -> List(Str)")) (patt (type "_arg -> List(Str)"))) (expressions - (expr (type "List(Error) -> List(Str)")) + (expr (type "List(Try(Str, Error)) -> List(Str)")) (expr (type "_arg -> List(Str)")))) ~~~ diff --git a/test/snapshots/type_comprehensive_scope.md b/test/snapshots/type_comprehensive_scope.md index e69de29bb2..2eaa3b6b80 100644 --- a/test/snapshots/type_comprehensive_scope.md +++ b/test/snapshots/type_comprehensive_scope.md @@ -0,0 +1,410 @@ +# META +~~~ini +description=Comprehensive type scope validation - built-ins, user types, redeclaration, forward refs +type=snippet +~~~ +# SOURCE +~~~roc +# Built-in types should work +MyU64 : U64 +MyString : Str +MyBool : Bool + +# Simple user-defined type +Person : { name: Str, age: U64 } + +# Type with parameters +Try(ok, err) : [Ok(ok), Err(err)] + +# Forward reference - Tree references Node before Node is defined +Tree(a) : [Branch(Node(a)), Leaf(a)] + +# Node definition comes after Tree +Node(a) : { value: a, children: List(Tree(a)) } + +# Using a previously defined type +MyTry : Try(Str, U64) + +# Type redeclaration (should error) +Person : U64 + +# Using an undeclared type (should error) +BadType : SomeUndeclaredType + +# Using built-in types with parameters +MyList : List(Str) +MyDict : Dict(Str, U64) + +# Complex nested type using multiple declared types +Complex : { + person: Person, + result: Try(Bool, Str), + tree: Tree(U64) +} +~~~ +# EXPECTED +TYPE REDECLARED - type_comprehensive_scope.md:10:1:10:34 +UNDECLARED TYPE - type_comprehensive_scope.md:13:19:13:23 +TYPE REDECLARED - type_comprehensive_scope.md:22:1:22:13 +UNDECLARED TYPE - type_comprehensive_scope.md:25:11:25:29 +TOO MANY ARGS - type_comprehensive_scope.md:29:10:29:24 +# PROBLEMS +**TYPE REDECLARED** +The type _Try_ is being redeclared. + +The redeclaration is here: +**type_comprehensive_scope.md:10:1:10:34:** +```roc +Try(ok, err) : [Ok(ok), Err(err)] +``` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +But _Try_ was already declared here: +**type_comprehensive_scope.md:1:1:1:1:** +```roc +# Built-in types should work +``` +^ + + +**UNDECLARED TYPE** +The type _Node_ is not declared in this scope. + +This type is referenced here: +**type_comprehensive_scope.md:13:19:13:23:** +```roc +Tree(a) : [Branch(Node(a)), Leaf(a)] +``` + ^^^^ + + +**TYPE REDECLARED** +The type _Person_ is being redeclared. + +The redeclaration is here: +**type_comprehensive_scope.md:22:1:22:13:** +```roc +Person : U64 +``` +^^^^^^^^^^^^ + +But _Person_ was already declared here: +**type_comprehensive_scope.md:7:1:7:33:** +```roc +Person : { name: Str, age: U64 } +``` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +**UNDECLARED TYPE** +The type _SomeUndeclaredType_ is not declared in this scope. + +This type is referenced here: +**type_comprehensive_scope.md:25:11:25:29:** +```roc +BadType : SomeUndeclaredType +``` + ^^^^^^^^^^^^^^^^^^ + + +**TOO MANY ARGS** +The type _Dict_ expects argument, but got instead. +**type_comprehensive_scope.md:29:10:29:24:** +```roc +MyDict : Dict(Str, U64) +``` + ^^^^^^^^^^^^^^ + + + +# TOKENS +~~~zig +UpperIdent,OpColon,UpperIdent, +UpperIdent,OpColon,UpperIdent, +UpperIdent,OpColon,UpperIdent, +UpperIdent,OpColon,OpenCurly,LowerIdent,OpColon,UpperIdent,Comma,LowerIdent,OpColon,UpperIdent,CloseCurly, +UpperIdent,NoSpaceOpenRound,LowerIdent,Comma,LowerIdent,CloseRound,OpColon,OpenSquare,UpperIdent,NoSpaceOpenRound,LowerIdent,CloseRound,Comma,UpperIdent,NoSpaceOpenRound,LowerIdent,CloseRound,CloseSquare, +UpperIdent,NoSpaceOpenRound,LowerIdent,CloseRound,OpColon,OpenSquare,UpperIdent,NoSpaceOpenRound,UpperIdent,NoSpaceOpenRound,LowerIdent,CloseRound,CloseRound,Comma,UpperIdent,NoSpaceOpenRound,LowerIdent,CloseRound,CloseSquare, +UpperIdent,NoSpaceOpenRound,LowerIdent,CloseRound,OpColon,OpenCurly,LowerIdent,OpColon,LowerIdent,Comma,LowerIdent,OpColon,UpperIdent,NoSpaceOpenRound,UpperIdent,NoSpaceOpenRound,LowerIdent,CloseRound,CloseRound,CloseCurly, +UpperIdent,OpColon,UpperIdent,NoSpaceOpenRound,UpperIdent,Comma,UpperIdent,CloseRound, +UpperIdent,OpColon,UpperIdent, +UpperIdent,OpColon,UpperIdent, +UpperIdent,OpColon,UpperIdent,NoSpaceOpenRound,UpperIdent,CloseRound, +UpperIdent,OpColon,UpperIdent,NoSpaceOpenRound,UpperIdent,Comma,UpperIdent,CloseRound, +UpperIdent,OpColon,OpenCurly, +LowerIdent,OpColon,UpperIdent,Comma, +LowerIdent,OpColon,UpperIdent,NoSpaceOpenRound,UpperIdent,Comma,UpperIdent,CloseRound,Comma, +LowerIdent,OpColon,UpperIdent,NoSpaceOpenRound,UpperIdent,CloseRound, +CloseCurly, +EndOfFile, +~~~ +# PARSE +~~~clojure +(file + (type-module) + (statements + (s-type-decl + (header (name "MyU64") + (args)) + (ty (name "U64"))) + (s-type-decl + (header (name "MyString") + (args)) + (ty (name "Str"))) + (s-type-decl + (header (name "MyBool") + (args)) + (ty (name "Bool"))) + (s-type-decl + (header (name "Person") + (args)) + (ty-record + (anno-record-field (name "name") + (ty (name "Str"))) + (anno-record-field (name "age") + (ty (name "U64"))))) + (s-type-decl + (header (name "Try") + (args + (ty-var (raw "ok")) + (ty-var (raw "err")))) + (ty-tag-union + (tags + (ty-apply + (ty (name "Ok")) + (ty-var (raw "ok"))) + (ty-apply + (ty (name "Err")) + (ty-var (raw "err")))))) + (s-type-decl + (header (name "Tree") + (args + (ty-var (raw "a")))) + (ty-tag-union + (tags + (ty-apply + (ty (name "Branch")) + (ty-apply + (ty (name "Node")) + (ty-var (raw "a")))) + (ty-apply + (ty (name "Leaf")) + (ty-var (raw "a")))))) + (s-type-decl + (header (name "Node") + (args + (ty-var (raw "a")))) + (ty-record + (anno-record-field (name "value") + (ty-var (raw "a"))) + (anno-record-field (name "children") + (ty-apply + (ty (name "List")) + (ty-apply + (ty (name "Tree")) + (ty-var (raw "a"))))))) + (s-type-decl + (header (name "MyTry") + (args)) + (ty-apply + (ty (name "Try")) + (ty (name "Str")) + (ty (name "U64")))) + (s-type-decl + (header (name "Person") + (args)) + (ty (name "U64"))) + (s-type-decl + (header (name "BadType") + (args)) + (ty (name "SomeUndeclaredType"))) + (s-type-decl + (header (name "MyList") + (args)) + (ty-apply + (ty (name "List")) + (ty (name "Str")))) + (s-type-decl + (header (name "MyDict") + (args)) + (ty-apply + (ty (name "Dict")) + (ty (name "Str")) + (ty (name "U64")))) + (s-type-decl + (header (name "Complex") + (args)) + (ty-record + (anno-record-field (name "person") + (ty (name "Person"))) + (anno-record-field (name "result") + (ty-apply + (ty (name "Try")) + (ty (name "Bool")) + (ty (name "Str")))) + (anno-record-field (name "tree") + (ty-apply + (ty (name "Tree")) + (ty (name "U64")))))))) +~~~ +# FORMATTED +~~~roc +# Built-in types should work +MyU64 : U64 +MyString : Str +MyBool : Bool + +# Simple user-defined type +Person : { name : Str, age : U64 } + +# Type with parameters +Try(ok, err) : [Ok(ok), Err(err)] + +# Forward reference - Tree references Node before Node is defined +Tree(a) : [Branch(Node(a)), Leaf(a)] + +# Node definition comes after Tree +Node(a) : { value : a, children : List(Tree(a)) } + +# Using a previously defined type +MyTry : Try(Str, U64) + +# Type redeclaration (should error) +Person : U64 + +# Using an undeclared type (should error) +BadType : SomeUndeclaredType + +# Using built-in types with parameters +MyList : List(Str) +MyDict : Dict(Str, U64) + +# Complex nested type using multiple declared types +Complex : { + person : Person, + result : Try(Bool, Str), + tree : Tree(U64), +} +~~~ +# CANONICALIZE +~~~clojure +(can-ir + (s-alias-decl + (ty-header (name "MyU64")) + (ty-lookup (name "U64") (builtin))) + (s-alias-decl + (ty-header (name "MyString")) + (ty-lookup (name "Str") (builtin))) + (s-alias-decl + (ty-header (name "MyBool")) + (ty-lookup (name "Bool") (builtin))) + (s-alias-decl + (ty-header (name "Person")) + (ty-record + (field (field "name") + (ty-lookup (name "Str") (builtin))) + (field (field "age") + (ty-lookup (name "U64") (builtin))))) + (s-alias-decl + (ty-header (name "Try") + (ty-args + (ty-rigid-var (name "ok")) + (ty-rigid-var (name "err")))) + (ty-tag-union + (ty-tag-name (name "Ok") + (ty-rigid-var-lookup (ty-rigid-var (name "ok")))) + (ty-tag-name (name "Err") + (ty-rigid-var-lookup (ty-rigid-var (name "err")))))) + (s-alias-decl + (ty-header (name "Tree") + (ty-args + (ty-rigid-var (name "a")))) + (ty-tag-union + (ty-tag-name (name "Branch") + (ty-malformed)) + (ty-tag-name (name "Leaf") + (ty-rigid-var-lookup (ty-rigid-var (name "a")))))) + (s-alias-decl + (ty-header (name "Node") + (ty-args + (ty-rigid-var (name "a")))) + (ty-record + (field (field "value") + (ty-rigid-var-lookup (ty-rigid-var (name "a")))) + (field (field "children") + (ty-apply (name "List") (builtin) + (ty-apply (name "Tree") (local) + (ty-rigid-var-lookup (ty-rigid-var (name "a")))))))) + (s-alias-decl + (ty-header (name "MyTry")) + (ty-apply (name "Try") (builtin) + (ty-lookup (name "Str") (builtin)) + (ty-lookup (name "U64") (builtin)))) + (s-alias-decl + (ty-header (name "Person")) + (ty-lookup (name "U64") (builtin))) + (s-alias-decl + (ty-header (name "BadType")) + (ty-malformed)) + (s-alias-decl + (ty-header (name "MyList")) + (ty-apply (name "List") (builtin) + (ty-lookup (name "Str") (builtin)))) + (s-alias-decl + (ty-header (name "MyDict")) + (ty-apply (name "Dict") (builtin) + (ty-lookup (name "Str") (builtin)) + (ty-lookup (name "U64") (builtin)))) + (s-alias-decl + (ty-header (name "Complex")) + (ty-record + (field (field "person") + (ty-lookup (name "Person") (local))) + (field (field "result") + (ty-apply (name "Try") (builtin) + (ty-lookup (name "Bool") (builtin)) + (ty-lookup (name "Str") (builtin)))) + (field (field "tree") + (ty-apply (name "Tree") (local) + (ty-lookup (name "U64") (builtin))))))) +~~~ +# TYPES +~~~clojure +(inferred-types + (defs) + (type_decls + (alias (type "MyU64") + (ty-header (name "MyU64"))) + (alias (type "MyString") + (ty-header (name "MyString"))) + (alias (type "MyBool") + (ty-header (name "MyBool"))) + (alias (type "Person") + (ty-header (name "Person"))) + (alias (type "Try(ok, err)") + (ty-header (name "Try") + (ty-args + (ty-rigid-var (name "ok")) + (ty-rigid-var (name "err"))))) + (alias (type "Tree(a)") + (ty-header (name "Tree") + (ty-args + (ty-rigid-var (name "a"))))) + (alias (type "Node(a)") + (ty-header (name "Node") + (ty-args + (ty-rigid-var (name "a"))))) + (alias (type "MyTry") + (ty-header (name "MyTry"))) + (alias (type "Person") + (ty-header (name "Person"))) + (alias (type "BadType") + (ty-header (name "BadType"))) + (alias (type "MyList") + (ty-header (name "MyList"))) + (alias (type "MyDict") + (ty-header (name "MyDict"))) + (alias (type "Complex") + (ty-header (name "Complex")))) + (expressions)) +~~~ diff --git a/test/snapshots/type_tag_union_basic.md b/test/snapshots/type_tag_union_basic.md index 1f06babf91..186bfb7e88 100644 --- a/test/snapshots/type_tag_union_basic.md +++ b/test/snapshots/type_tag_union_basic.md @@ -254,12 +254,12 @@ main! = |_| {} (inferred-types (defs (patt (type "[None, Some(Str)] -> Str")) - (patt (type "[Err2(_err)][Ok2(_ok)] -> Error")) - (patt (type "[Err2(_err2)][Ok2(_ok2)] -> Error")) + (patt (type "[Err2(_err)][Ok2(_ok)] -> Bool")) + (patt (type "[Err2(_err2)][Ok2(_ok2)] -> Bool")) (patt (type "_arg -> {}"))) (expressions (expr (type "[None, Some(Str)] -> Str")) - (expr (type "[Err2(_err)][Ok2(_ok)] -> Error")) - (expr (type "[Err2(_err2)][Ok2(_ok2)] -> Error")) + (expr (type "[Err2(_err)][Ok2(_ok)] -> Bool")) + (expr (type "[Err2(_err2)][Ok2(_ok2)] -> Bool")) (expr (type "_arg -> {}")))) ~~~ diff --git a/test/snapshots/type_tag_union_complex.md b/test/snapshots/type_tag_union_complex.md index 367a447de8..8a286858d0 100644 --- a/test/snapshots/type_tag_union_complex.md +++ b/test/snapshots/type_tag_union_complex.md @@ -243,7 +243,7 @@ NO CHANGE ~~~clojure (inferred-types (defs - (patt (type "Error -> Str")) + (patt (type "Try(ok, err) -> Str")) (patt (type "Response -> Str")) (patt (type "_arg -> {}"))) (type_decls @@ -258,7 +258,7 @@ NO CHANGE (alias (type "ConnectionState") (ty-header (name "ConnectionState")))) (expressions - (expr (type "Error -> Str")) + (expr (type "Try(ok, err) -> Str")) (expr (type "Response -> Str")) (expr (type "_arg -> {}")))) ~~~ diff --git a/test/snapshots/type_var_namespace.md b/test/snapshots/type_var_namespace.md index 455baca2fc..fcf990853a 100644 --- a/test/snapshots/type_var_namespace.md +++ b/test/snapshots/type_var_namespace.md @@ -23,9 +23,19 @@ process = |list| { main! = |_| {} ~~~ # EXPECTED -NIL +MISSING METHOD - type_var_namespace.md:11:14:11:42 # PROBLEMS -NIL +**MISSING METHOD** +This **ok_or** method is being called on the type **Try(item, [ListWasEmpty])**, which has no method with that name: +**type_var_namespace.md:11:14:11:42:** +```roc + result = List.first(list).ok_or(item) +``` + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +**Hint: **For this to work, the type would need to have a method named **ok_or** associated with it in the type's declaration. + # TOKENS ~~~zig KwApp,OpenSquare,LowerIdent,CloseSquare,OpenCurly,LowerIdent,OpColon,KwPlatform,StringStart,StringPart,StringEnd,CloseCurly,