Repository: mun-lang/mun (language: rust)

Issue:
Replace return type annotation `:` with `->` 
We would benefit from staying close to Rust syntax, however, currently return type annotations are written like:

```
fn foo(): int {
}
```

we would like to replace this syntax with this:

```
fn foo() -> int {
}
```

to be closer to Rust.

**Good first issue process:**

- [x] [read our contributing guidelines](https://github.com/mun-lang/mun/blob/master/CONTRIBUTING.md)
- [x] claim this issue (assign yourself or comment below)
- [x] implement the feature and start a Pull Request with in the description: closes #105. 

If this is your first PR, welcome 🎉 😄


Discussion / hints:
What are the obvious benefits of bearing a resemblance to Rust?
The `:` syntax to declare a function return type is the same as many programming languages such as Kotlin, Scala, Swift, etc. Changing it to `->` is no real benefit, but type one more character.
There is no obvious benefit here. The main reason for doing this is that most of our users are coming from Rust at this point and its an inconvenience to have this small difference between the two languages. 
I think I've gotten this working. Should I update the tests accordingly?

~~EDIT: I just looked through some of the crates, and it looks like that's a lot of tests...~~
Never mind, looks like I'll have to to commit.
Yes all test should be updated accordingly. Thats indeed probably a lot of them. Once you run all tests once you can use:

cargo insta review

To validate the new outputs. See: https://github.com/mitsuhiko/insta
Okay, it's done! I'll open a pull request soon.

Fix patch:
diff --git a/README.md b/README.md
index 1bb104d5b..a0e50a242 100644
--- a/README.md
+++ b/README.md
@@ -59,7 +59,7 @@ fn main() {
 }
 
 // The order of function definitions doesn't matter
-fn add(a: int, b: int): int {
+fn add(a: int, b: int) -> int {
     a + b
 }
 ```
diff --git a/crates/mun_runtime/benches/resources/empty.mun b/crates/mun_runtime/benches/resources/empty.mun
index 7dbca061f..f27f1c571 100644
--- a/crates/mun_runtime/benches/resources/empty.mun
+++ b/crates/mun_runtime/benches/resources/empty.mun
@@ -1,3 +1,3 @@
-pub fn empty(n:int):int {
+pub fn empty(n:int)->int {
     n
 }
\ No newline at end of file
diff --git a/crates/mun_runtime/benches/resources/fibonacci.mun b/crates/mun_runtime/benches/resources/fibonacci.mun
index 63c9f3ba1..9962833c2 100644
--- a/crates/mun_runtime/benches/resources/fibonacci.mun
+++ b/crates/mun_runtime/benches/resources/fibonacci.mun
@@ -1,4 +1,4 @@
-pub fn fibonacci(n:int):int {
+pub fn fibonacci(n:int)->int {
     let a = 0;
     let b = 1;
     let i = 1;
@@ -13,6 +13,6 @@ pub fn fibonacci(n:int):int {
     }
 }
 
-pub fn main(n:int):int {
+pub fn main(n:int)->int {
     fibonacci(n)
 }
\ No newline at end of file
diff --git a/crates/mun_runtime/examples/resources/fibonacci.mun b/crates/mun_runtime/examples/resources/fibonacci.mun
index 4645748e7..9d9a84c46 100644
--- a/crates/mun_runtime/examples/resources/fibonacci.mun
+++ b/crates/mun_runtime/examples/resources/fibonacci.mun
@@ -1,8 +1,8 @@
-fn nth(): int {
+fn nth() -> int {
     3
 }
 
-fn fibonacci(n:int):int {
+fn fibonacci(n:int) -> int {
     if n <= 1 {
         n
     } else {
diff --git a/crates/mun_syntax/src/grammar.ron b/crates/mun_syntax/src/grammar.ron
index 88f3f43c2..83130414c 100644
--- a/crates/mun_syntax/src/grammar.ron
+++ b/crates/mun_syntax/src/grammar.ron
@@ -48,6 +48,7 @@ Grammar(
         ["%=", "PERCENTEQ"],
         ["..=", "DOTDOTEQ"],
         ["::", "COLONCOLON"],
+        ["->", "THIN_ARROW"],
     ],
     keywords: [
         // Original Lua keywords
diff --git a/crates/mun_syntax/src/parsing/grammar/declarations.rs b/crates/mun_syntax/src/parsing/grammar/declarations.rs
index afeae46bb..fc38ac140 100644
--- a/crates/mun_syntax/src/parsing/grammar/declarations.rs
+++ b/crates/mun_syntax/src/parsing/grammar/declarations.rs
@@ -92,9 +92,9 @@ pub(super) fn fn_def(p: &mut Parser) {
 }
 
 fn opt_fn_ret_type(p: &mut Parser) -> bool {
-    if p.at(T![:]) {
+    if p.at(T![->]) {
         let m = p.start();
-        p.bump(T![:]);
+        p.bump(T![->]);
         types::type_(p);
         m.complete(p, RET_TYPE);
         true
diff --git a/crates/mun_syntax/src/parsing/parser.rs b/crates/mun_syntax/src/parsing/parser.rs
index 25ce3fb4c..ad5d90882 100644
--- a/crates/mun_syntax/src/parsing/parser.rs
+++ b/crates/mun_syntax/src/parsing/parser.rs
@@ -56,7 +56,7 @@ impl<'t> Parser<'t> {
     pub(crate) fn nth_at(&self, n: usize, kind: SyntaxKind) -> bool {
         match kind {
             T![-=] => self.at_composite2(n, T![-], T![=]),
-            //T![->] => self.at_composite2(n, T![-], T![>]),
+            T![->] => self.at_composite2(n, T![-], T![>]),
             T![::] => self.at_composite2(n, T![:], T![:]),
             T![!=] => self.at_composite2(n, T![!], T![=]),
             T![..] => self.at_composite2(n, T![.], T![.]),
@@ -185,7 +185,7 @@ impl<'t> Parser<'t> {
         }
         let n_raw_tokens = match kind {
             T![-=]
-            //| T![->]
+            | T![->]
             | T![::]
             | T![!=]
             | T![..]
diff --git a/crates/mun_syntax/src/syntax_kind/generated.rs b/crates/mun_syntax/src/syntax_kind/generated.rs
index 7cf561f48..445ad0a94 100644
--- a/crates/mun_syntax/src/syntax_kind/generated.rs
+++ b/crates/mun_syntax/src/syntax_kind/generated.rs
@@ -53,6 +53,7 @@ pub enum SyntaxKind {
     PERCENTEQ,
     DOTDOTEQ,
     COLONCOLON,
+    THIN_ARROW,
     AND_KW,
     BREAK_KW,
     DO_KW,
@@ -172,6 +173,7 @@ macro_rules! T {
     (%=) => { $crate::SyntaxKind::PERCENTEQ };
     (..=) => { $crate::SyntaxKind::DOTDOTEQ };
     (::) => { $crate::SyntaxKind::COLONCOLON };
+    (->) => { $crate::SyntaxKind::THIN_ARROW };
     (and) => { $crate::SyntaxKind::AND_KW };
     (break) => { $crate::SyntaxKind::BREAK_KW };
     (do) => { $crate::SyntaxKind::DO_KW };
@@ -281,6 +283,7 @@ impl SyntaxKind {
                 | PERCENTEQ
                 | DOTDOTEQ
                 | COLONCOLON
+                | THIN_ARROW
                     => true,
                 _ => false
             }
@@ -334,6 +337,7 @@ impl SyntaxKind {
                 PERCENTEQ => &SyntaxInfo { name: "PERCENTEQ" },
                 DOTDOTEQ => &SyntaxInfo { name: "DOTDOTEQ" },
                 COLONCOLON => &SyntaxInfo { name: "COLONCOLON" },
+                THIN_ARROW => &SyntaxInfo { name: "THIN_ARROW" },
                 AND_KW => &SyntaxInfo { name: "AND_KW" },
                 BREAK_KW => &SyntaxInfo { name: "BREAK_KW" },
                 DO_KW => &SyntaxInfo { name: "DO_KW" },


Test patch:
diff --git a/crates/mun_codegen/src/test.rs b/crates/mun_codegen/src/test.rs
index 9693b9714..08a9e24c1 100644
--- a/crates/mun_codegen/src/test.rs
+++ b/crates/mun_codegen/src/test.rs
@@ -19,7 +19,7 @@ fn function() {
 fn return_type() {
     test_snapshot(
         r#"
-    fn main():int {
+    fn main()->int {
       0
     }
     "#,
@@ -30,7 +30,7 @@ fn return_type() {
 fn function_arguments() {
     test_snapshot(
         r#"
-    fn main(a:int):int {
+    fn main(a:int)->int {
       a
     }
     "#,
@@ -41,15 +41,15 @@ fn function_arguments() {
 fn binary_expressions() {
     test_snapshot(
         r#"
-    fn add(a:int, b:int):int {
+    fn add(a:int, b:int)->int {
       a+b
     }
 
-    fn subtract(a:int, b:int):int {
+    fn subtract(a:int, b:int)->int {
       a-b
     }
 
-    fn multiply(a:int, b:int):int {
+    fn multiply(a:int, b:int)->int {
       a*b
     }
     "#,
@@ -60,7 +60,7 @@ fn binary_expressions() {
 fn let_statement() {
     test_snapshot(
         r#"
-    fn main(a:int):int {
+    fn main(a:int)->int {
       let b = a+1
       b
     }
@@ -84,25 +84,25 @@ fn invalid_binary_ops() {
 fn update_operators() {
     test_snapshot(
         r#"
-    fn add(a:int, b:int):int {
+    fn add(a:int, b:int)->int {
       let result = a
       result += b
       result
     }
 
-    fn subtract(a:int, b:int):int {
+    fn subtract(a:int, b:int)->int {
       let result = a
       result -= b
       result
     }
 
-    fn multiply(a:int, b:int):int {
+    fn multiply(a:int, b:int)->int {
       let result = a
       result *= b
       result
     }
 
-    fn divide(a:int, b:int):int {
+    fn divide(a:int, b:int)->int {
       let result = a
       result /= b
       result
@@ -115,7 +115,7 @@ fn update_operators() {
 fn update_parameter() {
     test_snapshot(
         r#"
-    fn add_three(a:int):int {
+    fn add_three(a:int)->int {
       a += 3;
       a
     }
@@ -127,15 +127,15 @@ fn update_parameter() {
 fn function_calls() {
     test_snapshot(
         r#"
-    fn add_impl(a:int, b:int):int {
+    fn add_impl(a:int, b:int)->int {
         a+b
     }
 
-    fn add(a:int, b:int):int {
+    fn add(a:int, b:int)->int {
       add_impl(a,b)
     }
 
-    fn test():int {
+    fn test()->int {
       add(4,5)
       add_impl(4,5)
       add(4,5)
@@ -148,18 +148,18 @@ fn function_calls() {
 fn equality_operands() {
     test_snapshot(
         r#"
-    fn equals(a:int, b:int):bool                { a == b }
-    fn not_equals(a:int, b:int):bool            { a != b }
-    fn less(a:int, b:int):bool                  { a < b }
-    fn less_equal(a:int, b:int):bool            { a <= b }
-    fn greater(a:int, b:int):bool               { a > b }
-    fn greater_equal(a:int, b:int):bool         { a >= b }
-    fn equalsf(a:float, b:float):bool           { a == b }
-    fn not_equalsf(a:float, b:float):bool       { a != b }
-    fn lessf(a:float, b:float):bool             { a < b }
-    fn less_equalf(a:float, b:float):bool       { a <= b }
-    fn greaterf(a:float, b:float):bool          { a > b }
-    fn greater_equalf(a:float, b:float):bool    { a >= b }
+    fn equals(a:int, b:int)->bool                { a == b }
+    fn not_equals(a:int, b:int)->bool            { a != b }
+    fn less(a:int, b:int)->bool                  { a < b }
+    fn less_equal(a:int, b:int)->bool            { a <= b }
+    fn greater(a:int, b:int)->bool               { a > b }
+    fn greater_equal(a:int, b:int)->bool         { a >= b }
+    fn equalsf(a:float, b:float)->bool           { a == b }
+    fn not_equalsf(a:float, b:float)->bool       { a != b }
+    fn lessf(a:float, b:float)->bool             { a < b }
+    fn less_equalf(a:float, b:float)->bool       { a <= b }
+    fn greaterf(a:float, b:float)->bool          { a > b }
+    fn greater_equalf(a:float, b:float)->bool    { a >= b }
     "#,
     );
 }
@@ -168,7 +168,7 @@ fn equality_operands() {
 fn if_statement() {
     test_snapshot(
         r#"
-    fn foo(a:int):int {
+    fn foo(a:int)->int {
         let b = if a > 3 {
             let c = if a > 4 {
                 a+1
@@ -203,7 +203,7 @@ fn void_return() {
 fn fibonacci() {
     test_snapshot(
         r#"
-    fn fibonacci(n:int):int {
+    fn fibonacci(n:int)->int {
         if n <= 1 {
             n
         } else {
@@ -218,7 +218,7 @@ fn fibonacci() {
 fn fibonacci_loop() {
     test_snapshot(
         r#"
-    fn fibonacci(n:int):int {
+    fn fibonacci(n:int)->int {
         let a = 0;
         let b = 1;
         let i = 1;
@@ -240,7 +240,7 @@ fn fibonacci_loop() {
 fn shadowing() {
     test_snapshot(
         r#"
-    fn foo(a:int):int {
+    fn foo(a:int)->int {
         let a = a+1;
         {
             let a = a+2;
@@ -248,7 +248,7 @@ fn shadowing() {
         a+3
     }
 
-    fn bar(a:int):int {
+    fn bar(a:int)->int {
         let a = a+1;
         let a = {
             let a = a+2;
@@ -264,7 +264,7 @@ fn shadowing() {
 fn return_expr() {
     test_snapshot(
         r#"
-    fn main():int {
+    fn main()->int {
         return 5;
         let a = 3; // Nothing regarding this statement should be in the IR
     }
@@ -276,7 +276,7 @@ fn return_expr() {
 fn conditional_return_expr() {
     test_snapshot(
         r#"
-    fn main(a:int):int {
+    fn main(a:int)->int {
         if a > 4 {
             return a;
         }
@@ -290,7 +290,7 @@ fn conditional_return_expr() {
 fn never_conditional_return_expr() {
     test_snapshot(
         r#"
-    fn main(a:int):int {
+    fn main(a:int)->int {
         if a > 4 {
             return a;
         } else {
@@ -305,11 +305,11 @@ fn never_conditional_return_expr() {
 fn true_is_true() {
     test_snapshot(
         r#"
-    fn test_true():bool {
+    fn test_true()->bool {
         true
     }
 
-    fn test_false():bool {
+    fn test_false()->bool {
         false
     }"#,
     );
@@ -330,7 +330,7 @@ fn loop_expr() {
 fn loop_break_expr() {
     test_snapshot(
         r#"
-    fn foo(n:int):int {
+    fn foo(n:int)->int {
         loop {
             if n > 5 {
                 break n;
@@ -386,27 +386,27 @@ fn field_expr() {
     struct(value) Bar(float, Foo);
     struct(value) Foo { a: int };
 
-    fn bar_0(bar: Bar): float {
+    fn bar_0(bar: Bar) -> float {
         bar.0
     }
 
-    fn bar_1(bar: Bar): Foo {
+    fn bar_1(bar: Bar) -> Foo {
         bar.1
     }
 
-    fn bar_1_a(bar: Bar): int {
+    fn bar_1_a(bar: Bar) -> int {
         bar.1.a
     }
 
-    fn foo_a(foo: Foo): int {
+    fn foo_a(foo: Foo) -> int {
         foo.a
     }
 
-    fn bar_1_foo_a(bar: Bar): int {
+    fn bar_1_foo_a(bar: Bar) -> int {
         foo_a(bar_1(bar))
     }
 
-    fn main(): int {
+    fn main() -> int {
         let a: Foo = Foo { a: 5 };
         let b: Bar = Bar(1.23, a);
         let aa_lhs = a.a + 2;
@@ -423,7 +423,7 @@ fn field_crash() {
         r#"
     struct(gc) Foo { a: int };
 
-    fn main(c:int):int {
+    fn main(c:int)->int {
         let b = Foo { a: c + 5 }
         b.a
     }
@@ -450,19 +450,19 @@ fn gc_struct() {
 fn primitive_types() {
     test_snapshot(
         r#"
-   fn add(a: u8, b: u8): u8 { a+b }
-   fn less(a: u16, b: u16): bool { a<b }
-   fn greater(a: u32, b: u32): bool { a>b }
-   fn equal(a: u64, b: u64): bool { a==b }
-   fn greater_equal(a: usize, b: usize): bool { a>=b }
-   fn less_equal(a: uint, b: uint): bool { a<=b }
-
-   fn iadd(a: i8, b: i8): i8 { a+b }
-   fn iless(a: i16, b: i16): bool { a<b }
-   fn igreater(a: i32, b: i32): bool { a>b }
-   fn iequal(a: i64, b: i64): bool { a==b }
-   fn igreater_equal(a: isize, b: isize): bool { a>=b }
-   fn iless_equal(a: int, b: int): bool { a<=b }
+   fn add(a: u8, b: u8) -> u8 { a+b }
+   fn less(a: u16, b: u16) -> bool { a<b }
+   fn greater(a: u32, b: u32) -> bool { a>b }
+   fn equal(a: u64, b: u64) -> bool { a==b }
+   fn greater_equal(a: usize, b: usize) -> bool { a>=b }
+   fn less_equal(a: uint, b: uint) -> bool { a<=b }
+
+   fn iadd(a: i8, b: i8) -> i8 { a+b }
+   fn iless(a: i16, b: i16) -> bool { a<b }
+   fn igreater(a: i32, b: i32) -> bool { a>b }
+   fn iequal(a: i64, b: i64) -> bool { a==b }
+   fn igreater_equal(a: isize, b: isize) -> bool { a>=b }
+   fn iless_equal(a: int, b: int) -> bool { a<=b }
     "#,
     )
 }
@@ -471,7 +471,7 @@ fn primitive_types() {
 fn extern_fn() {
     test_snapshot(
         r#"
-    extern fn add(a:int, b:int): int;
+    extern fn add(a:int, b:int) -> int;
     fn main() {
         add(3,4);
     }
@@ -485,7 +485,7 @@ fn incremental_compilation() {
         r#"
         struct Foo(int);
 
-        pub fn foo(foo: Foo):int {
+        pub fn foo(foo: Foo) -> int {
             foo.0
         }
         "#,
diff --git a/crates/mun_hir/src/tests.rs b/crates/mun_hir/src/tests.rs
index 789b7520c..7fdf8b4e5 100644
--- a/crates/mun_hir/src/tests.rs
+++ b/crates/mun_hir/src/tests.rs
@@ -9,7 +9,7 @@ use std::sync::Arc;
 fn check_module_data_does_not_change() {
     let (mut db, file_id) = MockDatabase::with_single_file(
         r#"
-    fn foo():int {
+    fn foo()->int {
         1+1
     }
     "#,
@@ -29,7 +29,7 @@ fn check_module_data_does_not_change() {
         file_id,
         Arc::new(
             r#"
-    fn foo():int {
+    fn foo()->int {
         90
     }
     "#
diff --git a/crates/mun_hir/src/ty/snapshots/tests__extern_fn.snap b/crates/mun_hir/src/ty/snapshots/tests__extern_fn.snap
index ea144cf1f..7f7b8a18d 100644
--- a/crates/mun_hir/src/ty/snapshots/tests__extern_fn.snap
+++ b/crates/mun_hir/src/ty/snapshots/tests__extern_fn.snap
@@ -1,16 +1,16 @@
 ---
 source: crates/mun_hir/src/ty/tests.rs
-expression: "extern fn foo(a:int, b:int): int;\nfn main() {\n    foo(3,4);\n}\n\nextern fn with_body() {}    // extern functions cannot have bodies\n\nstruct S;\nextern fn with_non_primitive(s:S);  // extern functions can only have primitives as parameters\nextern fn with_non_primitive_return(): S;  // extern functions can only have primitives as parameters"
+expression: "extern fn foo(a:int, b:int) -> int;\nfn main() {\n    foo(3,4);\n}\n\nextern fn with_body() {}    // extern functions cannot have bodies\n\nstruct S;\nextern fn with_non_primitive(s:S);  // extern functions can only have primitives as parameters\nextern fn with_non_primitive_return() -> S;  // extern functions can only have primitives as parameters"
 ---
-[63; 87): extern functions cannot have bodies
-[172; 173): extern functions can only have primitives as parameter- and return types
-[275; 276): extern functions can only have primitives as parameter- and return types
+[65; 89): extern functions cannot have bodies
+[174; 175): extern functions can only have primitives as parameter- and return types
+[279; 280): extern functions can only have primitives as parameter- and return types
 [14; 15) 'a': int
 [21; 22) 'b': int
-[44; 61) '{     ...,4); }': nothing
-[50; 53) 'foo': function foo(int, int) -> int
-[50; 58) 'foo(3,4)': int
-[54; 55) '3': int
-[56; 57) '4': int
-[85; 87) '{}': nothing
-[170; 171) 's': S
+[46; 63) '{     ...,4); }': nothing
+[52; 55) 'foo': function foo(int, int) -> int
+[52; 60) 'foo(3,4)': int
+[56; 57) '3': int
+[58; 59) '4': int
+[87; 89) '{}': nothing
+[172; 173) 's': S
diff --git a/crates/mun_hir/src/ty/snapshots/tests__infer_basics.snap b/crates/mun_hir/src/ty/snapshots/tests__infer_basics.snap
index 89ef31cb3..3b8761faf 100644
--- a/crates/mun_hir/src/ty/snapshots/tests__infer_basics.snap
+++ b/crates/mun_hir/src/ty/snapshots/tests__infer_basics.snap
@@ -1,13 +1,13 @@
 ---
 source: crates/mun_hir/src/ty/tests.rs
-expression: "fn test(a:int, b:float, c:never, d:bool): bool {\n    a;\n    b;\n    c;\n    d\n}"
+expression: "fn test(a:int, b:float, c:never, d:bool) -> bool {\n    a;\n    b;\n    c;\n    d\n}"
 ---
 [8; 9) 'a': int
 [15; 16) 'b': float
 [24; 25) 'c': never
 [33; 34) 'd': bool
-[47; 77) '{     ...   d }': never
-[53; 54) 'a': int
-[60; 61) 'b': float
-[67; 68) 'c': never
-[74; 75) 'd': bool
+[49; 79) '{     ...   d }': never
+[55; 56) 'a': int
+[62; 63) 'b': float
+[69; 70) 'c': never
+[76; 77) 'd': bool
diff --git a/crates/mun_hir/src/ty/snapshots/tests__infer_break.snap b/crates/mun_hir/src/ty/snapshots/tests__infer_break.snap
index be793ed35..1862bad15 100644
--- a/crates/mun_hir/src/ty/snapshots/tests__infer_break.snap
+++ b/crates/mun_hir/src/ty/snapshots/tests__infer_break.snap
@@ -1,40 +1,40 @@
 ---
 source: crates/mun_hir/src/ty/tests.rs
-expression: "fn foo():int {\n    break; // error: not in a loop\n    loop { break 3; break 3.0; } // error: mismatched type\n    let a:int = loop { break 3.0; } // error: mismatched type\n    loop { break 3; }\n    let a:int = loop { break loop { break 3; } }\n    loop { break loop { break 3.0; } } // error: mismatched type\n}"
+expression: "fn foo()->int {\n    break; // error: not in a loop\n    loop { break 3; break 3.0; } // error: mismatched type\n    let a:int = loop { break 3.0; } // error: mismatched type\n    loop { break 3; }\n    let a:int = loop { break loop { break 3; } }\n    loop { break loop { break 3.0; } } // error: mismatched type\n}"
 ---
-[19; 24): `break` outside of a loop
-[70; 79): mismatched type
-[132; 141): mismatched type
-[266; 275): mismatched type
-[13; 308) '{     ...type }': never
-[19; 24) 'break': never
-[54; 82) 'loop {...3.0; }': int
-[59; 82) '{ brea...3.0; }': never
-[61; 68) 'break 3': never
-[67; 68) '3': int
-[70; 79) 'break 3.0': never
-[76; 79) '3.0': float
-[117; 118) 'a': int
-[125; 144) 'loop {...3.0; }': int
-[130; 144) '{ break 3.0; }': never
-[132; 141) 'break 3.0': never
-[138; 141) '3.0': float
-[175; 192) 'loop {...k 3; }': int
-[180; 192) '{ break 3; }': never
-[182; 189) 'break 3': never
-[188; 189) '3': int
-[201; 202) 'a': int
-[209; 241) 'loop {...3; } }': int
-[214; 241) '{ brea...3; } }': never
-[216; 239) 'break ...k 3; }': never
-[222; 239) 'loop {...k 3; }': int
-[227; 239) '{ break 3; }': never
-[229; 236) 'break 3': never
-[235; 236) '3': int
-[246; 280) 'loop {...0; } }': int
-[251; 280) '{ brea...0; } }': never
-[253; 278) 'break ...3.0; }': never
-[259; 278) 'loop {...3.0; }': int
-[264; 278) '{ break 3.0; }': never
-[266; 275) 'break 3.0': never
-[272; 275) '3.0': float
+[20; 25): `break` outside of a loop
+[71; 80): mismatched type
+[133; 142): mismatched type
+[267; 276): mismatched type
+[14; 309) '{     ...type }': never
+[20; 25) 'break': never
+[55; 83) 'loop {...3.0; }': int
+[60; 83) '{ brea...3.0; }': never
+[62; 69) 'break 3': never
+[68; 69) '3': int
+[71; 80) 'break 3.0': never
+[77; 80) '3.0': float
+[118; 119) 'a': int
+[126; 145) 'loop {...3.0; }': int
+[131; 145) '{ break 3.0; }': never
+[133; 142) 'break 3.0': never
+[139; 142) '3.0': float
+[176; 193) 'loop {...k 3; }': int
+[181; 193) '{ break 3; }': never
+[183; 190) 'break 3': never
+[189; 190) '3': int
+[202; 203) 'a': int
+[210; 242) 'loop {...3; } }': int
+[215; 242) '{ brea...3; } }': never
+[217; 240) 'break ...k 3; }': never
+[223; 240) 'loop {...k 3; }': int
+[228; 240) '{ break 3; }': never
+[230; 237) 'break 3': never
+[236; 237) '3': int
+[247; 281) 'loop {...0; } }': int
+[252; 281) '{ brea...0; } }': never
+[254; 279) 'break ...3.0; }': never
+[260; 279) 'loop {...3.0; }': int
+[265; 279) '{ break 3.0; }': never
+[267; 276) 'break 3.0': never
+[273; 276) '3.0': float
diff --git a/crates/mun_hir/src/ty/snapshots/tests__infer_conditional_return.snap b/crates/mun_hir/src/ty/snapshots/tests__infer_conditional_return.snap
index 4164ac212..b5ba28aca 100644
--- a/crates/mun_hir/src/ty/snapshots/tests__infer_conditional_return.snap
+++ b/crates/mun_hir/src/ty/snapshots/tests__infer_conditional_return.snap
@@ -1,26 +1,26 @@
 ---
 source: crates/mun_hir/src/ty/tests.rs
-expression: "fn foo(a:int):int {\n    if a > 4 {\n        return 4;\n    }\n    a\n}\n\nfn bar(a:int):int {\n    if a > 4 {\n        return 4;\n    } else {\n        return 1;\n    }\n}"
+expression: "fn foo(a:int)->int {\n    if a > 4 {\n        return 4;\n    }\n    a\n}\n\nfn bar(a:int)->int {\n    if a > 4 {\n        return 4;\n    } else {\n        return 1;\n    }\n}"
 ---
 [7; 8) 'a': int
-[18; 66) '{     ...   a }': int
-[24; 58) 'if a >...     }': nothing
-[27; 28) 'a': int
-[27; 32) 'a > 4': bool
-[31; 32) '4': int
-[33; 58) '{     ...     }': never
-[43; 51) 'return 4': never
-[50; 51) '4': int
-[63; 64) 'a': int
-[75; 76) 'a': int
-[86; 159) '{     ...   } }': int
-[92; 157) 'if a >...     }': int
-[95; 96) 'a': int
-[95; 100) 'a > 4': bool
-[99; 100) '4': int
-[101; 126) '{     ...     }': never
-[111; 119) 'return 4': never
-[118; 119) '4': int
-[132; 157) '{     ...     }': never
-[142; 150) 'return 1': never
-[149; 150) '1': int
+[19; 67) '{     ...   a }': int
+[25; 59) 'if a >...     }': nothing
+[28; 29) 'a': int
+[28; 33) 'a > 4': bool
+[32; 33) '4': int
+[34; 59) '{     ...     }': never
+[44; 52) 'return 4': never
+[51; 52) '4': int
+[64; 65) 'a': int
+[76; 77) 'a': int
+[88; 161) '{     ...   } }': int
+[94; 159) 'if a >...     }': int
+[97; 98) 'a': int
+[97; 102) 'a > 4': bool
+[101; 102) '4': int
+[103; 128) '{     ...     }': never
+[113; 121) 'return 4': never
+[120; 121) '4': int
+[134; 159) '{     ...     }': never
+[144; 152) 'return 1': never
+[151; 152) '1': int
diff --git a/crates/mun_hir/src/ty/snapshots/tests__infer_return.snap b/crates/mun_hir/src/ty/snapshots/tests__infer_return.snap
index c1407d453..b2855c0e8 100644
--- a/crates/mun_hir/src/ty/snapshots/tests__infer_return.snap
+++ b/crates/mun_hir/src/ty/snapshots/tests__infer_return.snap
@@ -1,9 +1,9 @@
 ---
 source: crates/mun_hir/src/ty/tests.rs
-expression: "fn test():int {\n    return; // error: mismatched type\n    return 5;\n}"
+expression: "fn test()->int {\n    return; // error: mismatched type\n    return 5;\n}"
 ---
-[20; 26): `return;` in a function whose return type is not `()`
-[14; 69) '{     ...n 5; }': never
-[20; 26) 'return': never
-[58; 66) 'return 5': never
-[65; 66) '5': int
+[21; 27): `return;` in a function whose return type is not `()`
+[15; 70) '{     ...n 5; }': never
+[21; 27) 'return': never
+[59; 67) 'return 5': never
+[66; 67) '5': int
diff --git a/crates/mun_hir/src/ty/snapshots/tests__primitives.snap b/crates/mun_hir/src/ty/snapshots/tests__primitives.snap
index 24d54fd2e..968ff6e1e 100644
--- a/crates/mun_hir/src/ty/snapshots/tests__primitives.snap
+++ b/crates/mun_hir/src/ty/snapshots/tests__primitives.snap
@@ -1,6 +1,6 @@
 ---
 source: crates/mun_hir/src/ty/tests.rs
-expression: "fn unsigned_primitives(a: u8, b: u16, c: u32, d: u64, e: usize, f: uint) : u8 { a }\nfn signed_primitives(a: i8, b: i16, c: i32, d: i64, e: isize, f: int) : i8 { a }\nfn float_primitives(a: f32, b: f64, c: float) : f32 { a }"
+expression: "fn unsigned_primitives(a: u8, b: u16, c: u32, d: u64, e: usize, f: uint) -> u8 { a }\nfn signed_primitives(a: i8, b: i16, c: i32, d: i64, e: isize, f: int) -> i8 { a }\nfn float_primitives(a: f32, b: f64, c: float) -> f32 { a }"
 ---
 [23; 24) 'a': u8
 [30; 31) 'b': u16
@@ -8,18 +8,18 @@ expression: "fn unsigned_primitives(a: u8, b: u16, c: u32, d: u64, e: usize, f:
 [46; 47) 'd': u64
 [54; 55) 'e': usize
 [64; 65) 'f': uint
-[78; 83) '{ a }': u8
-[80; 81) 'a': u8
-[105; 106) 'a': i8
-[112; 113) 'b': i16
-[120; 121) 'c': i32
-[128; 129) 'd': i64
-[136; 137) 'e': isize
-[146; 147) 'f': int
-[159; 164) '{ a }': i8
-[161; 162) 'a': i8
-[185; 186) 'a': f32
-[193; 194) 'b': f64
-[201; 202) 'c': float
-[217; 222) '{ a }': f32
-[219; 220) 'a': f32
+[79; 84) '{ a }': u8
+[81; 82) 'a': u8
+[106; 107) 'a': i8
+[113; 114) 'b': i16
+[121; 122) 'c': i32
+[129; 130) 'd': i64
+[137; 138) 'e': isize
+[147; 148) 'f': int
+[161; 166) '{ a }': i8
+[163; 164) 'a': i8
+[187; 188) 'a': f32
+[195; 196) 'b': f64
+[203; 204) 'c': float
+[220; 225) '{ a }': f32
+[222; 223) 'a': f32
diff --git a/crates/mun_hir/src/ty/tests.rs b/crates/mun_hir/src/ty/tests.rs
index c03aaf945..d4a61cbe4 100644
--- a/crates/mun_hir/src/ty/tests.rs
+++ b/crates/mun_hir/src/ty/tests.rs
@@ -22,14 +22,14 @@ fn infer_invalid_struct_type() {
 fn infer_conditional_return() {
     infer_snapshot(
         r#"
-    fn foo(a:int):int {
+    fn foo(a:int)->int {
         if a > 4 {
             return 4;
         }
         a
     }
 
-    fn bar(a:int):int {
+    fn bar(a:int)->int {
         if a > 4 {
             return 4;
         } else {
@@ -44,7 +44,7 @@ fn infer_conditional_return() {
 fn infer_return() {
     infer_snapshot(
         r#"
-    fn test():int {
+    fn test()->int {
         return; // error: mismatched type
         return 5;
     }
@@ -56,7 +56,7 @@ fn infer_return() {
 fn infer_basics() {
     infer_snapshot(
         r#"
-    fn test(a:int, b:float, c:never, d:bool): bool {
+    fn test(a:int, b:float, c:never, d:bool) -> bool {
         a;
         b;
         c;
@@ -142,7 +142,7 @@ fn infer_loop() {
 fn infer_break() {
     infer_snapshot(
         r#"
-    fn foo():int {
+    fn foo()->int {
         break; // error: not in a loop
         loop { break 3; break 3.0; } // error: mismatched type
         let a:int = loop { break 3.0; } // error: mismatched type
@@ -264,9 +264,9 @@ fn struct_field_index() {
 fn primitives() {
     infer_snapshot(
         r#"
-    fn unsigned_primitives(a: u8, b: u16, c: u32, d: u64, e: usize, f: uint) : u8 { a }
-    fn signed_primitives(a: i8, b: i16, c: i32, d: i64, e: isize, f: int) : i8 { a }
-    fn float_primitives(a: f32, b: f64, c: float) : f32 { a }
+    fn unsigned_primitives(a: u8, b: u16, c: u32, d: u64, e: usize, f: uint) -> u8 { a }
+    fn signed_primitives(a: i8, b: i16, c: i32, d: i64, e: isize, f: int) -> i8 { a }
+    fn float_primitives(a: f32, b: f64, c: float) -> f32 { a }
     "#,
     )
 }
@@ -275,7 +275,7 @@ fn primitives() {
 fn extern_fn() {
     infer_snapshot(
         r#"
-    extern fn foo(a:int, b:int): int;
+    extern fn foo(a:int, b:int) -> int;
     fn main() {
         foo(3,4);
     }
@@ -284,7 +284,7 @@ fn extern_fn() {
 
     struct S;
     extern fn with_non_primitive(s:S);  // extern functions can only have primitives as parameters
-    extern fn with_non_primitive_return(): S;  // extern functions can only have primitives as parameters
+    extern fn with_non_primitive_return() -> S;  // extern functions can only have primitives as parameters
     "#,
     )
 }
diff --git a/crates/mun_runtime/src/test.rs b/crates/mun_runtime/src/test.rs
index 5f3387d8b..3cace9b96 100644
--- a/crates/mun_runtime/src/test.rs
+++ b/crates/mun_runtime/src/test.rs
@@ -127,7 +127,7 @@ fn compile_and_run() {
 fn return_value() {
     let mut driver = TestDriver::new(
         r"
-        pub fn main():int { 3 }
+        pub fn main()->int { 3 }
     ",
     );
     assert_invoke_eq!(i64, 3, driver, "main");
@@ -137,7 +137,7 @@ fn return_value() {
 fn arguments() {
     let mut driver = TestDriver::new(
         r"
-        pub fn main(a:int, b:int):int { a+b }
+        pub fn main(a:int, b:int)->int { a+b }
     ",
     );
     let a: i64 = 52;
@@ -149,8 +149,8 @@ fn arguments() {
 fn dispatch_table() {
     let mut driver = TestDriver::new(
         r"
-        pub fn add(a:int, b:int):int { a+b }
-        pub fn main(a:int, b:int):int { add(a,b) }
+        pub fn add(a:int, b:int)->int { a+b }
+        pub fn main(a:int, b:int)->int { add(a,b) }
     ",
     );
 
@@ -167,18 +167,18 @@ fn dispatch_table() {
 fn booleans() {
     let mut driver = TestDriver::new(
         r#"
-        pub fn equal(a:int, b:int):bool                 { a==b }
-        pub fn equalf(a:float, b:float):bool            { a==b }
-        pub fn not_equal(a:int, b:int):bool             { a!=b }
-        pub fn not_equalf(a:float, b:float):bool        { a!=b }
-        pub fn less(a:int, b:int):bool                  { a<b }
-        pub fn lessf(a:float, b:float):bool             { a<b }
-        pub fn greater(a:int, b:int):bool               { a>b }
-        pub fn greaterf(a:float, b:float):bool          { a>b }
-        pub fn less_equal(a:int, b:int):bool            { a<=b }
-        pub fn less_equalf(a:float, b:float):bool       { a<=b }
-        pub fn greater_equal(a:int, b:int):bool         { a>=b }
-        pub fn greater_equalf(a:float, b:float):bool    { a>=b }
+        pub fn equal(a:int, b:int)->bool                 { a==b }
+        pub fn equalf(a:float, b:float)->bool            { a==b }
+        pub fn not_equal(a:int, b:int)->bool             { a!=b }
+        pub fn not_equalf(a:float, b:float)->bool        { a!=b }
+        pub fn less(a:int, b:int)->bool                  { a<b }
+        pub fn lessf(a:float, b:float)->bool             { a<b }
+        pub fn greater(a:int, b:int)->bool               { a>b }
+        pub fn greaterf(a:float, b:float)->bool          { a>b }
+        pub fn less_equal(a:int, b:int)->bool            { a<=b }
+        pub fn less_equalf(a:float, b:float)->bool       { a<=b }
+        pub fn greater_equal(a:int, b:int)->bool         { a>=b }
+        pub fn greater_equalf(a:float, b:float)->bool    { a>=b }
     "#,
     );
     assert_invoke_eq!(bool, false, driver, "equal", 52i64, 764i64);
@@ -211,7 +211,7 @@ fn booleans() {
 fn fibonacci() {
     let mut driver = TestDriver::new(
         r#"
-    pub fn fibonacci(n:int):int {
+    pub fn fibonacci(n:int)->int {
         if n <= 1 {
             n
         } else {
@@ -230,7 +230,7 @@ fn fibonacci() {
 fn fibonacci_loop() {
     let mut driver = TestDriver::new(
         r#"
-    pub fn fibonacci(n:int):int {
+    pub fn fibonacci(n:int)->int {
         let a = 0;
         let b = 1;
         let i = 1;
@@ -257,7 +257,7 @@ fn fibonacci_loop() {
 fn fibonacci_loop_break() {
     let mut driver = TestDriver::new(
         r#"
-    pub fn fibonacci(n:int):int {
+    pub fn fibonacci(n:int)->int {
         let a = 0;
         let b = 1;
         let i = 1;
@@ -284,7 +284,7 @@ fn fibonacci_loop_break() {
 fn fibonacci_while() {
     let mut driver = TestDriver::new(
         r#"
-    pub fn fibonacci(n:int):int {
+    pub fn fibonacci(n:int)->int {
         let a = 0;
         let b = 1;
         let i = 1;
@@ -309,11 +309,11 @@ fn fibonacci_while() {
 fn true_is_true() {
     let mut driver = TestDriver::new(
         r#"
-    pub fn test_true():bool {
+    pub fn test_true()->bool {
         true
     }
 
-    pub fn test_false():bool {
+    pub fn test_false()->bool {
         false
     }
     "#,
@@ -326,13 +326,13 @@ fn true_is_true() {
 fn hotreloadable() {
     let mut driver = TestDriver::new(
         r"
-    pub fn main():int { 5 }
+    pub fn main()->int { 5 }
     ",
     );
     assert_invoke_eq!(i64, 5, driver, "main");
     driver.update(
         r"
-    pub fn main():int { 10 }
+    pub fn main()->int { 10 }
     ",
     );
     assert_invoke_eq!(i64, 10, driver, "main");
@@ -349,7 +349,7 @@ fn compiler_valid_utf8() {
         a: int,
     }
 
-    pub fn foo(n:Foo):bool { false }
+    pub fn foo(n:Foo)->bool { false }
     "#,
     );
 
@@ -393,7 +393,7 @@ fn fields() {
     let mut driver = TestDriver::new(
         r#"
         struct(gc) Foo { a:int, b:int };
-        pub fn main(foo:int):bool {
+        pub fn main(foo:int)->bool {
             let a = Foo { a: foo, b: foo };
             a.a += a.b;
             let result = a;
@@ -411,7 +411,7 @@ fn field_crash() {
         r#"
     struct(gc) Foo { a: int };
 
-    pub fn main(c:int):int {
+    pub fn main(c:int)->int {
         let b = Foo { a: c + 5 }
         b.a
     }
@@ -429,19 +429,19 @@ fn marshal_struct() {
     struct(value) Baz(Foo);
     struct(gc) Qux(Bar);
 
-    pub fn foo_new(a: int, b: bool): Foo {
+    pub fn foo_new(a: int, b: bool) -> Foo {
         Foo { a, b, }
     }
-    pub fn bar_new(a: int, b: bool): Bar {
+    pub fn bar_new(a: int, b: bool) -> Bar {
         Bar(a, b)
     }
-    pub fn baz_new(foo: Foo): Baz {
+    pub fn baz_new(foo: Foo) -> Baz {
         Baz(foo)
     }
-    pub fn qux_new(bar: Bar): Qux {
+    pub fn qux_new(bar: Bar) -> Qux {
         Qux(bar)
     }
-    pub fn baz_new_transitive(foo_a: int, foo_b: bool) : Baz {
+    pub fn baz_new_transitive(foo_a: int, foo_b: bool) -> Baz {
         Baz(foo_new(foo_a, foo_b))
     }
     "#,
@@ -588,7 +588,7 @@ fn hotreload_struct_decl() {
         m: float,
     }
 
-    pub fn args(): Args {
+    pub fn args() -> Args {
         Args { n: 3, foo: Bar { m: 1.0 }, }
     }
     "#,
@@ -604,7 +604,7 @@ fn hotreload_struct_decl() {
         m: int,
     }
 
-    pub fn args(): Args {
+    pub fn args() -> Args {
         Args { n: 3, foo: Bar { m: 1 }, }
     }
     "#,
@@ -620,8 +620,8 @@ fn extern_fn() {
 
     let mut driver = TestDriver::new(
         r#"
-    extern fn add(a: int, b: int): int;
-    pub fn main(): int {
+    extern fn add(a: int, b: int) -> int;
+    pub fn main() -> int {
         add(3,4)
     }
     "#,
@@ -635,8 +635,8 @@ fn extern_fn() {
 fn extern_fn_missing() {
     let mut driver = TestDriver::new(
         r#"
-    extern fn add(a: int, b: int): int;
-    pub fn main(): int { add(3,4) }
+    extern fn add(a: int, b: int) -> int;
+    pub fn main() -> int { add(3,4) }
     "#,
     );
     assert_invoke_eq!(isize, 16, driver, "main");
@@ -651,8 +651,8 @@ fn extern_fn_invalid_sig() {
 
     let mut driver = TestDriver::new(
         r#"
-    extern fn add(a: int, b: int): int;
-    pub fn main(): int { add(3,4) }
+    extern fn add(a: int, b: int) -> int;
+    pub fn main() -> int { add(3,4) }
     "#,
     )
     .insert_fn("add", add_int as extern "C" fn(i8, isize) -> isize);
@@ -682,7 +682,7 @@ fn test_primitive_types() {
         m: float
     }
 
-    pub fn new_primitives(a:u8, b:u16, c:u32, d:u64, e:i8, f:i16, g:i32, h:i64, i:f32, j:f64, k: int, l: uint, m: float): Primitives {
+    pub fn new_primitives(a:u8, b:u16, c:u32, d:u64, e:i8, f:i16, g:i32, h:i64, i:f32, j:f64, k: int, l: uint, m: float) -> Primitives {
         Primitives { a:a, b:b, c:c, d:d, e:e, f:f, g:g, h:h, i:i, j:j, k:k, l:l, m:m }
     }
     "#,
@@ -748,7 +748,7 @@ fn gc_trace() {
         baz: int
     }
 
-    pub fn new_foo(): Foo {
+    pub fn new_foo() -> Foo {
         Foo {
             quz: 1.0,
             bar: Bar {
diff --git a/crates/mun_runtime_capi/src/tests.rs b/crates/mun_runtime_capi/src/tests.rs
index b43e2916a..edfd70769 100644
--- a/crates/mun_runtime_capi/src/tests.rs
+++ b/crates/mun_runtime_capi/src/tests.rs
@@ -118,7 +118,7 @@ fn test_runtime_get_function_info_invalid_runtime() {
 fn test_runtime_get_function_info_invalid_fn_name() {
     let driver = TestDriver::new(
         r#"
-        pub fn main(): int { 3 }
+        pub fn main() -> int { 3 }
     "#,
     );
 
@@ -144,7 +144,7 @@ fn test_runtime_get_function_info_invalid_fn_name() {
 fn test_runtime_get_function_info_invalid_fn_name_encoding() {
     let driver = TestDriver::new(
         r#"
-        pub fn main(): int { 3 }
+        pub fn main() -> int { 3 }
     "#,
     );
 
@@ -171,7 +171,7 @@ fn test_runtime_get_function_info_invalid_fn_name_encoding() {
 fn test_runtime_get_function_info_invalid_has_fn_info() {
     let driver = TestDriver::new(
         r#"
-        pub fn main(): int { 3 }
+        pub fn main() -> int { 3 }
     "#,
     );
 
@@ -198,7 +198,7 @@ fn test_runtime_get_function_info_invalid_has_fn_info() {
 fn test_runtime_get_function_info_invalid_fn_info() {
     let driver = TestDriver::new(
         r#"
-        pub fn main(): int { 3 }
+        pub fn main() -> int { 3 }
     "#,
     );
 
@@ -226,7 +226,7 @@ fn test_runtime_get_function_info_invalid_fn_info() {
 fn test_runtime_get_function_info() {
     let driver = TestDriver::new(
         r#"
-        pub fn main(): int { 3 }
+        pub fn main() -> int { 3 }
     "#,
     );
 
@@ -262,7 +262,7 @@ fn test_runtime_update_invalid_runtime() {
 fn test_runtime_update_invalid_updated() {
     let driver = TestDriver::new(
         r#"
-        pub fn main(): int { 3 }
+        pub fn main() -> int { 3 }
     "#,
     );
 
@@ -281,7 +281,7 @@ fn test_runtime_update_invalid_updated() {
 fn test_runtime_update() {
     let driver = TestDriver::new(
         r#"
-        pub fn main(): int { 3 }
+        pub fn main() -> int { 3 }
     "#,
     );
 
@@ -321,7 +321,7 @@ fn test_type_info_as_struct_invalid_struct_info() {
 fn test_type_info_as_struct_not_a_struct() {
     let driver = TestDriver::new(
         r#"
-        pub fn main(): int { 3 }
+        pub fn main() -> int { 3 }
     "#,
     );
 
@@ -356,7 +356,7 @@ fn test_type_info_as_struct() {
         r#"
         struct Foo;
 
-        pub fn main(): Foo { Foo }
+        pub fn main() -> Foo { Foo }
     "#,
     );
 
diff --git a/crates/mun_syntax/src/tests/lexer.rs b/crates/mun_syntax/src/tests/lexer.rs
index 13ea9fb16..35e3cf712 100644
--- a/crates/mun_syntax/src/tests/lexer.rs
+++ b/crates/mun_syntax/src/tests/lexer.rs
@@ -86,6 +86,7 @@ fn symbols() {
     ^ ^=
     % %=
     : ::
+    ->
     "#,
     )
 }
diff --git a/crates/mun_syntax/src/tests/parser.rs b/crates/mun_syntax/src/tests/parser.rs
index b6fa9cb0d..4ea9cc3cf 100644
--- a/crates/mun_syntax/src/tests/parser.rs
+++ b/crates/mun_syntax/src/tests/parser.rs
@@ -21,8 +21,8 @@ fn function() {
     fn a() {}
     fn b(value:number) {}
     pub fn d() {}
-    pub fn c():never {}
-    fn b(value:number):number {}"#,
+    pub fn c()->never {}
+    fn b(value:number)->number {}"#,
     );
 }
 
diff --git a/crates/mun_syntax/src/tests/snapshots/lexer__symbols.snap b/crates/mun_syntax/src/tests/snapshots/lexer__symbols.snap
index b4c0b6419..80ce91baf 100644
--- a/crates/mun_syntax/src/tests/snapshots/lexer__symbols.snap
+++ b/crates/mun_syntax/src/tests/snapshots/lexer__symbols.snap
@@ -1,6 +1,6 @@
 ---
 source: crates/mun_syntax/src/tests/lexer.rs
-expression: "# ( ) { } [ ] ; ,\n= ==\n!=\n< <=\n> >=\n. .. ... ..=\n+ +=\n- -=\n* *=\n/ /=\n^ ^=\n% %=\n: ::"
+expression: "# ( ) { } [ ] ; ,\n= ==\n!=\n< <=\n> >=\n. .. ... ..=\n+ +=\n- -=\n* *=\n/ /=\n^ ^=\n% %=\n: ::\n->"
 ---
 HASH 1 "#"
 WHITESPACE 1 " "
@@ -85,4 +85,7 @@ COLON 1 ":"
 WHITESPACE 1 " "
 COLON 1 ":"
 COLON 1 ":"
+WHITESPACE 1 "\n"
+MINUS 1 "-"
+GT 1 ">"
 
diff --git a/crates/mun_syntax/src/tests/snapshots/parser__function.snap b/crates/mun_syntax/src/tests/snapshots/parser__function.snap
index 83a6cfdb1..b7550f942 100644
--- a/crates/mun_syntax/src/tests/snapshots/parser__function.snap
+++ b/crates/mun_syntax/src/tests/snapshots/parser__function.snap
@@ -1,8 +1,8 @@
 ---
 source: crates/mun_syntax/src/tests/parser.rs
-expression: "// Source file comment\n\n// Comment that belongs to the function\nfn a() {}\nfn b(value:number) {}\npub fn d() {}\npub fn c():never {}\nfn b(value:number):number {}"
+expression: "// Source file comment\n\n// Comment that belongs to the function\nfn a() {}\nfn b(value:number) {}\npub fn d() {}\npub fn c()->never {}\nfn b(value:number)->number {}"
 ---
-SOURCE_FILE@[0; 158)
+SOURCE_FILE@[0; 160)
   COMMENT@[0; 22) "// Source file comment"
   WHITESPACE@[22; 24) "\n\n"
   FUNCTION_DEF@[24; 73)
@@ -58,7 +58,7 @@ SOURCE_FILE@[0; 158)
     BLOCK_EXPR@[107; 109)
       L_CURLY@[107; 108) "{"
       R_CURLY@[108; 109) "}"
-  FUNCTION_DEF@[109; 129)
+  FUNCTION_DEF@[109; 130)
     WHITESPACE@[109; 110) "\n"
     VISIBILITY@[110; 113)
       PUB_KW@[110; 113) "pub"
@@ -70,42 +70,42 @@ SOURCE_FILE@[0; 158)
     PARAM_LIST@[118; 120)
       L_PAREN@[118; 119) "("
       R_PAREN@[119; 120) ")"
-    RET_TYPE@[120; 126)
-      COLON@[120; 121) ":"
-      NEVER_TYPE@[121; 126)
-        NEVER_KW@[121; 126) "never"
-    WHITESPACE@[126; 127) " "
-    BLOCK_EXPR@[127; 129)
-      L_CURLY@[127; 128) "{"
-      R_CURLY@[128; 129) "}"
-  FUNCTION_DEF@[129; 158)
-    WHITESPACE@[129; 130) "\n"
-    FN_KW@[130; 132) "fn"
-    WHITESPACE@[132; 133) " "
-    NAME@[133; 134)
-      IDENT@[133; 134) "b"
-    PARAM_LIST@[134; 148)
-      L_PAREN@[134; 135) "("
-      PARAM@[135; 147)
-        BIND_PAT@[135; 140)
-          NAME@[135; 140)
-            IDENT@[135; 140) "value"
-        COLON@[140; 141) ":"
-        PATH_TYPE@[141; 147)
-          PATH@[141; 147)
-            PATH_SEGMENT@[141; 147)
-              NAME_REF@[141; 147)
-                IDENT@[141; 147) "number"
-      R_PAREN@[147; 148) ")"
-    RET_TYPE@[148; 155)
-      COLON@[148; 149) ":"
-      PATH_TYPE@[149; 155)
-        PATH@[149; 155)
-          PATH_SEGMENT@[149; 155)
-            NAME_REF@[149; 155)
-              IDENT@[149; 155) "number"
-    WHITESPACE@[155; 156) " "
-    BLOCK_EXPR@[156; 158)
-      L_CURLY@[156; 157) "{"
-      R_CURLY@[157; 158) "}"
+    RET_TYPE@[120; 127)
+      THIN_ARROW@[120; 122) "->"
+      NEVER_TYPE@[122; 127)
+        NEVER_KW@[122; 127) "never"
+    WHITESPACE@[127; 128) " "
+    BLOCK_EXPR@[128; 130)
+      L_CURLY@[128; 129) "{"
+      R_CURLY@[129; 130) "}"
+  FUNCTION_DEF@[130; 160)
+    WHITESPACE@[130; 131) "\n"
+    FN_KW@[131; 133) "fn"
+    WHITESPACE@[133; 134) " "
+    NAME@[134; 135)
+      IDENT@[134; 135) "b"
+    PARAM_LIST@[135; 149)
+      L_PAREN@[135; 136) "("
+      PARAM@[136; 148)
+        BIND_PAT@[136; 141)
+          NAME@[136; 141)
+            IDENT@[136; 141) "value"
+        COLON@[141; 142) ":"
+        PATH_TYPE@[142; 148)
+          PATH@[142; 148)
+            PATH_SEGMENT@[142; 148)
+              NAME_REF@[142; 148)
+                IDENT@[142; 148) "number"
+      R_PAREN@[148; 149) ")"
+    RET_TYPE@[149; 157)
+      THIN_ARROW@[149; 151) "->"
+      PATH_TYPE@[151; 157)
+        PATH@[151; 157)
+          PATH_SEGMENT@[151; 157)
+            NAME_REF@[151; 157)
+              IDENT@[151; 157) "number"
+    WHITESPACE@[157; 158) " "
+    BLOCK_EXPR@[158; 160)
+      L_CURLY@[158; 159) "{"
+      R_CURLY@[159; 160) "}"