about summary refs log tree commit diff
path: root/crates/syntax
diff options
context:
space:
mode:
authorAleksey Kladov <aleksey.kladov@gmail.com>2020-08-12 18:26:51 +0200
committerAleksey Kladov <aleksey.kladov@gmail.com>2020-08-12 18:30:53 +0200
commita1c187eef3ba08076aedb5154929f7eda8d1b424 (patch)
tree9d898eb9600b0c36a74e4f95238f679c683fa566 /crates/syntax
parent3d6889cba72a9d02199f7adaa2ecc69bc30af834 (diff)
downloadrust-a1c187eef3ba08076aedb5154929f7eda8d1b424.tar.gz
rust-a1c187eef3ba08076aedb5154929f7eda8d1b424.zip
Rename ra_syntax -> syntax
Diffstat (limited to 'crates/syntax')
-rw-r--r--crates/syntax/Cargo.toml35
-rw-r--r--crates/syntax/fuzz/.gitignore4
-rw-r--r--crates/syntax/fuzz/Cargo.toml27
-rw-r--r--crates/syntax/fuzz/fuzz_targets/parser.rs11
-rw-r--r--crates/syntax/fuzz/fuzz_targets/reparse.rs11
-rw-r--r--crates/syntax/src/algo.rs406
-rw-r--r--crates/syntax/src/ast.rs331
-rw-r--r--crates/syntax/src/ast/edit.rs642
-rw-r--r--crates/syntax/src/ast/expr_ext.rs418
-rw-r--r--crates/syntax/src/ast/generated.rs41
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs4067
-rw-r--r--crates/syntax/src/ast/generated/tokens.rs91
-rw-r--r--crates/syntax/src/ast/make.rs392
-rw-r--r--crates/syntax/src/ast/node_ext.rs485
-rw-r--r--crates/syntax/src/ast/token_ext.rs538
-rw-r--r--crates/syntax/src/ast/traits.rs141
-rw-r--r--crates/syntax/src/fuzz.rs73
-rw-r--r--crates/syntax/src/lib.rs388
-rw-r--r--crates/syntax/src/parsing.rs59
-rw-r--r--crates/syntax/src/parsing/lexer.rs244
-rw-r--r--crates/syntax/src/parsing/reparsing.rs455
-rw-r--r--crates/syntax/src/parsing/text_token_source.rs84
-rw-r--r--crates/syntax/src/parsing/text_tree_sink.rs183
-rw-r--r--crates/syntax/src/ptr.rs105
-rw-r--r--crates/syntax/src/syntax_error.rs44
-rw-r--r--crates/syntax/src/syntax_node.rs77
-rw-r--r--crates/syntax/src/tests.rs280
-rw-r--r--crates/syntax/src/validation.rs303
-rw-r--r--crates/syntax/src/validation/block.rs22
-rw-r--r--crates/syntax/test_data/accidentally_quadratic3980
-rw-r--r--crates/syntax/test_data/lexer/err/0001_unclosed_char_at_eof.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0001_unclosed_char_at_eof.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0002_unclosed_char_with_ferris.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0002_unclosed_char_with_ferris.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0003_unclosed_char_with_ascii_escape.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0003_unclosed_char_with_ascii_escape.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0004_unclosed_char_with_unicode_escape.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0004_unclosed_char_with_unicode_escape.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0005_unclosed_char_with_space.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0005_unclosed_char_with_space.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0006_unclosed_char_with_slash.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0006_unclosed_char_with_slash.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0007_unclosed_char_with_slash_n.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0007_unclosed_char_with_slash_n.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0008_unclosed_char_with_slash_single_quote.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0008_unclosed_char_with_slash_single_quote.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0009_unclosed_byte_at_eof.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0009_unclosed_byte_at_eof.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0010_unclosed_byte_with_ferris.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0010_unclosed_byte_with_ferris.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0011_unclosed_byte_with_ascii_escape.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0011_unclosed_byte_with_ascii_escape.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0012_unclosed_byte_with_unicode_escape.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0012_unclosed_byte_with_unicode_escape.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0013_unclosed_byte_with_space.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0013_unclosed_byte_with_space.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0014_unclosed_byte_with_slash.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0014_unclosed_byte_with_slash.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0015_unclosed_byte_with_slash_n.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0015_unclosed_byte_with_slash_n.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0016_unclosed_byte_with_slash_single_quote.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0016_unclosed_byte_with_slash_single_quote.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0017_unclosed_string_at_eof.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0017_unclosed_string_at_eof.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0018_unclosed_string_with_ferris.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0018_unclosed_string_with_ferris.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0019_unclosed_string_with_ascii_escape.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0019_unclosed_string_with_ascii_escape.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0020_unclosed_string_with_unicode_escape.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0020_unclosed_string_with_unicode_escape.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0021_unclosed_string_with_space.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0021_unclosed_string_with_space.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0022_unclosed_string_with_slash.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0022_unclosed_string_with_slash.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0023_unclosed_string_with_slash_n.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0023_unclosed_string_with_slash_n.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0024_unclosed_string_with_slash_double_quote.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0024_unclosed_string_with_slash_double_quote.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0025_unclosed_byte_string_at_eof.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0025_unclosed_byte_string_at_eof.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0026_unclosed_byte_string_with_ferris.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0026_unclosed_byte_string_with_ferris.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0027_unclosed_byte_string_with_ascii_escape.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0027_unclosed_byte_string_with_ascii_escape.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0028_unclosed_byte_string_with_unicode_escape.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0028_unclosed_byte_string_with_unicode_escape.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0029_unclosed_byte_string_with_space.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0029_unclosed_byte_string_with_space.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0030_unclosed_byte_string_with_slash.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0030_unclosed_byte_string_with_slash.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0031_unclosed_byte_string_with_slash_n.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0031_unclosed_byte_string_with_slash_n.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0032_unclosed_byte_string_with_slash_double_quote.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0032_unclosed_byte_string_with_slash_double_quote.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0033_unclosed_raw_string_at_eof.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0033_unclosed_raw_string_at_eof.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0034_unclosed_raw_string_with_ferris.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0034_unclosed_raw_string_with_ferris.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0035_unclosed_raw_string_with_ascii_escape.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0035_unclosed_raw_string_with_ascii_escape.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0036_unclosed_raw_string_with_unicode_escape.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0036_unclosed_raw_string_with_unicode_escape.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0037_unclosed_raw_string_with_space.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0037_unclosed_raw_string_with_space.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0038_unclosed_raw_string_with_slash.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0038_unclosed_raw_string_with_slash.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0039_unclosed_raw_string_with_slash_n.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0039_unclosed_raw_string_with_slash_n.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0040_unclosed_raw_byte_string_at_eof.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0040_unclosed_raw_byte_string_at_eof.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0041_unclosed_raw_byte_string_with_ferris.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0041_unclosed_raw_byte_string_with_ferris.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0042_unclosed_raw_byte_string_with_ascii_escape.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0042_unclosed_raw_byte_string_with_ascii_escape.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0043_unclosed_raw_byte_string_with_unicode_escape.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0043_unclosed_raw_byte_string_with_unicode_escape.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0044_unclosed_raw_byte_string_with_space.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0044_unclosed_raw_byte_string_with_space.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0045_unclosed_raw_byte_string_with_slash.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0045_unclosed_raw_byte_string_with_slash.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0046_unclosed_raw_byte_string_with_slash_n.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0046_unclosed_raw_byte_string_with_slash_n.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0047_unstarted_raw_string_at_eof.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0047_unstarted_raw_string_at_eof.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0048_unstarted_raw_byte_string_at_eof.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0048_unstarted_raw_byte_string_at_eof.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0049_unstarted_raw_string_with_ascii.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0049_unstarted_raw_string_with_ascii.txt10
-rw-r--r--crates/syntax/test_data/lexer/err/0050_unstarted_raw_byte_string_with_ascii.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0050_unstarted_raw_byte_string_with_ascii.txt10
-rw-r--r--crates/syntax/test_data/lexer/err/0051_unclosed_block_comment_at_eof.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0051_unclosed_block_comment_at_eof.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0052_unclosed_block_comment_with_content.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0052_unclosed_block_comment_with_content.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0053_unclosed_nested_block_comment_entirely.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0053_unclosed_nested_block_comment_entirely.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0054_unclosed_nested_block_comment_partially.rs1
-rw-r--r--crates/syntax/test_data/lexer/err/0054_unclosed_nested_block_comment_partially.txt2
-rw-r--r--crates/syntax/test_data/lexer/err/0055_empty_int.rs17
-rw-r--r--crates/syntax/test_data/lexer/err/0055_empty_int.txt39
-rw-r--r--crates/syntax/test_data/lexer/err/0056_empty_exponent.rs22
-rw-r--r--crates/syntax/test_data/lexer/err/0056_empty_exponent.txt62
-rw-r--r--crates/syntax/test_data/lexer/err/0057_lifetime_strarts_with_a_number.rs2
-rw-r--r--crates/syntax/test_data/lexer/err/0057_lifetime_strarts_with_a_number.txt6
-rw-r--r--crates/syntax/test_data/lexer/ok/0001_hello.rs1
-rw-r--r--crates/syntax/test_data/lexer/ok/0001_hello.txt3
-rw-r--r--crates/syntax/test_data/lexer/ok/0002_whitespace.rs4
-rw-r--r--crates/syntax/test_data/lexer/ok/0002_whitespace.txt12
-rw-r--r--crates/syntax/test_data/lexer/ok/0003_ident.rs1
-rw-r--r--crates/syntax/test_data/lexer/ok/0003_ident.txt14
-rw-r--r--crates/syntax/test_data/lexer/ok/0004_numbers.rs9
-rw-r--r--crates/syntax/test_data/lexer/ok/0004_numbers.txt57
-rw-r--r--crates/syntax/test_data/lexer/ok/0005_symbols.rs6
-rw-r--r--crates/syntax/test_data/lexer/ok/0005_symbols.txt77
-rw-r--r--crates/syntax/test_data/lexer/ok/0006_chars.rs1
-rw-r--r--crates/syntax/test_data/lexer/ok/0006_chars.txt16
-rw-r--r--crates/syntax/test_data/lexer/ok/0007_lifetimes.rs1
-rw-r--r--crates/syntax/test_data/lexer/ok/0007_lifetimes.txt8
-rw-r--r--crates/syntax/test_data/lexer/ok/0008_byte_strings.rs3
-rw-r--r--crates/syntax/test_data/lexer/ok/0008_byte_strings.txt22
-rw-r--r--crates/syntax/test_data/lexer/ok/0009_strings.rs2
-rw-r--r--crates/syntax/test_data/lexer/ok/0009_strings.txt8
-rw-r--r--crates/syntax/test_data/lexer/ok/0010_single_line_comments.rs12
-rw-r--r--crates/syntax/test_data/lexer/ok/0010_single_line_comments.txt22
-rw-r--r--crates/syntax/test_data/lexer/ok/0011_keywords.rs3
-rw-r--r--crates/syntax/test_data/lexer/ok/0011_keywords.txt64
-rw-r--r--crates/syntax/test_data/lexer/ok/0012_block_comment.rs3
-rw-r--r--crates/syntax/test_data/lexer/ok/0012_block_comment.txt6
-rw-r--r--crates/syntax/test_data/lexer/ok/0013_raw_strings.rs1
-rw-r--r--crates/syntax/test_data/lexer/ok/0013_raw_strings.txt2
-rw-r--r--crates/syntax/test_data/lexer/ok/0014_raw_ident.rs1
-rw-r--r--crates/syntax/test_data/lexer/ok/0014_raw_ident.txt2
-rw-r--r--crates/syntax/test_data/parser/err/0000_struct_field_missing_comma.rast34
-rw-r--r--crates/syntax/test_data/parser/err/0000_struct_field_missing_comma.rs4
-rw-r--r--crates/syntax/test_data/parser/err/0001_item_recovery_in_file.rast18
-rw-r--r--crates/syntax/test_data/parser/err/0001_item_recovery_in_file.rs3
-rw-r--r--crates/syntax/test_data/parser/err/0002_duplicate_shebang.rast39
-rw-r--r--crates/syntax/test_data/parser/err/0002_duplicate_shebang.rs2
-rw-r--r--crates/syntax/test_data/parser/err/0003_C++_semicolon.rast39
-rw-r--r--crates/syntax/test_data/parser/err/0003_C++_semicolon.rs4
-rw-r--r--crates/syntax/test_data/parser/err/0004_use_path_bad_segment.rast15
-rw-r--r--crates/syntax/test_data/parser/err/0004_use_path_bad_segment.rs1
-rw-r--r--crates/syntax/test_data/parser/err/0005_attribute_recover.rast59
-rw-r--r--crates/syntax/test_data/parser/err/0005_attribute_recover.rs8
-rw-r--r--crates/syntax/test_data/parser/err/0006_named_field_recovery.rast74
-rw-r--r--crates/syntax/test_data/parser/err/0006_named_field_recovery.rs7
-rw-r--r--crates/syntax/test_data/parser/err/0007_stray_curly_in_file.rast32
-rw-r--r--crates/syntax/test_data/parser/err/0007_stray_curly_in_file.rs9
-rw-r--r--crates/syntax/test_data/parser/err/0008_item_block_recovery.rast77
-rw-r--r--crates/syntax/test_data/parser/err/0008_item_block_recovery.rs13
-rw-r--r--crates/syntax/test_data/parser/err/0009_broken_struct_type_parameter.rast58
-rw-r--r--crates/syntax/test_data/parser/err/0009_broken_struct_type_parameter.rs5
-rw-r--r--crates/syntax/test_data/parser/err/0010_unsafe_lambda_block.rast44
-rw-r--r--crates/syntax/test_data/parser/err/0010_unsafe_lambda_block.rs3
-rw-r--r--crates/syntax/test_data/parser/err/0011_extern_struct.rast13
-rw-r--r--crates/syntax/test_data/parser/err/0011_extern_struct.rs1
-rw-r--r--crates/syntax/test_data/parser/err/0012_broken_lambda.rast387
-rw-r--r--crates/syntax/test_data/parser/err/0013_invalid_type.rast89
-rw-r--r--crates/syntax/test_data/parser/err/0013_invalid_type.rs7
-rw-r--r--crates/syntax/test_data/parser/err/0014_where_no_bounds.rast31
-rw-r--r--crates/syntax/test_data/parser/err/0014_where_no_bounds.rs1
-rw-r--r--crates/syntax/test_data/parser/err/0015_curly_in_params.rast24
-rw-r--r--crates/syntax/test_data/parser/err/0015_curly_in_params.rs2
-rw-r--r--crates/syntax/test_data/parser/err/0016_missing_semi.rast43
-rw-r--r--crates/syntax/test_data/parser/err/0016_missing_semi.rs6
-rw-r--r--crates/syntax/test_data/parser/err/0017_incomplete_binexpr.rast46
-rw-r--r--crates/syntax/test_data/parser/err/0017_incomplete_binexpr.rs4
-rw-r--r--crates/syntax/test_data/parser/err/0018_incomplete_fn.rast131
-rw-r--r--crates/syntax/test_data/parser/err/0018_incomplete_fn.rs8
-rw-r--r--crates/syntax/test_data/parser/err/0019_let_recover.rast103
-rw-r--r--crates/syntax/test_data/parser/err/0019_let_recover.rs12
-rw-r--r--crates/syntax/test_data/parser/err/0020_fn_recover.rast20
-rw-r--r--crates/syntax/test_data/parser/err/0020_fn_recover.rs3
-rw-r--r--crates/syntax/test_data/parser/err/0021_incomplete_param.rast34
-rw-r--r--crates/syntax/test_data/parser/err/0021_incomplete_param.rs2
-rw-r--r--crates/syntax/test_data/parser/err/0022_bad_exprs.rast180
-rw-r--r--crates/syntax/test_data/parser/err/0022_bad_exprs.rs3
-rw-r--r--crates/syntax/test_data/parser/err/0023_mismatched_paren.rast43
-rw-r--r--crates/syntax/test_data/parser/err/0023_mismatched_paren.rs5
-rw-r--r--crates/syntax/test_data/parser/err/0024_many_type_parens.rast319
-rw-r--r--crates/syntax/test_data/parser/err/0024_many_type_parens.rs7
-rw-r--r--crates/syntax/test_data/parser/err/0025_nope.rast202
-rw-r--r--crates/syntax/test_data/parser/err/0025_nope.rs31
-rw-r--r--crates/syntax/test_data/parser/err/0026_imp_recovery.rast49
-rw-r--r--crates/syntax/test_data/parser/err/0026_imp_recovery.rs2
-rw-r--r--crates/syntax/test_data/parser/err/0027_incomplere_where_for.rast27
-rw-r--r--crates/syntax/test_data/parser/err/0027_incomplere_where_for.rs3
-rw-r--r--crates/syntax/test_data/parser/err/0029_field_completion.rast35
-rw-r--r--crates/syntax/test_data/parser/err/0029_field_completion.rs3
-rw-r--r--crates/syntax/test_data/parser/err/0031_block_inner_attrs.rast121
-rw-r--r--crates/syntax/test_data/parser/err/0031_block_inner_attrs.rs15
-rw-r--r--crates/syntax/test_data/parser/err/0032_match_arms_inner_attrs.rast203
-rw-r--r--crates/syntax/test_data/parser/err/0032_match_arms_inner_attrs.rs20
-rw-r--r--crates/syntax/test_data/parser/err/0033_match_arms_outer_attrs.rast66
-rw-r--r--crates/syntax/test_data/parser/err/0033_match_arms_outer_attrs.rs7
-rw-r--r--crates/syntax/test_data/parser/err/0034_bad_box_pattern.rast95
-rw-r--r--crates/syntax/test_data/parser/err/0034_bad_box_pattern.rs6
-rw-r--r--crates/syntax/test_data/parser/err/0035_use_recover.rast53
-rw-r--r--crates/syntax/test_data/parser/err/0035_use_recover.rs5
-rw-r--r--crates/syntax/test_data/parser/err/0036_partial_use.rast51
-rw-r--r--crates/syntax/test_data/parser/err/0036_partial_use.rs2
-rw-r--r--crates/syntax/test_data/parser/err/0037_visibility_in_traits.rast97
-rw-r--r--crates/syntax/test_data/parser/err/0037_visibility_in_traits.rs6
-rw-r--r--crates/syntax/test_data/parser/err/0038_endless_inclusive_range.rast29
-rw-r--r--crates/syntax/test_data/parser/err/0038_endless_inclusive_range.rs4
-rw-r--r--crates/syntax/test_data/parser/err/0039_lambda_recovery.rast82
-rw-r--r--crates/syntax/test_data/parser/err/0039_lambda_recovery.rs5
-rw-r--r--crates/syntax/test_data/parser/err/0040_illegal_crate_kw_location.rast91
-rw-r--r--crates/syntax/test_data/parser/err/0040_illegal_crate_kw_location.rs4
-rw-r--r--crates/syntax/test_data/parser/err/0041_illegal_super_keyword_location.rast70
-rw-r--r--crates/syntax/test_data/parser/err/0041_illegal_super_keyword_location.rs4
-rw-r--r--crates/syntax/test_data/parser/err/0042_illegal_self_keyword_location.rast27
-rw-r--r--crates/syntax/test_data/parser/err/0042_illegal_self_keyword_location.rs2
-rw-r--r--crates/syntax/test_data/parser/err/0043_weird_blocks.rast71
-rw-r--r--crates/syntax/test_data/parser/err/0043_weird_blocks.rs6
-rw-r--r--crates/syntax/test_data/parser/err/0044_unexpected_for_type.rast240
-rw-r--r--crates/syntax/test_data/parser/err/0044_unexpected_for_type.rs9
-rw-r--r--crates/syntax/test_data/parser/err/0045_item_modifiers.rast45
-rw-r--r--crates/syntax/test_data/parser/err/0045_item_modifiers.rs2
-rw-r--r--crates/syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rast1
-rw-r--r--crates/syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/expr/ok/0000_add.rast8
-rw-r--r--crates/syntax/test_data/parser/fragments/expr/ok/0000_add.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rast1
-rw-r--r--crates/syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/item/ok/0000_fn.rast12
-rw-r--r--crates/syntax/test_data/parser/fragments/item/ok/0000_fn.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/path/err/0000_reserved_word.rast1
-rw-r--r--crates/syntax/test_data/parser/fragments/path/err/0000_reserved_word.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/path/err/0001_expression.rast1
-rw-r--r--crates/syntax/test_data/parser/fragments/path/err/0001_expression.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/path/ok/0000_single_ident.rast4
-rw-r--r--crates/syntax/test_data/parser/fragments/path/ok/0000_single_ident.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/path/ok/0001_multipart.rast14
-rw-r--r--crates/syntax/test_data/parser/fragments/path/ok/0001_multipart.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rast1
-rw-r--r--crates/syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rast1
-rw-r--r--crates/syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/pattern/ok/0000_enum.rast10
-rw-r--r--crates/syntax/test_data/parser/fragments/pattern/ok/0000_enum.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/type/err/0000_missing_close.rast1
-rw-r--r--crates/syntax/test_data/parser/fragments/type/err/0000_missing_close.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/type/ok/0000_result.rast22
-rw-r--r--crates/syntax/test_data/parser/fragments/type/ok/0000_result.rs1
-rw-r--r--crates/syntax/test_data/parser/fuzz-failures/0000.rs199
-rw-r--r--crates/syntax/test_data/parser/fuzz-failures/0001.rs106
-rw-r--r--crates/syntax/test_data/parser/fuzz-failures/0002.rs1
-rw-r--r--crates/syntax/test_data/parser/fuzz-failures/0003.rs1
-rw-r--r--crates/syntax/test_data/parser/fuzz-failures/0004.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/err/0001_array_type_missing_semi.rast27
-rw-r--r--crates/syntax/test_data/parser/inline/err/0001_array_type_missing_semi.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/err/0002_misplaced_label_err.rast28
-rw-r--r--crates/syntax/test_data/parser/inline/err/0002_misplaced_label_err.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/err/0003_pointer_type_no_mutability.rast17
-rw-r--r--crates/syntax/test_data/parser/inline/err/0003_pointer_type_no_mutability.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/err/0004_impl_type.rast79
-rw-r--r--crates/syntax/test_data/parser/inline/err/0004_impl_type.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/err/0005_fn_pointer_type_missing_fn.rast23
-rw-r--r--crates/syntax/test_data/parser/inline/err/0005_fn_pointer_type_missing_fn.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/err/0006_unsafe_block_in_mod.rast35
-rw-r--r--crates/syntax/test_data/parser/inline/err/0006_unsafe_block_in_mod.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/err/0007_async_without_semicolon.rast31
-rw-r--r--crates/syntax/test_data/parser/inline/err/0007_async_without_semicolon.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/err/0008_pub_expr.rast25
-rw-r--r--crates/syntax/test_data/parser/inline/err/0008_pub_expr.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.rast58
-rw-r--r--crates/syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.rast52
-rw-r--r--crates/syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.rs5
-rw-r--r--crates/syntax/test_data/parser/inline/err/0013_static_underscore.rast21
-rw-r--r--crates/syntax/test_data/parser/inline/err/0013_static_underscore.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rast48
-rw-r--r--crates/syntax/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/err/0015_empty_segment.rast15
-rw-r--r--crates/syntax/test_data/parser/inline/err/0015_empty_segment.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0001_trait_item_list.rast71
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0001_trait_item_list.rs6
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0002_use_tree_list.rast136
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0002_use_tree_list.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0003_where_pred_for.rast60
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0003_where_pred_for.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rast60
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0005_function_type_params.rast37
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0005_function_type_params.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0006_self_param.rast116
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0006_self_param.rs7
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0007_type_param_bounds.rast40
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0007_type_param_bounds.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0008_path_part.rast96
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0008_path_part.rs6
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0009_loop_expr.rast24
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0009_loop_expr.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0010_extern_block.rast9
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0010_extern_block.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0011_field_expr.rast59
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0011_field_expr.rs5
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0012_type_item_where_clause.rast33
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0012_type_item_where_clause.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0013_pointer_type_mut.rast35
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0013_pointer_type_mut.rs2
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0014_never_type.rast13
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0014_never_type.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0015_continue_expr.rast35
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0015_continue_expr.rs6
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0017_array_type.rast21
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0017_array_type.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0018_arb_self_types.rast72
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0018_arb_self_types.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0019_unary_expr.rast44
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0019_unary_expr.rs5
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0020_use_star.rast59
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0020_use_star.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0021_impl_item_list.rast78
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0021_impl_item_list.rs6
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0022_crate_visibility.rast53
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0022_crate_visibility.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0023_placeholder_type.rast13
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0023_placeholder_type.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0024_slice_pat.rast41
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0024_slice_pat.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0025_slice_type.rast17
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0025_slice_type.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0026_tuple_pat_fields.rast104
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0026_tuple_pat_fields.rs6
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0027_ref_pat.rast49
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0027_ref_pat.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0028_impl_trait_type.rast43
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0028_impl_trait_type.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0029_cast_expr.rast89
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0029_cast_expr.rs6
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0030_cond.rast202
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0030_cond.rs7
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0031_while_expr.rast84
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0031_while_expr.rs5
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0032_fn_pointer_type.rast98
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0032_fn_pointer_type.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0033_reference_type;.rast50
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0033_reference_type;.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0034_break_expr.rast53
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0034_break_expr.rs8
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0037_qual_paths.rast78
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0037_qual_paths.rs2
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0038_full_range_expr.rast28
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0038_full_range_expr.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0039_type_arg.rast55
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0039_type_arg.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.rast62
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0041_trait_item.rast125
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0041_trait_item.rs2
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0042_call_expr.rast147
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0042_call_expr.rs6
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0043_use_alias.rast138
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0043_use_alias.rs8
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0044_block_items.rast28
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0044_block_items.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0045_param_list_opt_patterns.rast46
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0045_param_list_opt_patterns.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0046_singleton_tuple_type.rast20
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0046_singleton_tuple_type.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0048_path_type_with_bounds.rast81
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0048_path_type_with_bounds.rs2
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0050_fn_decl.rast22
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0050_fn_decl.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0051_unit_type.rast14
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0051_unit_type.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0052_path_type.rast70
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0052_path_type.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0053_path_expr.rast95
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0053_path_expr.rs6
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0054_record_field_attrs.rast44
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0054_record_field_attrs.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0055_literal_pattern.rast76
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0055_literal_pattern.rs8
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0056_where_clause.rast110
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0056_where_clause.rs7
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0058_range_pat.rast82
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0058_range_pat.rs7
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0059_match_arms_commas.rast58
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0059_match_arms_commas.rs7
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0060_extern_crate.rast10
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0060_extern_crate.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0061_record_lit.rast124
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0061_record_lit.rs6
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0062_mod_contents.rast66
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0062_mod_contents.rs5
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0063_impl_def_neg.rast23
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0063_impl_def_neg.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0064_if_expr.rast121
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0064_if_expr.rs7
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0065_dyn_trait_type.rast43
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0065_dyn_trait_type.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0066_match_arm.rast151
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0066_match_arm.rs9
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0067_crate_path.rast15
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0067_crate_path.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0068_union_items.rast46
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0068_union_items.rs5
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0069_use_tree_list_after_path.rast37
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0069_use_tree_list_after_path.rs2
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rast50
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0071_match_expr.rast93
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0071_match_expr.rs6
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0072_return_expr.rast28
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0072_return_expr.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0073_type_item_type_params.rast20
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0073_type_item_type_params.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0074_stmt_postfix_expr_ambiguity.rast59
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0074_stmt_postfix_expr_ambiguity.rs7
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0075_block.rast86
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0075_block.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0076_function_where_clause.rast39
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0076_function_where_clause.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0077_try_expr.rast25
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0077_try_expr.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0078_type_item.rast16
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0078_type_item.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0079_impl_def.rast14
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0079_impl_def.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0080_postfix_range.rast95
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0080_postfix_range.rs5
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0081_for_type.rast112
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0081_for_type.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0082_ref_expr.rast138
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0082_ref_expr.rs10
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0083_struct_items.rast87
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0083_struct_items.rs8
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0084_paren_type.rast19
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0084_paren_type.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0085_expr_literals.rast135
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0085_expr_literals.rs12
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0086_function_ret_type.rast34
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0086_function_ret_type.rs2
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0088_break_ambiguity.rast65
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0088_break_ambiguity.rs6
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0090_type_param_default.rast22
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0090_type_param_default.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0092_fn_pointer_type_with_ret.rast23
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0092_fn_pointer_type_with_ret.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0093_index_expr.rast33
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0093_index_expr.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0095_placeholder_pat.rast28
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0095_placeholder_pat.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast123
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rs13
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0099_param_list.rast99
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0099_param_list.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0100_for_expr.rast34
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0100_for_expr.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rast132
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rs6
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0103_array_expr.rast54
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0103_array_expr.rs6
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.rast41
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0106_lambda_expr.rast135
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0106_lambda_expr.rs9
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0107_method_call_expr.rast62
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0107_method_call_expr.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0108_tuple_expr.rast38
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0108_tuple_expr.rs5
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0109_label.rast64
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0109_label.rs5
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0110_use_path.rast38
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0110_use_path.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0111_tuple_pat.rast89
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0111_tuple_pat.rs6
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0112_bind_pat.rast127
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0112_bind_pat.rs8
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0113_nocontentexpr.rast55
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0113_nocontentexpr.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0114_tuple_struct_where.rast64
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0114_tuple_struct_where.rs2
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.rast41
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0117_macro_call_type.rast43
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0117_macro_call_type.rs2
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0118_impl_inner_attributes.rast40
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0118_impl_inner_attributes.rs5
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0118_match_guard.rast47
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0118_match_guard.rs5
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.rast80
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.rs8
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0121_match_arms_outer_attributes.rast145
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0121_match_arms_outer_attributes.rs12
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.rast65
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.rs2
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0123_param_list_vararg.rast50
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0123_param_list_vararg.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0125_crate_keyword_path.rast31
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0125_crate_keyword_path.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rast47
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.rast97
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.rs6
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.rast57
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0129_marco_pat.rast36
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0129_marco_pat.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0130_let_stmt.rast126
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0130_let_stmt.rs9
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0130_try_block_expr.rast31
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0130_try_block_expr.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0131_existential_type.rast31
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0131_existential_type.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0132_box_expr.rast89
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0132_box_expr.rs5
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.rast62
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.rs8
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0137_await_expr.rast69
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0137_await_expr.rs5
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0138_associated_type_bounds.rast55
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0138_associated_type_bounds.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0138_expression_after_block.rast64
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0138_expression_after_block.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast25
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0139_param_outer_arg.rast34
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0139_param_outer_arg.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0142_for_range_from.rast40
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0142_for_range_from.rs5
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0143_box_pat.rast110
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0143_box_pat.rs5
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0144_dot_dot_pat.rast455
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0144_dot_dot_pat.rs25
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0145_record_field_pat.rast75
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0145_record_field_pat.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0146_as_precedence.rast42
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0146_as_precedence.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0147_const_param.rast23
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0147_const_param.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0147_macro_def.rast45
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0147_macro_def.rs2
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0148_pub_macro_def.rast21
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0148_pub_macro_def.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0150_array_attrs.rast47
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0150_array_attrs.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0150_impl_type_params.rast38
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0150_impl_type_params.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0151_fn.rast14
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0151_fn.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0151_trait_alias.rast128
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0151_trait_alias.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0152_arg_with_attr.rast36
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0152_arg_with_attr.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0152_impl.rast22
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0152_impl.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0153_trait.rast11
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0153_trait.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rast58
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rs2
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0155_closure_params.rast69
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0155_closure_params.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0156_fn_def_param.rast43
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0156_fn_def_param.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0156_or_pattern.rast111
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0156_or_pattern.rs8
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rast26
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0157_variant_discriminant.rast30
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0157_variant_discriminant.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.rast36
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0158_lambda_ret_block.rast43
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0158_lambda_ret_block.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0159_try_macro_fallback.rast34
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0159_try_macro_fallback.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0160_try_macro_rules.rast27
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0160_try_macro_rules.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0161_labeled_block.rast26
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0161_labeled_block.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0162_unsafe_block.rast23
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0162_unsafe_block.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0163_default_unsafe_item.rast44
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0163_default_unsafe_item.rs3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0164_default_item.rast24
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0164_default_item.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0164_type_path_in_pattern.rast38
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0164_type_path_in_pattern.rs1
-rw-r--r--crates/syntax/test_data/parser/ok/0000_empty.rast1
-rw-r--r--crates/syntax/test_data/parser/ok/0000_empty.rs0
-rw-r--r--crates/syntax/test_data/parser/ok/0001_struct_item.rast39
-rw-r--r--crates/syntax/test_data/parser/ok/0001_struct_item.rs3
-rw-r--r--crates/syntax/test_data/parser/ok/0002_struct_item_field.rast22
-rw-r--r--crates/syntax/test_data/parser/ok/0002_struct_item_field.rs3
-rw-r--r--crates/syntax/test_data/parser/ok/0004_file_shebang.rast2
-rw-r--r--crates/syntax/test_data/parser/ok/0004_file_shebang.rs1
-rw-r--r--crates/syntax/test_data/parser/ok/0005_fn_item.rast15
-rw-r--r--crates/syntax/test_data/parser/ok/0005_fn_item.rs2
-rw-r--r--crates/syntax/test_data/parser/ok/0006_inner_attributes.rast184
-rw-r--r--crates/syntax/test_data/parser/ok/0006_inner_attributes.rs10
-rw-r--r--crates/syntax/test_data/parser/ok/0007_extern_crate.rast39
-rw-r--r--crates/syntax/test_data/parser/ok/0007_extern_crate.rs3
-rw-r--r--crates/syntax/test_data/parser/ok/0008_mod_item.rast92
-rw-r--r--crates/syntax/test_data/parser/ok/0008_mod_item.rs17
-rw-r--r--crates/syntax/test_data/parser/ok/0009_use_item.rast21
-rw-r--r--crates/syntax/test_data/parser/ok/0009_use_item.rs2
-rw-r--r--crates/syntax/test_data/parser/ok/0010_use_path_segments.rast42
-rw-r--r--crates/syntax/test_data/parser/ok/0010_use_path_segments.rs2
-rw-r--r--crates/syntax/test_data/parser/ok/0011_outer_attribute.rast57
-rw-r--r--crates/syntax/test_data/parser/ok/0011_outer_attribute.rs6
-rw-r--r--crates/syntax/test_data/parser/ok/0012_visibility.rast102
-rw-r--r--crates/syntax/test_data/parser/ok/0012_visibility.rs5
-rw-r--r--crates/syntax/test_data/parser/ok/0013_use_path_self_super.rast33
-rw-r--r--crates/syntax/test_data/parser/ok/0013_use_path_self_super.rs2
-rw-r--r--crates/syntax/test_data/parser/ok/0014_use_tree.rast95
-rw-r--r--crates/syntax/test_data/parser/ok/0014_use_tree.rs7
-rw-r--r--crates/syntax/test_data/parser/ok/0015_use_tree.rast65
-rw-r--r--crates/syntax/test_data/parser/ok/0015_use_tree.rs2
-rw-r--r--crates/syntax/test_data/parser/ok/0016_struct_flavors.rast93
-rw-r--r--crates/syntax/test_data/parser/ok/0016_struct_flavors.rs10
-rw-r--r--crates/syntax/test_data/parser/ok/0017_attr_trailing_comma.rast28
-rw-r--r--crates/syntax/test_data/parser/ok/0017_attr_trailing_comma.rs2
-rw-r--r--crates/syntax/test_data/parser/ok/0018_struct_type_params.rast257
-rw-r--r--crates/syntax/test_data/parser/ok/0018_struct_type_params.rs17
-rw-r--r--crates/syntax/test_data/parser/ok/0019_enums.rast155
-rw-r--r--crates/syntax/test_data/parser/ok/0019_enums.rs25
-rw-r--r--crates/syntax/test_data/parser/ok/0020_type_param_bounds.rast268
-rw-r--r--crates/syntax/test_data/parser/ok/0020_type_param_bounds.rs10
-rw-r--r--crates/syntax/test_data/parser/ok/0022_empty_extern_block.rast21
-rw-r--r--crates/syntax/test_data/parser/ok/0022_empty_extern_block.rs5
-rw-r--r--crates/syntax/test_data/parser/ok/0023_static_items.rast41
-rw-r--r--crates/syntax/test_data/parser/ok/0023_static_items.rs2
-rw-r--r--crates/syntax/test_data/parser/ok/0024_const_item.rast59
-rw-r--r--crates/syntax/test_data/parser/ok/0024_const_item.rs3
-rw-r--r--crates/syntax/test_data/parser/ok/0025_extern_fn_in_block.rast31
-rw-r--r--crates/syntax/test_data/parser/ok/0025_extern_fn_in_block.rs3
-rw-r--r--crates/syntax/test_data/parser/ok/0026_const_fn_in_block.rast30
-rw-r--r--crates/syntax/test_data/parser/ok/0026_const_fn_in_block.rs3
-rw-r--r--crates/syntax/test_data/parser/ok/0027_unsafe_fn_in_block.rast41
-rw-r--r--crates/syntax/test_data/parser/ok/0027_unsafe_fn_in_block.rs4
-rw-r--r--crates/syntax/test_data/parser/ok/0028_operator_binding_power.rast185
-rw-r--r--crates/syntax/test_data/parser/ok/0028_operator_binding_power.rs14
-rw-r--r--crates/syntax/test_data/parser/ok/0029_range_forms.rast151
-rw-r--r--crates/syntax/test_data/parser/ok/0029_range_forms.rs11
-rw-r--r--crates/syntax/test_data/parser/ok/0030_string_suffixes.rast63
-rw-r--r--crates/syntax/test_data/parser/ok/0030_string_suffixes.rs6
-rw-r--r--crates/syntax/test_data/parser/ok/0030_traits.rast61
-rw-r--r--crates/syntax/test_data/parser/ok/0030_traits.rs7
-rw-r--r--crates/syntax/test_data/parser/ok/0031_extern.rast973
-rw-r--r--crates/syntax/test_data/parser/ok/0031_extern.rs29
-rw-r--r--crates/syntax/test_data/parser/ok/0032_where_for.rast90
-rw-r--r--crates/syntax/test_data/parser/ok/0032_where_for.rs4
-rw-r--r--crates/syntax/test_data/parser/ok/0033_label_break.rast215
-rw-r--r--crates/syntax/test_data/parser/ok/0033_label_break.rs28
-rw-r--r--crates/syntax/test_data/parser/ok/0034_crate_path_in_call.rast41
-rw-r--r--crates/syntax/test_data/parser/ok/0034_crate_path_in_call.rs3
-rw-r--r--crates/syntax/test_data/parser/ok/0035_weird_exprs.rast2291
-rw-r--r--crates/syntax/test_data/parser/ok/0035_weird_exprs.rs154
-rw-r--r--crates/syntax/test_data/parser/ok/0036_fully_qualified.rast92
-rw-r--r--crates/syntax/test_data/parser/ok/0036_fully_qualified.rs8
-rw-r--r--crates/syntax/test_data/parser/ok/0037_mod.rast16
-rw-r--r--crates/syntax/test_data/parser/ok/0037_mod.rs5
-rw-r--r--crates/syntax/test_data/parser/ok/0038_where_pred_type.rast42
-rw-r--r--crates/syntax/test_data/parser/ok/0038_where_pred_type.rs1
-rw-r--r--crates/syntax/test_data/parser/ok/0039_raw_fn_item.rast15
-rw-r--r--crates/syntax/test_data/parser/ok/0039_raw_fn_item.rs2
-rw-r--r--crates/syntax/test_data/parser/ok/0040_raw_struct_item_field.rast22
-rw-r--r--crates/syntax/test_data/parser/ok/0040_raw_struct_item_field.rs3
-rw-r--r--crates/syntax/test_data/parser/ok/0041_raw_keywords.rast49
-rw-r--r--crates/syntax/test_data/parser/ok/0041_raw_keywords.rs1
-rw-r--r--crates/syntax/test_data/parser/ok/0042_ufcs_call_list.rast123
-rw-r--r--crates/syntax/test_data/parser/ok/0042_ufcs_call_list.rs15
-rw-r--r--crates/syntax/test_data/parser/ok/0043_complex_assignment.rast109
-rw-r--r--crates/syntax/test_data/parser/ok/0043_complex_assignment.rs8
-rw-r--r--crates/syntax/test_data/parser/ok/0044_let_attrs.rast75
-rw-r--r--crates/syntax/test_data/parser/ok/0044_let_attrs.rs5
-rw-r--r--crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rast177
-rw-r--r--crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rs20
-rw-r--r--crates/syntax/test_data/parser/ok/0046_extern_inner_attributes.rast28
-rw-r--r--crates/syntax/test_data/parser/ok/0046_extern_inner_attributes.rs4
-rw-r--r--crates/syntax/test_data/parser/ok/0047_minus_in_inner_pattern.rast320
-rw-r--r--crates/syntax/test_data/parser/ok/0047_minus_in_inner_pattern.rs27
-rw-r--r--crates/syntax/test_data/parser/ok/0048_compound_assignment.rast200
-rw-r--r--crates/syntax/test_data/parser/ok/0048_compound_assignment.rs17
-rw-r--r--crates/syntax/test_data/parser/ok/0049_async_block.rast35
-rw-r--r--crates/syntax/test_data/parser/ok/0049_async_block.rs5
-rw-r--r--crates/syntax/test_data/parser/ok/0050_async_block_as_argument.rast90
-rw-r--r--crates/syntax/test_data/parser/ok/0050_async_block_as_argument.rs5
-rw-r--r--crates/syntax/test_data/parser/ok/0051_parameter_attrs.rast508
-rw-r--r--crates/syntax/test_data/parser/ok/0051_parameter_attrs.rs21
-rw-r--r--crates/syntax/test_data/parser/ok/0052_for_range_block.rast78
-rw-r--r--crates/syntax/test_data/parser/ok/0052_for_range_block.rs5
-rw-r--r--crates/syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast39
-rw-r--r--crates/syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rs5
-rw-r--r--crates/syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rast123
-rw-r--r--crates/syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rs5
-rw-r--r--crates/syntax/test_data/parser/ok/0055_dot_dot_dot.rast49
-rw-r--r--crates/syntax/test_data/parser/ok/0055_dot_dot_dot.rs5
-rw-r--r--crates/syntax/test_data/parser/ok/0056_neq_in_type.rast64
-rw-r--r--crates/syntax/test_data/parser/ok/0056_neq_in_type.rs3
-rw-r--r--crates/syntax/test_data/parser/ok/0057_loop_in_call.rast56
-rw-r--r--crates/syntax/test_data/parser/ok/0057_loop_in_call.rs5
-rw-r--r--crates/syntax/test_data/parser/ok/0058_unary_expr_precedence.rast96
-rw-r--r--crates/syntax/test_data/parser/ok/0058_unary_expr_precedence.rs7
-rw-r--r--crates/syntax/test_data/parser/ok/0059_loops_in_parens.rast97
-rw-r--r--crates/syntax/test_data/parser/ok/0059_loops_in_parens.rs5
-rw-r--r--crates/syntax/test_data/parser/ok/0060_as_range.rast55
-rw-r--r--crates/syntax/test_data/parser/ok/0060_as_range.rs4
-rw-r--r--crates/syntax/test_data/parser/ok/0061_match_full_range.rast26
-rw-r--r--crates/syntax/test_data/parser/ok/0061_match_full_range.rs4
-rw-r--r--crates/syntax/test_data/parser/ok/0062_macro_2.0.rast175
-rw-r--r--crates/syntax/test_data/parser/ok/0062_macro_2.0.rs15
-rw-r--r--crates/syntax/test_data/parser/ok/0063_trait_fn_patterns.rast194
-rw-r--r--crates/syntax/test_data/parser/ok/0063_trait_fn_patterns.rs7
-rw-r--r--crates/syntax/test_data/parser/ok/0063_variadic_fun.rast133
-rw-r--r--crates/syntax/test_data/parser/ok/0063_variadic_fun.rs5
-rw-r--r--crates/syntax/test_data/parser/ok/0064_impl_fn_params.rast162
-rw-r--r--crates/syntax/test_data/parser/ok/0064_impl_fn_params.rs6
-rw-r--r--crates/syntax/test_data/parser/ok/0065_comment_newline.rast16
-rw-r--r--crates/syntax/test_data/parser/ok/0065_comment_newline.rs3
-rw-r--r--crates/syntax/test_data/parser/ok/0065_plus_after_fn_trait_bound.rast60
-rw-r--r--crates/syntax/test_data/parser/ok/0065_plus_after_fn_trait_bound.rs1
-rw-r--r--crates/syntax/test_data/parser/ok/0066_default_modifier.rast218
-rw-r--r--crates/syntax/test_data/parser/ok/0066_default_modifier.rs16
-rw-r--r--crates/syntax/test_data/parser/ok/0067_where_for_pred.rast392
-rw-r--r--crates/syntax/test_data/parser/ok/0067_where_for_pred.rs30
-rw-r--r--crates/syntax/test_data/parser/ok/0068_item_modifiers.rast218
-rw-r--r--crates/syntax/test_data/parser/ok/0068_item_modifiers.rs16
-rw-r--r--crates/syntax/test_data/reparse/fuzz-failures/0000.rs6
-rw-r--r--crates/syntax/test_data/reparse/fuzz-failures/0001.rs4
-rw-r--r--crates/syntax/test_data/reparse/fuzz-failures/0002.rs4
-rw-r--r--crates/syntax/test_data/reparse/fuzz-failures/0003.rsbin0 -> 8 bytes
-rw-r--r--crates/syntax/test_data/reparse/fuzz-failures/0004.rs4
-rw-r--r--crates/syntax/test_data/reparse/fuzz-failures/0005.rs7
768 files changed, 40214 insertions, 0 deletions
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
new file mode 100644
index 00000000000..47e351f9d1a
--- /dev/null
+++ b/crates/syntax/Cargo.toml
@@ -0,0 +1,35 @@
+[package]
+name = "syntax"
+version = "0.0.0"
+description = "Comment and whitespace preserving parser for the Rust language"
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/rust-analyzer/rust-analyzer"
+authors = ["rust-analyzer developers"]
+edition = "2018"
+
+[lib]
+doctest = false
+
+[dependencies]
+itertools = "0.9.0"
+rowan = "0.10.0"
+rustc_lexer = { version = "671.0.0", package = "rustc-ap-rustc_lexer" }
+rustc-hash = "1.1.0"
+arrayvec = "0.5.1"
+once_cell = "1.3.1"
+# This crate transitively depends on `smol_str` via `rowan`.
+# ideally, `serde` should be enabled by `rust-analyzer`, but we enable it here
+# to reduce number of compilations
+smol_str = { version = "0.1.15", features = ["serde"] }
+serde = { version = "1.0.106", features = ["derive"] }
+
+stdx = { path = "../stdx" }
+text_edit = { path = "../text_edit" }
+parser = { path = "../parser" }
+
+[dev-dependencies]
+walkdir = "2.3.1"
+rayon = "1"
+
+test_utils = { path = "../test_utils" }
+expect = { path = "../expect" }
diff --git a/crates/syntax/fuzz/.gitignore b/crates/syntax/fuzz/.gitignore
new file mode 100644
index 00000000000..f734abd499c
--- /dev/null
+++ b/crates/syntax/fuzz/.gitignore
@@ -0,0 +1,4 @@
+Cargo.lock
+target
+corpus
+artifacts
diff --git a/crates/syntax/fuzz/Cargo.toml b/crates/syntax/fuzz/Cargo.toml
new file mode 100644
index 00000000000..32c40d1b95c
--- /dev/null
+++ b/crates/syntax/fuzz/Cargo.toml
@@ -0,0 +1,27 @@
+
+[package]
+name = "syntax-fuzz"
+version = "0.0.1"
+authors = ["rust-analyzer developers"]
+publish = false
+edition = "2018"
+
+[package.metadata]
+cargo-fuzz = true
+
+[dependencies]
+syntax = { path = ".." }
+text_edit = { path = "../../text_edit" }
+libfuzzer-sys = { git = "https://github.com/rust-fuzz/libfuzzer-sys.git" }
+
+# Prevent this from interfering with workspaces
+[workspace]
+members = ["."]
+
+[[bin]]
+name = "parser"
+path = "fuzz_targets/parser.rs"
+
+[[bin]]
+name = "reparse"
+path = "fuzz_targets/reparse.rs"
diff --git a/crates/syntax/fuzz/fuzz_targets/parser.rs b/crates/syntax/fuzz/fuzz_targets/parser.rs
new file mode 100644
index 00000000000..386768343bd
--- /dev/null
+++ b/crates/syntax/fuzz/fuzz_targets/parser.rs
@@ -0,0 +1,11 @@
+//! FIXME: write short doc here
+
+#![no_main]
+use libfuzzer_sys::fuzz_target;
+use syntax::fuzz::check_parser;
+
+fuzz_target!(|data: &[u8]| {
+    if let Ok(text) = std::str::from_utf8(data) {
+        check_parser(text)
+    }
+});
diff --git a/crates/syntax/fuzz/fuzz_targets/reparse.rs b/crates/syntax/fuzz/fuzz_targets/reparse.rs
new file mode 100644
index 00000000000..5ac99fdafdf
--- /dev/null
+++ b/crates/syntax/fuzz/fuzz_targets/reparse.rs
@@ -0,0 +1,11 @@
+//! FIXME: write short doc here
+
+#![no_main]
+use libfuzzer_sys::fuzz_target;
+use syntax::fuzz::CheckReparse;
+
+fuzz_target!(|data: &[u8]| {
+    if let Some(check) = CheckReparse::from_data(data) {
+        check.run();
+    }
+});
diff --git a/crates/syntax/src/algo.rs b/crates/syntax/src/algo.rs
new file mode 100644
index 00000000000..6254b38ba1c
--- /dev/null
+++ b/crates/syntax/src/algo.rs
@@ -0,0 +1,406 @@
+//! FIXME: write short doc here
+
+use std::{
+    fmt,
+    ops::{self, RangeInclusive},
+};
+
+use itertools::Itertools;
+use rustc_hash::FxHashMap;
+use text_edit::TextEditBuilder;
+
+use crate::{
+    AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxNodePtr,
+    SyntaxToken, TextRange, TextSize,
+};
+
+/// Returns ancestors of the node at the offset, sorted by length. This should
+/// do the right thing at an edge, e.g. when searching for expressions at `{
+/// <|>foo }` we will get the name reference instead of the whole block, which
+/// we would get if we just did `find_token_at_offset(...).flat_map(|t|
+/// t.parent().ancestors())`.
+pub fn ancestors_at_offset(
+    node: &SyntaxNode,
+    offset: TextSize,
+) -> impl Iterator<Item = SyntaxNode> {
+    node.token_at_offset(offset)
+        .map(|token| token.parent().ancestors())
+        .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len())
+}
+
+/// Finds a node of specific Ast type at offset. Note that this is slightly
+/// imprecise: if the cursor is strictly between two nodes of the desired type,
+/// as in
+///
+/// ```no-run
+/// struct Foo {}|struct Bar;
+/// ```
+///
+/// then the shorter node will be silently preferred.
+pub fn find_node_at_offset<N: AstNode>(syntax: &SyntaxNode, offset: TextSize) -> Option<N> {
+    ancestors_at_offset(syntax, offset).find_map(N::cast)
+}
+
+pub fn find_node_at_range<N: AstNode>(syntax: &SyntaxNode, range: TextRange) -> Option<N> {
+    find_covering_element(syntax, range).ancestors().find_map(N::cast)
+}
+
+/// Skip to next non `trivia` token
+pub fn skip_trivia_token(mut token: SyntaxToken, direction: Direction) -> Option<SyntaxToken> {
+    while token.kind().is_trivia() {
+        token = match direction {
+            Direction::Next => token.next_token()?,
+            Direction::Prev => token.prev_token()?,
+        }
+    }
+    Some(token)
+}
+
+/// Finds the first sibling in the given direction which is not `trivia`
+pub fn non_trivia_sibling(element: SyntaxElement, direction: Direction) -> Option<SyntaxElement> {
+    return match element {
+        NodeOrToken::Node(node) => node.siblings_with_tokens(direction).skip(1).find(not_trivia),
+        NodeOrToken::Token(token) => token.siblings_with_tokens(direction).skip(1).find(not_trivia),
+    };
+
+    fn not_trivia(element: &SyntaxElement) -> bool {
+        match element {
+            NodeOrToken::Node(_) => true,
+            NodeOrToken::Token(token) => !token.kind().is_trivia(),
+        }
+    }
+}
+
+pub fn find_covering_element(root: &SyntaxNode, range: TextRange) -> SyntaxElement {
+    root.covering_element(range)
+}
+
+pub fn least_common_ancestor(u: &SyntaxNode, v: &SyntaxNode) -> Option<SyntaxNode> {
+    if u == v {
+        return Some(u.clone());
+    }
+
+    let u_depth = u.ancestors().count();
+    let v_depth = v.ancestors().count();
+    let keep = u_depth.min(v_depth);
+
+    let u_candidates = u.ancestors().skip(u_depth - keep);
+    let v_canidates = v.ancestors().skip(v_depth - keep);
+    let (res, _) = u_candidates.zip(v_canidates).find(|(x, y)| x == y)?;
+    Some(res)
+}
+
+pub fn neighbor<T: AstNode>(me: &T, direction: Direction) -> Option<T> {
+    me.syntax().siblings(direction).skip(1).find_map(T::cast)
+}
+
+pub fn has_errors(node: &SyntaxNode) -> bool {
+    node.children().any(|it| it.kind() == SyntaxKind::ERROR)
+}
+
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub enum InsertPosition<T> {
+    First,
+    Last,
+    Before(T),
+    After(T),
+}
+
+pub struct TreeDiff {
+    replacements: FxHashMap<SyntaxElement, SyntaxElement>,
+}
+
+impl TreeDiff {
+    pub fn into_text_edit(&self, builder: &mut TextEditBuilder) {
+        for (from, to) in self.replacements.iter() {
+            builder.replace(from.text_range(), to.to_string())
+        }
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.replacements.is_empty()
+    }
+}
+
+/// Finds minimal the diff, which, applied to `from`, will result in `to`.
+///
+/// Specifically, returns a map whose keys are descendants of `from` and values
+/// are descendants of `to`, such that  `replace_descendants(from, map) == to`.
+///
+/// A trivial solution is a singleton map `{ from: to }`, but this function
+/// tries to find a more fine-grained diff.
+pub fn diff(from: &SyntaxNode, to: &SyntaxNode) -> TreeDiff {
+    let mut buf = FxHashMap::default();
+    // FIXME: this is both horrible inefficient and gives larger than
+    // necessary diff. I bet there's a cool algorithm to diff trees properly.
+    go(&mut buf, from.clone().into(), to.clone().into());
+    return TreeDiff { replacements: buf };
+
+    fn go(
+        buf: &mut FxHashMap<SyntaxElement, SyntaxElement>,
+        lhs: SyntaxElement,
+        rhs: SyntaxElement,
+    ) {
+        if lhs.kind() == rhs.kind()
+            && lhs.text_range().len() == rhs.text_range().len()
+            && match (&lhs, &rhs) {
+                (NodeOrToken::Node(lhs), NodeOrToken::Node(rhs)) => {
+                    lhs.green() == rhs.green() || lhs.text() == rhs.text()
+                }
+                (NodeOrToken::Token(lhs), NodeOrToken::Token(rhs)) => lhs.text() == rhs.text(),
+                _ => false,
+            }
+        {
+            return;
+        }
+        if let (Some(lhs), Some(rhs)) = (lhs.as_node(), rhs.as_node()) {
+            if lhs.children_with_tokens().count() == rhs.children_with_tokens().count() {
+                for (lhs, rhs) in lhs.children_with_tokens().zip(rhs.children_with_tokens()) {
+                    go(buf, lhs, rhs)
+                }
+                return;
+            }
+        }
+        buf.insert(lhs, rhs);
+    }
+}
+
+/// Adds specified children (tokens or nodes) to the current node at the
+/// specific position.
+///
+/// This is a type-unsafe low-level editing API, if you need to use it,
+/// prefer to create a type-safe abstraction on top of it instead.
+pub fn insert_children(
+    parent: &SyntaxNode,
+    position: InsertPosition<SyntaxElement>,
+    to_insert: impl IntoIterator<Item = SyntaxElement>,
+) -> SyntaxNode {
+    let mut to_insert = to_insert.into_iter();
+    _insert_children(parent, position, &mut to_insert)
+}
+
+fn _insert_children(
+    parent: &SyntaxNode,
+    position: InsertPosition<SyntaxElement>,
+    to_insert: &mut dyn Iterator<Item = SyntaxElement>,
+) -> SyntaxNode {
+    let mut delta = TextSize::default();
+    let to_insert = to_insert.map(|element| {
+        delta += element.text_range().len();
+        to_green_element(element)
+    });
+
+    let mut old_children = parent.green().children().map(|it| match it {
+        NodeOrToken::Token(it) => NodeOrToken::Token(it.clone()),
+        NodeOrToken::Node(it) => NodeOrToken::Node(it.clone()),
+    });
+
+    let new_children = match &position {
+        InsertPosition::First => to_insert.chain(old_children).collect::<Vec<_>>(),
+        InsertPosition::Last => old_children.chain(to_insert).collect::<Vec<_>>(),
+        InsertPosition::Before(anchor) | InsertPosition::After(anchor) => {
+            let take_anchor = if let InsertPosition::After(_) = position { 1 } else { 0 };
+            let split_at = position_of_child(parent, anchor.clone()) + take_anchor;
+            let before = old_children.by_ref().take(split_at).collect::<Vec<_>>();
+            before.into_iter().chain(to_insert).chain(old_children).collect::<Vec<_>>()
+        }
+    };
+
+    with_children(parent, new_children)
+}
+
+/// Replaces all nodes in `to_delete` with nodes from `to_insert`
+///
+/// This is a type-unsafe low-level editing API, if you need to use it,
+/// prefer to create a type-safe abstraction on top of it instead.
+pub fn replace_children(
+    parent: &SyntaxNode,
+    to_delete: RangeInclusive<SyntaxElement>,
+    to_insert: impl IntoIterator<Item = SyntaxElement>,
+) -> SyntaxNode {
+    let mut to_insert = to_insert.into_iter();
+    _replace_children(parent, to_delete, &mut to_insert)
+}
+
+fn _replace_children(
+    parent: &SyntaxNode,
+    to_delete: RangeInclusive<SyntaxElement>,
+    to_insert: &mut dyn Iterator<Item = SyntaxElement>,
+) -> SyntaxNode {
+    let start = position_of_child(parent, to_delete.start().clone());
+    let end = position_of_child(parent, to_delete.end().clone());
+    let mut old_children = parent.green().children().map(|it| match it {
+        NodeOrToken::Token(it) => NodeOrToken::Token(it.clone()),
+        NodeOrToken::Node(it) => NodeOrToken::Node(it.clone()),
+    });
+
+    let before = old_children.by_ref().take(start).collect::<Vec<_>>();
+    let new_children = before
+        .into_iter()
+        .chain(to_insert.map(to_green_element))
+        .chain(old_children.skip(end + 1 - start))
+        .collect::<Vec<_>>();
+    with_children(parent, new_children)
+}
+
+#[derive(Default)]
+pub struct SyntaxRewriter<'a> {
+    f: Option<Box<dyn Fn(&SyntaxElement) -> Option<SyntaxElement> + 'a>>,
+    //FIXME: add debug_assertions that all elements are in fact from the same file.
+    replacements: FxHashMap<SyntaxElement, Replacement>,
+}
+
+impl fmt::Debug for SyntaxRewriter<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("SyntaxRewriter").field("replacements", &self.replacements).finish()
+    }
+}
+
+impl<'a> SyntaxRewriter<'a> {
+    pub fn from_fn(f: impl Fn(&SyntaxElement) -> Option<SyntaxElement> + 'a) -> SyntaxRewriter<'a> {
+        SyntaxRewriter { f: Some(Box::new(f)), replacements: FxHashMap::default() }
+    }
+    pub fn delete<T: Clone + Into<SyntaxElement>>(&mut self, what: &T) {
+        let what = what.clone().into();
+        let replacement = Replacement::Delete;
+        self.replacements.insert(what, replacement);
+    }
+    pub fn replace<T: Clone + Into<SyntaxElement>>(&mut self, what: &T, with: &T) {
+        let what = what.clone().into();
+        let replacement = Replacement::Single(with.clone().into());
+        self.replacements.insert(what, replacement);
+    }
+    pub fn replace_with_many<T: Clone + Into<SyntaxElement>>(
+        &mut self,
+        what: &T,
+        with: Vec<SyntaxElement>,
+    ) {
+        let what = what.clone().into();
+        let replacement = Replacement::Many(with);
+        self.replacements.insert(what, replacement);
+    }
+    pub fn replace_ast<T: AstNode>(&mut self, what: &T, with: &T) {
+        self.replace(what.syntax(), with.syntax())
+    }
+
+    pub fn rewrite(&self, node: &SyntaxNode) -> SyntaxNode {
+        if self.f.is_none() && self.replacements.is_empty() {
+            return node.clone();
+        }
+        self.rewrite_children(node)
+    }
+
+    pub fn rewrite_ast<N: AstNode>(self, node: &N) -> N {
+        N::cast(self.rewrite(node.syntax())).unwrap()
+    }
+
+    /// Returns a node that encompasses all replacements to be done by this rewriter.
+    ///
+    /// Passing the returned node to `rewrite` will apply all replacements queued up in `self`.
+    ///
+    /// Returns `None` when there are no replacements.
+    pub fn rewrite_root(&self) -> Option<SyntaxNode> {
+        assert!(self.f.is_none());
+        self.replacements
+            .keys()
+            .map(|element| match element {
+                SyntaxElement::Node(it) => it.clone(),
+                SyntaxElement::Token(it) => it.parent(),
+            })
+            // If we only have one replacement, we must return its parent node, since `rewrite` does
+            // not replace the node passed to it.
+            .map(|it| it.parent().unwrap_or(it))
+            .fold1(|a, b| least_common_ancestor(&a, &b).unwrap())
+    }
+
+    fn replacement(&self, element: &SyntaxElement) -> Option<Replacement> {
+        if let Some(f) = &self.f {
+            assert!(self.replacements.is_empty());
+            return f(element).map(Replacement::Single);
+        }
+        self.replacements.get(element).cloned()
+    }
+
+    fn rewrite_children(&self, node: &SyntaxNode) -> SyntaxNode {
+        //  FIXME: this could be made much faster.
+        let mut new_children = Vec::new();
+        for child in node.children_with_tokens() {
+            self.rewrite_self(&mut new_children, &child);
+        }
+        with_children(node, new_children)
+    }
+
+    fn rewrite_self(
+        &self,
+        acc: &mut Vec<NodeOrToken<rowan::GreenNode, rowan::GreenToken>>,
+        element: &SyntaxElement,
+    ) {
+        if let Some(replacement) = self.replacement(&element) {
+            match replacement {
+                Replacement::Single(NodeOrToken::Node(it)) => {
+                    acc.push(NodeOrToken::Node(it.green().clone()))
+                }
+                Replacement::Single(NodeOrToken::Token(it)) => {
+                    acc.push(NodeOrToken::Token(it.green().clone()))
+                }
+                Replacement::Many(replacements) => {
+                    acc.extend(replacements.iter().map(|it| match it {
+                        NodeOrToken::Node(it) => NodeOrToken::Node(it.green().clone()),
+                        NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()),
+                    }))
+                }
+                Replacement::Delete => (),
+            };
+            return;
+        }
+        let res = match element {
+            NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()),
+            NodeOrToken::Node(it) => NodeOrToken::Node(self.rewrite_children(it).green().clone()),
+        };
+        acc.push(res)
+    }
+}
+
+impl ops::AddAssign for SyntaxRewriter<'_> {
+    fn add_assign(&mut self, rhs: SyntaxRewriter) {
+        assert!(rhs.f.is_none());
+        self.replacements.extend(rhs.replacements)
+    }
+}
+
+#[derive(Clone, Debug)]
+enum Replacement {
+    Delete,
+    Single(SyntaxElement),
+    Many(Vec<SyntaxElement>),
+}
+
+fn with_children(
+    parent: &SyntaxNode,
+    new_children: Vec<NodeOrToken<rowan::GreenNode, rowan::GreenToken>>,
+) -> SyntaxNode {
+    let len = new_children.iter().map(|it| it.text_len()).sum::<TextSize>();
+    let new_node = rowan::GreenNode::new(rowan::SyntaxKind(parent.kind() as u16), new_children);
+    let new_root_node = parent.replace_with(new_node);
+    let new_root_node = SyntaxNode::new_root(new_root_node);
+
+    // FIXME: use a more elegant way to re-fetch the node (#1185), make
+    // `range` private afterwards
+    let mut ptr = SyntaxNodePtr::new(parent);
+    ptr.range = TextRange::at(ptr.range.start(), len);
+    ptr.to_node(&new_root_node)
+}
+
+fn position_of_child(parent: &SyntaxNode, child: SyntaxElement) -> usize {
+    parent
+        .children_with_tokens()
+        .position(|it| it == child)
+        .expect("element is not a child of current element")
+}
+
+fn to_green_element(element: SyntaxElement) -> NodeOrToken<rowan::GreenNode, rowan::GreenToken> {
+    match element {
+        NodeOrToken::Node(it) => it.green().clone().into(),
+        NodeOrToken::Token(it) => it.green().clone().into(),
+    }
+}
diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs
new file mode 100644
index 00000000000..d536bb1e7d6
--- /dev/null
+++ b/crates/syntax/src/ast.rs
@@ -0,0 +1,331 @@
+//! Abstract Syntax Tree, layered on top of untyped `SyntaxNode`s
+
+mod generated;
+mod traits;
+mod token_ext;
+mod node_ext;
+mod expr_ext;
+pub mod edit;
+pub mod make;
+
+use std::marker::PhantomData;
+
+use crate::{
+    syntax_node::{SyntaxNode, SyntaxNodeChildren, SyntaxToken},
+    SmolStr, SyntaxKind,
+};
+
+pub use self::{
+    expr_ext::{ArrayExprKind, BinOp, Effect, ElseBranch, LiteralKind, PrefixOp, RangeOp},
+    generated::*,
+    node_ext::{
+        AttrKind, FieldKind, NameOrNameRef, PathSegmentKind, SelfParamKind, SlicePatComponents,
+        StructKind, TypeBoundKind, VisibilityKind,
+    },
+    token_ext::*,
+    traits::*,
+};
+
+/// The main trait to go from untyped `SyntaxNode`  to a typed ast. The
+/// conversion itself has zero runtime cost: ast and syntax nodes have exactly
+/// the same representation: a pointer to the tree root and a pointer to the
+/// node itself.
+pub trait AstNode {
+    fn can_cast(kind: SyntaxKind) -> bool
+    where
+        Self: Sized;
+
+    fn cast(syntax: SyntaxNode) -> Option<Self>
+    where
+        Self: Sized;
+
+    fn syntax(&self) -> &SyntaxNode;
+}
+
+/// Like `AstNode`, but wraps tokens rather than interior nodes.
+pub trait AstToken {
+    fn can_cast(token: SyntaxKind) -> bool
+    where
+        Self: Sized;
+
+    fn cast(syntax: SyntaxToken) -> Option<Self>
+    where
+        Self: Sized;
+
+    fn syntax(&self) -> &SyntaxToken;
+
+    fn text(&self) -> &SmolStr {
+        self.syntax().text()
+    }
+}
+
+/// An iterator over `SyntaxNode` children of a particular AST type.
+#[derive(Debug, Clone)]
+pub struct AstChildren<N> {
+    inner: SyntaxNodeChildren,
+    ph: PhantomData<N>,
+}
+
+impl<N> AstChildren<N> {
+    fn new(parent: &SyntaxNode) -> Self {
+        AstChildren { inner: parent.children(), ph: PhantomData }
+    }
+}
+
+impl<N: AstNode> Iterator for AstChildren<N> {
+    type Item = N;
+    fn next(&mut self) -> Option<N> {
+        self.inner.find_map(N::cast)
+    }
+}
+
+mod support {
+    use super::{AstChildren, AstNode, SyntaxKind, SyntaxNode, SyntaxToken};
+
+    pub(super) fn child<N: AstNode>(parent: &SyntaxNode) -> Option<N> {
+        parent.children().find_map(N::cast)
+    }
+
+    pub(super) fn children<N: AstNode>(parent: &SyntaxNode) -> AstChildren<N> {
+        AstChildren::new(parent)
+    }
+
+    pub(super) fn token(parent: &SyntaxNode, kind: SyntaxKind) -> Option<SyntaxToken> {
+        parent.children_with_tokens().filter_map(|it| it.into_token()).find(|it| it.kind() == kind)
+    }
+}
+
+#[test]
+fn assert_ast_is_object_safe() {
+    fn _f(_: &dyn AstNode, _: &dyn NameOwner) {}
+}
+
+#[test]
+fn test_doc_comment_none() {
+    let file = SourceFile::parse(
+        r#"
+        // non-doc
+        mod foo {}
+        "#,
+    )
+    .ok()
+    .unwrap();
+    let module = file.syntax().descendants().find_map(Module::cast).unwrap();
+    assert!(module.doc_comment_text().is_none());
+}
+
+#[test]
+fn test_doc_comment_of_items() {
+    let file = SourceFile::parse(
+        r#"
+        //! doc
+        // non-doc
+        mod foo {}
+        "#,
+    )
+    .ok()
+    .unwrap();
+    let module = file.syntax().descendants().find_map(Module::cast).unwrap();
+    assert_eq!("doc", module.doc_comment_text().unwrap());
+}
+
+#[test]
+fn test_doc_comment_of_statics() {
+    let file = SourceFile::parse(
+        r#"
+        /// Number of levels
+        static LEVELS: i32 = 0;
+        "#,
+    )
+    .ok()
+    .unwrap();
+    let st = file.syntax().descendants().find_map(Static::cast).unwrap();
+    assert_eq!("Number of levels", st.doc_comment_text().unwrap());
+}
+
+#[test]
+fn test_doc_comment_preserves_indents() {
+    let file = SourceFile::parse(
+        r#"
+        /// doc1
+        /// ```
+        /// fn foo() {
+        ///     // ...
+        /// }
+        /// ```
+        mod foo {}
+        "#,
+    )
+    .ok()
+    .unwrap();
+    let module = file.syntax().descendants().find_map(Module::cast).unwrap();
+    assert_eq!("doc1\n```\nfn foo() {\n    // ...\n}\n```", module.doc_comment_text().unwrap());
+}
+
+#[test]
+fn test_doc_comment_preserves_newlines() {
+    let file = SourceFile::parse(
+        r#"
+        /// this
+        /// is
+        /// mod
+        /// foo
+        mod foo {}
+        "#,
+    )
+    .ok()
+    .unwrap();
+    let module = file.syntax().descendants().find_map(Module::cast).unwrap();
+    assert_eq!("this\nis\nmod\nfoo", module.doc_comment_text().unwrap());
+}
+
+#[test]
+fn test_doc_comment_single_line_block_strips_suffix() {
+    let file = SourceFile::parse(
+        r#"
+        /** this is mod foo*/
+        mod foo {}
+        "#,
+    )
+    .ok()
+    .unwrap();
+    let module = file.syntax().descendants().find_map(Module::cast).unwrap();
+    assert_eq!("this is mod foo", module.doc_comment_text().unwrap());
+}
+
+#[test]
+fn test_doc_comment_single_line_block_strips_suffix_whitespace() {
+    let file = SourceFile::parse(
+        r#"
+        /** this is mod foo */
+        mod foo {}
+        "#,
+    )
+    .ok()
+    .unwrap();
+    let module = file.syntax().descendants().find_map(Module::cast).unwrap();
+    assert_eq!("this is mod foo ", module.doc_comment_text().unwrap());
+}
+
+#[test]
+fn test_doc_comment_multi_line_block_strips_suffix() {
+    let file = SourceFile::parse(
+        r#"
+        /**
+        this
+        is
+        mod foo
+        */
+        mod foo {}
+        "#,
+    )
+    .ok()
+    .unwrap();
+    let module = file.syntax().descendants().find_map(Module::cast).unwrap();
+    assert_eq!(
+        "        this\n        is\n        mod foo\n        ",
+        module.doc_comment_text().unwrap()
+    );
+}
+
+#[test]
+fn test_comments_preserve_trailing_whitespace() {
+    let file = SourceFile::parse(
+        "\n/// Representation of a Realm.   \n/// In the specification these are called Realm Records.\nstruct Realm {}",
+    )
+    .ok()
+    .unwrap();
+    let def = file.syntax().descendants().find_map(Struct::cast).unwrap();
+    assert_eq!(
+        "Representation of a Realm.   \nIn the specification these are called Realm Records.",
+        def.doc_comment_text().unwrap()
+    );
+}
+
+#[test]
+fn test_four_slash_line_comment() {
+    let file = SourceFile::parse(
+        r#"
+        //// too many slashes to be a doc comment
+        /// doc comment
+        mod foo {}
+        "#,
+    )
+    .ok()
+    .unwrap();
+    let module = file.syntax().descendants().find_map(Module::cast).unwrap();
+    assert_eq!("doc comment", module.doc_comment_text().unwrap());
+}
+
+#[test]
+fn test_where_predicates() {
+    fn assert_bound(text: &str, bound: Option<TypeBound>) {
+        assert_eq!(text, bound.unwrap().syntax().text().to_string());
+    }
+
+    let file = SourceFile::parse(
+        r#"
+fn foo()
+where
+   T: Clone + Copy + Debug + 'static,
+   'a: 'b + 'c,
+   Iterator::Item: 'a + Debug,
+   Iterator::Item: Debug + 'a,
+   <T as Iterator>::Item: Debug + 'a,
+   for<'a> F: Fn(&'a str)
+{}
+        "#,
+    )
+    .ok()
+    .unwrap();
+    let where_clause = file.syntax().descendants().find_map(WhereClause::cast).unwrap();
+
+    let mut predicates = where_clause.predicates();
+
+    let pred = predicates.next().unwrap();
+    let mut bounds = pred.type_bound_list().unwrap().bounds();
+
+    assert!(pred.for_token().is_none());
+    assert!(pred.generic_param_list().is_none());
+    assert_eq!("T", pred.ty().unwrap().syntax().text().to_string());
+    assert_bound("Clone", bounds.next());
+    assert_bound("Copy", bounds.next());
+    assert_bound("Debug", bounds.next());
+    assert_bound("'static", bounds.next());
+
+    let pred = predicates.next().unwrap();
+    let mut bounds = pred.type_bound_list().unwrap().bounds();
+
+    assert_eq!("'a", pred.lifetime_token().unwrap().text());
+
+    assert_bound("'b", bounds.next());
+    assert_bound("'c", bounds.next());
+
+    let pred = predicates.next().unwrap();
+    let mut bounds = pred.type_bound_list().unwrap().bounds();
+
+    assert_eq!("Iterator::Item", pred.ty().unwrap().syntax().text().to_string());
+    assert_bound("'a", bounds.next());
+
+    let pred = predicates.next().unwrap();
+    let mut bounds = pred.type_bound_list().unwrap().bounds();
+
+    assert_eq!("Iterator::Item", pred.ty().unwrap().syntax().text().to_string());
+    assert_bound("Debug", bounds.next());
+    assert_bound("'a", bounds.next());
+
+    let pred = predicates.next().unwrap();
+    let mut bounds = pred.type_bound_list().unwrap().bounds();
+
+    assert_eq!("<T as Iterator>::Item", pred.ty().unwrap().syntax().text().to_string());
+    assert_bound("Debug", bounds.next());
+    assert_bound("'a", bounds.next());
+
+    let pred = predicates.next().unwrap();
+    let mut bounds = pred.type_bound_list().unwrap().bounds();
+
+    assert!(pred.for_token().is_some());
+    assert_eq!("<'a>", pred.generic_param_list().unwrap().syntax().text().to_string());
+    assert_eq!("F", pred.ty().unwrap().syntax().text().to_string());
+    assert_bound("Fn(&'a str)", bounds.next());
+}
diff --git a/crates/syntax/src/ast/edit.rs b/crates/syntax/src/ast/edit.rs
new file mode 100644
index 00000000000..5ed123f91fe
--- /dev/null
+++ b/crates/syntax/src/ast/edit.rs
@@ -0,0 +1,642 @@
+//! This module contains functions for editing syntax trees. As the trees are
+//! immutable, all function here return a fresh copy of the tree, instead of
+//! doing an in-place modification.
+use std::{
+    fmt, iter,
+    ops::{self, RangeInclusive},
+};
+
+use arrayvec::ArrayVec;
+
+use crate::{
+    algo::{self, neighbor, SyntaxRewriter},
+    ast::{
+        self,
+        make::{self, tokens},
+        AstNode, TypeBoundsOwner,
+    },
+    AstToken, Direction, InsertPosition, SmolStr, SyntaxElement, SyntaxKind,
+    SyntaxKind::{ATTR, COMMENT, WHITESPACE},
+    SyntaxNode, SyntaxToken, T,
+};
+
+impl ast::BinExpr {
+    #[must_use]
+    pub fn replace_op(&self, op: SyntaxKind) -> Option<ast::BinExpr> {
+        let op_node: SyntaxElement = self.op_details()?.0.into();
+        let to_insert: Option<SyntaxElement> = Some(make::token(op).into());
+        Some(self.replace_children(single_node(op_node), to_insert))
+    }
+}
+
+impl ast::Fn {
+    #[must_use]
+    pub fn with_body(&self, body: ast::BlockExpr) -> ast::Fn {
+        let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new();
+        let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() {
+            old_body.syntax().clone().into()
+        } else if let Some(semi) = self.semicolon_token() {
+            to_insert.push(make::tokens::single_space().into());
+            semi.into()
+        } else {
+            to_insert.push(make::tokens::single_space().into());
+            to_insert.push(body.syntax().clone().into());
+            return self.insert_children(InsertPosition::Last, to_insert);
+        };
+        to_insert.push(body.syntax().clone().into());
+        self.replace_children(single_node(old_body_or_semi), to_insert)
+    }
+}
+
+fn make_multiline<N>(node: N) -> N
+where
+    N: AstNode + Clone,
+{
+    let l_curly = match node.syntax().children_with_tokens().find(|it| it.kind() == T!['{']) {
+        Some(it) => it,
+        None => return node,
+    };
+    let sibling = match l_curly.next_sibling_or_token() {
+        Some(it) => it,
+        None => return node,
+    };
+    let existing_ws = match sibling.as_token() {
+        None => None,
+        Some(tok) if tok.kind() != WHITESPACE => None,
+        Some(ws) => {
+            if ws.text().contains('\n') {
+                return node;
+            }
+            Some(ws.clone())
+        }
+    };
+
+    let indent = leading_indent(node.syntax()).unwrap_or_default();
+    let ws = tokens::WsBuilder::new(&format!("\n{}", indent));
+    let to_insert = iter::once(ws.ws().into());
+    match existing_ws {
+        None => node.insert_children(InsertPosition::After(l_curly), to_insert),
+        Some(ws) => node.replace_children(single_node(ws), to_insert),
+    }
+}
+
+impl ast::AssocItemList {
+    #[must_use]
+    pub fn append_items(
+        &self,
+        items: impl IntoIterator<Item = ast::AssocItem>,
+    ) -> ast::AssocItemList {
+        let mut res = self.clone();
+        if !self.syntax().text().contains_char('\n') {
+            res = make_multiline(res);
+        }
+        items.into_iter().for_each(|it| res = res.append_item(it));
+        res
+    }
+
+    #[must_use]
+    pub fn append_item(&self, item: ast::AssocItem) -> ast::AssocItemList {
+        let (indent, position) = match self.assoc_items().last() {
+            Some(it) => (
+                leading_indent(it.syntax()).unwrap_or_default().to_string(),
+                InsertPosition::After(it.syntax().clone().into()),
+            ),
+            None => match self.l_curly_token() {
+                Some(it) => (
+                    "    ".to_string() + &leading_indent(self.syntax()).unwrap_or_default(),
+                    InsertPosition::After(it.into()),
+                ),
+                None => return self.clone(),
+            },
+        };
+        let ws = tokens::WsBuilder::new(&format!("\n{}", indent));
+        let to_insert: ArrayVec<[SyntaxElement; 2]> =
+            [ws.ws().into(), item.syntax().clone().into()].into();
+        self.insert_children(position, to_insert)
+    }
+}
+
+impl ast::RecordExprFieldList {
+    #[must_use]
+    pub fn append_field(&self, field: &ast::RecordExprField) -> ast::RecordExprFieldList {
+        self.insert_field(InsertPosition::Last, field)
+    }
+
+    #[must_use]
+    pub fn insert_field(
+        &self,
+        position: InsertPosition<&'_ ast::RecordExprField>,
+        field: &ast::RecordExprField,
+    ) -> ast::RecordExprFieldList {
+        let is_multiline = self.syntax().text().contains_char('\n');
+        let ws;
+        let space = if is_multiline {
+            ws = tokens::WsBuilder::new(&format!(
+                "\n{}    ",
+                leading_indent(self.syntax()).unwrap_or_default()
+            ));
+            ws.ws()
+        } else {
+            tokens::single_space()
+        };
+
+        let mut to_insert: ArrayVec<[SyntaxElement; 4]> = ArrayVec::new();
+        to_insert.push(space.into());
+        to_insert.push(field.syntax().clone().into());
+        to_insert.push(make::token(T![,]).into());
+
+        macro_rules! after_l_curly {
+            () => {{
+                let anchor = match self.l_curly_token() {
+                    Some(it) => it.into(),
+                    None => return self.clone(),
+                };
+                InsertPosition::After(anchor)
+            }};
+        }
+
+        macro_rules! after_field {
+            ($anchor:expr) => {
+                if let Some(comma) = $anchor
+                    .syntax()
+                    .siblings_with_tokens(Direction::Next)
+                    .find(|it| it.kind() == T![,])
+                {
+                    InsertPosition::After(comma)
+                } else {
+                    to_insert.insert(0, make::token(T![,]).into());
+                    InsertPosition::After($anchor.syntax().clone().into())
+                }
+            };
+        };
+
+        let position = match position {
+            InsertPosition::First => after_l_curly!(),
+            InsertPosition::Last => {
+                if !is_multiline {
+                    // don't insert comma before curly
+                    to_insert.pop();
+                }
+                match self.fields().last() {
+                    Some(it) => after_field!(it),
+                    None => after_l_curly!(),
+                }
+            }
+            InsertPosition::Before(anchor) => {
+                InsertPosition::Before(anchor.syntax().clone().into())
+            }
+            InsertPosition::After(anchor) => after_field!(anchor),
+        };
+
+        self.insert_children(position, to_insert)
+    }
+}
+
+impl ast::TypeAlias {
+    #[must_use]
+    pub fn remove_bounds(&self) -> ast::TypeAlias {
+        let colon = match self.colon_token() {
+            Some(it) => it,
+            None => return self.clone(),
+        };
+        let end = match self.type_bound_list() {
+            Some(it) => it.syntax().clone().into(),
+            None => colon.clone().into(),
+        };
+        self.replace_children(colon.into()..=end, iter::empty())
+    }
+}
+
+impl ast::TypeParam {
+    #[must_use]
+    pub fn remove_bounds(&self) -> ast::TypeParam {
+        let colon = match self.colon_token() {
+            Some(it) => it,
+            None => return self.clone(),
+        };
+        let end = match self.type_bound_list() {
+            Some(it) => it.syntax().clone().into(),
+            None => colon.clone().into(),
+        };
+        self.replace_children(colon.into()..=end, iter::empty())
+    }
+}
+
+impl ast::Path {
+    #[must_use]
+    pub fn with_segment(&self, segment: ast::PathSegment) -> ast::Path {
+        if let Some(old) = self.segment() {
+            return self.replace_children(
+                single_node(old.syntax().clone()),
+                iter::once(segment.syntax().clone().into()),
+            );
+        }
+        self.clone()
+    }
+}
+
+impl ast::PathSegment {
+    #[must_use]
+    pub fn with_type_args(&self, type_args: ast::GenericArgList) -> ast::PathSegment {
+        self._with_type_args(type_args, false)
+    }
+
+    #[must_use]
+    pub fn with_turbo_fish(&self, type_args: ast::GenericArgList) -> ast::PathSegment {
+        self._with_type_args(type_args, true)
+    }
+
+    fn _with_type_args(&self, type_args: ast::GenericArgList, turbo: bool) -> ast::PathSegment {
+        if let Some(old) = self.generic_arg_list() {
+            return self.replace_children(
+                single_node(old.syntax().clone()),
+                iter::once(type_args.syntax().clone().into()),
+            );
+        }
+        let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new();
+        if turbo {
+            to_insert.push(make::token(T![::]).into());
+        }
+        to_insert.push(type_args.syntax().clone().into());
+        self.insert_children(InsertPosition::Last, to_insert)
+    }
+}
+
+impl ast::Use {
+    #[must_use]
+    pub fn with_use_tree(&self, use_tree: ast::UseTree) -> ast::Use {
+        if let Some(old) = self.use_tree() {
+            return self.replace_descendant(old, use_tree);
+        }
+        self.clone()
+    }
+
+    pub fn remove(&self) -> SyntaxRewriter<'static> {
+        let mut res = SyntaxRewriter::default();
+        res.delete(self.syntax());
+        let next_ws = self
+            .syntax()
+            .next_sibling_or_token()
+            .and_then(|it| it.into_token())
+            .and_then(ast::Whitespace::cast);
+        if let Some(next_ws) = next_ws {
+            let ws_text = next_ws.syntax().text();
+            if ws_text.starts_with('\n') {
+                let rest = &ws_text[1..];
+                if rest.is_empty() {
+                    res.delete(next_ws.syntax())
+                } else {
+                    res.replace(next_ws.syntax(), &make::tokens::whitespace(rest));
+                }
+            }
+        }
+        res
+    }
+}
+
+impl ast::UseTree {
+    #[must_use]
+    pub fn with_path(&self, path: ast::Path) -> ast::UseTree {
+        if let Some(old) = self.path() {
+            return self.replace_descendant(old, path);
+        }
+        self.clone()
+    }
+
+    #[must_use]
+    pub fn with_use_tree_list(&self, use_tree_list: ast::UseTreeList) -> ast::UseTree {
+        if let Some(old) = self.use_tree_list() {
+            return self.replace_descendant(old, use_tree_list);
+        }
+        self.clone()
+    }
+
+    #[must_use]
+    pub fn split_prefix(&self, prefix: &ast::Path) -> ast::UseTree {
+        let suffix = match split_path_prefix(&prefix) {
+            Some(it) => it,
+            None => return self.clone(),
+        };
+        let use_tree = make::use_tree(
+            suffix,
+            self.use_tree_list(),
+            self.rename(),
+            self.star_token().is_some(),
+        );
+        let nested = make::use_tree_list(iter::once(use_tree));
+        return make::use_tree(prefix.clone(), Some(nested), None, false);
+
+        fn split_path_prefix(prefix: &ast::Path) -> Option<ast::Path> {
+            let parent = prefix.parent_path()?;
+            let segment = parent.segment()?;
+            if algo::has_errors(segment.syntax()) {
+                return None;
+            }
+            let mut res = make::path_unqualified(segment);
+            for p in iter::successors(parent.parent_path(), |it| it.parent_path()) {
+                res = make::path_qualified(res, p.segment()?);
+            }
+            Some(res)
+        }
+    }
+
+    pub fn remove(&self) -> SyntaxRewriter<'static> {
+        let mut res = SyntaxRewriter::default();
+        res.delete(self.syntax());
+        for &dir in [Direction::Next, Direction::Prev].iter() {
+            if let Some(nb) = neighbor(self, dir) {
+                self.syntax()
+                    .siblings_with_tokens(dir)
+                    .skip(1)
+                    .take_while(|it| it.as_node() != Some(nb.syntax()))
+                    .for_each(|el| res.delete(&el));
+                return res;
+            }
+        }
+        res
+    }
+}
+
+impl ast::MatchArmList {
+    #[must_use]
+    pub fn append_arms(&self, items: impl IntoIterator<Item = ast::MatchArm>) -> ast::MatchArmList {
+        let mut res = self.clone();
+        res = res.strip_if_only_whitespace();
+        if !res.syntax().text().contains_char('\n') {
+            res = make_multiline(res);
+        }
+        items.into_iter().for_each(|it| res = res.append_arm(it));
+        res
+    }
+
+    fn strip_if_only_whitespace(&self) -> ast::MatchArmList {
+        let mut iter = self.syntax().children_with_tokens().skip_while(|it| it.kind() != T!['{']);
+        iter.next(); // Eat the curly
+        let mut inner = iter.take_while(|it| it.kind() != T!['}']);
+        if !inner.clone().all(|it| it.kind() == WHITESPACE) {
+            return self.clone();
+        }
+        let start = match inner.next() {
+            Some(s) => s,
+            None => return self.clone(),
+        };
+        let end = match inner.last() {
+            Some(s) => s,
+            None => start.clone(),
+        };
+        self.replace_children(start..=end, &mut iter::empty())
+    }
+
+    #[must_use]
+    pub fn remove_placeholder(&self) -> ast::MatchArmList {
+        let placeholder =
+            self.arms().find(|arm| matches!(arm.pat(), Some(ast::Pat::WildcardPat(_))));
+        if let Some(placeholder) = placeholder {
+            self.remove_arm(&placeholder)
+        } else {
+            self.clone()
+        }
+    }
+
+    #[must_use]
+    fn remove_arm(&self, arm: &ast::MatchArm) -> ast::MatchArmList {
+        let start = arm.syntax().clone();
+        let end = if let Some(comma) = start
+            .siblings_with_tokens(Direction::Next)
+            .skip(1)
+            .skip_while(|it| it.kind().is_trivia())
+            .next()
+            .filter(|it| it.kind() == T![,])
+        {
+            comma
+        } else {
+            start.clone().into()
+        };
+        self.replace_children(start.into()..=end, None)
+    }
+
+    #[must_use]
+    pub fn append_arm(&self, item: ast::MatchArm) -> ast::MatchArmList {
+        let r_curly = match self.syntax().children_with_tokens().find(|it| it.kind() == T!['}']) {
+            Some(t) => t,
+            None => return self.clone(),
+        };
+        let position = InsertPosition::Before(r_curly.into());
+        let arm_ws = tokens::WsBuilder::new("    ");
+        let match_indent = &leading_indent(self.syntax()).unwrap_or_default();
+        let match_ws = tokens::WsBuilder::new(&format!("\n{}", match_indent));
+        let to_insert: ArrayVec<[SyntaxElement; 3]> =
+            [arm_ws.ws().into(), item.syntax().clone().into(), match_ws.ws().into()].into();
+        self.insert_children(position, to_insert)
+    }
+}
+
+#[must_use]
+pub fn remove_attrs_and_docs<N: ast::AttrsOwner>(node: &N) -> N {
+    N::cast(remove_attrs_and_docs_inner(node.syntax().clone())).unwrap()
+}
+
+fn remove_attrs_and_docs_inner(mut node: SyntaxNode) -> SyntaxNode {
+    while let Some(start) =
+        node.children_with_tokens().find(|it| it.kind() == ATTR || it.kind() == COMMENT)
+    {
+        let end = match &start.next_sibling_or_token() {
+            Some(el) if el.kind() == WHITESPACE => el.clone(),
+            Some(_) | None => start.clone(),
+        };
+        node = algo::replace_children(&node, start..=end, &mut iter::empty());
+    }
+    node
+}
+
+#[derive(Debug, Clone, Copy)]
+pub struct IndentLevel(pub u8);
+
+impl From<u8> for IndentLevel {
+    fn from(level: u8) -> IndentLevel {
+        IndentLevel(level)
+    }
+}
+
+impl fmt::Display for IndentLevel {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let spaces = "                                        ";
+        let buf;
+        let len = self.0 as usize * 4;
+        let indent = if len <= spaces.len() {
+            &spaces[..len]
+        } else {
+            buf = iter::repeat(' ').take(len).collect::<String>();
+            &buf
+        };
+        fmt::Display::fmt(indent, f)
+    }
+}
+
+impl ops::Add<u8> for IndentLevel {
+    type Output = IndentLevel;
+    fn add(self, rhs: u8) -> IndentLevel {
+        IndentLevel(self.0 + rhs)
+    }
+}
+
+impl IndentLevel {
+    pub fn from_node(node: &SyntaxNode) -> IndentLevel {
+        let first_token = match node.first_token() {
+            Some(it) => it,
+            None => return IndentLevel(0),
+        };
+        for ws in prev_tokens(first_token).filter_map(ast::Whitespace::cast) {
+            let text = ws.syntax().text();
+            if let Some(pos) = text.rfind('\n') {
+                let level = text[pos + 1..].chars().count() / 4;
+                return IndentLevel(level as u8);
+            }
+        }
+        IndentLevel(0)
+    }
+
+    /// XXX: this intentionally doesn't change the indent of the very first token.
+    /// Ie, in something like
+    /// ```
+    /// fn foo() {
+    ///    92
+    /// }
+    /// ```
+    /// if you indent the block, the `{` token would stay put.
+    fn increase_indent(self, node: SyntaxNode) -> SyntaxNode {
+        let mut rewriter = SyntaxRewriter::default();
+        node.descendants_with_tokens()
+            .filter_map(|el| el.into_token())
+            .filter_map(ast::Whitespace::cast)
+            .filter(|ws| {
+                let text = ws.syntax().text();
+                text.contains('\n')
+            })
+            .for_each(|ws| {
+                let new_ws = make::tokens::whitespace(&format!("{}{}", ws.syntax(), self,));
+                rewriter.replace(ws.syntax(), &new_ws)
+            });
+        rewriter.rewrite(&node)
+    }
+
+    fn decrease_indent(self, node: SyntaxNode) -> SyntaxNode {
+        let mut rewriter = SyntaxRewriter::default();
+        node.descendants_with_tokens()
+            .filter_map(|el| el.into_token())
+            .filter_map(ast::Whitespace::cast)
+            .filter(|ws| {
+                let text = ws.syntax().text();
+                text.contains('\n')
+            })
+            .for_each(|ws| {
+                let new_ws = make::tokens::whitespace(
+                    &ws.syntax().text().replace(&format!("\n{}", self), "\n"),
+                );
+                rewriter.replace(ws.syntax(), &new_ws)
+            });
+        rewriter.rewrite(&node)
+    }
+}
+
+// FIXME: replace usages with IndentLevel above
+fn leading_indent(node: &SyntaxNode) -> Option<SmolStr> {
+    for token in prev_tokens(node.first_token()?) {
+        if let Some(ws) = ast::Whitespace::cast(token.clone()) {
+            let ws_text = ws.text();
+            if let Some(pos) = ws_text.rfind('\n') {
+                return Some(ws_text[pos + 1..].into());
+            }
+        }
+        if token.text().contains('\n') {
+            break;
+        }
+    }
+    None
+}
+
+fn prev_tokens(token: SyntaxToken) -> impl Iterator<Item = SyntaxToken> {
+    iter::successors(Some(token), |token| token.prev_token())
+}
+
+pub trait AstNodeEdit: AstNode + Clone + Sized {
+    #[must_use]
+    fn insert_children(
+        &self,
+        position: InsertPosition<SyntaxElement>,
+        to_insert: impl IntoIterator<Item = SyntaxElement>,
+    ) -> Self {
+        let new_syntax = algo::insert_children(self.syntax(), position, to_insert);
+        Self::cast(new_syntax).unwrap()
+    }
+
+    #[must_use]
+    fn replace_children(
+        &self,
+        to_replace: RangeInclusive<SyntaxElement>,
+        to_insert: impl IntoIterator<Item = SyntaxElement>,
+    ) -> Self {
+        let new_syntax = algo::replace_children(self.syntax(), to_replace, to_insert);
+        Self::cast(new_syntax).unwrap()
+    }
+
+    #[must_use]
+    fn replace_descendant<D: AstNode>(&self, old: D, new: D) -> Self {
+        self.replace_descendants(iter::once((old, new)))
+    }
+
+    #[must_use]
+    fn replace_descendants<D: AstNode>(
+        &self,
+        replacement_map: impl IntoIterator<Item = (D, D)>,
+    ) -> Self {
+        let mut rewriter = SyntaxRewriter::default();
+        for (from, to) in replacement_map {
+            rewriter.replace(from.syntax(), to.syntax())
+        }
+        rewriter.rewrite_ast(self)
+    }
+    #[must_use]
+    fn indent(&self, level: IndentLevel) -> Self {
+        Self::cast(level.increase_indent(self.syntax().clone())).unwrap()
+    }
+    #[must_use]
+    fn dedent(&self, level: IndentLevel) -> Self {
+        Self::cast(level.decrease_indent(self.syntax().clone())).unwrap()
+    }
+    #[must_use]
+    fn reset_indent(&self) -> Self {
+        let level = IndentLevel::from_node(self.syntax());
+        self.dedent(level)
+    }
+}
+
+impl<N: AstNode + Clone> AstNodeEdit for N {}
+
+fn single_node(element: impl Into<SyntaxElement>) -> RangeInclusive<SyntaxElement> {
+    let element = element.into();
+    element.clone()..=element
+}
+
+#[test]
+fn test_increase_indent() {
+    let arm_list = {
+        let arm = make::match_arm(iter::once(make::wildcard_pat().into()), make::expr_unit());
+        make::match_arm_list(vec![arm.clone(), arm])
+    };
+    assert_eq!(
+        arm_list.syntax().to_string(),
+        "{
+    _ => (),
+    _ => (),
+}"
+    );
+    let indented = arm_list.indent(IndentLevel(2));
+    assert_eq!(
+        indented.syntax().to_string(),
+        "{
+            _ => (),
+            _ => (),
+        }"
+    );
+}
diff --git a/crates/syntax/src/ast/expr_ext.rs b/crates/syntax/src/ast/expr_ext.rs
new file mode 100644
index 00000000000..f5ba872233f
--- /dev/null
+++ b/crates/syntax/src/ast/expr_ext.rs
@@ -0,0 +1,418 @@
+//! Various extension methods to ast Expr Nodes, which are hard to code-generate.
+
+use crate::{
+    ast::{self, support, AstChildren, AstNode},
+    SmolStr,
+    SyntaxKind::*,
+    SyntaxToken, T,
+};
+
+impl ast::AttrsOwner for ast::Expr {}
+
+impl ast::Expr {
+    pub fn is_block_like(&self) -> bool {
+        match self {
+            ast::Expr::IfExpr(_)
+            | ast::Expr::LoopExpr(_)
+            | ast::Expr::ForExpr(_)
+            | ast::Expr::WhileExpr(_)
+            | ast::Expr::BlockExpr(_)
+            | ast::Expr::MatchExpr(_)
+            | ast::Expr::EffectExpr(_) => true,
+            _ => false,
+        }
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum ElseBranch {
+    Block(ast::BlockExpr),
+    IfExpr(ast::IfExpr),
+}
+
+impl ast::IfExpr {
+    pub fn then_branch(&self) -> Option<ast::BlockExpr> {
+        self.blocks().next()
+    }
+    pub fn else_branch(&self) -> Option<ElseBranch> {
+        let res = match self.blocks().nth(1) {
+            Some(block) => ElseBranch::Block(block),
+            None => {
+                let elif: ast::IfExpr = support::child(self.syntax())?;
+                ElseBranch::IfExpr(elif)
+            }
+        };
+        Some(res)
+    }
+
+    pub fn blocks(&self) -> AstChildren<ast::BlockExpr> {
+        support::children(self.syntax())
+    }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub enum PrefixOp {
+    /// The `*` operator for dereferencing
+    Deref,
+    /// The `!` operator for logical inversion
+    Not,
+    /// The `-` operator for negation
+    Neg,
+}
+
+impl ast::PrefixExpr {
+    pub fn op_kind(&self) -> Option<PrefixOp> {
+        match self.op_token()?.kind() {
+            T![*] => Some(PrefixOp::Deref),
+            T![!] => Some(PrefixOp::Not),
+            T![-] => Some(PrefixOp::Neg),
+            _ => None,
+        }
+    }
+
+    pub fn op_token(&self) -> Option<SyntaxToken> {
+        self.syntax().first_child_or_token()?.into_token()
+    }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub enum BinOp {
+    /// The `||` operator for boolean OR
+    BooleanOr,
+    /// The `&&` operator for boolean AND
+    BooleanAnd,
+    /// The `==` operator for equality testing
+    EqualityTest,
+    /// The `!=` operator for equality testing
+    NegatedEqualityTest,
+    /// The `<=` operator for lesser-equal testing
+    LesserEqualTest,
+    /// The `>=` operator for greater-equal testing
+    GreaterEqualTest,
+    /// The `<` operator for comparison
+    LesserTest,
+    /// The `>` operator for comparison
+    GreaterTest,
+    /// The `+` operator for addition
+    Addition,
+    /// The `*` operator for multiplication
+    Multiplication,
+    /// The `-` operator for subtraction
+    Subtraction,
+    /// The `/` operator for division
+    Division,
+    /// The `%` operator for remainder after division
+    Remainder,
+    /// The `<<` operator for left shift
+    LeftShift,
+    /// The `>>` operator for right shift
+    RightShift,
+    /// The `^` operator for bitwise XOR
+    BitwiseXor,
+    /// The `|` operator for bitwise OR
+    BitwiseOr,
+    /// The `&` operator for bitwise AND
+    BitwiseAnd,
+    /// The `=` operator for assignment
+    Assignment,
+    /// The `+=` operator for assignment after addition
+    AddAssign,
+    /// The `/=` operator for assignment after division
+    DivAssign,
+    /// The `*=` operator for assignment after multiplication
+    MulAssign,
+    /// The `%=` operator for assignment after remainders
+    RemAssign,
+    /// The `>>=` operator for assignment after shifting right
+    ShrAssign,
+    /// The `<<=` operator for assignment after shifting left
+    ShlAssign,
+    /// The `-=` operator for assignment after subtraction
+    SubAssign,
+    /// The `|=` operator for assignment after bitwise OR
+    BitOrAssign,
+    /// The `&=` operator for assignment after bitwise AND
+    BitAndAssign,
+    /// The `^=` operator for assignment after bitwise XOR
+    BitXorAssign,
+}
+
+impl BinOp {
+    pub fn is_assignment(self) -> bool {
+        match self {
+            BinOp::Assignment
+            | BinOp::AddAssign
+            | BinOp::DivAssign
+            | BinOp::MulAssign
+            | BinOp::RemAssign
+            | BinOp::ShrAssign
+            | BinOp::ShlAssign
+            | BinOp::SubAssign
+            | BinOp::BitOrAssign
+            | BinOp::BitAndAssign
+            | BinOp::BitXorAssign => true,
+            _ => false,
+        }
+    }
+}
+
+impl ast::BinExpr {
+    pub fn op_details(&self) -> Option<(SyntaxToken, BinOp)> {
+        self.syntax().children_with_tokens().filter_map(|it| it.into_token()).find_map(|c| {
+            let bin_op = match c.kind() {
+                T![||] => BinOp::BooleanOr,
+                T![&&] => BinOp::BooleanAnd,
+                T![==] => BinOp::EqualityTest,
+                T![!=] => BinOp::NegatedEqualityTest,
+                T![<=] => BinOp::LesserEqualTest,
+                T![>=] => BinOp::GreaterEqualTest,
+                T![<] => BinOp::LesserTest,
+                T![>] => BinOp::GreaterTest,
+                T![+] => BinOp::Addition,
+                T![*] => BinOp::Multiplication,
+                T![-] => BinOp::Subtraction,
+                T![/] => BinOp::Division,
+                T![%] => BinOp::Remainder,
+                T![<<] => BinOp::LeftShift,
+                T![>>] => BinOp::RightShift,
+                T![^] => BinOp::BitwiseXor,
+                T![|] => BinOp::BitwiseOr,
+                T![&] => BinOp::BitwiseAnd,
+                T![=] => BinOp::Assignment,
+                T![+=] => BinOp::AddAssign,
+                T![/=] => BinOp::DivAssign,
+                T![*=] => BinOp::MulAssign,
+                T![%=] => BinOp::RemAssign,
+                T![>>=] => BinOp::ShrAssign,
+                T![<<=] => BinOp::ShlAssign,
+                T![-=] => BinOp::SubAssign,
+                T![|=] => BinOp::BitOrAssign,
+                T![&=] => BinOp::BitAndAssign,
+                T![^=] => BinOp::BitXorAssign,
+                _ => return None,
+            };
+            Some((c, bin_op))
+        })
+    }
+
+    pub fn op_kind(&self) -> Option<BinOp> {
+        self.op_details().map(|t| t.1)
+    }
+
+    pub fn op_token(&self) -> Option<SyntaxToken> {
+        self.op_details().map(|t| t.0)
+    }
+
+    pub fn lhs(&self) -> Option<ast::Expr> {
+        support::children(self.syntax()).next()
+    }
+
+    pub fn rhs(&self) -> Option<ast::Expr> {
+        support::children(self.syntax()).nth(1)
+    }
+
+    pub fn sub_exprs(&self) -> (Option<ast::Expr>, Option<ast::Expr>) {
+        let mut children = support::children(self.syntax());
+        let first = children.next();
+        let second = children.next();
+        (first, second)
+    }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub enum RangeOp {
+    /// `..`
+    Exclusive,
+    /// `..=`
+    Inclusive,
+}
+
+impl ast::RangeExpr {
+    fn op_details(&self) -> Option<(usize, SyntaxToken, RangeOp)> {
+        self.syntax().children_with_tokens().enumerate().find_map(|(ix, child)| {
+            let token = child.into_token()?;
+            let bin_op = match token.kind() {
+                T![..] => RangeOp::Exclusive,
+                T![..=] => RangeOp::Inclusive,
+                _ => return None,
+            };
+            Some((ix, token, bin_op))
+        })
+    }
+
+    pub fn op_kind(&self) -> Option<RangeOp> {
+        self.op_details().map(|t| t.2)
+    }
+
+    pub fn op_token(&self) -> Option<SyntaxToken> {
+        self.op_details().map(|t| t.1)
+    }
+
+    pub fn start(&self) -> Option<ast::Expr> {
+        let op_ix = self.op_details()?.0;
+        self.syntax()
+            .children_with_tokens()
+            .take(op_ix)
+            .find_map(|it| ast::Expr::cast(it.into_node()?))
+    }
+
+    pub fn end(&self) -> Option<ast::Expr> {
+        let op_ix = self.op_details()?.0;
+        self.syntax()
+            .children_with_tokens()
+            .skip(op_ix + 1)
+            .find_map(|it| ast::Expr::cast(it.into_node()?))
+    }
+}
+
+impl ast::IndexExpr {
+    pub fn base(&self) -> Option<ast::Expr> {
+        support::children(self.syntax()).next()
+    }
+    pub fn index(&self) -> Option<ast::Expr> {
+        support::children(self.syntax()).nth(1)
+    }
+}
+
+pub enum ArrayExprKind {
+    Repeat { initializer: Option<ast::Expr>, repeat: Option<ast::Expr> },
+    ElementList(AstChildren<ast::Expr>),
+}
+
+impl ast::ArrayExpr {
+    pub fn kind(&self) -> ArrayExprKind {
+        if self.is_repeat() {
+            ArrayExprKind::Repeat {
+                initializer: support::children(self.syntax()).next(),
+                repeat: support::children(self.syntax()).nth(1),
+            }
+        } else {
+            ArrayExprKind::ElementList(support::children(self.syntax()))
+        }
+    }
+
+    fn is_repeat(&self) -> bool {
+        self.syntax().children_with_tokens().any(|it| it.kind() == T![;])
+    }
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub enum LiteralKind {
+    String,
+    ByteString,
+    Char,
+    Byte,
+    IntNumber { suffix: Option<SmolStr> },
+    FloatNumber { suffix: Option<SmolStr> },
+    Bool(bool),
+}
+
+impl ast::Literal {
+    pub fn token(&self) -> SyntaxToken {
+        self.syntax()
+            .children_with_tokens()
+            .find(|e| e.kind() != ATTR && !e.kind().is_trivia())
+            .and_then(|e| e.into_token())
+            .unwrap()
+    }
+
+    fn find_suffix(text: &str, possible_suffixes: &[&str]) -> Option<SmolStr> {
+        possible_suffixes
+            .iter()
+            .find(|&suffix| text.ends_with(suffix))
+            .map(|&suffix| SmolStr::new(suffix))
+    }
+
+    pub fn kind(&self) -> LiteralKind {
+        const INT_SUFFIXES: [&str; 12] = [
+            "u64", "u32", "u16", "u8", "usize", "isize", "i64", "i32", "i16", "i8", "u128", "i128",
+        ];
+        const FLOAT_SUFFIXES: [&str; 2] = ["f32", "f64"];
+
+        let token = self.token();
+
+        match token.kind() {
+            INT_NUMBER => {
+                // FYI: there was a bug here previously, thus the if statement below is necessary.
+                // The lexer treats e.g. `1f64` as an integer literal. See
+                // https://github.com/rust-analyzer/rust-analyzer/issues/1592
+                // and the comments on the linked PR.
+
+                let text = token.text();
+                if let suffix @ Some(_) = Self::find_suffix(&text, &FLOAT_SUFFIXES) {
+                    LiteralKind::FloatNumber { suffix }
+                } else {
+                    LiteralKind::IntNumber { suffix: Self::find_suffix(&text, &INT_SUFFIXES) }
+                }
+            }
+            FLOAT_NUMBER => {
+                let text = token.text();
+                LiteralKind::FloatNumber { suffix: Self::find_suffix(&text, &FLOAT_SUFFIXES) }
+            }
+            STRING | RAW_STRING => LiteralKind::String,
+            T![true] => LiteralKind::Bool(true),
+            T![false] => LiteralKind::Bool(false),
+            BYTE_STRING | RAW_BYTE_STRING => LiteralKind::ByteString,
+            CHAR => LiteralKind::Char,
+            BYTE => LiteralKind::Byte,
+            _ => unreachable!(),
+        }
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum Effect {
+    Async(SyntaxToken),
+    Unsafe(SyntaxToken),
+    Try(SyntaxToken),
+    // Very much not an effect, but we stuff it into this node anyway
+    Label(ast::Label),
+}
+
+impl ast::EffectExpr {
+    pub fn effect(&self) -> Effect {
+        if let Some(token) = self.async_token() {
+            return Effect::Async(token);
+        }
+        if let Some(token) = self.unsafe_token() {
+            return Effect::Unsafe(token);
+        }
+        if let Some(token) = self.try_token() {
+            return Effect::Try(token);
+        }
+        if let Some(label) = self.label() {
+            return Effect::Label(label);
+        }
+        unreachable!("ast::EffectExpr without Effect")
+    }
+}
+
+impl ast::BlockExpr {
+    /// false if the block is an intrinsic part of the syntax and can't be
+    /// replaced with arbitrary expression.
+    ///
+    /// ```not_rust
+    /// fn foo() { not_stand_alone }
+    /// const FOO: () = { stand_alone };
+    /// ```
+    pub fn is_standalone(&self) -> bool {
+        let parent = match self.syntax().parent() {
+            Some(it) => it,
+            None => return true,
+        };
+        !matches!(parent.kind(), FN | IF_EXPR | WHILE_EXPR | LOOP_EXPR | EFFECT_EXPR)
+    }
+}
+
+#[test]
+fn test_literal_with_attr() {
+    let parse = ast::SourceFile::parse(r#"const _: &str = { #[attr] "Hello" };"#);
+    let lit = parse.tree().syntax().descendants().find_map(ast::Literal::cast).unwrap();
+    assert_eq!(lit.token().text(), r#""Hello""#);
+}
+
+impl ast::RecordExprField {
+    pub fn parent_record_lit(&self) -> ast::RecordExpr {
+        self.syntax().ancestors().find_map(ast::RecordExpr::cast).unwrap()
+    }
+}
diff --git a/crates/syntax/src/ast/generated.rs b/crates/syntax/src/ast/generated.rs
new file mode 100644
index 00000000000..4a6f41ee71f
--- /dev/null
+++ b/crates/syntax/src/ast/generated.rs
@@ -0,0 +1,41 @@
+//! This file is actually hand-written, but the submodules are indeed generated.
+#[rustfmt::skip]
+mod nodes;
+#[rustfmt::skip]
+mod tokens;
+
+use crate::{
+    AstNode,
+    SyntaxKind::{self, *},
+    SyntaxNode,
+};
+
+pub use {nodes::*, tokens::*};
+
+// Stmt is the only nested enum, so it's easier to just hand-write it
+impl AstNode for Stmt {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        match kind {
+            LET_STMT | EXPR_STMT => true,
+            _ => Item::can_cast(kind),
+        }
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        let res = match syntax.kind() {
+            LET_STMT => Stmt::LetStmt(LetStmt { syntax }),
+            EXPR_STMT => Stmt::ExprStmt(ExprStmt { syntax }),
+            _ => {
+                let item = Item::cast(syntax)?;
+                Stmt::Item(item)
+            }
+        };
+        Some(res)
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        match self {
+            Stmt::LetStmt(it) => &it.syntax,
+            Stmt::ExprStmt(it) => &it.syntax,
+            Stmt::Item(it) => it.syntax(),
+        }
+    }
+}
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
new file mode 100644
index 00000000000..3d49309d148
--- /dev/null
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -0,0 +1,4067 @@
+//! Generated file, do not edit by hand, see `xtask/src/codegen`
+
+use crate::{
+    ast::{self, support, AstChildren, AstNode},
+    SyntaxKind::{self, *},
+    SyntaxNode, SyntaxToken, T,
+};
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Name {
+    pub(crate) syntax: SyntaxNode,
+}
+impl Name {
+    pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct NameRef {
+    pub(crate) syntax: SyntaxNode,
+}
+impl NameRef {
+    pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Path {
+    pub(crate) syntax: SyntaxNode,
+}
+impl Path {
+    pub fn qualifier(&self) -> Option<Path> { support::child(&self.syntax) }
+    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
+    pub fn segment(&self) -> Option<PathSegment> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct PathSegment {
+    pub(crate) syntax: SyntaxNode,
+}
+impl PathSegment {
+    pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
+    pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
+    pub fn super_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![super]) }
+    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
+    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
+    pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) }
+    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
+    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
+    pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
+    pub fn path_type(&self) -> Option<PathType> { support::child(&self.syntax) }
+    pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
+    pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct GenericArgList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl GenericArgList {
+    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
+    pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
+    pub fn generic_args(&self) -> AstChildren<GenericArg> { support::children(&self.syntax) }
+    pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ParamList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ParamList {
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn self_param(&self) -> Option<SelfParam> { support::child(&self.syntax) }
+    pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
+    pub fn params(&self) -> AstChildren<Param> { support::children(&self.syntax) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct RetType {
+    pub(crate) syntax: SyntaxNode,
+}
+impl RetType {
+    pub fn thin_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![->]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct PathType {
+    pub(crate) syntax: SyntaxNode,
+}
+impl PathType {
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct TypeArg {
+    pub(crate) syntax: SyntaxNode,
+}
+impl TypeArg {
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct AssocTypeArg {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::TypeBoundsOwner for AssocTypeArg {}
+impl AssocTypeArg {
+    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct LifetimeArg {
+    pub(crate) syntax: SyntaxNode,
+}
+impl LifetimeArg {
+    pub fn lifetime_token(&self) -> Option<SyntaxToken> {
+        support::token(&self.syntax, T![lifetime])
+    }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ConstArg {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ConstArg {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct TypeBoundList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl TypeBoundList {
+    pub fn bounds(&self) -> AstChildren<TypeBound> { support::children(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct MacroCall {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for MacroCall {}
+impl ast::NameOwner for MacroCall {}
+impl MacroCall {
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
+    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
+    pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Attr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl Attr {
+    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
+    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
+    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) }
+    pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
+    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct TokenTree {
+    pub(crate) syntax: SyntaxNode,
+}
+impl TokenTree {
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
+    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct MacroItems {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::ModuleItemOwner for MacroItems {}
+impl MacroItems {}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct MacroStmts {
+    pub(crate) syntax: SyntaxNode,
+}
+impl MacroStmts {
+    pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct SourceFile {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for SourceFile {}
+impl ast::ModuleItemOwner for SourceFile {}
+impl SourceFile {
+    pub fn shebang_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![shebang]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Const {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for Const {}
+impl ast::NameOwner for Const {}
+impl ast::VisibilityOwner for Const {}
+impl Const {
+    pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
+    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Enum {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for Enum {}
+impl ast::NameOwner for Enum {}
+impl ast::VisibilityOwner for Enum {}
+impl ast::GenericParamsOwner for Enum {}
+impl Enum {
+    pub fn enum_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![enum]) }
+    pub fn variant_list(&self) -> Option<VariantList> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ExternBlock {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for ExternBlock {}
+impl ExternBlock {
+    pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) }
+    pub fn extern_item_list(&self) -> Option<ExternItemList> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ExternCrate {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for ExternCrate {}
+impl ast::VisibilityOwner for ExternCrate {}
+impl ExternCrate {
+    pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) }
+    pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
+    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
+    pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
+    pub fn rename(&self) -> Option<Rename> { support::child(&self.syntax) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Fn {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for Fn {}
+impl ast::NameOwner for Fn {}
+impl ast::VisibilityOwner for Fn {}
+impl ast::GenericParamsOwner for Fn {}
+impl Fn {
+    pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
+    pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
+    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
+    pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) }
+    pub fn fn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![fn]) }
+    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
+    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
+    pub fn body(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Impl {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for Impl {}
+impl ast::VisibilityOwner for Impl {}
+impl ast::GenericParamsOwner for Impl {}
+impl Impl {
+    pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
+    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
+    pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) }
+    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
+    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
+    pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Module {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for Module {}
+impl ast::NameOwner for Module {}
+impl ast::VisibilityOwner for Module {}
+impl Module {
+    pub fn mod_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mod]) }
+    pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Static {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for Static {}
+impl ast::NameOwner for Static {}
+impl ast::VisibilityOwner for Static {}
+impl Static {
+    pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) }
+    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Struct {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for Struct {}
+impl ast::NameOwner for Struct {}
+impl ast::VisibilityOwner for Struct {}
+impl ast::GenericParamsOwner for Struct {}
+impl Struct {
+    pub fn struct_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![struct]) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+    pub fn field_list(&self) -> Option<FieldList> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Trait {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for Trait {}
+impl ast::NameOwner for Trait {}
+impl ast::VisibilityOwner for Trait {}
+impl ast::GenericParamsOwner for Trait {}
+impl ast::TypeBoundsOwner for Trait {}
+impl Trait {
+    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
+    pub fn auto_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![auto]) }
+    pub fn trait_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![trait]) }
+    pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct TypeAlias {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for TypeAlias {}
+impl ast::NameOwner for TypeAlias {}
+impl ast::VisibilityOwner for TypeAlias {}
+impl ast::GenericParamsOwner for TypeAlias {}
+impl ast::TypeBoundsOwner for TypeAlias {}
+impl TypeAlias {
+    pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
+    pub fn type_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![type]) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Union {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for Union {}
+impl ast::NameOwner for Union {}
+impl ast::VisibilityOwner for Union {}
+impl ast::GenericParamsOwner for Union {}
+impl Union {
+    pub fn union_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![union]) }
+    pub fn record_field_list(&self) -> Option<RecordFieldList> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Use {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for Use {}
+impl ast::VisibilityOwner for Use {}
+impl Use {
+    pub fn use_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![use]) }
+    pub fn use_tree(&self) -> Option<UseTree> { support::child(&self.syntax) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Visibility {
+    pub(crate) syntax: SyntaxNode,
+}
+impl Visibility {
+    pub fn pub_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![pub]) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn super_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![super]) }
+    pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
+    pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
+    pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) }
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ItemList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for ItemList {}
+impl ast::ModuleItemOwner for ItemList {}
+impl ItemList {
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Rename {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::NameOwner for Rename {}
+impl Rename {
+    pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
+    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct UseTree {
+    pub(crate) syntax: SyntaxNode,
+}
+impl UseTree {
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
+    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
+    pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) }
+    pub fn use_tree_list(&self) -> Option<UseTreeList> { support::child(&self.syntax) }
+    pub fn rename(&self) -> Option<Rename> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct UseTreeList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl UseTreeList {
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn use_trees(&self) -> AstChildren<UseTree> { support::children(&self.syntax) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Abi {
+    pub(crate) syntax: SyntaxNode,
+}
+impl Abi {
+    pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct GenericParamList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl GenericParamList {
+    pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
+    pub fn generic_params(&self) -> AstChildren<GenericParam> { support::children(&self.syntax) }
+    pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct WhereClause {
+    pub(crate) syntax: SyntaxNode,
+}
+impl WhereClause {
+    pub fn where_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![where]) }
+    pub fn predicates(&self) -> AstChildren<WherePred> { support::children(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct BlockExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for BlockExpr {}
+impl BlockExpr {
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct SelfParam {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for SelfParam {}
+impl SelfParam {
+    pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
+    pub fn lifetime_token(&self) -> Option<SyntaxToken> {
+        support::token(&self.syntax, T![lifetime])
+    }
+    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
+    pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Param {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for Param {}
+impl Param {
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn dotdotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![...]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct RecordFieldList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl RecordFieldList {
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn fields(&self) -> AstChildren<RecordField> { support::children(&self.syntax) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct TupleFieldList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl TupleFieldList {
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn fields(&self) -> AstChildren<TupleField> { support::children(&self.syntax) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct RecordField {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for RecordField {}
+impl ast::NameOwner for RecordField {}
+impl ast::VisibilityOwner for RecordField {}
+impl RecordField {
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct TupleField {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for TupleField {}
+impl ast::VisibilityOwner for TupleField {}
+impl TupleField {
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct VariantList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl VariantList {
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn variants(&self) -> AstChildren<Variant> { support::children(&self.syntax) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Variant {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for Variant {}
+impl ast::NameOwner for Variant {}
+impl ast::VisibilityOwner for Variant {}
+impl Variant {
+    pub fn field_list(&self) -> Option<FieldList> { support::child(&self.syntax) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct AssocItemList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for AssocItemList {}
+impl AssocItemList {
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn assoc_items(&self) -> AstChildren<AssocItem> { support::children(&self.syntax) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ExternItemList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for ExternItemList {}
+impl ExternItemList {
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn extern_items(&self) -> AstChildren<ExternItem> { support::children(&self.syntax) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ConstParam {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for ConstParam {}
+impl ast::NameOwner for ConstParam {}
+impl ConstParam {
+    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn default_val(&self) -> Option<Expr> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct LifetimeParam {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for LifetimeParam {}
+impl ast::TypeBoundsOwner for LifetimeParam {}
+impl LifetimeParam {
+    pub fn lifetime_token(&self) -> Option<SyntaxToken> {
+        support::token(&self.syntax, T![lifetime])
+    }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct TypeParam {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for TypeParam {}
+impl ast::NameOwner for TypeParam {}
+impl ast::TypeBoundsOwner for TypeParam {}
+impl TypeParam {
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn default_type(&self) -> Option<Type> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct WherePred {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::TypeBoundsOwner for WherePred {}
+impl WherePred {
+    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
+    pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
+    pub fn lifetime_token(&self) -> Option<SyntaxToken> {
+        support::token(&self.syntax, T![lifetime])
+    }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Literal {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for Literal {}
+impl Literal {}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ExprStmt {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for ExprStmt {}
+impl ExprStmt {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct LetStmt {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for LetStmt {}
+impl LetStmt {
+    pub fn let_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![let]) }
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn initializer(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ArrayExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for ArrayExpr {}
+impl ArrayExpr {
+    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
+    pub fn exprs(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct AwaitExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for AwaitExpr {}
+impl AwaitExpr {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
+    pub fn await_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![await]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct BinExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for BinExpr {}
+impl BinExpr {}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct BoxExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for BoxExpr {}
+impl BoxExpr {
+    pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct BreakExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for BreakExpr {}
+impl BreakExpr {
+    pub fn break_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![break]) }
+    pub fn lifetime_token(&self) -> Option<SyntaxToken> {
+        support::token(&self.syntax, T![lifetime])
+    }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct CallExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for CallExpr {}
+impl ast::ArgListOwner for CallExpr {}
+impl CallExpr {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct CastExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for CastExpr {}
+impl CastExpr {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ClosureExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for ClosureExpr {}
+impl ClosureExpr {
+    pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) }
+    pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
+    pub fn move_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![move]) }
+    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
+    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
+    pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ContinueExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for ContinueExpr {}
+impl ContinueExpr {
+    pub fn continue_token(&self) -> Option<SyntaxToken> {
+        support::token(&self.syntax, T![continue])
+    }
+    pub fn lifetime_token(&self) -> Option<SyntaxToken> {
+        support::token(&self.syntax, T![lifetime])
+    }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct EffectExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for EffectExpr {}
+impl EffectExpr {
+    pub fn label(&self) -> Option<Label> { support::child(&self.syntax) }
+    pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) }
+    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
+    pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
+    pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct FieldExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for FieldExpr {}
+impl FieldExpr {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
+    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ForExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for ForExpr {}
+impl ast::LoopBodyOwner for ForExpr {}
+impl ForExpr {
+    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+    pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) }
+    pub fn iterable(&self) -> Option<Expr> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct IfExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for IfExpr {}
+impl IfExpr {
+    pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) }
+    pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) }
+    pub fn else_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![else]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct IndexExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for IndexExpr {}
+impl IndexExpr {
+    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
+    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct LoopExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for LoopExpr {}
+impl ast::LoopBodyOwner for LoopExpr {}
+impl LoopExpr {
+    pub fn loop_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![loop]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct MatchExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for MatchExpr {}
+impl MatchExpr {
+    pub fn match_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![match]) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn match_arm_list(&self) -> Option<MatchArmList> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct MethodCallExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for MethodCallExpr {}
+impl ast::ArgListOwner for MethodCallExpr {}
+impl MethodCallExpr {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
+    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
+    pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ParenExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for ParenExpr {}
+impl ParenExpr {
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct PathExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for PathExpr {}
+impl PathExpr {
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct PrefixExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for PrefixExpr {}
+impl PrefixExpr {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct RangeExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for RangeExpr {}
+impl RangeExpr {}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct RecordExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl RecordExpr {
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
+    pub fn record_expr_field_list(&self) -> Option<RecordExprFieldList> {
+        support::child(&self.syntax)
+    }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct RefExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for RefExpr {}
+impl RefExpr {
+    pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
+    pub fn raw_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![raw]) }
+    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
+    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ReturnExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for ReturnExpr {}
+impl ReturnExpr {
+    pub fn return_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![return]) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct TryExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for TryExpr {}
+impl TryExpr {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct TupleExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for TupleExpr {}
+impl TupleExpr {
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn fields(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct WhileExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for WhileExpr {}
+impl ast::LoopBodyOwner for WhileExpr {}
+impl WhileExpr {
+    pub fn while_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![while]) }
+    pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Label {
+    pub(crate) syntax: SyntaxNode,
+}
+impl Label {
+    pub fn lifetime_token(&self) -> Option<SyntaxToken> {
+        support::token(&self.syntax, T![lifetime])
+    }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct RecordExprFieldList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for RecordExprFieldList {}
+impl RecordExprFieldList {
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn fields(&self) -> AstChildren<RecordExprField> { support::children(&self.syntax) }
+    pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
+    pub fn spread(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct RecordExprField {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for RecordExprField {}
+impl RecordExprField {
+    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ArgList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ArgList {
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn args(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Condition {
+    pub(crate) syntax: SyntaxNode,
+}
+impl Condition {
+    pub fn let_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![let]) }
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct MatchArmList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for MatchArmList {}
+impl MatchArmList {
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn arms(&self) -> AstChildren<MatchArm> { support::children(&self.syntax) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct MatchArm {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for MatchArm {}
+impl MatchArm {
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+    pub fn guard(&self) -> Option<MatchGuard> { support::child(&self.syntax) }
+    pub fn fat_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=>]) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct MatchGuard {
+    pub(crate) syntax: SyntaxNode,
+}
+impl MatchGuard {
+    pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ArrayType {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ArrayType {
+    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct DynTraitType {
+    pub(crate) syntax: SyntaxNode,
+}
+impl DynTraitType {
+    pub fn dyn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![dyn]) }
+    pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct FnPtrType {
+    pub(crate) syntax: SyntaxNode,
+}
+impl FnPtrType {
+    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+    pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
+    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
+    pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) }
+    pub fn fn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![fn]) }
+    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
+    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ForType {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ForType {
+    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
+    pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ImplTraitType {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ImplTraitType {
+    pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) }
+    pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct InferType {
+    pub(crate) syntax: SyntaxNode,
+}
+impl InferType {
+    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct NeverType {
+    pub(crate) syntax: SyntaxNode,
+}
+impl NeverType {
+    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ParenType {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ParenType {
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct PtrType {
+    pub(crate) syntax: SyntaxNode,
+}
+impl PtrType {
+    pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) }
+    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct RefType {
+    pub(crate) syntax: SyntaxNode,
+}
+impl RefType {
+    pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
+    pub fn lifetime_token(&self) -> Option<SyntaxToken> {
+        support::token(&self.syntax, T![lifetime])
+    }
+    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct SliceType {
+    pub(crate) syntax: SyntaxNode,
+}
+impl SliceType {
+    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct TupleType {
+    pub(crate) syntax: SyntaxNode,
+}
+impl TupleType {
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn fields(&self) -> AstChildren<Type> { support::children(&self.syntax) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct TypeBound {
+    pub(crate) syntax: SyntaxNode,
+}
+impl TypeBound {
+    pub fn lifetime_token(&self) -> Option<SyntaxToken> {
+        support::token(&self.syntax, T![lifetime])
+    }
+    pub fn question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct IdentPat {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for IdentPat {}
+impl ast::NameOwner for IdentPat {}
+impl IdentPat {
+    pub fn ref_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ref]) }
+    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
+    pub fn at_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![@]) }
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct BoxPat {
+    pub(crate) syntax: SyntaxNode,
+}
+impl BoxPat {
+    pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) }
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct RestPat {
+    pub(crate) syntax: SyntaxNode,
+}
+impl RestPat {
+    pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct LiteralPat {
+    pub(crate) syntax: SyntaxNode,
+}
+impl LiteralPat {
+    pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct MacroPat {
+    pub(crate) syntax: SyntaxNode,
+}
+impl MacroPat {
+    pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct OrPat {
+    pub(crate) syntax: SyntaxNode,
+}
+impl OrPat {
+    pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ParenPat {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ParenPat {
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct PathPat {
+    pub(crate) syntax: SyntaxNode,
+}
+impl PathPat {
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct WildcardPat {
+    pub(crate) syntax: SyntaxNode,
+}
+impl WildcardPat {
+    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct RangePat {
+    pub(crate) syntax: SyntaxNode,
+}
+impl RangePat {}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct RecordPat {
+    pub(crate) syntax: SyntaxNode,
+}
+impl RecordPat {
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
+    pub fn record_pat_field_list(&self) -> Option<RecordPatFieldList> {
+        support::child(&self.syntax)
+    }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct RefPat {
+    pub(crate) syntax: SyntaxNode,
+}
+impl RefPat {
+    pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
+    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct SlicePat {
+    pub(crate) syntax: SyntaxNode,
+}
+impl SlicePat {
+    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
+    pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
+    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct TuplePat {
+    pub(crate) syntax: SyntaxNode,
+}
+impl TuplePat {
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn fields(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct TupleStructPat {
+    pub(crate) syntax: SyntaxNode,
+}
+impl TupleStructPat {
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn fields(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct RecordPatFieldList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl RecordPatFieldList {
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn fields(&self) -> AstChildren<RecordPatField> { support::children(&self.syntax) }
+    pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct RecordPatField {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for RecordPatField {}
+impl RecordPatField {
+    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum GenericArg {
+    TypeArg(TypeArg),
+    AssocTypeArg(AssocTypeArg),
+    LifetimeArg(LifetimeArg),
+    ConstArg(ConstArg),
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum Type {
+    ArrayType(ArrayType),
+    DynTraitType(DynTraitType),
+    FnPtrType(FnPtrType),
+    ForType(ForType),
+    ImplTraitType(ImplTraitType),
+    InferType(InferType),
+    NeverType(NeverType),
+    ParenType(ParenType),
+    PathType(PathType),
+    PtrType(PtrType),
+    RefType(RefType),
+    SliceType(SliceType),
+    TupleType(TupleType),
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum Expr {
+    ArrayExpr(ArrayExpr),
+    AwaitExpr(AwaitExpr),
+    BinExpr(BinExpr),
+    BlockExpr(BlockExpr),
+    BoxExpr(BoxExpr),
+    BreakExpr(BreakExpr),
+    CallExpr(CallExpr),
+    CastExpr(CastExpr),
+    ClosureExpr(ClosureExpr),
+    ContinueExpr(ContinueExpr),
+    EffectExpr(EffectExpr),
+    FieldExpr(FieldExpr),
+    ForExpr(ForExpr),
+    IfExpr(IfExpr),
+    IndexExpr(IndexExpr),
+    Literal(Literal),
+    LoopExpr(LoopExpr),
+    MacroCall(MacroCall),
+    MatchExpr(MatchExpr),
+    MethodCallExpr(MethodCallExpr),
+    ParenExpr(ParenExpr),
+    PathExpr(PathExpr),
+    PrefixExpr(PrefixExpr),
+    RangeExpr(RangeExpr),
+    RecordExpr(RecordExpr),
+    RefExpr(RefExpr),
+    ReturnExpr(ReturnExpr),
+    TryExpr(TryExpr),
+    TupleExpr(TupleExpr),
+    WhileExpr(WhileExpr),
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum Item {
+    Const(Const),
+    Enum(Enum),
+    ExternBlock(ExternBlock),
+    ExternCrate(ExternCrate),
+    Fn(Fn),
+    Impl(Impl),
+    MacroCall(MacroCall),
+    Module(Module),
+    Static(Static),
+    Struct(Struct),
+    Trait(Trait),
+    TypeAlias(TypeAlias),
+    Union(Union),
+    Use(Use),
+}
+impl ast::AttrsOwner for Item {}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum Stmt {
+    ExprStmt(ExprStmt),
+    Item(Item),
+    LetStmt(LetStmt),
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum Pat {
+    IdentPat(IdentPat),
+    BoxPat(BoxPat),
+    RestPat(RestPat),
+    LiteralPat(LiteralPat),
+    MacroPat(MacroPat),
+    OrPat(OrPat),
+    ParenPat(ParenPat),
+    PathPat(PathPat),
+    WildcardPat(WildcardPat),
+    RangePat(RangePat),
+    RecordPat(RecordPat),
+    RefPat(RefPat),
+    SlicePat(SlicePat),
+    TuplePat(TuplePat),
+    TupleStructPat(TupleStructPat),
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum FieldList {
+    RecordFieldList(RecordFieldList),
+    TupleFieldList(TupleFieldList),
+}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum AdtDef {
+    Enum(Enum),
+    Struct(Struct),
+    Union(Union),
+}
+impl ast::AttrsOwner for AdtDef {}
+impl ast::GenericParamsOwner for AdtDef {}
+impl ast::NameOwner for AdtDef {}
+impl ast::VisibilityOwner for AdtDef {}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum AssocItem {
+    Const(Const),
+    Fn(Fn),
+    MacroCall(MacroCall),
+    TypeAlias(TypeAlias),
+}
+impl ast::AttrsOwner for AssocItem {}
+impl ast::NameOwner for AssocItem {}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum ExternItem {
+    Fn(Fn),
+    MacroCall(MacroCall),
+    Static(Static),
+}
+impl ast::AttrsOwner for ExternItem {}
+impl ast::NameOwner for ExternItem {}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum GenericParam {
+    ConstParam(ConstParam),
+    LifetimeParam(LifetimeParam),
+    TypeParam(TypeParam),
+}
+impl ast::AttrsOwner for GenericParam {}
+impl AstNode for Name {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == NAME }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for NameRef {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == NAME_REF }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Path {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for PathSegment {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_SEGMENT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for GenericArgList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == GENERIC_ARG_LIST }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ParamList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM_LIST }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for RetType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RET_TYPE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for PathType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_TYPE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for TypeArg {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ARG }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for AssocTypeArg {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ASSOC_TYPE_ARG }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for LifetimeArg {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_ARG }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ConstArg {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_ARG }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for TypeBoundList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND_LIST }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for MacroCall {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_CALL }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Attr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ATTR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for TokenTree {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TOKEN_TREE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for MacroItems {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_ITEMS }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for MacroStmts {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_STMTS }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for SourceFile {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == SOURCE_FILE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Const {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == CONST }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Enum {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ENUM }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ExternBlock {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_BLOCK }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ExternCrate {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_CRATE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Fn {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == FN }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Impl {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == IMPL }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Module {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MODULE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Static {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == STATIC }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Struct {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == STRUCT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Trait {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TRAIT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for TypeAlias {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ALIAS }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Union {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == UNION }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Use {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == USE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Visibility {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == VISIBILITY }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ItemList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ITEM_LIST }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Rename {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RENAME }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for UseTree {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for UseTreeList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE_LIST }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Abi {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ABI }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for GenericParamList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == GENERIC_PARAM_LIST }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for WhereClause {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == WHERE_CLAUSE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for BlockExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == BLOCK_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for SelfParam {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == SELF_PARAM }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Param {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for RecordFieldList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_LIST }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for TupleFieldList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_FIELD_LIST }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for RecordField {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for TupleField {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_FIELD }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for VariantList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == VARIANT_LIST }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Variant {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == VARIANT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for AssocItemList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ASSOC_ITEM_LIST }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ExternItemList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_ITEM_LIST }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ConstParam {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_PARAM }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for LifetimeParam {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_PARAM }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for TypeParam {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_PARAM }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for WherePred {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == WHERE_PRED }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Literal {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ExprStmt {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_STMT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for LetStmt {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == LET_STMT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ArrayExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ARRAY_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for AwaitExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == AWAIT_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for BinExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == BIN_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for BoxExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == BOX_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for BreakExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == BREAK_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for CallExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == CALL_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for CastExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == CAST_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ClosureExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == CLOSURE_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ContinueExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == CONTINUE_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for EffectExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == EFFECT_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for FieldExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == FIELD_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ForExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for IfExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == IF_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for IndexExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == INDEX_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for LoopExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == LOOP_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for MatchExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for MethodCallExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == METHOD_CALL_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ParenExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for PathExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for PrefixExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PREFIX_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for RangeExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RANGE_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for RecordExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for RefExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == REF_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ReturnExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RETURN_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for TryExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TRY_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for TupleExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for WhileExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == WHILE_EXPR }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Label {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == LABEL }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for RecordExprFieldList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR_FIELD_LIST }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for RecordExprField {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR_FIELD }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ArgList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ARG_LIST }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for Condition {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == CONDITION }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for MatchArmList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_ARM_LIST }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for MatchArm {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_ARM }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for MatchGuard {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_GUARD }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ArrayType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ARRAY_TYPE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for DynTraitType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == DYN_TRAIT_TYPE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for FnPtrType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == FN_PTR_TYPE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ForType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_TYPE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ImplTraitType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == IMPL_TRAIT_TYPE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for InferType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == INFER_TYPE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for NeverType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == NEVER_TYPE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ParenType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_TYPE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for PtrType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PTR_TYPE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for RefType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == REF_TYPE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for SliceType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == SLICE_TYPE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for TupleType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_TYPE }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for TypeBound {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for IdentPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == IDENT_PAT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for BoxPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == BOX_PAT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for RestPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == REST_PAT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for LiteralPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL_PAT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for MacroPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_PAT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for OrPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == OR_PAT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for ParenPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_PAT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for PathPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_PAT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for WildcardPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == WILDCARD_PAT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for RangePat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RANGE_PAT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for RecordPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for RefPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == REF_PAT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for SlicePat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == SLICE_PAT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for TuplePat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_PAT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for TupleStructPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_STRUCT_PAT }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for RecordPatFieldList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD_LIST }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl AstNode for RecordPatField {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxNode { &self.syntax }
+}
+impl From<TypeArg> for GenericArg {
+    fn from(node: TypeArg) -> GenericArg { GenericArg::TypeArg(node) }
+}
+impl From<AssocTypeArg> for GenericArg {
+    fn from(node: AssocTypeArg) -> GenericArg { GenericArg::AssocTypeArg(node) }
+}
+impl From<LifetimeArg> for GenericArg {
+    fn from(node: LifetimeArg) -> GenericArg { GenericArg::LifetimeArg(node) }
+}
+impl From<ConstArg> for GenericArg {
+    fn from(node: ConstArg) -> GenericArg { GenericArg::ConstArg(node) }
+}
+impl AstNode for GenericArg {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        match kind {
+            TYPE_ARG | ASSOC_TYPE_ARG | LIFETIME_ARG | CONST_ARG => true,
+            _ => false,
+        }
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        let res = match syntax.kind() {
+            TYPE_ARG => GenericArg::TypeArg(TypeArg { syntax }),
+            ASSOC_TYPE_ARG => GenericArg::AssocTypeArg(AssocTypeArg { syntax }),
+            LIFETIME_ARG => GenericArg::LifetimeArg(LifetimeArg { syntax }),
+            CONST_ARG => GenericArg::ConstArg(ConstArg { syntax }),
+            _ => return None,
+        };
+        Some(res)
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        match self {
+            GenericArg::TypeArg(it) => &it.syntax,
+            GenericArg::AssocTypeArg(it) => &it.syntax,
+            GenericArg::LifetimeArg(it) => &it.syntax,
+            GenericArg::ConstArg(it) => &it.syntax,
+        }
+    }
+}
+impl From<ArrayType> for Type {
+    fn from(node: ArrayType) -> Type { Type::ArrayType(node) }
+}
+impl From<DynTraitType> for Type {
+    fn from(node: DynTraitType) -> Type { Type::DynTraitType(node) }
+}
+impl From<FnPtrType> for Type {
+    fn from(node: FnPtrType) -> Type { Type::FnPtrType(node) }
+}
+impl From<ForType> for Type {
+    fn from(node: ForType) -> Type { Type::ForType(node) }
+}
+impl From<ImplTraitType> for Type {
+    fn from(node: ImplTraitType) -> Type { Type::ImplTraitType(node) }
+}
+impl From<InferType> for Type {
+    fn from(node: InferType) -> Type { Type::InferType(node) }
+}
+impl From<NeverType> for Type {
+    fn from(node: NeverType) -> Type { Type::NeverType(node) }
+}
+impl From<ParenType> for Type {
+    fn from(node: ParenType) -> Type { Type::ParenType(node) }
+}
+impl From<PathType> for Type {
+    fn from(node: PathType) -> Type { Type::PathType(node) }
+}
+impl From<PtrType> for Type {
+    fn from(node: PtrType) -> Type { Type::PtrType(node) }
+}
+impl From<RefType> for Type {
+    fn from(node: RefType) -> Type { Type::RefType(node) }
+}
+impl From<SliceType> for Type {
+    fn from(node: SliceType) -> Type { Type::SliceType(node) }
+}
+impl From<TupleType> for Type {
+    fn from(node: TupleType) -> Type { Type::TupleType(node) }
+}
+impl AstNode for Type {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        match kind {
+            ARRAY_TYPE | DYN_TRAIT_TYPE | FN_PTR_TYPE | FOR_TYPE | IMPL_TRAIT_TYPE | INFER_TYPE
+            | NEVER_TYPE | PAREN_TYPE | PATH_TYPE | PTR_TYPE | REF_TYPE | SLICE_TYPE
+            | TUPLE_TYPE => true,
+            _ => false,
+        }
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        let res = match syntax.kind() {
+            ARRAY_TYPE => Type::ArrayType(ArrayType { syntax }),
+            DYN_TRAIT_TYPE => Type::DynTraitType(DynTraitType { syntax }),
+            FN_PTR_TYPE => Type::FnPtrType(FnPtrType { syntax }),
+            FOR_TYPE => Type::ForType(ForType { syntax }),
+            IMPL_TRAIT_TYPE => Type::ImplTraitType(ImplTraitType { syntax }),
+            INFER_TYPE => Type::InferType(InferType { syntax }),
+            NEVER_TYPE => Type::NeverType(NeverType { syntax }),
+            PAREN_TYPE => Type::ParenType(ParenType { syntax }),
+            PATH_TYPE => Type::PathType(PathType { syntax }),
+            PTR_TYPE => Type::PtrType(PtrType { syntax }),
+            REF_TYPE => Type::RefType(RefType { syntax }),
+            SLICE_TYPE => Type::SliceType(SliceType { syntax }),
+            TUPLE_TYPE => Type::TupleType(TupleType { syntax }),
+            _ => return None,
+        };
+        Some(res)
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        match self {
+            Type::ArrayType(it) => &it.syntax,
+            Type::DynTraitType(it) => &it.syntax,
+            Type::FnPtrType(it) => &it.syntax,
+            Type::ForType(it) => &it.syntax,
+            Type::ImplTraitType(it) => &it.syntax,
+            Type::InferType(it) => &it.syntax,
+            Type::NeverType(it) => &it.syntax,
+            Type::ParenType(it) => &it.syntax,
+            Type::PathType(it) => &it.syntax,
+            Type::PtrType(it) => &it.syntax,
+            Type::RefType(it) => &it.syntax,
+            Type::SliceType(it) => &it.syntax,
+            Type::TupleType(it) => &it.syntax,
+        }
+    }
+}
+impl From<ArrayExpr> for Expr {
+    fn from(node: ArrayExpr) -> Expr { Expr::ArrayExpr(node) }
+}
+impl From<AwaitExpr> for Expr {
+    fn from(node: AwaitExpr) -> Expr { Expr::AwaitExpr(node) }
+}
+impl From<BinExpr> for Expr {
+    fn from(node: BinExpr) -> Expr { Expr::BinExpr(node) }
+}
+impl From<BlockExpr> for Expr {
+    fn from(node: BlockExpr) -> Expr { Expr::BlockExpr(node) }
+}
+impl From<BoxExpr> for Expr {
+    fn from(node: BoxExpr) -> Expr { Expr::BoxExpr(node) }
+}
+impl From<BreakExpr> for Expr {
+    fn from(node: BreakExpr) -> Expr { Expr::BreakExpr(node) }
+}
+impl From<CallExpr> for Expr {
+    fn from(node: CallExpr) -> Expr { Expr::CallExpr(node) }
+}
+impl From<CastExpr> for Expr {
+    fn from(node: CastExpr) -> Expr { Expr::CastExpr(node) }
+}
+impl From<ClosureExpr> for Expr {
+    fn from(node: ClosureExpr) -> Expr { Expr::ClosureExpr(node) }
+}
+impl From<ContinueExpr> for Expr {
+    fn from(node: ContinueExpr) -> Expr { Expr::ContinueExpr(node) }
+}
+impl From<EffectExpr> for Expr {
+    fn from(node: EffectExpr) -> Expr { Expr::EffectExpr(node) }
+}
+impl From<FieldExpr> for Expr {
+    fn from(node: FieldExpr) -> Expr { Expr::FieldExpr(node) }
+}
+impl From<ForExpr> for Expr {
+    fn from(node: ForExpr) -> Expr { Expr::ForExpr(node) }
+}
+impl From<IfExpr> for Expr {
+    fn from(node: IfExpr) -> Expr { Expr::IfExpr(node) }
+}
+impl From<IndexExpr> for Expr {
+    fn from(node: IndexExpr) -> Expr { Expr::IndexExpr(node) }
+}
+impl From<Literal> for Expr {
+    fn from(node: Literal) -> Expr { Expr::Literal(node) }
+}
+impl From<LoopExpr> for Expr {
+    fn from(node: LoopExpr) -> Expr { Expr::LoopExpr(node) }
+}
+impl From<MacroCall> for Expr {
+    fn from(node: MacroCall) -> Expr { Expr::MacroCall(node) }
+}
+impl From<MatchExpr> for Expr {
+    fn from(node: MatchExpr) -> Expr { Expr::MatchExpr(node) }
+}
+impl From<MethodCallExpr> for Expr {
+    fn from(node: MethodCallExpr) -> Expr { Expr::MethodCallExpr(node) }
+}
+impl From<ParenExpr> for Expr {
+    fn from(node: ParenExpr) -> Expr { Expr::ParenExpr(node) }
+}
+impl From<PathExpr> for Expr {
+    fn from(node: PathExpr) -> Expr { Expr::PathExpr(node) }
+}
+impl From<PrefixExpr> for Expr {
+    fn from(node: PrefixExpr) -> Expr { Expr::PrefixExpr(node) }
+}
+impl From<RangeExpr> for Expr {
+    fn from(node: RangeExpr) -> Expr { Expr::RangeExpr(node) }
+}
+impl From<RecordExpr> for Expr {
+    fn from(node: RecordExpr) -> Expr { Expr::RecordExpr(node) }
+}
+impl From<RefExpr> for Expr {
+    fn from(node: RefExpr) -> Expr { Expr::RefExpr(node) }
+}
+impl From<ReturnExpr> for Expr {
+    fn from(node: ReturnExpr) -> Expr { Expr::ReturnExpr(node) }
+}
+impl From<TryExpr> for Expr {
+    fn from(node: TryExpr) -> Expr { Expr::TryExpr(node) }
+}
+impl From<TupleExpr> for Expr {
+    fn from(node: TupleExpr) -> Expr { Expr::TupleExpr(node) }
+}
+impl From<WhileExpr> for Expr {
+    fn from(node: WhileExpr) -> Expr { Expr::WhileExpr(node) }
+}
+impl AstNode for Expr {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        match kind {
+            ARRAY_EXPR | AWAIT_EXPR | BIN_EXPR | BLOCK_EXPR | BOX_EXPR | BREAK_EXPR | CALL_EXPR
+            | CAST_EXPR | CLOSURE_EXPR | CONTINUE_EXPR | EFFECT_EXPR | FIELD_EXPR | FOR_EXPR
+            | IF_EXPR | INDEX_EXPR | LITERAL | LOOP_EXPR | MACRO_CALL | MATCH_EXPR
+            | METHOD_CALL_EXPR | PAREN_EXPR | PATH_EXPR | PREFIX_EXPR | RANGE_EXPR
+            | RECORD_EXPR | REF_EXPR | RETURN_EXPR | TRY_EXPR | TUPLE_EXPR | WHILE_EXPR => true,
+            _ => false,
+        }
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        let res = match syntax.kind() {
+            ARRAY_EXPR => Expr::ArrayExpr(ArrayExpr { syntax }),
+            AWAIT_EXPR => Expr::AwaitExpr(AwaitExpr { syntax }),
+            BIN_EXPR => Expr::BinExpr(BinExpr { syntax }),
+            BLOCK_EXPR => Expr::BlockExpr(BlockExpr { syntax }),
+            BOX_EXPR => Expr::BoxExpr(BoxExpr { syntax }),
+            BREAK_EXPR => Expr::BreakExpr(BreakExpr { syntax }),
+            CALL_EXPR => Expr::CallExpr(CallExpr { syntax }),
+            CAST_EXPR => Expr::CastExpr(CastExpr { syntax }),
+            CLOSURE_EXPR => Expr::ClosureExpr(ClosureExpr { syntax }),
+            CONTINUE_EXPR => Expr::ContinueExpr(ContinueExpr { syntax }),
+            EFFECT_EXPR => Expr::EffectExpr(EffectExpr { syntax }),
+            FIELD_EXPR => Expr::FieldExpr(FieldExpr { syntax }),
+            FOR_EXPR => Expr::ForExpr(ForExpr { syntax }),
+            IF_EXPR => Expr::IfExpr(IfExpr { syntax }),
+            INDEX_EXPR => Expr::IndexExpr(IndexExpr { syntax }),
+            LITERAL => Expr::Literal(Literal { syntax }),
+            LOOP_EXPR => Expr::LoopExpr(LoopExpr { syntax }),
+            MACRO_CALL => Expr::MacroCall(MacroCall { syntax }),
+            MATCH_EXPR => Expr::MatchExpr(MatchExpr { syntax }),
+            METHOD_CALL_EXPR => Expr::MethodCallExpr(MethodCallExpr { syntax }),
+            PAREN_EXPR => Expr::ParenExpr(ParenExpr { syntax }),
+            PATH_EXPR => Expr::PathExpr(PathExpr { syntax }),
+            PREFIX_EXPR => Expr::PrefixExpr(PrefixExpr { syntax }),
+            RANGE_EXPR => Expr::RangeExpr(RangeExpr { syntax }),
+            RECORD_EXPR => Expr::RecordExpr(RecordExpr { syntax }),
+            REF_EXPR => Expr::RefExpr(RefExpr { syntax }),
+            RETURN_EXPR => Expr::ReturnExpr(ReturnExpr { syntax }),
+            TRY_EXPR => Expr::TryExpr(TryExpr { syntax }),
+            TUPLE_EXPR => Expr::TupleExpr(TupleExpr { syntax }),
+            WHILE_EXPR => Expr::WhileExpr(WhileExpr { syntax }),
+            _ => return None,
+        };
+        Some(res)
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        match self {
+            Expr::ArrayExpr(it) => &it.syntax,
+            Expr::AwaitExpr(it) => &it.syntax,
+            Expr::BinExpr(it) => &it.syntax,
+            Expr::BlockExpr(it) => &it.syntax,
+            Expr::BoxExpr(it) => &it.syntax,
+            Expr::BreakExpr(it) => &it.syntax,
+            Expr::CallExpr(it) => &it.syntax,
+            Expr::CastExpr(it) => &it.syntax,
+            Expr::ClosureExpr(it) => &it.syntax,
+            Expr::ContinueExpr(it) => &it.syntax,
+            Expr::EffectExpr(it) => &it.syntax,
+            Expr::FieldExpr(it) => &it.syntax,
+            Expr::ForExpr(it) => &it.syntax,
+            Expr::IfExpr(it) => &it.syntax,
+            Expr::IndexExpr(it) => &it.syntax,
+            Expr::Literal(it) => &it.syntax,
+            Expr::LoopExpr(it) => &it.syntax,
+            Expr::MacroCall(it) => &it.syntax,
+            Expr::MatchExpr(it) => &it.syntax,
+            Expr::MethodCallExpr(it) => &it.syntax,
+            Expr::ParenExpr(it) => &it.syntax,
+            Expr::PathExpr(it) => &it.syntax,
+            Expr::PrefixExpr(it) => &it.syntax,
+            Expr::RangeExpr(it) => &it.syntax,
+            Expr::RecordExpr(it) => &it.syntax,
+            Expr::RefExpr(it) => &it.syntax,
+            Expr::ReturnExpr(it) => &it.syntax,
+            Expr::TryExpr(it) => &it.syntax,
+            Expr::TupleExpr(it) => &it.syntax,
+            Expr::WhileExpr(it) => &it.syntax,
+        }
+    }
+}
+impl From<Const> for Item {
+    fn from(node: Const) -> Item { Item::Const(node) }
+}
+impl From<Enum> for Item {
+    fn from(node: Enum) -> Item { Item::Enum(node) }
+}
+impl From<ExternBlock> for Item {
+    fn from(node: ExternBlock) -> Item { Item::ExternBlock(node) }
+}
+impl From<ExternCrate> for Item {
+    fn from(node: ExternCrate) -> Item { Item::ExternCrate(node) }
+}
+impl From<Fn> for Item {
+    fn from(node: Fn) -> Item { Item::Fn(node) }
+}
+impl From<Impl> for Item {
+    fn from(node: Impl) -> Item { Item::Impl(node) }
+}
+impl From<MacroCall> for Item {
+    fn from(node: MacroCall) -> Item { Item::MacroCall(node) }
+}
+impl From<Module> for Item {
+    fn from(node: Module) -> Item { Item::Module(node) }
+}
+impl From<Static> for Item {
+    fn from(node: Static) -> Item { Item::Static(node) }
+}
+impl From<Struct> for Item {
+    fn from(node: Struct) -> Item { Item::Struct(node) }
+}
+impl From<Trait> for Item {
+    fn from(node: Trait) -> Item { Item::Trait(node) }
+}
+impl From<TypeAlias> for Item {
+    fn from(node: TypeAlias) -> Item { Item::TypeAlias(node) }
+}
+impl From<Union> for Item {
+    fn from(node: Union) -> Item { Item::Union(node) }
+}
+impl From<Use> for Item {
+    fn from(node: Use) -> Item { Item::Use(node) }
+}
+impl AstNode for Item {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        match kind {
+            CONST | ENUM | EXTERN_BLOCK | EXTERN_CRATE | FN | IMPL | MACRO_CALL | MODULE
+            | STATIC | STRUCT | TRAIT | TYPE_ALIAS | UNION | USE => true,
+            _ => false,
+        }
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        let res = match syntax.kind() {
+            CONST => Item::Const(Const { syntax }),
+            ENUM => Item::Enum(Enum { syntax }),
+            EXTERN_BLOCK => Item::ExternBlock(ExternBlock { syntax }),
+            EXTERN_CRATE => Item::ExternCrate(ExternCrate { syntax }),
+            FN => Item::Fn(Fn { syntax }),
+            IMPL => Item::Impl(Impl { syntax }),
+            MACRO_CALL => Item::MacroCall(MacroCall { syntax }),
+            MODULE => Item::Module(Module { syntax }),
+            STATIC => Item::Static(Static { syntax }),
+            STRUCT => Item::Struct(Struct { syntax }),
+            TRAIT => Item::Trait(Trait { syntax }),
+            TYPE_ALIAS => Item::TypeAlias(TypeAlias { syntax }),
+            UNION => Item::Union(Union { syntax }),
+            USE => Item::Use(Use { syntax }),
+            _ => return None,
+        };
+        Some(res)
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        match self {
+            Item::Const(it) => &it.syntax,
+            Item::Enum(it) => &it.syntax,
+            Item::ExternBlock(it) => &it.syntax,
+            Item::ExternCrate(it) => &it.syntax,
+            Item::Fn(it) => &it.syntax,
+            Item::Impl(it) => &it.syntax,
+            Item::MacroCall(it) => &it.syntax,
+            Item::Module(it) => &it.syntax,
+            Item::Static(it) => &it.syntax,
+            Item::Struct(it) => &it.syntax,
+            Item::Trait(it) => &it.syntax,
+            Item::TypeAlias(it) => &it.syntax,
+            Item::Union(it) => &it.syntax,
+            Item::Use(it) => &it.syntax,
+        }
+    }
+}
+impl From<ExprStmt> for Stmt {
+    fn from(node: ExprStmt) -> Stmt { Stmt::ExprStmt(node) }
+}
+impl From<Item> for Stmt {
+    fn from(node: Item) -> Stmt { Stmt::Item(node) }
+}
+impl From<LetStmt> for Stmt {
+    fn from(node: LetStmt) -> Stmt { Stmt::LetStmt(node) }
+}
+impl From<IdentPat> for Pat {
+    fn from(node: IdentPat) -> Pat { Pat::IdentPat(node) }
+}
+impl From<BoxPat> for Pat {
+    fn from(node: BoxPat) -> Pat { Pat::BoxPat(node) }
+}
+impl From<RestPat> for Pat {
+    fn from(node: RestPat) -> Pat { Pat::RestPat(node) }
+}
+impl From<LiteralPat> for Pat {
+    fn from(node: LiteralPat) -> Pat { Pat::LiteralPat(node) }
+}
+impl From<MacroPat> for Pat {
+    fn from(node: MacroPat) -> Pat { Pat::MacroPat(node) }
+}
+impl From<OrPat> for Pat {
+    fn from(node: OrPat) -> Pat { Pat::OrPat(node) }
+}
+impl From<ParenPat> for Pat {
+    fn from(node: ParenPat) -> Pat { Pat::ParenPat(node) }
+}
+impl From<PathPat> for Pat {
+    fn from(node: PathPat) -> Pat { Pat::PathPat(node) }
+}
+impl From<WildcardPat> for Pat {
+    fn from(node: WildcardPat) -> Pat { Pat::WildcardPat(node) }
+}
+impl From<RangePat> for Pat {
+    fn from(node: RangePat) -> Pat { Pat::RangePat(node) }
+}
+impl From<RecordPat> for Pat {
+    fn from(node: RecordPat) -> Pat { Pat::RecordPat(node) }
+}
+impl From<RefPat> for Pat {
+    fn from(node: RefPat) -> Pat { Pat::RefPat(node) }
+}
+impl From<SlicePat> for Pat {
+    fn from(node: SlicePat) -> Pat { Pat::SlicePat(node) }
+}
+impl From<TuplePat> for Pat {
+    fn from(node: TuplePat) -> Pat { Pat::TuplePat(node) }
+}
+impl From<TupleStructPat> for Pat {
+    fn from(node: TupleStructPat) -> Pat { Pat::TupleStructPat(node) }
+}
+impl AstNode for Pat {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        match kind {
+            IDENT_PAT | BOX_PAT | REST_PAT | LITERAL_PAT | MACRO_PAT | OR_PAT | PAREN_PAT
+            | PATH_PAT | WILDCARD_PAT | RANGE_PAT | RECORD_PAT | REF_PAT | SLICE_PAT
+            | TUPLE_PAT | TUPLE_STRUCT_PAT => true,
+            _ => false,
+        }
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        let res = match syntax.kind() {
+            IDENT_PAT => Pat::IdentPat(IdentPat { syntax }),
+            BOX_PAT => Pat::BoxPat(BoxPat { syntax }),
+            REST_PAT => Pat::RestPat(RestPat { syntax }),
+            LITERAL_PAT => Pat::LiteralPat(LiteralPat { syntax }),
+            MACRO_PAT => Pat::MacroPat(MacroPat { syntax }),
+            OR_PAT => Pat::OrPat(OrPat { syntax }),
+            PAREN_PAT => Pat::ParenPat(ParenPat { syntax }),
+            PATH_PAT => Pat::PathPat(PathPat { syntax }),
+            WILDCARD_PAT => Pat::WildcardPat(WildcardPat { syntax }),
+            RANGE_PAT => Pat::RangePat(RangePat { syntax }),
+            RECORD_PAT => Pat::RecordPat(RecordPat { syntax }),
+            REF_PAT => Pat::RefPat(RefPat { syntax }),
+            SLICE_PAT => Pat::SlicePat(SlicePat { syntax }),
+            TUPLE_PAT => Pat::TuplePat(TuplePat { syntax }),
+            TUPLE_STRUCT_PAT => Pat::TupleStructPat(TupleStructPat { syntax }),
+            _ => return None,
+        };
+        Some(res)
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        match self {
+            Pat::IdentPat(it) => &it.syntax,
+            Pat::BoxPat(it) => &it.syntax,
+            Pat::RestPat(it) => &it.syntax,
+            Pat::LiteralPat(it) => &it.syntax,
+            Pat::MacroPat(it) => &it.syntax,
+            Pat::OrPat(it) => &it.syntax,
+            Pat::ParenPat(it) => &it.syntax,
+            Pat::PathPat(it) => &it.syntax,
+            Pat::WildcardPat(it) => &it.syntax,
+            Pat::RangePat(it) => &it.syntax,
+            Pat::RecordPat(it) => &it.syntax,
+            Pat::RefPat(it) => &it.syntax,
+            Pat::SlicePat(it) => &it.syntax,
+            Pat::TuplePat(it) => &it.syntax,
+            Pat::TupleStructPat(it) => &it.syntax,
+        }
+    }
+}
+impl From<RecordFieldList> for FieldList {
+    fn from(node: RecordFieldList) -> FieldList { FieldList::RecordFieldList(node) }
+}
+impl From<TupleFieldList> for FieldList {
+    fn from(node: TupleFieldList) -> FieldList { FieldList::TupleFieldList(node) }
+}
+impl AstNode for FieldList {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        match kind {
+            RECORD_FIELD_LIST | TUPLE_FIELD_LIST => true,
+            _ => false,
+        }
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        let res = match syntax.kind() {
+            RECORD_FIELD_LIST => FieldList::RecordFieldList(RecordFieldList { syntax }),
+            TUPLE_FIELD_LIST => FieldList::TupleFieldList(TupleFieldList { syntax }),
+            _ => return None,
+        };
+        Some(res)
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        match self {
+            FieldList::RecordFieldList(it) => &it.syntax,
+            FieldList::TupleFieldList(it) => &it.syntax,
+        }
+    }
+}
+impl From<Enum> for AdtDef {
+    fn from(node: Enum) -> AdtDef { AdtDef::Enum(node) }
+}
+impl From<Struct> for AdtDef {
+    fn from(node: Struct) -> AdtDef { AdtDef::Struct(node) }
+}
+impl From<Union> for AdtDef {
+    fn from(node: Union) -> AdtDef { AdtDef::Union(node) }
+}
+impl AstNode for AdtDef {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        match kind {
+            ENUM | STRUCT | UNION => true,
+            _ => false,
+        }
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        let res = match syntax.kind() {
+            ENUM => AdtDef::Enum(Enum { syntax }),
+            STRUCT => AdtDef::Struct(Struct { syntax }),
+            UNION => AdtDef::Union(Union { syntax }),
+            _ => return None,
+        };
+        Some(res)
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        match self {
+            AdtDef::Enum(it) => &it.syntax,
+            AdtDef::Struct(it) => &it.syntax,
+            AdtDef::Union(it) => &it.syntax,
+        }
+    }
+}
+impl From<Const> for AssocItem {
+    fn from(node: Const) -> AssocItem { AssocItem::Const(node) }
+}
+impl From<Fn> for AssocItem {
+    fn from(node: Fn) -> AssocItem { AssocItem::Fn(node) }
+}
+impl From<MacroCall> for AssocItem {
+    fn from(node: MacroCall) -> AssocItem { AssocItem::MacroCall(node) }
+}
+impl From<TypeAlias> for AssocItem {
+    fn from(node: TypeAlias) -> AssocItem { AssocItem::TypeAlias(node) }
+}
+impl AstNode for AssocItem {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        match kind {
+            CONST | FN | MACRO_CALL | TYPE_ALIAS => true,
+            _ => false,
+        }
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        let res = match syntax.kind() {
+            CONST => AssocItem::Const(Const { syntax }),
+            FN => AssocItem::Fn(Fn { syntax }),
+            MACRO_CALL => AssocItem::MacroCall(MacroCall { syntax }),
+            TYPE_ALIAS => AssocItem::TypeAlias(TypeAlias { syntax }),
+            _ => return None,
+        };
+        Some(res)
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        match self {
+            AssocItem::Const(it) => &it.syntax,
+            AssocItem::Fn(it) => &it.syntax,
+            AssocItem::MacroCall(it) => &it.syntax,
+            AssocItem::TypeAlias(it) => &it.syntax,
+        }
+    }
+}
+impl From<Fn> for ExternItem {
+    fn from(node: Fn) -> ExternItem { ExternItem::Fn(node) }
+}
+impl From<MacroCall> for ExternItem {
+    fn from(node: MacroCall) -> ExternItem { ExternItem::MacroCall(node) }
+}
+impl From<Static> for ExternItem {
+    fn from(node: Static) -> ExternItem { ExternItem::Static(node) }
+}
+impl AstNode for ExternItem {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        match kind {
+            FN | MACRO_CALL | STATIC => true,
+            _ => false,
+        }
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        let res = match syntax.kind() {
+            FN => ExternItem::Fn(Fn { syntax }),
+            MACRO_CALL => ExternItem::MacroCall(MacroCall { syntax }),
+            STATIC => ExternItem::Static(Static { syntax }),
+            _ => return None,
+        };
+        Some(res)
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        match self {
+            ExternItem::Fn(it) => &it.syntax,
+            ExternItem::MacroCall(it) => &it.syntax,
+            ExternItem::Static(it) => &it.syntax,
+        }
+    }
+}
+impl From<ConstParam> for GenericParam {
+    fn from(node: ConstParam) -> GenericParam { GenericParam::ConstParam(node) }
+}
+impl From<LifetimeParam> for GenericParam {
+    fn from(node: LifetimeParam) -> GenericParam { GenericParam::LifetimeParam(node) }
+}
+impl From<TypeParam> for GenericParam {
+    fn from(node: TypeParam) -> GenericParam { GenericParam::TypeParam(node) }
+}
+impl AstNode for GenericParam {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        match kind {
+            CONST_PARAM | LIFETIME_PARAM | TYPE_PARAM => true,
+            _ => false,
+        }
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        let res = match syntax.kind() {
+            CONST_PARAM => GenericParam::ConstParam(ConstParam { syntax }),
+            LIFETIME_PARAM => GenericParam::LifetimeParam(LifetimeParam { syntax }),
+            TYPE_PARAM => GenericParam::TypeParam(TypeParam { syntax }),
+            _ => return None,
+        };
+        Some(res)
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        match self {
+            GenericParam::ConstParam(it) => &it.syntax,
+            GenericParam::LifetimeParam(it) => &it.syntax,
+            GenericParam::TypeParam(it) => &it.syntax,
+        }
+    }
+}
+impl std::fmt::Display for GenericArg {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Type {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Expr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Item {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Stmt {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Pat {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for FieldList {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for AdtDef {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for AssocItem {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ExternItem {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for GenericParam {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Name {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for NameRef {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Path {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for PathSegment {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for GenericArgList {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ParamList {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for RetType {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for PathType {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for TypeArg {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for AssocTypeArg {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for LifetimeArg {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ConstArg {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for TypeBoundList {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for MacroCall {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Attr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for TokenTree {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for MacroItems {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for MacroStmts {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for SourceFile {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Const {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Enum {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ExternBlock {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ExternCrate {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Fn {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Impl {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Module {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Static {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Struct {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Trait {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for TypeAlias {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Union {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Use {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Visibility {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ItemList {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Rename {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for UseTree {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for UseTreeList {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Abi {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for GenericParamList {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for WhereClause {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for BlockExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for SelfParam {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Param {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for RecordFieldList {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for TupleFieldList {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for RecordField {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for TupleField {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for VariantList {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Variant {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for AssocItemList {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ExternItemList {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ConstParam {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for LifetimeParam {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for TypeParam {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for WherePred {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Literal {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ExprStmt {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for LetStmt {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ArrayExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for AwaitExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for BinExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for BoxExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for BreakExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for CallExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for CastExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ClosureExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ContinueExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for EffectExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for FieldExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ForExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for IfExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for IndexExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for LoopExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for MatchExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for MethodCallExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ParenExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for PathExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for PrefixExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for RangeExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for RecordExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for RefExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ReturnExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for TryExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for TupleExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for WhileExpr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Label {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for RecordExprFieldList {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for RecordExprField {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ArgList {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for Condition {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for MatchArmList {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for MatchArm {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for MatchGuard {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ArrayType {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for DynTraitType {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for FnPtrType {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ForType {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ImplTraitType {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for InferType {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for NeverType {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ParenType {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for PtrType {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for RefType {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for SliceType {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for TupleType {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for TypeBound {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for IdentPat {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for BoxPat {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for RestPat {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for LiteralPat {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for MacroPat {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for OrPat {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for ParenPat {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for PathPat {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for WildcardPat {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for RangePat {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for RecordPat {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for RefPat {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for SlicePat {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for TuplePat {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for TupleStructPat {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for RecordPatFieldList {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
+impl std::fmt::Display for RecordPatField {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(self.syntax(), f)
+    }
+}
diff --git a/crates/syntax/src/ast/generated/tokens.rs b/crates/syntax/src/ast/generated/tokens.rs
new file mode 100644
index 00000000000..abadd0b61c6
--- /dev/null
+++ b/crates/syntax/src/ast/generated/tokens.rs
@@ -0,0 +1,91 @@
+//! Generated file, do not edit by hand, see `xtask/src/codegen`
+
+use crate::{
+    ast::AstToken,
+    SyntaxKind::{self, *},
+    SyntaxToken,
+};
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Whitespace {
+    pub(crate) syntax: SyntaxToken,
+}
+impl std::fmt::Display for Whitespace {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(&self.syntax, f)
+    }
+}
+impl AstToken for Whitespace {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == WHITESPACE }
+    fn cast(syntax: SyntaxToken) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxToken { &self.syntax }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Comment {
+    pub(crate) syntax: SyntaxToken,
+}
+impl std::fmt::Display for Comment {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(&self.syntax, f)
+    }
+}
+impl AstToken for Comment {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == COMMENT }
+    fn cast(syntax: SyntaxToken) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxToken { &self.syntax }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct String {
+    pub(crate) syntax: SyntaxToken,
+}
+impl std::fmt::Display for String {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(&self.syntax, f)
+    }
+}
+impl AstToken for String {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == STRING }
+    fn cast(syntax: SyntaxToken) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxToken { &self.syntax }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct RawString {
+    pub(crate) syntax: SyntaxToken,
+}
+impl std::fmt::Display for RawString {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(&self.syntax, f)
+    }
+}
+impl AstToken for RawString {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RAW_STRING }
+    fn cast(syntax: SyntaxToken) -> Option<Self> {
+        if Self::can_cast(syntax.kind()) {
+            Some(Self { syntax })
+        } else {
+            None
+        }
+    }
+    fn syntax(&self) -> &SyntaxToken { &self.syntax }
+}
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
new file mode 100644
index 00000000000..254a37fe3e4
--- /dev/null
+++ b/crates/syntax/src/ast/make.rs
@@ -0,0 +1,392 @@
+//! This module contains free-standing functions for creating AST fragments out
+//! of smaller pieces.
+//!
+//! Note that all functions here intended to be stupid constructors, which just
+//! assemble a finish node from immediate children. If you want to do something
+//! smarter than that, it probably doesn't belong in this module.
+use itertools::Itertools;
+use stdx::format_to;
+
+use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxToken};
+
+pub fn name(text: &str) -> ast::Name {
+    ast_from_text(&format!("mod {};", text))
+}
+
+pub fn name_ref(text: &str) -> ast::NameRef {
+    ast_from_text(&format!("fn f() {{ {}; }}", text))
+}
+
+pub fn ty(text: &str) -> ast::Type {
+    ast_from_text(&format!("impl {} for D {{}};", text))
+}
+
+pub fn path_segment(name_ref: ast::NameRef) -> ast::PathSegment {
+    ast_from_text(&format!("use {};", name_ref))
+}
+pub fn path_unqualified(segment: ast::PathSegment) -> ast::Path {
+    path_from_text(&format!("use {}", segment))
+}
+pub fn path_qualified(qual: ast::Path, segment: ast::PathSegment) -> ast::Path {
+    path_from_text(&format!("{}::{}", qual, segment))
+}
+pub fn path_from_text(text: &str) -> ast::Path {
+    ast_from_text(text)
+}
+
+pub fn use_tree(
+    path: ast::Path,
+    use_tree_list: Option<ast::UseTreeList>,
+    alias: Option<ast::Rename>,
+    add_star: bool,
+) -> ast::UseTree {
+    let mut buf = "use ".to_string();
+    buf += &path.syntax().to_string();
+    if let Some(use_tree_list) = use_tree_list {
+        format_to!(buf, "::{}", use_tree_list);
+    }
+    if add_star {
+        buf += "::*";
+    }
+
+    if let Some(alias) = alias {
+        format_to!(buf, " {}", alias);
+    }
+    ast_from_text(&buf)
+}
+
+pub fn use_tree_list(use_trees: impl IntoIterator<Item = ast::UseTree>) -> ast::UseTreeList {
+    let use_trees = use_trees.into_iter().map(|it| it.syntax().clone()).join(", ");
+    ast_from_text(&format!("use {{{}}};", use_trees))
+}
+
+pub fn use_(use_tree: ast::UseTree) -> ast::Use {
+    ast_from_text(&format!("use {};", use_tree))
+}
+
+pub fn record_expr_field(name: ast::NameRef, expr: Option<ast::Expr>) -> ast::RecordExprField {
+    return match expr {
+        Some(expr) => from_text(&format!("{}: {}", name, expr)),
+        None => from_text(&name.to_string()),
+    };
+
+    fn from_text(text: &str) -> ast::RecordExprField {
+        ast_from_text(&format!("fn f() {{ S {{ {}, }} }}", text))
+    }
+}
+
+pub fn record_field(name: ast::NameRef, ty: ast::Type) -> ast::RecordField {
+    ast_from_text(&format!("struct S {{ {}: {}, }}", name, ty))
+}
+
+pub fn block_expr(
+    stmts: impl IntoIterator<Item = ast::Stmt>,
+    tail_expr: Option<ast::Expr>,
+) -> ast::BlockExpr {
+    let mut buf = "{\n".to_string();
+    for stmt in stmts.into_iter() {
+        format_to!(buf, "    {}\n", stmt);
+    }
+    if let Some(tail_expr) = tail_expr {
+        format_to!(buf, "    {}\n", tail_expr)
+    }
+    buf += "}";
+    ast_from_text(&format!("fn f() {}", buf))
+}
+
+pub fn expr_unit() -> ast::Expr {
+    expr_from_text("()")
+}
+pub fn expr_empty_block() -> ast::Expr {
+    expr_from_text("{}")
+}
+pub fn expr_unimplemented() -> ast::Expr {
+    expr_from_text("unimplemented!()")
+}
+pub fn expr_unreachable() -> ast::Expr {
+    expr_from_text("unreachable!()")
+}
+pub fn expr_todo() -> ast::Expr {
+    expr_from_text("todo!()")
+}
+pub fn expr_path(path: ast::Path) -> ast::Expr {
+    expr_from_text(&path.to_string())
+}
+pub fn expr_continue() -> ast::Expr {
+    expr_from_text("continue")
+}
+pub fn expr_break() -> ast::Expr {
+    expr_from_text("break")
+}
+pub fn expr_return() -> ast::Expr {
+    expr_from_text("return")
+}
+pub fn expr_match(expr: ast::Expr, match_arm_list: ast::MatchArmList) -> ast::Expr {
+    expr_from_text(&format!("match {} {}", expr, match_arm_list))
+}
+pub fn expr_if(condition: ast::Condition, then_branch: ast::BlockExpr) -> ast::Expr {
+    expr_from_text(&format!("if {} {}", condition, then_branch))
+}
+pub fn expr_prefix(op: SyntaxKind, expr: ast::Expr) -> ast::Expr {
+    let token = token(op);
+    expr_from_text(&format!("{}{}", token, expr))
+}
+fn expr_from_text(text: &str) -> ast::Expr {
+    ast_from_text(&format!("const C: () = {};", text))
+}
+
+pub fn try_expr_from_text(text: &str) -> Option<ast::Expr> {
+    try_ast_from_text(&format!("const C: () = {};", text))
+}
+
+pub fn condition(expr: ast::Expr, pattern: Option<ast::Pat>) -> ast::Condition {
+    match pattern {
+        None => ast_from_text(&format!("const _: () = while {} {{}};", expr)),
+        Some(pattern) => {
+            ast_from_text(&format!("const _: () = while let {} = {} {{}};", pattern, expr))
+        }
+    }
+}
+
+pub fn ident_pat(name: ast::Name) -> ast::IdentPat {
+    return from_text(name.text());
+
+    fn from_text(text: &str) -> ast::IdentPat {
+        ast_from_text(&format!("fn f({}: ())", text))
+    }
+}
+
+pub fn wildcard_pat() -> ast::WildcardPat {
+    return from_text("_");
+
+    fn from_text(text: &str) -> ast::WildcardPat {
+        ast_from_text(&format!("fn f({}: ())", text))
+    }
+}
+
+/// Creates a tuple of patterns from an interator of patterns.
+///
+/// Invariant: `pats` must be length > 1
+///
+/// FIXME handle `pats` length == 1
+pub fn tuple_pat(pats: impl IntoIterator<Item = ast::Pat>) -> ast::TuplePat {
+    let pats_str = pats.into_iter().map(|p| p.to_string()).join(", ");
+    return from_text(&format!("({})", pats_str));
+
+    fn from_text(text: &str) -> ast::TuplePat {
+        ast_from_text(&format!("fn f({}: ())", text))
+    }
+}
+
+pub fn tuple_struct_pat(
+    path: ast::Path,
+    pats: impl IntoIterator<Item = ast::Pat>,
+) -> ast::TupleStructPat {
+    let pats_str = pats.into_iter().join(", ");
+    return from_text(&format!("{}({})", path, pats_str));
+
+    fn from_text(text: &str) -> ast::TupleStructPat {
+        ast_from_text(&format!("fn f({}: ())", text))
+    }
+}
+
+pub fn record_pat(path: ast::Path, pats: impl IntoIterator<Item = ast::Pat>) -> ast::RecordPat {
+    let pats_str = pats.into_iter().join(", ");
+    return from_text(&format!("{} {{ {} }}", path, pats_str));
+
+    fn from_text(text: &str) -> ast::RecordPat {
+        ast_from_text(&format!("fn f({}: ())", text))
+    }
+}
+
+/// Returns a `BindPat` if the path has just one segment, a `PathPat` otherwise.
+pub fn path_pat(path: ast::Path) -> ast::Pat {
+    return from_text(&path.to_string());
+    fn from_text(text: &str) -> ast::Pat {
+        ast_from_text(&format!("fn f({}: ())", text))
+    }
+}
+
+pub fn match_arm(pats: impl IntoIterator<Item = ast::Pat>, expr: ast::Expr) -> ast::MatchArm {
+    let pats_str = pats.into_iter().join(" | ");
+    return from_text(&format!("{} => {}", pats_str, expr));
+
+    fn from_text(text: &str) -> ast::MatchArm {
+        ast_from_text(&format!("fn f() {{ match () {{{}}} }}", text))
+    }
+}
+
+pub fn match_arm_list(arms: impl IntoIterator<Item = ast::MatchArm>) -> ast::MatchArmList {
+    let arms_str = arms
+        .into_iter()
+        .map(|arm| {
+            let needs_comma = arm.expr().map_or(true, |it| !it.is_block_like());
+            let comma = if needs_comma { "," } else { "" };
+            format!("    {}{}\n", arm.syntax(), comma)
+        })
+        .collect::<String>();
+    return from_text(&arms_str);
+
+    fn from_text(text: &str) -> ast::MatchArmList {
+        ast_from_text(&format!("fn f() {{ match () {{\n{}}} }}", text))
+    }
+}
+
+pub fn where_pred(
+    path: ast::Path,
+    bounds: impl IntoIterator<Item = ast::TypeBound>,
+) -> ast::WherePred {
+    let bounds = bounds.into_iter().join(" + ");
+    return from_text(&format!("{}: {}", path, bounds));
+
+    fn from_text(text: &str) -> ast::WherePred {
+        ast_from_text(&format!("fn f() where {} {{ }}", text))
+    }
+}
+
+pub fn where_clause(preds: impl IntoIterator<Item = ast::WherePred>) -> ast::WhereClause {
+    let preds = preds.into_iter().join(", ");
+    return from_text(preds.as_str());
+
+    fn from_text(text: &str) -> ast::WhereClause {
+        ast_from_text(&format!("fn f() where {} {{ }}", text))
+    }
+}
+
+pub fn let_stmt(pattern: ast::Pat, initializer: Option<ast::Expr>) -> ast::LetStmt {
+    let text = match initializer {
+        Some(it) => format!("let {} = {};", pattern, it),
+        None => format!("let {};", pattern),
+    };
+    ast_from_text(&format!("fn f() {{ {} }}", text))
+}
+pub fn expr_stmt(expr: ast::Expr) -> ast::ExprStmt {
+    let semi = if expr.is_block_like() { "" } else { ";" };
+    ast_from_text(&format!("fn f() {{ {}{} (); }}", expr, semi))
+}
+
+pub fn token(kind: SyntaxKind) -> SyntaxToken {
+    tokens::SOURCE_FILE
+        .tree()
+        .syntax()
+        .descendants_with_tokens()
+        .filter_map(|it| it.into_token())
+        .find(|it| it.kind() == kind)
+        .unwrap_or_else(|| panic!("unhandled token: {:?}", kind))
+}
+
+pub fn param(name: String, ty: String) -> ast::Param {
+    ast_from_text(&format!("fn f({}: {}) {{ }}", name, ty))
+}
+
+pub fn param_list(pats: impl IntoIterator<Item = ast::Param>) -> ast::ParamList {
+    let args = pats.into_iter().join(", ");
+    ast_from_text(&format!("fn f({}) {{ }}", args))
+}
+
+pub fn visibility_pub_crate() -> ast::Visibility {
+    ast_from_text("pub(crate) struct S")
+}
+
+pub fn fn_(
+    visibility: Option<ast::Visibility>,
+    fn_name: ast::Name,
+    type_params: Option<ast::GenericParamList>,
+    params: ast::ParamList,
+    body: ast::BlockExpr,
+) -> ast::Fn {
+    let type_params =
+        if let Some(type_params) = type_params { format!("<{}>", type_params) } else { "".into() };
+    let visibility = match visibility {
+        None => String::new(),
+        Some(it) => format!("{} ", it),
+    };
+    ast_from_text(&format!("{}fn {}{}{} {}", visibility, fn_name, type_params, params, body))
+}
+
+fn ast_from_text<N: AstNode>(text: &str) -> N {
+    let parse = SourceFile::parse(text);
+    let node = match parse.tree().syntax().descendants().find_map(N::cast) {
+        Some(it) => it,
+        None => {
+            panic!("Failed to make ast node `{}` from text {}", std::any::type_name::<N>(), text)
+        }
+    };
+    let node = node.syntax().clone();
+    let node = unroot(node);
+    let node = N::cast(node).unwrap();
+    assert_eq!(node.syntax().text_range().start(), 0.into());
+    node
+}
+
+fn try_ast_from_text<N: AstNode>(text: &str) -> Option<N> {
+    let parse = SourceFile::parse(text);
+    let node = parse.tree().syntax().descendants().find_map(N::cast)?;
+    let node = node.syntax().clone();
+    let node = unroot(node);
+    let node = N::cast(node).unwrap();
+    assert_eq!(node.syntax().text_range().start(), 0.into());
+    Some(node)
+}
+
+fn unroot(n: SyntaxNode) -> SyntaxNode {
+    SyntaxNode::new_root(n.green().clone())
+}
+
+pub mod tokens {
+    use once_cell::sync::Lazy;
+
+    use crate::{ast, AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken};
+
+    pub(super) static SOURCE_FILE: Lazy<Parse<SourceFile>> =
+        Lazy::new(|| SourceFile::parse("const C: <()>::Item = (1 != 1, 2 == 2, !true)\n;"));
+
+    pub fn single_space() -> SyntaxToken {
+        SOURCE_FILE
+            .tree()
+            .syntax()
+            .descendants_with_tokens()
+            .filter_map(|it| it.into_token())
+            .find(|it| it.kind() == WHITESPACE && it.text().as_str() == " ")
+            .unwrap()
+    }
+
+    pub fn whitespace(text: &str) -> SyntaxToken {
+        assert!(text.trim().is_empty());
+        let sf = SourceFile::parse(text).ok().unwrap();
+        sf.syntax().first_child_or_token().unwrap().into_token().unwrap()
+    }
+
+    pub fn doc_comment(text: &str) -> SyntaxToken {
+        assert!(!text.trim().is_empty());
+        let sf = SourceFile::parse(text).ok().unwrap();
+        sf.syntax().first_child_or_token().unwrap().into_token().unwrap()
+    }
+
+    pub fn literal(text: &str) -> SyntaxToken {
+        assert_eq!(text.trim(), text);
+        let lit: ast::Literal = super::ast_from_text(&format!("fn f() {{ let _ = {}; }}", text));
+        lit.syntax().first_child_or_token().unwrap().into_token().unwrap()
+    }
+
+    pub fn single_newline() -> SyntaxToken {
+        SOURCE_FILE
+            .tree()
+            .syntax()
+            .descendants_with_tokens()
+            .filter_map(|it| it.into_token())
+            .find(|it| it.kind() == WHITESPACE && it.text().as_str() == "\n")
+            .unwrap()
+    }
+
+    pub struct WsBuilder(SourceFile);
+
+    impl WsBuilder {
+        pub fn new(text: &str) -> WsBuilder {
+            WsBuilder(SourceFile::parse(text).ok().unwrap())
+        }
+        pub fn ws(&self) -> SyntaxToken {
+            self.0.syntax().first_child_or_token().unwrap().into_token().unwrap()
+        }
+    }
+}
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
new file mode 100644
index 00000000000..50c1c157d87
--- /dev/null
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -0,0 +1,485 @@
+//! Various extension methods to ast Nodes, which are hard to code-generate.
+//! Extensions for various expressions live in a sibling `expr_extensions` module.
+
+use std::fmt;
+
+use itertools::Itertools;
+use parser::SyntaxKind;
+
+use crate::{
+    ast::{self, support, AstNode, NameOwner, SyntaxNode},
+    SmolStr, SyntaxElement, SyntaxToken, T,
+};
+
+impl ast::Name {
+    pub fn text(&self) -> &SmolStr {
+        text_of_first_token(self.syntax())
+    }
+}
+
+impl ast::NameRef {
+    pub fn text(&self) -> &SmolStr {
+        text_of_first_token(self.syntax())
+    }
+
+    pub fn as_tuple_field(&self) -> Option<usize> {
+        self.text().parse().ok()
+    }
+}
+
+fn text_of_first_token(node: &SyntaxNode) -> &SmolStr {
+    node.green().children().next().and_then(|it| it.into_token()).unwrap().text()
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum AttrKind {
+    Inner,
+    Outer,
+}
+
+impl ast::Attr {
+    pub fn as_simple_atom(&self) -> Option<SmolStr> {
+        if self.eq_token().is_some() || self.token_tree().is_some() {
+            return None;
+        }
+        self.simple_name()
+    }
+
+    pub fn as_simple_call(&self) -> Option<(SmolStr, ast::TokenTree)> {
+        let tt = self.token_tree()?;
+        Some((self.simple_name()?, tt))
+    }
+
+    pub fn as_simple_key_value(&self) -> Option<(SmolStr, SmolStr)> {
+        let lit = self.literal()?;
+        let key = self.simple_name()?;
+        // FIXME: escape? raw string?
+        let value = lit.syntax().first_token()?.text().trim_matches('"').into();
+        Some((key, value))
+    }
+
+    pub fn simple_name(&self) -> Option<SmolStr> {
+        let path = self.path()?;
+        match (path.segment(), path.qualifier()) {
+            (Some(segment), None) => Some(segment.syntax().first_token()?.text().clone()),
+            _ => None,
+        }
+    }
+
+    pub fn kind(&self) -> AttrKind {
+        let first_token = self.syntax().first_token();
+        let first_token_kind = first_token.as_ref().map(SyntaxToken::kind);
+        let second_token_kind =
+            first_token.and_then(|token| token.next_token()).as_ref().map(SyntaxToken::kind);
+
+        match (first_token_kind, second_token_kind) {
+            (Some(SyntaxKind::POUND), Some(T![!])) => AttrKind::Inner,
+            _ => AttrKind::Outer,
+        }
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum PathSegmentKind {
+    Name(ast::NameRef),
+    Type { type_ref: Option<ast::Type>, trait_ref: Option<ast::PathType> },
+    SelfKw,
+    SuperKw,
+    CrateKw,
+}
+
+impl ast::PathSegment {
+    pub fn parent_path(&self) -> ast::Path {
+        self.syntax()
+            .parent()
+            .and_then(ast::Path::cast)
+            .expect("segments are always nested in paths")
+    }
+
+    pub fn kind(&self) -> Option<PathSegmentKind> {
+        let res = if let Some(name_ref) = self.name_ref() {
+            PathSegmentKind::Name(name_ref)
+        } else {
+            match self.syntax().first_child_or_token()?.kind() {
+                T![self] => PathSegmentKind::SelfKw,
+                T![super] => PathSegmentKind::SuperKw,
+                T![crate] => PathSegmentKind::CrateKw,
+                T![<] => {
+                    // <T> or <T as Trait>
+                    // T is any TypeRef, Trait has to be a PathType
+                    let mut type_refs =
+                        self.syntax().children().filter(|node| ast::Type::can_cast(node.kind()));
+                    let type_ref = type_refs.next().and_then(ast::Type::cast);
+                    let trait_ref = type_refs.next().and_then(ast::PathType::cast);
+                    PathSegmentKind::Type { type_ref, trait_ref }
+                }
+                _ => return None,
+            }
+        };
+        Some(res)
+    }
+}
+
+impl ast::Path {
+    pub fn parent_path(&self) -> Option<ast::Path> {
+        self.syntax().parent().and_then(ast::Path::cast)
+    }
+}
+
+impl ast::UseTreeList {
+    pub fn parent_use_tree(&self) -> ast::UseTree {
+        self.syntax()
+            .parent()
+            .and_then(ast::UseTree::cast)
+            .expect("UseTreeLists are always nested in UseTrees")
+    }
+}
+
+impl ast::Impl {
+    pub fn self_ty(&self) -> Option<ast::Type> {
+        match self.target() {
+            (Some(t), None) | (_, Some(t)) => Some(t),
+            _ => None,
+        }
+    }
+
+    pub fn trait_(&self) -> Option<ast::Type> {
+        match self.target() {
+            (Some(t), Some(_)) => Some(t),
+            _ => None,
+        }
+    }
+
+    fn target(&self) -> (Option<ast::Type>, Option<ast::Type>) {
+        let mut types = support::children(self.syntax());
+        let first = types.next();
+        let second = types.next();
+        (first, second)
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum StructKind {
+    Record(ast::RecordFieldList),
+    Tuple(ast::TupleFieldList),
+    Unit,
+}
+
+impl StructKind {
+    fn from_node<N: AstNode>(node: &N) -> StructKind {
+        if let Some(nfdl) = support::child::<ast::RecordFieldList>(node.syntax()) {
+            StructKind::Record(nfdl)
+        } else if let Some(pfl) = support::child::<ast::TupleFieldList>(node.syntax()) {
+            StructKind::Tuple(pfl)
+        } else {
+            StructKind::Unit
+        }
+    }
+}
+
+impl ast::Struct {
+    pub fn kind(&self) -> StructKind {
+        StructKind::from_node(self)
+    }
+}
+
+impl ast::RecordExprField {
+    pub fn for_field_name(field_name: &ast::NameRef) -> Option<ast::RecordExprField> {
+        let candidate =
+            field_name.syntax().parent().and_then(ast::RecordExprField::cast).or_else(|| {
+                field_name.syntax().ancestors().nth(4).and_then(ast::RecordExprField::cast)
+            })?;
+        if candidate.field_name().as_ref() == Some(field_name) {
+            Some(candidate)
+        } else {
+            None
+        }
+    }
+
+    /// Deals with field init shorthand
+    pub fn field_name(&self) -> Option<ast::NameRef> {
+        if let Some(name_ref) = self.name_ref() {
+            return Some(name_ref);
+        }
+        if let Some(ast::Expr::PathExpr(expr)) = self.expr() {
+            let path = expr.path()?;
+            let segment = path.segment()?;
+            let name_ref = segment.name_ref()?;
+            if path.qualifier().is_none() {
+                return Some(name_ref);
+            }
+        }
+        None
+    }
+}
+
+pub enum NameOrNameRef {
+    Name(ast::Name),
+    NameRef(ast::NameRef),
+}
+
+impl fmt::Display for NameOrNameRef {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            NameOrNameRef::Name(it) => fmt::Display::fmt(it, f),
+            NameOrNameRef::NameRef(it) => fmt::Display::fmt(it, f),
+        }
+    }
+}
+
+impl ast::RecordPatField {
+    /// Deals with field init shorthand
+    pub fn field_name(&self) -> Option<NameOrNameRef> {
+        if let Some(name_ref) = self.name_ref() {
+            return Some(NameOrNameRef::NameRef(name_ref));
+        }
+        if let Some(ast::Pat::IdentPat(pat)) = self.pat() {
+            let name = pat.name()?;
+            return Some(NameOrNameRef::Name(name));
+        }
+        None
+    }
+}
+
+impl ast::Variant {
+    pub fn parent_enum(&self) -> ast::Enum {
+        self.syntax()
+            .parent()
+            .and_then(|it| it.parent())
+            .and_then(ast::Enum::cast)
+            .expect("EnumVariants are always nested in Enums")
+    }
+    pub fn kind(&self) -> StructKind {
+        StructKind::from_node(self)
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum FieldKind {
+    Name(ast::NameRef),
+    Index(SyntaxToken),
+}
+
+impl ast::FieldExpr {
+    pub fn index_token(&self) -> Option<SyntaxToken> {
+        self.syntax
+            .children_with_tokens()
+            // FIXME: Accepting floats here to reject them in validation later
+            .find(|c| c.kind() == SyntaxKind::INT_NUMBER || c.kind() == SyntaxKind::FLOAT_NUMBER)
+            .as_ref()
+            .and_then(SyntaxElement::as_token)
+            .cloned()
+    }
+
+    pub fn field_access(&self) -> Option<FieldKind> {
+        if let Some(nr) = self.name_ref() {
+            Some(FieldKind::Name(nr))
+        } else if let Some(tok) = self.index_token() {
+            Some(FieldKind::Index(tok))
+        } else {
+            None
+        }
+    }
+}
+
+pub struct SlicePatComponents {
+    pub prefix: Vec<ast::Pat>,
+    pub slice: Option<ast::Pat>,
+    pub suffix: Vec<ast::Pat>,
+}
+
+impl ast::SlicePat {
+    pub fn components(&self) -> SlicePatComponents {
+        let mut args = self.pats().peekable();
+        let prefix = args
+            .peeking_take_while(|p| match p {
+                ast::Pat::RestPat(_) => false,
+                ast::Pat::IdentPat(bp) => match bp.pat() {
+                    Some(ast::Pat::RestPat(_)) => false,
+                    _ => true,
+                },
+                ast::Pat::RefPat(rp) => match rp.pat() {
+                    Some(ast::Pat::RestPat(_)) => false,
+                    Some(ast::Pat::IdentPat(bp)) => match bp.pat() {
+                        Some(ast::Pat::RestPat(_)) => false,
+                        _ => true,
+                    },
+                    _ => true,
+                },
+                _ => true,
+            })
+            .collect();
+        let slice = args.next();
+        let suffix = args.collect();
+
+        SlicePatComponents { prefix, slice, suffix }
+    }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub enum SelfParamKind {
+    /// self
+    Owned,
+    /// &self
+    Ref,
+    /// &mut self
+    MutRef,
+}
+
+impl ast::SelfParam {
+    pub fn kind(&self) -> SelfParamKind {
+        if self.amp_token().is_some() {
+            if self.mut_token().is_some() {
+                SelfParamKind::MutRef
+            } else {
+                SelfParamKind::Ref
+            }
+        } else {
+            SelfParamKind::Owned
+        }
+    }
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub enum TypeBoundKind {
+    /// Trait
+    PathType(ast::PathType),
+    /// for<'a> ...
+    ForType(ast::ForType),
+    /// 'a
+    Lifetime(SyntaxToken),
+}
+
+impl ast::TypeBound {
+    pub fn kind(&self) -> TypeBoundKind {
+        if let Some(path_type) = support::children(self.syntax()).next() {
+            TypeBoundKind::PathType(path_type)
+        } else if let Some(for_type) = support::children(self.syntax()).next() {
+            TypeBoundKind::ForType(for_type)
+        } else if let Some(lifetime) = self.lifetime_token() {
+            TypeBoundKind::Lifetime(lifetime)
+        } else {
+            unreachable!()
+        }
+    }
+}
+
+pub enum VisibilityKind {
+    In(ast::Path),
+    PubCrate,
+    PubSuper,
+    PubSelf,
+    Pub,
+}
+
+impl ast::Visibility {
+    pub fn kind(&self) -> VisibilityKind {
+        if let Some(path) = support::children(self.syntax()).next() {
+            VisibilityKind::In(path)
+        } else if self.crate_token().is_some() {
+            VisibilityKind::PubCrate
+        } else if self.super_token().is_some() {
+            VisibilityKind::PubSuper
+        } else if self.self_token().is_some() {
+            VisibilityKind::PubSelf
+        } else {
+            VisibilityKind::Pub
+        }
+    }
+}
+
+impl ast::MacroCall {
+    pub fn is_macro_rules(&self) -> Option<ast::Name> {
+        let name_ref = self.path()?.segment()?.name_ref()?;
+        if name_ref.text() == "macro_rules" {
+            self.name()
+        } else {
+            None
+        }
+    }
+
+    pub fn is_bang(&self) -> bool {
+        self.is_macro_rules().is_none()
+    }
+}
+
+impl ast::LifetimeParam {
+    pub fn lifetime_bounds(&self) -> impl Iterator<Item = SyntaxToken> {
+        self.syntax()
+            .children_with_tokens()
+            .filter_map(|it| it.into_token())
+            .skip_while(|x| x.kind() != T![:])
+            .filter(|it| it.kind() == T![lifetime])
+    }
+}
+
+impl ast::RangePat {
+    pub fn start(&self) -> Option<ast::Pat> {
+        self.syntax()
+            .children_with_tokens()
+            .take_while(|it| !(it.kind() == T![..] || it.kind() == T![..=]))
+            .filter_map(|it| it.into_node())
+            .find_map(ast::Pat::cast)
+    }
+
+    pub fn end(&self) -> Option<ast::Pat> {
+        self.syntax()
+            .children_with_tokens()
+            .skip_while(|it| !(it.kind() == T![..] || it.kind() == T![..=]))
+            .filter_map(|it| it.into_node())
+            .find_map(ast::Pat::cast)
+    }
+}
+
+impl ast::TokenTree {
+    pub fn left_delimiter_token(&self) -> Option<SyntaxToken> {
+        self.syntax()
+            .first_child_or_token()?
+            .into_token()
+            .filter(|it| matches!(it.kind(), T!['{'] | T!['('] | T!['[']))
+    }
+
+    pub fn right_delimiter_token(&self) -> Option<SyntaxToken> {
+        self.syntax()
+            .last_child_or_token()?
+            .into_token()
+            .filter(|it| matches!(it.kind(), T!['}'] | T![')'] | T![']']))
+    }
+}
+
+impl ast::GenericParamList {
+    pub fn lifetime_params(&self) -> impl Iterator<Item = ast::LifetimeParam> {
+        self.generic_params().filter_map(|param| match param {
+            ast::GenericParam::LifetimeParam(it) => Some(it),
+            ast::GenericParam::TypeParam(_) | ast::GenericParam::ConstParam(_) => None,
+        })
+    }
+    pub fn type_params(&self) -> impl Iterator<Item = ast::TypeParam> {
+        self.generic_params().filter_map(|param| match param {
+            ast::GenericParam::TypeParam(it) => Some(it),
+            ast::GenericParam::LifetimeParam(_) | ast::GenericParam::ConstParam(_) => None,
+        })
+    }
+    pub fn const_params(&self) -> impl Iterator<Item = ast::ConstParam> {
+        self.generic_params().filter_map(|param| match param {
+            ast::GenericParam::ConstParam(it) => Some(it),
+            ast::GenericParam::TypeParam(_) | ast::GenericParam::LifetimeParam(_) => None,
+        })
+    }
+}
+
+impl ast::DocCommentsOwner for ast::SourceFile {}
+impl ast::DocCommentsOwner for ast::Fn {}
+impl ast::DocCommentsOwner for ast::Struct {}
+impl ast::DocCommentsOwner for ast::Union {}
+impl ast::DocCommentsOwner for ast::RecordField {}
+impl ast::DocCommentsOwner for ast::TupleField {}
+impl ast::DocCommentsOwner for ast::Enum {}
+impl ast::DocCommentsOwner for ast::Variant {}
+impl ast::DocCommentsOwner for ast::Trait {}
+impl ast::DocCommentsOwner for ast::Module {}
+impl ast::DocCommentsOwner for ast::Static {}
+impl ast::DocCommentsOwner for ast::Const {}
+impl ast::DocCommentsOwner for ast::TypeAlias {}
+impl ast::DocCommentsOwner for ast::Impl {}
+impl ast::DocCommentsOwner for ast::MacroCall {}
diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs
new file mode 100644
index 00000000000..c5ef92733d8
--- /dev/null
+++ b/crates/syntax/src/ast/token_ext.rs
@@ -0,0 +1,538 @@
+//! There are many AstNodes, but only a few tokens, so we hand-write them here.
+
+use std::{
+    borrow::Cow,
+    convert::{TryFrom, TryInto},
+};
+
+use rustc_lexer::unescape::{unescape_literal, Mode};
+
+use crate::{
+    ast::{AstToken, Comment, RawString, String, Whitespace},
+    TextRange, TextSize,
+};
+
+impl Comment {
+    pub fn kind(&self) -> CommentKind {
+        kind_by_prefix(self.text())
+    }
+
+    pub fn prefix(&self) -> &'static str {
+        for (prefix, k) in COMMENT_PREFIX_TO_KIND.iter() {
+            if *k == self.kind() && self.text().starts_with(prefix) {
+                return prefix;
+            }
+        }
+        unreachable!()
+    }
+}
+
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub struct CommentKind {
+    pub shape: CommentShape,
+    pub doc: Option<CommentPlacement>,
+}
+
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub enum CommentShape {
+    Line,
+    Block,
+}
+
+impl CommentShape {
+    pub fn is_line(self) -> bool {
+        self == CommentShape::Line
+    }
+
+    pub fn is_block(self) -> bool {
+        self == CommentShape::Block
+    }
+}
+
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub enum CommentPlacement {
+    Inner,
+    Outer,
+}
+
+const COMMENT_PREFIX_TO_KIND: &[(&str, CommentKind)] = {
+    use {CommentPlacement::*, CommentShape::*};
+    &[
+        ("////", CommentKind { shape: Line, doc: None }),
+        ("///", CommentKind { shape: Line, doc: Some(Outer) }),
+        ("//!", CommentKind { shape: Line, doc: Some(Inner) }),
+        ("/**", CommentKind { shape: Block, doc: Some(Outer) }),
+        ("/*!", CommentKind { shape: Block, doc: Some(Inner) }),
+        ("//", CommentKind { shape: Line, doc: None }),
+        ("/*", CommentKind { shape: Block, doc: None }),
+    ]
+};
+
+fn kind_by_prefix(text: &str) -> CommentKind {
+    if text == "/**/" {
+        return CommentKind { shape: CommentShape::Block, doc: None };
+    }
+    for (prefix, kind) in COMMENT_PREFIX_TO_KIND.iter() {
+        if text.starts_with(prefix) {
+            return *kind;
+        }
+    }
+    panic!("bad comment text: {:?}", text)
+}
+
+impl Whitespace {
+    pub fn spans_multiple_lines(&self) -> bool {
+        let text = self.text();
+        text.find('\n').map_or(false, |idx| text[idx + 1..].contains('\n'))
+    }
+}
+
+pub struct QuoteOffsets {
+    pub quotes: (TextRange, TextRange),
+    pub contents: TextRange,
+}
+
+impl QuoteOffsets {
+    fn new(literal: &str) -> Option<QuoteOffsets> {
+        let left_quote = literal.find('"')?;
+        let right_quote = literal.rfind('"')?;
+        if left_quote == right_quote {
+            // `literal` only contains one quote
+            return None;
+        }
+
+        let start = TextSize::from(0);
+        let left_quote = TextSize::try_from(left_quote).unwrap() + TextSize::of('"');
+        let right_quote = TextSize::try_from(right_quote).unwrap();
+        let end = TextSize::of(literal);
+
+        let res = QuoteOffsets {
+            quotes: (TextRange::new(start, left_quote), TextRange::new(right_quote, end)),
+            contents: TextRange::new(left_quote, right_quote),
+        };
+        Some(res)
+    }
+}
+
+pub trait HasQuotes: AstToken {
+    fn quote_offsets(&self) -> Option<QuoteOffsets> {
+        let text = self.text().as_str();
+        let offsets = QuoteOffsets::new(text)?;
+        let o = self.syntax().text_range().start();
+        let offsets = QuoteOffsets {
+            quotes: (offsets.quotes.0 + o, offsets.quotes.1 + o),
+            contents: offsets.contents + o,
+        };
+        Some(offsets)
+    }
+    fn open_quote_text_range(&self) -> Option<TextRange> {
+        self.quote_offsets().map(|it| it.quotes.0)
+    }
+
+    fn close_quote_text_range(&self) -> Option<TextRange> {
+        self.quote_offsets().map(|it| it.quotes.1)
+    }
+
+    fn text_range_between_quotes(&self) -> Option<TextRange> {
+        self.quote_offsets().map(|it| it.contents)
+    }
+}
+
+impl HasQuotes for String {}
+impl HasQuotes for RawString {}
+
+pub trait HasStringValue: HasQuotes {
+    fn value(&self) -> Option<Cow<'_, str>>;
+}
+
+impl HasStringValue for String {
+    fn value(&self) -> Option<Cow<'_, str>> {
+        let text = self.text().as_str();
+        let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
+
+        let mut buf = std::string::String::with_capacity(text.len());
+        let mut has_error = false;
+        unescape_literal(text, Mode::Str, &mut |_, unescaped_char| match unescaped_char {
+            Ok(c) => buf.push(c),
+            Err(_) => has_error = true,
+        });
+
+        if has_error {
+            return None;
+        }
+        // FIXME: don't actually allocate for borrowed case
+        let res = if buf == text { Cow::Borrowed(text) } else { Cow::Owned(buf) };
+        Some(res)
+    }
+}
+
+impl HasStringValue for RawString {
+    fn value(&self) -> Option<Cow<'_, str>> {
+        let text = self.text().as_str();
+        let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
+        Some(Cow::Borrowed(text))
+    }
+}
+
+impl RawString {
+    pub fn map_range_up(&self, range: TextRange) -> Option<TextRange> {
+        let contents_range = self.text_range_between_quotes()?;
+        assert!(TextRange::up_to(contents_range.len()).contains_range(range));
+        Some(range + contents_range.start())
+    }
+}
+
+#[derive(Debug)]
+pub enum FormatSpecifier {
+    Open,
+    Close,
+    Integer,
+    Identifier,
+    Colon,
+    Fill,
+    Align,
+    Sign,
+    NumberSign,
+    Zero,
+    DollarSign,
+    Dot,
+    Asterisk,
+    QuestionMark,
+}
+
+pub trait HasFormatSpecifier: AstToken {
+    fn char_ranges(
+        &self,
+    ) -> Option<Vec<(TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>>;
+
+    fn lex_format_specifier<F>(&self, mut callback: F)
+    where
+        F: FnMut(TextRange, FormatSpecifier),
+    {
+        let char_ranges = if let Some(char_ranges) = self.char_ranges() {
+            char_ranges
+        } else {
+            return;
+        };
+        let mut chars = char_ranges.iter().peekable();
+
+        while let Some((range, first_char)) = chars.next() {
+            match first_char {
+                Ok('{') => {
+                    // Format specifier, see syntax at https://doc.rust-lang.org/std/fmt/index.html#syntax
+                    if let Some((_, Ok('{'))) = chars.peek() {
+                        // Escaped format specifier, `{{`
+                        chars.next();
+                        continue;
+                    }
+
+                    callback(*range, FormatSpecifier::Open);
+
+                    // check for integer/identifier
+                    match chars
+                        .peek()
+                        .and_then(|next| next.1.as_ref().ok())
+                        .copied()
+                        .unwrap_or_default()
+                    {
+                        '0'..='9' => {
+                            // integer
+                            read_integer(&mut chars, &mut callback);
+                        }
+                        c if c == '_' || c.is_alphabetic() => {
+                            // identifier
+                            read_identifier(&mut chars, &mut callback);
+                        }
+                        _ => {}
+                    }
+
+                    if let Some((_, Ok(':'))) = chars.peek() {
+                        skip_char_and_emit(&mut chars, FormatSpecifier::Colon, &mut callback);
+
+                        // check for fill/align
+                        let mut cloned = chars.clone().take(2);
+                        let first = cloned
+                            .next()
+                            .and_then(|next| next.1.as_ref().ok())
+                            .copied()
+                            .unwrap_or_default();
+                        let second = cloned
+                            .next()
+                            .and_then(|next| next.1.as_ref().ok())
+                            .copied()
+                            .unwrap_or_default();
+                        match second {
+                            '<' | '^' | '>' => {
+                                // alignment specifier, first char specifies fillment
+                                skip_char_and_emit(
+                                    &mut chars,
+                                    FormatSpecifier::Fill,
+                                    &mut callback,
+                                );
+                                skip_char_and_emit(
+                                    &mut chars,
+                                    FormatSpecifier::Align,
+                                    &mut callback,
+                                );
+                            }
+                            _ => match first {
+                                '<' | '^' | '>' => {
+                                    skip_char_and_emit(
+                                        &mut chars,
+                                        FormatSpecifier::Align,
+                                        &mut callback,
+                                    );
+                                }
+                                _ => {}
+                            },
+                        }
+
+                        // check for sign
+                        match chars
+                            .peek()
+                            .and_then(|next| next.1.as_ref().ok())
+                            .copied()
+                            .unwrap_or_default()
+                        {
+                            '+' | '-' => {
+                                skip_char_and_emit(
+                                    &mut chars,
+                                    FormatSpecifier::Sign,
+                                    &mut callback,
+                                );
+                            }
+                            _ => {}
+                        }
+
+                        // check for `#`
+                        if let Some((_, Ok('#'))) = chars.peek() {
+                            skip_char_and_emit(
+                                &mut chars,
+                                FormatSpecifier::NumberSign,
+                                &mut callback,
+                            );
+                        }
+
+                        // check for `0`
+                        let mut cloned = chars.clone().take(2);
+                        let first = cloned.next().and_then(|next| next.1.as_ref().ok()).copied();
+                        let second = cloned.next().and_then(|next| next.1.as_ref().ok()).copied();
+
+                        if first == Some('0') && second != Some('$') {
+                            skip_char_and_emit(&mut chars, FormatSpecifier::Zero, &mut callback);
+                        }
+
+                        // width
+                        match chars
+                            .peek()
+                            .and_then(|next| next.1.as_ref().ok())
+                            .copied()
+                            .unwrap_or_default()
+                        {
+                            '0'..='9' => {
+                                read_integer(&mut chars, &mut callback);
+                                if let Some((_, Ok('$'))) = chars.peek() {
+                                    skip_char_and_emit(
+                                        &mut chars,
+                                        FormatSpecifier::DollarSign,
+                                        &mut callback,
+                                    );
+                                }
+                            }
+                            c if c == '_' || c.is_alphabetic() => {
+                                read_identifier(&mut chars, &mut callback);
+                                // can be either width (indicated by dollar sign, or type in which case
+                                // the next sign has to be `}`)
+                                let next =
+                                    chars.peek().and_then(|next| next.1.as_ref().ok()).copied();
+                                match next {
+                                    Some('$') => skip_char_and_emit(
+                                        &mut chars,
+                                        FormatSpecifier::DollarSign,
+                                        &mut callback,
+                                    ),
+                                    Some('}') => {
+                                        skip_char_and_emit(
+                                            &mut chars,
+                                            FormatSpecifier::Close,
+                                            &mut callback,
+                                        );
+                                        continue;
+                                    }
+                                    _ => continue,
+                                };
+                            }
+                            _ => {}
+                        }
+
+                        // precision
+                        if let Some((_, Ok('.'))) = chars.peek() {
+                            skip_char_and_emit(&mut chars, FormatSpecifier::Dot, &mut callback);
+
+                            match chars
+                                .peek()
+                                .and_then(|next| next.1.as_ref().ok())
+                                .copied()
+                                .unwrap_or_default()
+                            {
+                                '*' => {
+                                    skip_char_and_emit(
+                                        &mut chars,
+                                        FormatSpecifier::Asterisk,
+                                        &mut callback,
+                                    );
+                                }
+                                '0'..='9' => {
+                                    read_integer(&mut chars, &mut callback);
+                                    if let Some((_, Ok('$'))) = chars.peek() {
+                                        skip_char_and_emit(
+                                            &mut chars,
+                                            FormatSpecifier::DollarSign,
+                                            &mut callback,
+                                        );
+                                    }
+                                }
+                                c if c == '_' || c.is_alphabetic() => {
+                                    read_identifier(&mut chars, &mut callback);
+                                    if chars.peek().and_then(|next| next.1.as_ref().ok()).copied()
+                                        != Some('$')
+                                    {
+                                        continue;
+                                    }
+                                    skip_char_and_emit(
+                                        &mut chars,
+                                        FormatSpecifier::DollarSign,
+                                        &mut callback,
+                                    );
+                                }
+                                _ => {
+                                    continue;
+                                }
+                            }
+                        }
+
+                        // type
+                        match chars
+                            .peek()
+                            .and_then(|next| next.1.as_ref().ok())
+                            .copied()
+                            .unwrap_or_default()
+                        {
+                            '?' => {
+                                skip_char_and_emit(
+                                    &mut chars,
+                                    FormatSpecifier::QuestionMark,
+                                    &mut callback,
+                                );
+                            }
+                            c if c == '_' || c.is_alphabetic() => {
+                                read_identifier(&mut chars, &mut callback);
+                            }
+                            _ => {}
+                        }
+                    }
+
+                    if let Some((_, Ok('}'))) = chars.peek() {
+                        skip_char_and_emit(&mut chars, FormatSpecifier::Close, &mut callback);
+                    } else {
+                        continue;
+                    }
+                }
+                _ => {
+                    while let Some((_, Ok(next_char))) = chars.peek() {
+                        match next_char {
+                            '{' => break,
+                            _ => {}
+                        }
+                        chars.next();
+                    }
+                }
+            };
+        }
+
+        fn skip_char_and_emit<'a, I, F>(
+            chars: &mut std::iter::Peekable<I>,
+            emit: FormatSpecifier,
+            callback: &mut F,
+        ) where
+            I: Iterator<Item = &'a (TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>,
+            F: FnMut(TextRange, FormatSpecifier),
+        {
+            let (range, _) = chars.next().unwrap();
+            callback(*range, emit);
+        }
+
+        fn read_integer<'a, I, F>(chars: &mut std::iter::Peekable<I>, callback: &mut F)
+        where
+            I: Iterator<Item = &'a (TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>,
+            F: FnMut(TextRange, FormatSpecifier),
+        {
+            let (mut range, c) = chars.next().unwrap();
+            assert!(c.as_ref().unwrap().is_ascii_digit());
+            while let Some((r, Ok(next_char))) = chars.peek() {
+                if next_char.is_ascii_digit() {
+                    chars.next();
+                    range = range.cover(*r);
+                } else {
+                    break;
+                }
+            }
+            callback(range, FormatSpecifier::Integer);
+        }
+
+        fn read_identifier<'a, I, F>(chars: &mut std::iter::Peekable<I>, callback: &mut F)
+        where
+            I: Iterator<Item = &'a (TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>,
+            F: FnMut(TextRange, FormatSpecifier),
+        {
+            let (mut range, c) = chars.next().unwrap();
+            assert!(c.as_ref().unwrap().is_alphabetic() || *c.as_ref().unwrap() == '_');
+            while let Some((r, Ok(next_char))) = chars.peek() {
+                if *next_char == '_' || next_char.is_ascii_digit() || next_char.is_alphabetic() {
+                    chars.next();
+                    range = range.cover(*r);
+                } else {
+                    break;
+                }
+            }
+            callback(range, FormatSpecifier::Identifier);
+        }
+    }
+}
+
+impl HasFormatSpecifier for String {
+    fn char_ranges(
+        &self,
+    ) -> Option<Vec<(TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>> {
+        let text = self.text().as_str();
+        let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
+        let offset = self.text_range_between_quotes()?.start() - self.syntax().text_range().start();
+
+        let mut res = Vec::with_capacity(text.len());
+        unescape_literal(text, Mode::Str, &mut |range, unescaped_char| {
+            res.push((
+                TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap())
+                    + offset,
+                unescaped_char,
+            ))
+        });
+
+        Some(res)
+    }
+}
+
+impl HasFormatSpecifier for RawString {
+    fn char_ranges(
+        &self,
+    ) -> Option<Vec<(TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>> {
+        let text = self.text().as_str();
+        let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
+        let offset = self.text_range_between_quotes()?.start() - self.syntax().text_range().start();
+
+        let mut res = Vec::with_capacity(text.len());
+        for (idx, c) in text.char_indices() {
+            res.push((TextRange::at(idx.try_into().unwrap(), TextSize::of(c)) + offset, Ok(c)));
+        }
+        Some(res)
+    }
+}
diff --git a/crates/syntax/src/ast/traits.rs b/crates/syntax/src/ast/traits.rs
new file mode 100644
index 00000000000..0bdc22d953f
--- /dev/null
+++ b/crates/syntax/src/ast/traits.rs
@@ -0,0 +1,141 @@
+//! Various traits that are implemented by ast nodes.
+//!
+//! The implementations are usually trivial, and live in generated.rs
+use itertools::Itertools;
+
+use crate::{
+    ast::{self, support, AstChildren, AstNode, AstToken},
+    syntax_node::SyntaxElementChildren,
+    SyntaxToken, T,
+};
+
+pub trait NameOwner: AstNode {
+    fn name(&self) -> Option<ast::Name> {
+        support::child(self.syntax())
+    }
+}
+
+pub trait VisibilityOwner: AstNode {
+    fn visibility(&self) -> Option<ast::Visibility> {
+        support::child(self.syntax())
+    }
+}
+
+pub trait LoopBodyOwner: AstNode {
+    fn loop_body(&self) -> Option<ast::BlockExpr> {
+        support::child(self.syntax())
+    }
+
+    fn label(&self) -> Option<ast::Label> {
+        support::child(self.syntax())
+    }
+}
+
+pub trait ArgListOwner: AstNode {
+    fn arg_list(&self) -> Option<ast::ArgList> {
+        support::child(self.syntax())
+    }
+}
+
+pub trait ModuleItemOwner: AstNode {
+    fn items(&self) -> AstChildren<ast::Item> {
+        support::children(self.syntax())
+    }
+}
+
+pub trait GenericParamsOwner: AstNode {
+    fn generic_param_list(&self) -> Option<ast::GenericParamList> {
+        support::child(self.syntax())
+    }
+
+    fn where_clause(&self) -> Option<ast::WhereClause> {
+        support::child(self.syntax())
+    }
+}
+
+pub trait TypeBoundsOwner: AstNode {
+    fn type_bound_list(&self) -> Option<ast::TypeBoundList> {
+        support::child(self.syntax())
+    }
+
+    fn colon_token(&self) -> Option<SyntaxToken> {
+        support::token(self.syntax(), T![:])
+    }
+}
+
+pub trait AttrsOwner: AstNode {
+    fn attrs(&self) -> AstChildren<ast::Attr> {
+        support::children(self.syntax())
+    }
+    fn has_atom_attr(&self, atom: &str) -> bool {
+        self.attrs().filter_map(|x| x.as_simple_atom()).any(|x| x == atom)
+    }
+}
+
+pub trait DocCommentsOwner: AstNode {
+    fn doc_comments(&self) -> CommentIter {
+        CommentIter { iter: self.syntax().children_with_tokens() }
+    }
+
+    fn doc_comment_text(&self) -> Option<String> {
+        self.doc_comments().doc_comment_text()
+    }
+}
+
+impl CommentIter {
+    pub fn from_syntax_node(syntax_node: &ast::SyntaxNode) -> CommentIter {
+        CommentIter { iter: syntax_node.children_with_tokens() }
+    }
+
+    /// Returns the textual content of a doc comment block as a single string.
+    /// That is, strips leading `///` (+ optional 1 character of whitespace),
+    /// trailing `*/`, trailing whitespace and then joins the lines.
+    pub fn doc_comment_text(self) -> Option<String> {
+        let mut has_comments = false;
+        let docs = self
+            .filter(|comment| comment.kind().doc.is_some())
+            .map(|comment| {
+                has_comments = true;
+                let prefix_len = comment.prefix().len();
+
+                let line: &str = comment.text().as_str();
+
+                // Determine if the prefix or prefix + 1 char is stripped
+                let pos =
+                    if let Some(ws) = line.chars().nth(prefix_len).filter(|c| c.is_whitespace()) {
+                        prefix_len + ws.len_utf8()
+                    } else {
+                        prefix_len
+                    };
+
+                let end = if comment.kind().shape.is_block() && line.ends_with("*/") {
+                    line.len() - 2
+                } else {
+                    line.len()
+                };
+
+                // Note that we do not trim the end of the line here
+                // since whitespace can have special meaning at the end
+                // of a line in markdown.
+                line[pos..end].to_owned()
+            })
+            .join("\n");
+
+        if has_comments {
+            Some(docs)
+        } else {
+            None
+        }
+    }
+}
+
+pub struct CommentIter {
+    iter: SyntaxElementChildren,
+}
+
+impl Iterator for CommentIter {
+    type Item = ast::Comment;
+    fn next(&mut self) -> Option<ast::Comment> {
+        self.iter.by_ref().find_map(|el| el.into_token().and_then(ast::Comment::cast))
+    }
+}
diff --git a/crates/syntax/src/fuzz.rs b/crates/syntax/src/fuzz.rs
new file mode 100644
index 00000000000..fbb97aa2736
--- /dev/null
+++ b/crates/syntax/src/fuzz.rs
@@ -0,0 +1,73 @@
+//! FIXME: write short doc here
+
+use std::{
+    convert::TryInto,
+    str::{self, FromStr},
+};
+
+use text_edit::Indel;
+
+use crate::{validation, AstNode, SourceFile, TextRange};
+
+fn check_file_invariants(file: &SourceFile) {
+    let root = file.syntax();
+    validation::validate_block_structure(root);
+}
+
+pub fn check_parser(text: &str) {
+    let file = SourceFile::parse(text);
+    check_file_invariants(&file.tree());
+}
+
+#[derive(Debug, Clone)]
+pub struct CheckReparse {
+    text: String,
+    edit: Indel,
+    edited_text: String,
+}
+
+impl CheckReparse {
+    pub fn from_data(data: &[u8]) -> Option<Self> {
+        const PREFIX: &str = "fn main(){\n\t";
+        const SUFFIX: &str = "\n}";
+
+        let data = str::from_utf8(data).ok()?;
+        let mut lines = data.lines();
+        let delete_start = usize::from_str(lines.next()?).ok()? + PREFIX.len();
+        let delete_len = usize::from_str(lines.next()?).ok()?;
+        let insert = lines.next()?.to_string();
+        let text = lines.collect::<Vec<_>>().join("\n");
+        let text = format!("{}{}{}", PREFIX, text, SUFFIX);
+        text.get(delete_start..delete_start.checked_add(delete_len)?)?; // make sure delete is a valid range
+        let delete =
+            TextRange::at(delete_start.try_into().unwrap(), delete_len.try_into().unwrap());
+        let edited_text =
+            format!("{}{}{}", &text[..delete_start], &insert, &text[delete_start + delete_len..]);
+        let edit = Indel { delete, insert };
+        Some(CheckReparse { text, edit, edited_text })
+    }
+
+    pub fn run(&self) {
+        let parse = SourceFile::parse(&self.text);
+        let new_parse = parse.reparse(&self.edit);
+        check_file_invariants(&new_parse.tree());
+        assert_eq!(&new_parse.tree().syntax().text().to_string(), &self.edited_text);
+        let full_reparse = SourceFile::parse(&self.edited_text);
+        for (a, b) in
+            new_parse.tree().syntax().descendants().zip(full_reparse.tree().syntax().descendants())
+        {
+            if (a.kind(), a.text_range()) != (b.kind(), b.text_range()) {
+                eprint!("original:\n{:#?}", parse.tree().syntax());
+                eprint!("reparsed:\n{:#?}", new_parse.tree().syntax());
+                eprint!("full reparse:\n{:#?}", full_reparse.tree().syntax());
+                assert_eq!(
+                    format!("{:?}", a),
+                    format!("{:?}", b),
+                    "different syntax tree produced by the full reparse"
+                );
+            }
+        }
+        // FIXME
+        // assert_eq!(new_file.errors(), full_reparse.errors());
+    }
+}
diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs
new file mode 100644
index 00000000000..7f8da66af07
--- /dev/null
+++ b/crates/syntax/src/lib.rs
@@ -0,0 +1,388 @@
+//! Syntax Tree library used throughout the rust analyzer.
+//!
+//! Properties:
+//!   - easy and fast incremental re-parsing
+//!   - graceful handling of errors
+//!   - full-fidelity representation (*any* text can be precisely represented as
+//!     a syntax tree)
+//!
+//! For more information, see the [RFC]. Current implementation is inspired by
+//! the [Swift] one.
+//!
+//! The most interesting modules here are `syntax_node` (which defines concrete
+//! syntax tree) and `ast` (which defines abstract syntax tree on top of the
+//! CST). The actual parser live in a separate `parser` crate, though the
+//! lexer lives in this crate.
+//!
+//! See `api_walkthrough` test in this file for a quick API tour!
+//!
+//! [RFC]: <https://github.com/rust-lang/rfcs/pull/2256>
+//! [Swift]: <https://github.com/apple/swift/blob/13d593df6f359d0cb2fc81cfaac273297c539455/lib/Syntax/README.md>
+
+#[allow(unused)]
+macro_rules! eprintln {
+    ($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
+}
+
+mod syntax_node;
+mod syntax_error;
+mod parsing;
+mod validation;
+mod ptr;
+#[cfg(test)]
+mod tests;
+
+pub mod algo;
+pub mod ast;
+#[doc(hidden)]
+pub mod fuzz;
+
+use std::{marker::PhantomData, sync::Arc};
+
+use stdx::format_to;
+use text_edit::Indel;
+
+pub use crate::{
+    algo::InsertPosition,
+    ast::{AstNode, AstToken},
+    parsing::{lex_single_syntax_kind, lex_single_valid_syntax_kind, tokenize, Token},
+    ptr::{AstPtr, SyntaxNodePtr},
+    syntax_error::SyntaxError,
+    syntax_node::{
+        Direction, GreenNode, NodeOrToken, SyntaxElement, SyntaxElementChildren, SyntaxNode,
+        SyntaxNodeChildren, SyntaxToken, SyntaxTreeBuilder,
+    },
+};
+pub use parser::{SyntaxKind, T};
+pub use rowan::{SmolStr, SyntaxText, TextRange, TextSize, TokenAtOffset, WalkEvent};
+
+/// `Parse` is the result of the parsing: a syntax tree and a collection of
+/// errors.
+///
+/// Note that we always produce a syntax tree, even for completely invalid
+/// files.
+#[derive(Debug, PartialEq, Eq)]
+pub struct Parse<T> {
+    green: GreenNode,
+    errors: Arc<Vec<SyntaxError>>,
+    _ty: PhantomData<fn() -> T>,
+}
+
+impl<T> Clone for Parse<T> {
+    fn clone(&self) -> Parse<T> {
+        Parse { green: self.green.clone(), errors: self.errors.clone(), _ty: PhantomData }
+    }
+}
+
+impl<T> Parse<T> {
+    fn new(green: GreenNode, errors: Vec<SyntaxError>) -> Parse<T> {
+        Parse { green, errors: Arc::new(errors), _ty: PhantomData }
+    }
+
+    pub fn syntax_node(&self) -> SyntaxNode {
+        SyntaxNode::new_root(self.green.clone())
+    }
+}
+
+impl<T: AstNode> Parse<T> {
+    pub fn to_syntax(self) -> Parse<SyntaxNode> {
+        Parse { green: self.green, errors: self.errors, _ty: PhantomData }
+    }
+
+    pub fn tree(&self) -> T {
+        T::cast(self.syntax_node()).unwrap()
+    }
+
+    pub fn errors(&self) -> &[SyntaxError] {
+        &*self.errors
+    }
+
+    pub fn ok(self) -> Result<T, Arc<Vec<SyntaxError>>> {
+        if self.errors.is_empty() {
+            Ok(self.tree())
+        } else {
+            Err(self.errors)
+        }
+    }
+}
+
+impl Parse<SyntaxNode> {
+    pub fn cast<N: AstNode>(self) -> Option<Parse<N>> {
+        if N::cast(self.syntax_node()).is_some() {
+            Some(Parse { green: self.green, errors: self.errors, _ty: PhantomData })
+        } else {
+            None
+        }
+    }
+}
+
+impl Parse<SourceFile> {
+    pub fn debug_dump(&self) -> String {
+        let mut buf = format!("{:#?}", self.tree().syntax());
+        for err in self.errors.iter() {
+            format_to!(buf, "error {:?}: {}\n", err.range(), err);
+        }
+        buf
+    }
+
+    pub fn reparse(&self, indel: &Indel) -> Parse<SourceFile> {
+        self.incremental_reparse(indel).unwrap_or_else(|| self.full_reparse(indel))
+    }
+
+    fn incremental_reparse(&self, indel: &Indel) -> Option<Parse<SourceFile>> {
+        // FIXME: validation errors are not handled here
+        parsing::incremental_reparse(self.tree().syntax(), indel, self.errors.to_vec()).map(
+            |(green_node, errors, _reparsed_range)| Parse {
+                green: green_node,
+                errors: Arc::new(errors),
+                _ty: PhantomData,
+            },
+        )
+    }
+
+    fn full_reparse(&self, indel: &Indel) -> Parse<SourceFile> {
+        let mut text = self.tree().syntax().text().to_string();
+        indel.apply(&mut text);
+        SourceFile::parse(&text)
+    }
+}
+
+/// `SourceFile` represents a parse tree for a single Rust file.
+pub use crate::ast::SourceFile;
+
+impl SourceFile {
+    pub fn parse(text: &str) -> Parse<SourceFile> {
+        let (green, mut errors) = parsing::parse_text(text);
+        let root = SyntaxNode::new_root(green.clone());
+
+        if cfg!(debug_assertions) {
+            validation::validate_block_structure(&root);
+        }
+
+        errors.extend(validation::validate(&root));
+
+        assert_eq!(root.kind(), SyntaxKind::SOURCE_FILE);
+        Parse { green, errors: Arc::new(errors), _ty: PhantomData }
+    }
+}
+
+impl ast::Path {
+    /// Returns `text`, parsed as a path, but only if it has no errors.
+    pub fn parse(text: &str) -> Result<Self, ()> {
+        parsing::parse_text_fragment(text, parser::FragmentKind::Path)
+    }
+}
+
+impl ast::Pat {
+    /// Returns `text`, parsed as a pattern, but only if it has no errors.
+    pub fn parse(text: &str) -> Result<Self, ()> {
+        parsing::parse_text_fragment(text, parser::FragmentKind::Pattern)
+    }
+}
+
+impl ast::Expr {
+    /// Returns `text`, parsed as an expression, but only if it has no errors.
+    pub fn parse(text: &str) -> Result<Self, ()> {
+        parsing::parse_text_fragment(text, parser::FragmentKind::Expr)
+    }
+}
+
+impl ast::Item {
+    /// Returns `text`, parsed as an item, but only if it has no errors.
+    pub fn parse(text: &str) -> Result<Self, ()> {
+        parsing::parse_text_fragment(text, parser::FragmentKind::Item)
+    }
+}
+
+impl ast::Type {
+    /// Returns `text`, parsed as an type reference, but only if it has no errors.
+    pub fn parse(text: &str) -> Result<Self, ()> {
+        parsing::parse_text_fragment(text, parser::FragmentKind::Type)
+    }
+}
+
+/// Matches a `SyntaxNode` against an `ast` type.
+///
+/// # Example:
+///
+/// ```ignore
+/// match_ast! {
+///     match node {
+///         ast::CallExpr(it) => { ... },
+///         ast::MethodCallExpr(it) => { ... },
+///         ast::MacroCall(it) => { ... },
+///         _ => None,
+///     }
+/// }
+/// ```
+#[macro_export]
+macro_rules! match_ast {
+    (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) };
+
+    (match ($node:expr) {
+        $( ast::$ast:ident($it:ident) => $res:expr, )*
+        _ => $catch_all:expr $(,)?
+    }) => {{
+        $( if let Some($it) = ast::$ast::cast($node.clone()) { $res } else )*
+        { $catch_all }
+    }};
+}
+
+/// This test does not assert anything and instead just shows off the crate's
+/// API.
+#[test]
+fn api_walkthrough() {
+    use ast::{ModuleItemOwner, NameOwner};
+
+    let source_code = "
+        fn foo() {
+            1 + 1
+        }
+    ";
+    // `SourceFile` is the main entry point.
+    //
+    // The `parse` method returns a `Parse` -- a pair of syntax tree and a list
+    // of errors. That is, syntax tree is constructed even in presence of errors.
+    let parse = SourceFile::parse(source_code);
+    assert!(parse.errors().is_empty());
+
+    // The `tree` method returns an owned syntax node of type `SourceFile`.
+    // Owned nodes are cheap: inside, they are `Rc` handles to the underling data.
+    let file: SourceFile = parse.tree();
+
+    // `SourceFile` is the root of the syntax tree. We can iterate file's items.
+    // Let's fetch the `foo` function.
+    let mut func = None;
+    for item in file.items() {
+        match item {
+            ast::Item::Fn(f) => func = Some(f),
+            _ => unreachable!(),
+        }
+    }
+    let func: ast::Fn = func.unwrap();
+
+    // Each AST node has a bunch of getters for children. All getters return
+    // `Option`s though, to account for incomplete code. Some getters are common
+    // for several kinds of node. In this case, a trait like `ast::NameOwner`
+    // usually exists. By convention, all ast types should be used with `ast::`
+    // qualifier.
+    let name: Option<ast::Name> = func.name();
+    let name = name.unwrap();
+    assert_eq!(name.text(), "foo");
+
+    // Let's get the `1 + 1` expression!
+    let body: ast::BlockExpr = func.body().unwrap();
+    let expr: ast::Expr = body.expr().unwrap();
+
+    // Enums are used to group related ast nodes together, and can be used for
+    // matching. However, because there are no public fields, it's possible to
+    // match only the top level enum: that is the price we pay for increased API
+    // flexibility
+    let bin_expr: &ast::BinExpr = match &expr {
+        ast::Expr::BinExpr(e) => e,
+        _ => unreachable!(),
+    };
+
+    // Besides the "typed" AST API, there's an untyped CST one as well.
+    // To switch from AST to CST, call `.syntax()` method:
+    let expr_syntax: &SyntaxNode = expr.syntax();
+
+    // Note how `expr` and `bin_expr` are in fact the same node underneath:
+    assert!(expr_syntax == bin_expr.syntax());
+
+    // To go from CST to AST, `AstNode::cast` function is used:
+    let _expr: ast::Expr = match ast::Expr::cast(expr_syntax.clone()) {
+        Some(e) => e,
+        None => unreachable!(),
+    };
+
+    // The two properties each syntax node has is a `SyntaxKind`:
+    assert_eq!(expr_syntax.kind(), SyntaxKind::BIN_EXPR);
+
+    // And text range:
+    assert_eq!(expr_syntax.text_range(), TextRange::new(32.into(), 37.into()));
+
+    // You can get node's text as a `SyntaxText` object, which will traverse the
+    // tree collecting token's text:
+    let text: SyntaxText = expr_syntax.text();
+    assert_eq!(text.to_string(), "1 + 1");
+
+    // There's a bunch of traversal methods on `SyntaxNode`:
+    assert_eq!(expr_syntax.parent().as_ref(), Some(body.syntax()));
+    assert_eq!(body.syntax().first_child_or_token().map(|it| it.kind()), Some(T!['{']));
+    assert_eq!(
+        expr_syntax.next_sibling_or_token().map(|it| it.kind()),
+        Some(SyntaxKind::WHITESPACE)
+    );
+
+    // As well as some iterator helpers:
+    let f = expr_syntax.ancestors().find_map(ast::Fn::cast);
+    assert_eq!(f, Some(func));
+    assert!(expr_syntax.siblings_with_tokens(Direction::Next).any(|it| it.kind() == T!['}']));
+    assert_eq!(
+        expr_syntax.descendants_with_tokens().count(),
+        8, // 5 tokens `1`, ` `, `+`, ` `, `!`
+           // 2 child literal expressions: `1`, `1`
+           // 1 the node itself: `1 + 1`
+    );
+
+    // There's also a `preorder` method with a more fine-grained iteration control:
+    let mut buf = String::new();
+    let mut indent = 0;
+    for event in expr_syntax.preorder_with_tokens() {
+        match event {
+            WalkEvent::Enter(node) => {
+                let text = match &node {
+                    NodeOrToken::Node(it) => it.text().to_string(),
+                    NodeOrToken::Token(it) => it.text().to_string(),
+                };
+                format_to!(buf, "{:indent$}{:?} {:?}\n", " ", text, node.kind(), indent = indent);
+                indent += 2;
+            }
+            WalkEvent::Leave(_) => indent -= 2,
+        }
+    }
+    assert_eq!(indent, 0);
+    assert_eq!(
+        buf.trim(),
+        r#"
+"1 + 1" BIN_EXPR
+  "1" LITERAL
+    "1" INT_NUMBER
+  " " WHITESPACE
+  "+" PLUS
+  " " WHITESPACE
+  "1" LITERAL
+    "1" INT_NUMBER
+"#
+        .trim()
+    );
+
+    // To recursively process the tree, there are three approaches:
+    // 1. explicitly call getter methods on AST nodes.
+    // 2. use descendants and `AstNode::cast`.
+    // 3. use descendants and `match_ast!`.
+    //
+    // Here's how the first one looks like:
+    let exprs_cast: Vec<String> = file
+        .syntax()
+        .descendants()
+        .filter_map(ast::Expr::cast)
+        .map(|expr| expr.syntax().text().to_string())
+        .collect();
+
+    // An alternative is to use a macro.
+    let mut exprs_visit = Vec::new();
+    for node in file.syntax().descendants() {
+        match_ast! {
+            match node {
+                ast::Expr(it) => {
+                    let res = it.syntax().text().to_string();
+                    exprs_visit.push(res);
+                },
+                _ => (),
+            }
+        }
+    }
+    assert_eq!(exprs_cast, exprs_visit);
+}
diff --git a/crates/syntax/src/parsing.rs b/crates/syntax/src/parsing.rs
new file mode 100644
index 00000000000..68a39eb2103
--- /dev/null
+++ b/crates/syntax/src/parsing.rs
@@ -0,0 +1,59 @@
+//! Lexing, bridging to parser (which does the actual parsing) and
+//! incremental reparsing.
+
+mod lexer;
+mod text_token_source;
+mod text_tree_sink;
+mod reparsing;
+
+use crate::{syntax_node::GreenNode, AstNode, SyntaxError, SyntaxNode};
+use text_token_source::TextTokenSource;
+use text_tree_sink::TextTreeSink;
+
+pub use lexer::*;
+
+pub(crate) use self::reparsing::incremental_reparse;
+use parser::SyntaxKind;
+
+pub(crate) fn parse_text(text: &str) -> (GreenNode, Vec<SyntaxError>) {
+    let (tokens, lexer_errors) = tokenize(&text);
+
+    let mut token_source = TextTokenSource::new(text, &tokens);
+    let mut tree_sink = TextTreeSink::new(text, &tokens);
+
+    parser::parse(&mut token_source, &mut tree_sink);
+
+    let (tree, mut parser_errors) = tree_sink.finish();
+    parser_errors.extend(lexer_errors);
+
+    (tree, parser_errors)
+}
+
+/// Returns `text` parsed as a `T` provided there are no parse errors.
+pub(crate) fn parse_text_fragment<T: AstNode>(
+    text: &str,
+    fragment_kind: parser::FragmentKind,
+) -> Result<T, ()> {
+    let (tokens, lexer_errors) = tokenize(&text);
+    if !lexer_errors.is_empty() {
+        return Err(());
+    }
+
+    let mut token_source = TextTokenSource::new(text, &tokens);
+    let mut tree_sink = TextTreeSink::new(text, &tokens);
+
+    // TextTreeSink assumes that there's at least some root node to which it can attach errors and
+    // tokens. We arbitrarily give it a SourceFile.
+    use parser::TreeSink;
+    tree_sink.start_node(SyntaxKind::SOURCE_FILE);
+    parser::parse_fragment(&mut token_source, &mut tree_sink, fragment_kind);
+    tree_sink.finish_node();
+
+    let (tree, parser_errors) = tree_sink.finish();
+    use parser::TokenSource;
+    if !parser_errors.is_empty() || token_source.current().kind != SyntaxKind::EOF {
+        return Err(());
+    }
+
+    SyntaxNode::new_root(tree).first_child().and_then(T::cast).ok_or(())
+}
diff --git a/crates/syntax/src/parsing/lexer.rs b/crates/syntax/src/parsing/lexer.rs
new file mode 100644
index 00000000000..fa3be101622
--- /dev/null
+++ b/crates/syntax/src/parsing/lexer.rs
@@ -0,0 +1,244 @@
+//! Lexer analyzes raw input string and produces lexemes (tokens).
+//! It is just a bridge to `rustc_lexer`.
+
+use rustc_lexer::{LiteralKind as LK, RawStrError};
+
+use std::convert::TryInto;
+
+use crate::{
+    SyntaxError,
+    SyntaxKind::{self, *},
+    TextRange, TextSize, T,
+};
+
+/// A token of Rust source.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct Token {
+    /// The kind of token.
+    pub kind: SyntaxKind,
+    /// The length of the token.
+    pub len: TextSize,
+}
+
+/// Break a string up into its component tokens.
+/// Beware that it checks for shebang first and its length contributes to resulting
+/// tokens offsets.
+pub fn tokenize(text: &str) -> (Vec<Token>, Vec<SyntaxError>) {
+    // non-empty string is a precondtion of `rustc_lexer::strip_shebang()`.
+    if text.is_empty() {
+        return Default::default();
+    }
+
+    let mut tokens = Vec::new();
+    let mut errors = Vec::new();
+
+    let mut offset = match rustc_lexer::strip_shebang(text) {
+        Some(shebang_len) => {
+            tokens.push(Token { kind: SHEBANG, len: shebang_len.try_into().unwrap() });
+            shebang_len
+        }
+        None => 0,
+    };
+
+    let text_without_shebang = &text[offset..];
+
+    for rustc_token in rustc_lexer::tokenize(text_without_shebang) {
+        let token_len: TextSize = rustc_token.len.try_into().unwrap();
+        let token_range = TextRange::at(offset.try_into().unwrap(), token_len);
+
+        let (syntax_kind, err_message) =
+            rustc_token_kind_to_syntax_kind(&rustc_token.kind, &text[token_range]);
+
+        tokens.push(Token { kind: syntax_kind, len: token_len });
+
+        if let Some(err_message) = err_message {
+            errors.push(SyntaxError::new(err_message, token_range));
+        }
+
+        offset += rustc_token.len;
+    }
+
+    (tokens, errors)
+}
+
+/// Returns `SyntaxKind` and `Option<SyntaxError>` of the first token
+/// encountered at the beginning of the string.
+///
+/// Returns `None` if the string contains zero *or two or more* tokens.
+/// The token is malformed if the returned error is not `None`.
+///
+/// Beware that unescape errors are not checked at tokenization time.
+pub fn lex_single_syntax_kind(text: &str) -> Option<(SyntaxKind, Option<SyntaxError>)> {
+    lex_first_token(text)
+        .filter(|(token, _)| token.len == TextSize::of(text))
+        .map(|(token, error)| (token.kind, error))
+}
+
+/// The same as `lex_single_syntax_kind()` but returns only `SyntaxKind` and
+/// returns `None` if any tokenization error occured.
+///
+/// Beware that unescape errors are not checked at tokenization time.
+pub fn lex_single_valid_syntax_kind(text: &str) -> Option<SyntaxKind> {
+    lex_first_token(text)
+        .filter(|(token, error)| !error.is_some() && token.len == TextSize::of(text))
+        .map(|(token, _error)| token.kind)
+}
+
+/// Returns `SyntaxKind` and `Option<SyntaxError>` of the first token
+/// encountered at the beginning of the string.
+///
+/// Returns `None` if the string contains zero tokens or if the token was parsed
+/// with an error.
+/// The token is malformed if the returned error is not `None`.
+///
+/// Beware that unescape errors are not checked at tokenization time.
+fn lex_first_token(text: &str) -> Option<(Token, Option<SyntaxError>)> {
+    // non-empty string is a precondtion of `rustc_lexer::first_token()`.
+    if text.is_empty() {
+        return None;
+    }
+
+    let rustc_token = rustc_lexer::first_token(text);
+    let (syntax_kind, err_message) = rustc_token_kind_to_syntax_kind(&rustc_token.kind, text);
+
+    let token = Token { kind: syntax_kind, len: rustc_token.len.try_into().unwrap() };
+    let optional_error = err_message
+        .map(|err_message| SyntaxError::new(err_message, TextRange::up_to(TextSize::of(text))));
+
+    Some((token, optional_error))
+}
+
+/// Returns `SyntaxKind` and an optional tokenize error message.
+fn rustc_token_kind_to_syntax_kind(
+    rustc_token_kind: &rustc_lexer::TokenKind,
+    token_text: &str,
+) -> (SyntaxKind, Option<&'static str>) {
+    // A note on an intended tradeoff:
+    // We drop some useful infromation here (see patterns with double dots `..`)
+    // Storing that info in `SyntaxKind` is not possible due to its layout requirements of
+    // being `u16` that come from `rowan::SyntaxKind`.
+
+    let syntax_kind = {
+        match rustc_token_kind {
+            rustc_lexer::TokenKind::LineComment => COMMENT,
+
+            rustc_lexer::TokenKind::BlockComment { terminated: true } => COMMENT,
+            rustc_lexer::TokenKind::BlockComment { terminated: false } => {
+                return (
+                    COMMENT,
+                    Some("Missing trailing `*/` symbols to terminate the block comment"),
+                );
+            }
+
+            rustc_lexer::TokenKind::Whitespace => WHITESPACE,
+
+            rustc_lexer::TokenKind::Ident => {
+                if token_text == "_" {
+                    UNDERSCORE
+                } else {
+                    SyntaxKind::from_keyword(token_text).unwrap_or(IDENT)
+                }
+            }
+
+            rustc_lexer::TokenKind::RawIdent => IDENT,
+            rustc_lexer::TokenKind::Literal { kind, .. } => return match_literal_kind(&kind),
+
+            rustc_lexer::TokenKind::Lifetime { starts_with_number: false } => LIFETIME,
+            rustc_lexer::TokenKind::Lifetime { starts_with_number: true } => {
+                return (LIFETIME, Some("Lifetime name cannot start with a number"))
+            }
+
+            rustc_lexer::TokenKind::Semi => T![;],
+            rustc_lexer::TokenKind::Comma => T![,],
+            rustc_lexer::TokenKind::Dot => T![.],
+            rustc_lexer::TokenKind::OpenParen => T!['('],
+            rustc_lexer::TokenKind::CloseParen => T![')'],
+            rustc_lexer::TokenKind::OpenBrace => T!['{'],
+            rustc_lexer::TokenKind::CloseBrace => T!['}'],
+            rustc_lexer::TokenKind::OpenBracket => T!['['],
+            rustc_lexer::TokenKind::CloseBracket => T![']'],
+            rustc_lexer::TokenKind::At => T![@],
+            rustc_lexer::TokenKind::Pound => T![#],
+            rustc_lexer::TokenKind::Tilde => T![~],
+            rustc_lexer::TokenKind::Question => T![?],
+            rustc_lexer::TokenKind::Colon => T![:],
+            rustc_lexer::TokenKind::Dollar => T![$],
+            rustc_lexer::TokenKind::Eq => T![=],
+            rustc_lexer::TokenKind::Not => T![!],
+            rustc_lexer::TokenKind::Lt => T![<],
+            rustc_lexer::TokenKind::Gt => T![>],
+            rustc_lexer::TokenKind::Minus => T![-],
+            rustc_lexer::TokenKind::And => T![&],
+            rustc_lexer::TokenKind::Or => T![|],
+            rustc_lexer::TokenKind::Plus => T![+],
+            rustc_lexer::TokenKind::Star => T![*],
+            rustc_lexer::TokenKind::Slash => T![/],
+            rustc_lexer::TokenKind::Caret => T![^],
+            rustc_lexer::TokenKind::Percent => T![%],
+            rustc_lexer::TokenKind::Unknown => ERROR,
+        }
+    };
+
+    return (syntax_kind, None);
+
+    fn match_literal_kind(kind: &rustc_lexer::LiteralKind) -> (SyntaxKind, Option<&'static str>) {
+        #[rustfmt::skip]
+        let syntax_kind = match *kind {
+            LK::Int { empty_int: false, .. } => INT_NUMBER,
+            LK::Int { empty_int: true, .. } => {
+                return (INT_NUMBER, Some("Missing digits after the integer base prefix"))
+            }
+
+            LK::Float { empty_exponent: false, .. } => FLOAT_NUMBER,
+            LK::Float { empty_exponent: true, .. } => {
+                return (FLOAT_NUMBER, Some("Missing digits after the exponent symbol"))
+            }
+
+            LK::Char { terminated: true } => CHAR,
+            LK::Char { terminated: false } => {
+                return (CHAR, Some("Missing trailing `'` symbol to terminate the character literal"))
+            }
+
+            LK::Byte { terminated: true } => BYTE,
+            LK::Byte { terminated: false } => {
+                return (BYTE, Some("Missing trailing `'` symbol to terminate the byte literal"))
+            }
+
+            LK::Str { terminated: true } => STRING,
+            LK::Str { terminated: false } => {
+                return (STRING, Some("Missing trailing `\"` symbol to terminate the string literal"))
+            }
+
+
+            LK::ByteStr { terminated: true } => BYTE_STRING,
+            LK::ByteStr { terminated: false } => {
+                return (BYTE_STRING, Some("Missing trailing `\"` symbol to terminate the byte string literal"))
+            }
+
+            LK::RawStr { err, .. } => match err {
+                None => RAW_STRING,
+                Some(RawStrError::InvalidStarter { .. }) => return (RAW_STRING, Some("Missing `\"` symbol after `#` symbols to begin the raw string literal")),
+                Some(RawStrError::NoTerminator { expected, found, .. }) => if expected == found {
+                    return (RAW_STRING, Some("Missing trailing `\"` to terminate the raw string literal"))
+                } else {
+                    return (RAW_STRING, Some("Missing trailing `\"` with `#` symbols to terminate the raw string literal"))
+
+                },
+                Some(RawStrError::TooManyDelimiters { .. }) => return (RAW_STRING, Some("Too many `#` symbols: raw strings may be delimited by up to 65535 `#` symbols")),
+            },
+            LK::RawByteStr { err, .. } => match err {
+                None => RAW_BYTE_STRING,
+                Some(RawStrError::InvalidStarter { .. }) => return (RAW_BYTE_STRING, Some("Missing `\"` symbol after `#` symbols to begin the raw byte string literal")),
+                Some(RawStrError::NoTerminator { expected, found, .. }) => if expected == found {
+                    return (RAW_BYTE_STRING, Some("Missing trailing `\"` to terminate the raw byte string literal"))
+                } else {
+                    return (RAW_BYTE_STRING, Some("Missing trailing `\"` with `#` symbols to terminate the raw byte string literal"))
+
+                },
+                Some(RawStrError::TooManyDelimiters { .. }) => return (RAW_BYTE_STRING, Some("Too many `#` symbols: raw byte strings may be delimited by up to 65535 `#` symbols")),
+            },
+        };
+
+        (syntax_kind, None)
+    }
+}
diff --git a/crates/syntax/src/parsing/reparsing.rs b/crates/syntax/src/parsing/reparsing.rs
new file mode 100644
index 00000000000..4149f856a83
--- /dev/null
+++ b/crates/syntax/src/parsing/reparsing.rs
@@ -0,0 +1,455 @@
+//! Implementation of incremental re-parsing.
+//!
+//! We use two simple strategies for this:
+//!   - if the edit modifies only a single token (like changing an identifier's
+//!     letter), we replace only this token.
+//!   - otherwise, we search for the nearest `{}` block which contains the edit
+//!     and try to parse only this block.
+
+use parser::Reparser;
+use text_edit::Indel;
+
+use crate::{
+    algo,
+    parsing::{
+        lexer::{lex_single_syntax_kind, tokenize, Token},
+        text_token_source::TextTokenSource,
+        text_tree_sink::TextTreeSink,
+    },
+    syntax_node::{GreenNode, GreenToken, NodeOrToken, SyntaxElement, SyntaxNode},
+    SyntaxError,
+    SyntaxKind::*,
+    TextRange, TextSize, T,
+};
+
+pub(crate) fn incremental_reparse(
+    node: &SyntaxNode,
+    edit: &Indel,
+    errors: Vec<SyntaxError>,
+) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> {
+    if let Some((green, new_errors, old_range)) = reparse_token(node, &edit) {
+        return Some((green, merge_errors(errors, new_errors, old_range, edit), old_range));
+    }
+
+    if let Some((green, new_errors, old_range)) = reparse_block(node, &edit) {
+        return Some((green, merge_errors(errors, new_errors, old_range, edit), old_range));
+    }
+    None
+}
+
+fn reparse_token<'node>(
+    root: &'node SyntaxNode,
+    edit: &Indel,
+) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> {
+    let prev_token = algo::find_covering_element(root, edit.delete).as_token()?.clone();
+    let prev_token_kind = prev_token.kind();
+    match prev_token_kind {
+        WHITESPACE | COMMENT | IDENT | STRING | RAW_STRING => {
+            if prev_token_kind == WHITESPACE || prev_token_kind == COMMENT {
+                // removing a new line may extends previous token
+                let deleted_range = edit.delete - prev_token.text_range().start();
+                if prev_token.text()[deleted_range].contains('\n') {
+                    return None;
+                }
+            }
+
+            let mut new_text = get_text_after_edit(prev_token.clone().into(), &edit);
+            let (new_token_kind, new_err) = lex_single_syntax_kind(&new_text)?;
+
+            if new_token_kind != prev_token_kind
+                || (new_token_kind == IDENT && is_contextual_kw(&new_text))
+            {
+                return None;
+            }
+
+            // Check that edited token is not a part of the bigger token.
+            // E.g. if for source code `bruh"str"` the user removed `ruh`, then
+            // `b` no longer remains an identifier, but becomes a part of byte string literal
+            if let Some(next_char) = root.text().char_at(prev_token.text_range().end()) {
+                new_text.push(next_char);
+                let token_with_next_char = lex_single_syntax_kind(&new_text);
+                if let Some((_kind, _error)) = token_with_next_char {
+                    return None;
+                }
+                new_text.pop();
+            }
+
+            let new_token =
+                GreenToken::new(rowan::SyntaxKind(prev_token_kind.into()), new_text.into());
+            Some((
+                prev_token.replace_with(new_token),
+                new_err.into_iter().collect(),
+                prev_token.text_range(),
+            ))
+        }
+        _ => None,
+    }
+}
+
+fn reparse_block<'node>(
+    root: &'node SyntaxNode,
+    edit: &Indel,
+) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> {
+    let (node, reparser) = find_reparsable_node(root, edit.delete)?;
+    let text = get_text_after_edit(node.clone().into(), edit);
+
+    let (tokens, new_lexer_errors) = tokenize(&text);
+    if !is_balanced(&tokens) {
+        return None;
+    }
+
+    let mut token_source = TextTokenSource::new(&text, &tokens);
+    let mut tree_sink = TextTreeSink::new(&text, &tokens);
+    reparser.parse(&mut token_source, &mut tree_sink);
+
+    let (green, mut new_parser_errors) = tree_sink.finish();
+    new_parser_errors.extend(new_lexer_errors);
+
+    Some((node.replace_with(green), new_parser_errors, node.text_range()))
+}
+
+fn get_text_after_edit(element: SyntaxElement, edit: &Indel) -> String {
+    let edit = Indel::replace(edit.delete - element.text_range().start(), edit.insert.clone());
+
+    let mut text = match element {
+        NodeOrToken::Token(token) => token.text().to_string(),
+        NodeOrToken::Node(node) => node.text().to_string(),
+    };
+    edit.apply(&mut text);
+    text
+}
+
+fn is_contextual_kw(text: &str) -> bool {
+    matches!(text, "auto" | "default" | "union")
+}
+
+fn find_reparsable_node(node: &SyntaxNode, range: TextRange) -> Option<(SyntaxNode, Reparser)> {
+    let node = algo::find_covering_element(node, range);
+
+    let mut ancestors = match node {
+        NodeOrToken::Token(it) => it.parent().ancestors(),
+        NodeOrToken::Node(it) => it.ancestors(),
+    };
+    ancestors.find_map(|node| {
+        let first_child = node.first_child_or_token().map(|it| it.kind());
+        let parent = node.parent().map(|it| it.kind());
+        Reparser::for_node(node.kind(), first_child, parent).map(|r| (node, r))
+    })
+}
+
+fn is_balanced(tokens: &[Token]) -> bool {
+    if tokens.is_empty()
+        || tokens.first().unwrap().kind != T!['{']
+        || tokens.last().unwrap().kind != T!['}']
+    {
+        return false;
+    }
+    let mut balance = 0usize;
+    for t in &tokens[1..tokens.len() - 1] {
+        match t.kind {
+            T!['{'] => balance += 1,
+            T!['}'] => {
+                balance = match balance.checked_sub(1) {
+                    Some(b) => b,
+                    None => return false,
+                }
+            }
+            _ => (),
+        }
+    }
+    balance == 0
+}
+
+fn merge_errors(
+    old_errors: Vec<SyntaxError>,
+    new_errors: Vec<SyntaxError>,
+    range_before_reparse: TextRange,
+    edit: &Indel,
+) -> Vec<SyntaxError> {
+    let mut res = Vec::new();
+
+    for old_err in old_errors {
+        let old_err_range = old_err.range();
+        if old_err_range.end() <= range_before_reparse.start() {
+            res.push(old_err);
+        } else if old_err_range.start() >= range_before_reparse.end() {
+            let inserted_len = TextSize::of(&edit.insert);
+            res.push(old_err.with_range((old_err_range + inserted_len) - edit.delete.len()));
+            // Note: extra parens are intentional to prevent uint underflow, HWAB (here was a bug)
+        }
+    }
+    res.extend(new_errors.into_iter().map(|new_err| {
+        // fighting borrow checker with a variable ;)
+        let offseted_range = new_err.range() + range_before_reparse.start();
+        new_err.with_range(offseted_range)
+    }));
+    res
+}
+
+#[cfg(test)]
+mod tests {
+    use test_utils::{assert_eq_text, extract_range};
+
+    use super::*;
+    use crate::{AstNode, Parse, SourceFile};
+
+    fn do_check(before: &str, replace_with: &str, reparsed_len: u32) {
+        let (range, before) = extract_range(before);
+        let edit = Indel::replace(range, replace_with.to_owned());
+        let after = {
+            let mut after = before.clone();
+            edit.apply(&mut after);
+            after
+        };
+
+        let fully_reparsed = SourceFile::parse(&after);
+        let incrementally_reparsed: Parse<SourceFile> = {
+            let before = SourceFile::parse(&before);
+            let (green, new_errors, range) =
+                incremental_reparse(before.tree().syntax(), &edit, before.errors.to_vec()).unwrap();
+            assert_eq!(range.len(), reparsed_len.into(), "reparsed fragment has wrong length");
+            Parse::new(green, new_errors)
+        };
+
+        assert_eq_text!(
+            &format!("{:#?}", fully_reparsed.tree().syntax()),
+            &format!("{:#?}", incrementally_reparsed.tree().syntax()),
+        );
+        assert_eq!(fully_reparsed.errors(), incrementally_reparsed.errors());
+    }
+
+    #[test] // FIXME: some test here actually test token reparsing
+    fn reparse_block_tests() {
+        do_check(
+            r"
+fn foo() {
+    let x = foo + <|>bar<|>
+}
+",
+            "baz",
+            3,
+        );
+        do_check(
+            r"
+fn foo() {
+    let x = foo<|> + bar<|>
+}
+",
+            "baz",
+            25,
+        );
+        do_check(
+            r"
+struct Foo {
+    f: foo<|><|>
+}
+",
+            ",\n    g: (),",
+            14,
+        );
+        do_check(
+            r"
+fn foo {
+    let;
+    1 + 1;
+    <|>92<|>;
+}
+",
+            "62",
+            31, // FIXME: reparse only int literal here
+        );
+        do_check(
+            r"
+mod foo {
+    fn <|><|>
+}
+",
+            "bar",
+            11,
+        );
+
+        do_check(
+            r"
+trait Foo {
+    type <|>Foo<|>;
+}
+",
+            "Output",
+            3,
+        );
+        do_check(
+            r"
+impl IntoIterator<Item=i32> for Foo {
+    f<|><|>
+}
+",
+            "n next(",
+            9,
+        );
+        do_check(r"use a::b::{foo,<|>,bar<|>};", "baz", 10);
+        do_check(
+            r"
+pub enum A {
+    Foo<|><|>
+}
+",
+            "\nBar;\n",
+            11,
+        );
+        do_check(
+            r"
+foo!{a, b<|><|> d}
+",
+            ", c[3]",
+            8,
+        );
+        do_check(
+            r"
+fn foo() {
+    vec![<|><|>]
+}
+",
+            "123",
+            14,
+        );
+        do_check(
+            r"
+extern {
+    fn<|>;<|>
+}
+",
+            " exit(code: c_int)",
+            11,
+        );
+    }
+
+    #[test]
+    fn reparse_token_tests() {
+        do_check(
+            r"<|><|>
+fn foo() -> i32 { 1 }
+",
+            "\n\n\n   \n",
+            1,
+        );
+        do_check(
+            r"
+fn foo() -> <|><|> {}
+",
+            "  \n",
+            2,
+        );
+        do_check(
+            r"
+fn <|>foo<|>() -> i32 { 1 }
+",
+            "bar",
+            3,
+        );
+        do_check(
+            r"
+fn foo<|><|>foo() {  }
+",
+            "bar",
+            6,
+        );
+        do_check(
+            r"
+fn foo /* <|><|> */ () {}
+",
+            "some comment",
+            6,
+        );
+        do_check(
+            r"
+fn baz <|><|> () {}
+",
+            "    \t\t\n\n",
+            2,
+        );
+        do_check(
+            r"
+fn baz <|><|> () {}
+",
+            "    \t\t\n\n",
+            2,
+        );
+        do_check(
+            r"
+/// foo <|><|>omment
+mod { }
+",
+            "c",
+            14,
+        );
+        do_check(
+            r#"
+fn -> &str { "Hello<|><|>" }
+"#,
+            ", world",
+            7,
+        );
+        do_check(
+            r#"
+fn -> &str { // "Hello<|><|>"
+"#,
+            ", world",
+            10,
+        );
+        do_check(
+            r##"
+fn -> &str { r#"Hello<|><|>"#
+"##,
+            ", world",
+            10,
+        );
+        do_check(
+            r"
+#[derive(<|>Copy<|>)]
+enum Foo {
+
+}
+",
+            "Clone",
+            4,
+        );
+    }
+
+    #[test]
+    fn reparse_str_token_with_error_unchanged() {
+        do_check(r#""<|>Unclosed<|> string literal"#, "Still unclosed", 24);
+    }
+
+    #[test]
+    fn reparse_str_token_with_error_fixed() {
+        do_check(r#""unterinated<|><|>"#, "\"", 12);
+    }
+
+    #[test]
+    fn reparse_block_with_error_in_middle_unchanged() {
+        do_check(
+            r#"fn main() {
+                if {}
+                32 + 4<|><|>
+                return
+                if {}
+            }"#,
+            "23",
+            105,
+        )
+    }
+
+    #[test]
+    fn reparse_block_with_error_in_middle_fixed() {
+        do_check(
+            r#"fn main() {
+                if {}
+                32 + 4<|><|>
+                return
+                if {}
+            }"#,
+            ";",
+            105,
+        )
+    }
+}
diff --git a/crates/syntax/src/parsing/text_token_source.rs b/crates/syntax/src/parsing/text_token_source.rs
new file mode 100644
index 00000000000..df866dc2b75
--- /dev/null
+++ b/crates/syntax/src/parsing/text_token_source.rs
@@ -0,0 +1,84 @@
+//! See `TextTokenSource` docs.
+
+use parser::TokenSource;
+
+use crate::{parsing::lexer::Token, SyntaxKind::EOF, TextRange, TextSize};
+
+/// Implementation of `parser::TokenSource` that takes tokens from source code text.
+pub(crate) struct TextTokenSource<'t> {
+    text: &'t str,
+    /// token and its start position (non-whitespace/comment tokens)
+    /// ```non-rust
+    ///  struct Foo;
+    ///  ^------^--^-
+    ///  |      |    \________
+    ///  |      \____         \
+    ///  |           \         |
+    ///  (struct, 0) (Foo, 7) (;, 10)
+    /// ```
+    /// `[(struct, 0), (Foo, 7), (;, 10)]`
+    token_offset_pairs: Vec<(Token, TextSize)>,
+
+    /// Current token and position
+    curr: (parser::Token, usize),
+}
+
+impl<'t> TokenSource for TextTokenSource<'t> {
+    fn current(&self) -> parser::Token {
+        self.curr.0
+    }
+
+    fn lookahead_nth(&self, n: usize) -> parser::Token {
+        mk_token(self.curr.1 + n, &self.token_offset_pairs)
+    }
+
+    fn bump(&mut self) {
+        if self.curr.0.kind == EOF {
+            return;
+        }
+
+        let pos = self.curr.1 + 1;
+        self.curr = (mk_token(pos, &self.token_offset_pairs), pos);
+    }
+
+    fn is_keyword(&self, kw: &str) -> bool {
+        self.token_offset_pairs
+            .get(self.curr.1)
+            .map(|(token, offset)| &self.text[TextRange::at(*offset, token.len)] == kw)
+            .unwrap_or(false)
+    }
+}
+
+fn mk_token(pos: usize, token_offset_pairs: &[(Token, TextSize)]) -> parser::Token {
+    let (kind, is_jointed_to_next) = match token_offset_pairs.get(pos) {
+        Some((token, offset)) => (
+            token.kind,
+            token_offset_pairs
+                .get(pos + 1)
+                .map(|(_, next_offset)| offset + token.len == *next_offset)
+                .unwrap_or(false),
+        ),
+        None => (EOF, false),
+    };
+    parser::Token { kind, is_jointed_to_next }
+}
+
+impl<'t> TextTokenSource<'t> {
+    /// Generate input from tokens(expect comment and whitespace).
+    pub fn new(text: &'t str, raw_tokens: &'t [Token]) -> TextTokenSource<'t> {
+        let token_offset_pairs: Vec<_> = raw_tokens
+            .iter()
+            .filter_map({
+                let mut len = 0.into();
+                move |token| {
+                    let pair = if token.kind.is_trivia() { None } else { Some((*token, len)) };
+                    len += token.len;
+                    pair
+                }
+            })
+            .collect();
+
+        let first = mk_token(0, &token_offset_pairs);
+        TextTokenSource { text, token_offset_pairs, curr: (first, 0) }
+    }
+}
diff --git a/crates/syntax/src/parsing/text_tree_sink.rs b/crates/syntax/src/parsing/text_tree_sink.rs
new file mode 100644
index 00000000000..c1b5f246d11
--- /dev/null
+++ b/crates/syntax/src/parsing/text_tree_sink.rs
@@ -0,0 +1,183 @@
+//! FIXME: write short doc here
+
+use std::mem;
+
+use parser::{ParseError, TreeSink};
+
+use crate::{
+    parsing::Token,
+    syntax_node::GreenNode,
+    SmolStr, SyntaxError,
+    SyntaxKind::{self, *},
+    SyntaxTreeBuilder, TextRange, TextSize,
+};
+
+/// Bridges the parser with our specific syntax tree representation.
+///
+/// `TextTreeSink` also handles attachment of trivia (whitespace) to nodes.
+pub(crate) struct TextTreeSink<'a> {
+    text: &'a str,
+    tokens: &'a [Token],
+    text_pos: TextSize,
+    token_pos: usize,
+    state: State,
+    inner: SyntaxTreeBuilder,
+}
+
+enum State {
+    PendingStart,
+    Normal,
+    PendingFinish,
+}
+
+impl<'a> TreeSink for TextTreeSink<'a> {
+    fn token(&mut self, kind: SyntaxKind, n_tokens: u8) {
+        match mem::replace(&mut self.state, State::Normal) {
+            State::PendingStart => unreachable!(),
+            State::PendingFinish => self.inner.finish_node(),
+            State::Normal => (),
+        }
+        self.eat_trivias();
+        let n_tokens = n_tokens as usize;
+        let len = self.tokens[self.token_pos..self.token_pos + n_tokens]
+            .iter()
+            .map(|it| it.len)
+            .sum::<TextSize>();
+        self.do_token(kind, len, n_tokens);
+    }
+
+    fn start_node(&mut self, kind: SyntaxKind) {
+        match mem::replace(&mut self.state, State::Normal) {
+            State::PendingStart => {
+                self.inner.start_node(kind);
+                // No need to attach trivias to previous node: there is no
+                // previous node.
+                return;
+            }
+            State::PendingFinish => self.inner.finish_node(),
+            State::Normal => (),
+        }
+
+        let n_trivias =
+            self.tokens[self.token_pos..].iter().take_while(|it| it.kind.is_trivia()).count();
+        let leading_trivias = &self.tokens[self.token_pos..self.token_pos + n_trivias];
+        let mut trivia_end =
+            self.text_pos + leading_trivias.iter().map(|it| it.len).sum::<TextSize>();
+
+        let n_attached_trivias = {
+            let leading_trivias = leading_trivias.iter().rev().map(|it| {
+                let next_end = trivia_end - it.len;
+                let range = TextRange::new(next_end, trivia_end);
+                trivia_end = next_end;
+                (it.kind, &self.text[range])
+            });
+            n_attached_trivias(kind, leading_trivias)
+        };
+        self.eat_n_trivias(n_trivias - n_attached_trivias);
+        self.inner.start_node(kind);
+        self.eat_n_trivias(n_attached_trivias);
+    }
+
+    fn finish_node(&mut self) {
+        match mem::replace(&mut self.state, State::PendingFinish) {
+            State::PendingStart => unreachable!(),
+            State::PendingFinish => self.inner.finish_node(),
+            State::Normal => (),
+        }
+    }
+
+    fn error(&mut self, error: ParseError) {
+        self.inner.error(error, self.text_pos)
+    }
+}
+
+impl<'a> TextTreeSink<'a> {
+    pub(super) fn new(text: &'a str, tokens: &'a [Token]) -> Self {
+        Self {
+            text,
+            tokens,
+            text_pos: 0.into(),
+            token_pos: 0,
+            state: State::PendingStart,
+            inner: SyntaxTreeBuilder::default(),
+        }
+    }
+
+    pub(super) fn finish(mut self) -> (GreenNode, Vec<SyntaxError>) {
+        match mem::replace(&mut self.state, State::Normal) {
+            State::PendingFinish => {
+                self.eat_trivias();
+                self.inner.finish_node()
+            }
+            State::PendingStart | State::Normal => unreachable!(),
+        }
+
+        self.inner.finish_raw()
+    }
+
+    fn eat_trivias(&mut self) {
+        while let Some(&token) = self.tokens.get(self.token_pos) {
+            if !token.kind.is_trivia() {
+                break;
+            }
+            self.do_token(token.kind, token.len, 1);
+        }
+    }
+
+    fn eat_n_trivias(&mut self, n: usize) {
+        for _ in 0..n {
+            let token = self.tokens[self.token_pos];
+            assert!(token.kind.is_trivia());
+            self.do_token(token.kind, token.len, 1);
+        }
+    }
+
+    fn do_token(&mut self, kind: SyntaxKind, len: TextSize, n_tokens: usize) {
+        let range = TextRange::at(self.text_pos, len);
+        let text: SmolStr = self.text[range].into();
+        self.text_pos += len;
+        self.token_pos += n_tokens;
+        self.inner.token(kind, text);
+    }
+}
+
+fn n_attached_trivias<'a>(
+    kind: SyntaxKind,
+    trivias: impl Iterator<Item = (SyntaxKind, &'a str)>,
+) -> usize {
+    match kind {
+        MACRO_CALL | CONST | TYPE_ALIAS | STRUCT | ENUM | VARIANT | FN | TRAIT | MODULE
+        | RECORD_FIELD | STATIC => {
+            let mut res = 0;
+            let mut trivias = trivias.enumerate().peekable();
+
+            while let Some((i, (kind, text))) = trivias.next() {
+                match kind {
+                    WHITESPACE => {
+                        if text.contains("\n\n") {
+                            // we check whether the next token is a doc-comment
+                            // and skip the whitespace in this case
+                            if let Some((peek_kind, peek_text)) =
+                                trivias.peek().map(|(_, pair)| pair)
+                            {
+                                if *peek_kind == COMMENT
+                                    && peek_text.starts_with("///")
+                                    && !peek_text.starts_with("////")
+                                {
+                                    continue;
+                                }
+                            }
+                            break;
+                        }
+                    }
+                    COMMENT => {
+                        res = i + 1;
+                    }
+                    _ => (),
+                }
+            }
+            res
+        }
+        _ => 0,
+    }
+}
diff --git a/crates/syntax/src/ptr.rs b/crates/syntax/src/ptr.rs
new file mode 100644
index 00000000000..ca795774713
--- /dev/null
+++ b/crates/syntax/src/ptr.rs
@@ -0,0 +1,105 @@
+//! FIXME: write short doc here
+
+use std::{
+    hash::{Hash, Hasher},
+    iter::successors,
+    marker::PhantomData,
+};
+
+use crate::{AstNode, SyntaxKind, SyntaxNode, TextRange};
+
+/// A pointer to a syntax node inside a file. It can be used to remember a
+/// specific node across reparses of the same file.
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct SyntaxNodePtr {
+    pub(crate) range: TextRange,
+    kind: SyntaxKind,
+}
+
+impl SyntaxNodePtr {
+    pub fn new(node: &SyntaxNode) -> SyntaxNodePtr {
+        SyntaxNodePtr { range: node.text_range(), kind: node.kind() }
+    }
+
+    pub fn to_node(&self, root: &SyntaxNode) -> SyntaxNode {
+        assert!(root.parent().is_none());
+        successors(Some(root.clone()), |node| {
+            node.children().find(|it| it.text_range().contains_range(self.range))
+        })
+        .find(|it| it.text_range() == self.range && it.kind() == self.kind)
+        .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self))
+    }
+
+    pub fn cast<N: AstNode>(self) -> Option<AstPtr<N>> {
+        if !N::can_cast(self.kind) {
+            return None;
+        }
+        Some(AstPtr { raw: self, _ty: PhantomData })
+    }
+}
+
+/// Like `SyntaxNodePtr`, but remembers the type of node
+#[derive(Debug)]
+pub struct AstPtr<N: AstNode> {
+    raw: SyntaxNodePtr,
+    _ty: PhantomData<fn() -> N>,
+}
+
+impl<N: AstNode> Clone for AstPtr<N> {
+    fn clone(&self) -> AstPtr<N> {
+        AstPtr { raw: self.raw.clone(), _ty: PhantomData }
+    }
+}
+
+impl<N: AstNode> Eq for AstPtr<N> {}
+
+impl<N: AstNode> PartialEq for AstPtr<N> {
+    fn eq(&self, other: &AstPtr<N>) -> bool {
+        self.raw == other.raw
+    }
+}
+
+impl<N: AstNode> Hash for AstPtr<N> {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.raw.hash(state)
+    }
+}
+
+impl<N: AstNode> AstPtr<N> {
+    pub fn new(node: &N) -> AstPtr<N> {
+        AstPtr { raw: SyntaxNodePtr::new(node.syntax()), _ty: PhantomData }
+    }
+
+    pub fn to_node(&self, root: &SyntaxNode) -> N {
+        let syntax_node = self.raw.to_node(root);
+        N::cast(syntax_node).unwrap()
+    }
+
+    pub fn syntax_node_ptr(&self) -> SyntaxNodePtr {
+        self.raw.clone()
+    }
+
+    pub fn cast<U: AstNode>(self) -> Option<AstPtr<U>> {
+        if !U::can_cast(self.raw.kind) {
+            return None;
+        }
+        Some(AstPtr { raw: self.raw, _ty: PhantomData })
+    }
+}
+
+impl<N: AstNode> From<AstPtr<N>> for SyntaxNodePtr {
+    fn from(ptr: AstPtr<N>) -> SyntaxNodePtr {
+        ptr.raw
+    }
+}
+
+#[test]
+fn test_local_syntax_ptr() {
+    use crate::{ast, AstNode, SourceFile};
+
+    let file = SourceFile::parse("struct Foo { f: u32, }").ok().unwrap();
+    let field = file.syntax().descendants().find_map(ast::RecordField::cast).unwrap();
+    let ptr = SyntaxNodePtr::new(field.syntax());
+    let field_syntax = ptr.to_node(file.syntax());
+    assert_eq!(field.syntax(), &field_syntax);
+}
diff --git a/crates/syntax/src/syntax_error.rs b/crates/syntax/src/syntax_error.rs
new file mode 100644
index 00000000000..7c4511fece0
--- /dev/null
+++ b/crates/syntax/src/syntax_error.rs
@@ -0,0 +1,44 @@
+//! See docs for `SyntaxError`.
+
+use std::fmt;
+
+use crate::{TextRange, TextSize};
+
+/// Represents the result of unsuccessful tokenization, parsing
+/// or tree validation.
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct SyntaxError(String, TextRange);
+
+// FIXME: there was an unused SyntaxErrorKind previously (before this enum was removed)
+// It was introduced in this PR: https://github.com/rust-analyzer/rust-analyzer/pull/846/files#diff-827da9b03b8f9faa1bade5cdd44d5dafR95
+// but it was not removed by a mistake.
+//
+// So, we need to find a place where to stick validation for attributes in match clauses.
+// Code before refactor:
+// InvalidMatchInnerAttr => {
+//    write!(f, "Inner attributes are only allowed directly after the opening brace of the match expression")
+// }
+
+impl SyntaxError {
+    pub fn new(message: impl Into<String>, range: TextRange) -> Self {
+        Self(message.into(), range)
+    }
+    pub fn new_at_offset(message: impl Into<String>, offset: TextSize) -> Self {
+        Self(message.into(), TextRange::empty(offset))
+    }
+
+    pub fn range(&self) -> TextRange {
+        self.1
+    }
+
+    pub fn with_range(mut self, range: TextRange) -> Self {
+        self.1 = range;
+        self
+    }
+}
+
+impl fmt::Display for SyntaxError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
diff --git a/crates/syntax/src/syntax_node.rs b/crates/syntax/src/syntax_node.rs
new file mode 100644
index 00000000000..b2abcbfbb36
--- /dev/null
+++ b/crates/syntax/src/syntax_node.rs
@@ -0,0 +1,77 @@
+//! This module defines Concrete Syntax Tree (CST), used by rust-analyzer.
+//!
+//! The CST includes comments and whitespace, provides a single node type,
+//! `SyntaxNode`, and a basic traversal API (parent, children, siblings).
+//!
+//! The *real* implementation is in the (language-agnostic) `rowan` crate, this
+//! module just wraps its API.
+
+use rowan::{GreenNodeBuilder, Language};
+
+use crate::{Parse, SmolStr, SyntaxError, SyntaxKind, TextSize};
+
+pub use rowan::GreenNode;
+
+pub(crate) use rowan::GreenToken;
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum RustLanguage {}
+impl Language for RustLanguage {
+    type Kind = SyntaxKind;
+
+    fn kind_from_raw(raw: rowan::SyntaxKind) -> SyntaxKind {
+        SyntaxKind::from(raw.0)
+    }
+
+    fn kind_to_raw(kind: SyntaxKind) -> rowan::SyntaxKind {
+        rowan::SyntaxKind(kind.into())
+    }
+}
+
+pub type SyntaxNode = rowan::SyntaxNode<RustLanguage>;
+pub type SyntaxToken = rowan::SyntaxToken<RustLanguage>;
+pub type SyntaxElement = rowan::SyntaxElement<RustLanguage>;
+pub type SyntaxNodeChildren = rowan::SyntaxNodeChildren<RustLanguage>;
+pub type SyntaxElementChildren = rowan::SyntaxElementChildren<RustLanguage>;
+
+pub use rowan::{Direction, NodeOrToken};
+
+#[derive(Default)]
+pub struct SyntaxTreeBuilder {
+    errors: Vec<SyntaxError>,
+    inner: GreenNodeBuilder<'static>,
+}
+
+impl SyntaxTreeBuilder {
+    pub(crate) fn finish_raw(self) -> (GreenNode, Vec<SyntaxError>) {
+        let green = self.inner.finish();
+        (green, self.errors)
+    }
+
+    pub fn finish(self) -> Parse<SyntaxNode> {
+        let (green, errors) = self.finish_raw();
+        if cfg!(debug_assertions) {
+            let node = SyntaxNode::new_root(green.clone());
+            crate::validation::validate_block_structure(&node);
+        }
+        Parse::new(green, errors)
+    }
+
+    pub fn token(&mut self, kind: SyntaxKind, text: SmolStr) {
+        let kind = RustLanguage::kind_to_raw(kind);
+        self.inner.token(kind, text)
+    }
+
+    pub fn start_node(&mut self, kind: SyntaxKind) {
+        let kind = RustLanguage::kind_to_raw(kind);
+        self.inner.start_node(kind)
+    }
+
+    pub fn finish_node(&mut self) {
+        self.inner.finish_node()
+    }
+
+    pub fn error(&mut self, error: parser::ParseError, text_pos: TextSize) {
+        self.errors.push(SyntaxError::new_at_offset(*error.0, text_pos))
+    }
+}
diff --git a/crates/syntax/src/tests.rs b/crates/syntax/src/tests.rs
new file mode 100644
index 00000000000..ddc71836940
--- /dev/null
+++ b/crates/syntax/src/tests.rs
@@ -0,0 +1,280 @@
+use std::{
+    fmt::Write,
+    fs,
+    path::{Path, PathBuf},
+};
+
+use expect::expect_file;
+use rayon::prelude::*;
+use test_utils::project_dir;
+
+use crate::{fuzz, tokenize, SourceFile, SyntaxError, TextRange, TextSize, Token};
+
+#[test]
+fn lexer_tests() {
+    // FIXME:
+    // * Add tests for unicode escapes in byte-character and [raw]-byte-string literals
+    // * Add tests for unescape errors
+
+    dir_tests(&test_data_dir(), &["lexer/ok"], "txt", |text, path| {
+        let (tokens, errors) = tokenize(text);
+        assert_errors_are_absent(&errors, path);
+        dump_tokens_and_errors(&tokens, &errors, text)
+    });
+    dir_tests(&test_data_dir(), &["lexer/err"], "txt", |text, path| {
+        let (tokens, errors) = tokenize(text);
+        assert_errors_are_present(&errors, path);
+        dump_tokens_and_errors(&tokens, &errors, text)
+    });
+}
+
+#[test]
+fn parse_smoke_test() {
+    let code = r##"
+fn main() {
+    println!("Hello, world!")
+}
+    "##;
+
+    let parse = SourceFile::parse(code);
+    // eprintln!("{:#?}", parse.syntax_node());
+    assert!(parse.ok().is_ok());
+}
+
+#[test]
+fn parser_tests() {
+    dir_tests(&test_data_dir(), &["parser/inline/ok", "parser/ok"], "rast", |text, path| {
+        let parse = SourceFile::parse(text);
+        let errors = parse.errors();
+        assert_errors_are_absent(&errors, path);
+        parse.debug_dump()
+    });
+    dir_tests(&test_data_dir(), &["parser/err", "parser/inline/err"], "rast", |text, path| {
+        let parse = SourceFile::parse(text);
+        let errors = parse.errors();
+        assert_errors_are_present(&errors, path);
+        parse.debug_dump()
+    });
+}
+
+#[test]
+fn expr_parser_tests() {
+    fragment_parser_dir_test(
+        &["parser/fragments/expr/ok"],
+        &["parser/fragments/expr/err"],
+        crate::ast::Expr::parse,
+    );
+}
+
+#[test]
+fn path_parser_tests() {
+    fragment_parser_dir_test(
+        &["parser/fragments/path/ok"],
+        &["parser/fragments/path/err"],
+        crate::ast::Path::parse,
+    );
+}
+
+#[test]
+fn pattern_parser_tests() {
+    fragment_parser_dir_test(
+        &["parser/fragments/pattern/ok"],
+        &["parser/fragments/pattern/err"],
+        crate::ast::Pat::parse,
+    );
+}
+
+#[test]
+fn item_parser_tests() {
+    fragment_parser_dir_test(
+        &["parser/fragments/item/ok"],
+        &["parser/fragments/item/err"],
+        crate::ast::Item::parse,
+    );
+}
+
+#[test]
+fn type_parser_tests() {
+    fragment_parser_dir_test(
+        &["parser/fragments/type/ok"],
+        &["parser/fragments/type/err"],
+        crate::ast::Type::parse,
+    );
+}
+
+#[test]
+fn parser_fuzz_tests() {
+    for (_, text) in collect_rust_files(&test_data_dir(), &["parser/fuzz-failures"]) {
+        fuzz::check_parser(&text)
+    }
+}
+
+#[test]
+fn reparse_fuzz_tests() {
+    for (_, text) in collect_rust_files(&test_data_dir(), &["reparse/fuzz-failures"]) {
+        let check = fuzz::CheckReparse::from_data(text.as_bytes()).unwrap();
+        println!("{:?}", check);
+        check.run();
+    }
+}
+
+/// Test that Rust-analyzer can parse and validate the rust-analyzer
+/// FIXME: Use this as a benchmark
+#[test]
+fn self_hosting_parsing() {
+    let dir = project_dir().join("crates");
+    let files = walkdir::WalkDir::new(dir)
+        .into_iter()
+        .filter_entry(|entry| {
+            // Get all files which are not in the crates/syntax/test_data folder
+            !entry.path().components().any(|component| component.as_os_str() == "test_data")
+        })
+        .map(|e| e.unwrap())
+        .filter(|entry| {
+            // Get all `.rs ` files
+            !entry.path().is_dir() && (entry.path().extension().unwrap_or_default() == "rs")
+        })
+        .map(|entry| entry.into_path())
+        .collect::<Vec<_>>();
+    assert!(
+        files.len() > 100,
+        "self_hosting_parsing found too few files - is it running in the right directory?"
+    );
+
+    let errors = files
+        .into_par_iter()
+        .filter_map(|file| {
+            let text = read_text(&file);
+            match SourceFile::parse(&text).ok() {
+                Ok(_) => None,
+                Err(err) => Some((file, err)),
+            }
+        })
+        .collect::<Vec<_>>();
+
+    if !errors.is_empty() {
+        let errors = errors
+            .into_iter()
+            .map(|(path, err)| format!("{}: {:?}\n", path.display(), err))
+            .collect::<String>();
+        panic!("Parsing errors:\n{}\n", errors);
+    }
+}
+
+fn test_data_dir() -> PathBuf {
+    project_dir().join("crates/syntax/test_data")
+}
+
+fn assert_errors_are_present(errors: &[SyntaxError], path: &Path) {
+    assert!(!errors.is_empty(), "There should be errors in the file {:?}", path.display());
+}
+fn assert_errors_are_absent(errors: &[SyntaxError], path: &Path) {
+    assert_eq!(
+        errors,
+        &[] as &[SyntaxError],
+        "There should be no errors in the file {:?}",
+        path.display(),
+    );
+}
+
+fn dump_tokens_and_errors(tokens: &[Token], errors: &[SyntaxError], text: &str) -> String {
+    let mut acc = String::new();
+    let mut offset: TextSize = 0.into();
+    for token in tokens {
+        let token_len = token.len;
+        let token_text = &text[TextRange::at(offset, token.len)];
+        offset += token.len;
+        writeln!(acc, "{:?} {:?} {:?}", token.kind, token_len, token_text).unwrap();
+    }
+    for err in errors {
+        writeln!(acc, "> error{:?} token({:?}) msg({})", err.range(), &text[err.range()], err)
+            .unwrap();
+    }
+    acc
+}
+
+fn fragment_parser_dir_test<T, F>(ok_paths: &[&str], err_paths: &[&str], f: F)
+where
+    T: crate::AstNode,
+    F: Fn(&str) -> Result<T, ()>,
+{
+    dir_tests(&test_data_dir(), ok_paths, "rast", |text, path| {
+        if let Ok(node) = f(text) {
+            format!("{:#?}", crate::ast::AstNode::syntax(&node))
+        } else {
+            panic!("Failed to parse '{:?}'", path);
+        }
+    });
+    dir_tests(&test_data_dir(), err_paths, "rast", |text, path| {
+        if let Ok(_) = f(text) {
+            panic!("'{:?}' successfully parsed when it should have errored", path);
+        } else {
+            "ERROR\n".to_owned()
+        }
+    });
+}
+
+/// Calls callback `f` with input code and file paths for each `.rs` file in `test_data_dir`
+/// subdirectories defined by `paths`.
+///
+/// If the content of the matching output file differs from the output of `f()`
+/// the test will fail.
+///
+/// If there is no matching output file it will be created and filled with the
+/// output of `f()`, but the test will fail.
+fn dir_tests<F>(test_data_dir: &Path, paths: &[&str], outfile_extension: &str, f: F)
+where
+    F: Fn(&str, &Path) -> String,
+{
+    for (path, input_code) in collect_rust_files(test_data_dir, paths) {
+        let actual = f(&input_code, &path);
+        let path = path.with_extension(outfile_extension);
+        expect_file![path].assert_eq(&actual)
+    }
+}
+
+/// Collects all `.rs` files from `dir` subdirectories defined by `paths`.
+fn collect_rust_files(root_dir: &Path, paths: &[&str]) -> Vec<(PathBuf, String)> {
+    paths
+        .iter()
+        .flat_map(|path| {
+            let path = root_dir.to_owned().join(path);
+            rust_files_in_dir(&path).into_iter()
+        })
+        .map(|path| {
+            let text = read_text(&path);
+            (path, text)
+        })
+        .collect()
+}
+
+/// Collects paths to all `.rs` files from `dir` in a sorted `Vec<PathBuf>`.
+fn rust_files_in_dir(dir: &Path) -> Vec<PathBuf> {
+    let mut acc = Vec::new();
+    for file in fs::read_dir(&dir).unwrap() {
+        let file = file.unwrap();
+        let path = file.path();
+        if path.extension().unwrap_or_default() == "rs" {
+            acc.push(path);
+        }
+    }
+    acc.sort();
+    acc
+}
+
+/// Read file and normalize newlines.
+///
+/// `rustc` seems to always normalize `\r\n` newlines to `\n`:
+///
+/// ```
+/// let s = "
+/// ";
+/// assert_eq!(s.as_bytes(), &[10]);
+/// ```
+///
+/// so this should always be correct.
+fn read_text(path: &Path) -> String {
+    fs::read_to_string(path)
+        .unwrap_or_else(|_| panic!("File at {:?} should be valid", path))
+        .replace("\r\n", "\n")
+}
diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs
new file mode 100644
index 00000000000..2dddaf09a40
--- /dev/null
+++ b/crates/syntax/src/validation.rs
@@ -0,0 +1,303 @@
+//! FIXME: write short doc here
+
+mod block;
+
+use crate::{
+    ast, match_ast, AstNode, SyntaxError,
+    SyntaxKind::{BYTE, BYTE_STRING, CHAR, CONST, FN, INT_NUMBER, STRING, TYPE_ALIAS},
+    SyntaxNode, SyntaxToken, TextSize, T,
+};
+use rustc_lexer::unescape::{
+    self, unescape_byte, unescape_byte_literal, unescape_char, unescape_literal, Mode,
+};
+use std::convert::TryFrom;
+
+fn rustc_unescape_error_to_string(err: unescape::EscapeError) -> &'static str {
+    use unescape::EscapeError as EE;
+
+    #[rustfmt::skip]
+    let err_message = match err {
+        EE::ZeroChars => {
+            "Literal must not be empty"
+        }
+        EE::MoreThanOneChar => {
+            "Literal must be one character long"
+        }
+        EE::LoneSlash => {
+            "Character must be escaped: `\\`"
+        }
+        EE::InvalidEscape => {
+            "Invalid escape"
+        }
+        EE::BareCarriageReturn | EE::BareCarriageReturnInRawString => {
+            "Character must be escaped: `\r`"
+        }
+        EE::EscapeOnlyChar => {
+            "Escape character `\\` must be escaped itself"
+        }
+        EE::TooShortHexEscape => {
+            "ASCII hex escape code must have exactly two digits"
+        }
+        EE::InvalidCharInHexEscape => {
+            "ASCII hex escape code must contain only hex characters"
+        }
+        EE::OutOfRangeHexEscape => {
+            "ASCII hex escape code must be at most 0x7F"
+        }
+        EE::NoBraceInUnicodeEscape => {
+            "Missing `{` to begin the unicode escape"
+        }
+        EE::InvalidCharInUnicodeEscape => {
+            "Unicode escape must contain only hex characters and underscores"
+        }
+        EE::EmptyUnicodeEscape => {
+            "Unicode escape must not be empty"
+        }
+        EE::UnclosedUnicodeEscape => {
+            "Missing `}` to terminate the unicode escape"
+        }
+        EE::LeadingUnderscoreUnicodeEscape => {
+            "Unicode escape code must not begin with an underscore"
+        }
+        EE::OverlongUnicodeEscape => {
+            "Unicode escape code must have at most 6 digits"
+        }
+        EE::LoneSurrogateUnicodeEscape => {
+            "Unicode escape code must not be a surrogate"
+        }
+        EE::OutOfRangeUnicodeEscape => {
+            "Unicode escape code must be at most 0x10FFFF"
+        }
+        EE::UnicodeEscapeInByte => {
+            "Byte literals must not contain unicode escapes"
+        }
+        EE::NonAsciiCharInByte | EE::NonAsciiCharInByteString => {
+            "Byte literals must not contain non-ASCII characters"
+        }
+    };
+
+    err_message
+}
+
+pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
+    // FIXME:
+    // * Add unescape validation of raw string literals and raw byte string literals
+    // * Add validation of doc comments are being attached to nodes
+
+    let mut errors = Vec::new();
+    for node in root.descendants() {
+        match_ast! {
+            match node {
+                ast::Literal(it) => validate_literal(it, &mut errors),
+                ast::BlockExpr(it) => block::validate_block_expr(it, &mut errors),
+                ast::FieldExpr(it) => validate_numeric_name(it.name_ref(), &mut errors),
+                ast::RecordExprField(it) => validate_numeric_name(it.name_ref(), &mut errors),
+                ast::Visibility(it) => validate_visibility(it, &mut errors),
+                ast::RangeExpr(it) => validate_range_expr(it, &mut errors),
+                ast::PathSegment(it) => validate_path_keywords(it, &mut errors),
+                _ => (),
+            }
+        }
+    }
+    errors
+}
+
+fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
+    // FIXME: move this function to outer scope (https://github.com/rust-analyzer/rust-analyzer/pull/2834#discussion_r366196658)
+    fn unquote(text: &str, prefix_len: usize, end_delimiter: char) -> Option<&str> {
+        text.rfind(end_delimiter).and_then(|end| text.get(prefix_len..end))
+    }
+
+    let token = literal.token();
+    let text = token.text().as_str();
+
+    // FIXME: lift this lambda refactor to `fn` (https://github.com/rust-analyzer/rust-analyzer/pull/2834#discussion_r366199205)
+    let mut push_err = |prefix_len, (off, err): (usize, unescape::EscapeError)| {
+        let off = token.text_range().start() + TextSize::try_from(off + prefix_len).unwrap();
+        acc.push(SyntaxError::new_at_offset(rustc_unescape_error_to_string(err), off));
+    };
+
+    match token.kind() {
+        BYTE => {
+            if let Some(Err(e)) = unquote(text, 2, '\'').map(unescape_byte) {
+                push_err(2, e);
+            }
+        }
+        CHAR => {
+            if let Some(Err(e)) = unquote(text, 1, '\'').map(unescape_char) {
+                push_err(1, e);
+            }
+        }
+        BYTE_STRING => {
+            if let Some(without_quotes) = unquote(text, 2, '"') {
+                unescape_byte_literal(without_quotes, Mode::ByteStr, &mut |range, char| {
+                    if let Err(err) = char {
+                        push_err(2, (range.start, err));
+                    }
+                })
+            }
+        }
+        STRING => {
+            if let Some(without_quotes) = unquote(text, 1, '"') {
+                unescape_literal(without_quotes, Mode::Str, &mut |range, char| {
+                    if let Err(err) = char {
+                        push_err(1, (range.start, err));
+                    }
+                })
+            }
+        }
+        _ => (),
+    }
+}
+
+pub(crate) fn validate_block_structure(root: &SyntaxNode) {
+    let mut stack = Vec::new();
+    for node in root.descendants() {
+        match node.kind() {
+            T!['{'] => stack.push(node),
+            T!['}'] => {
+                if let Some(pair) = stack.pop() {
+                    assert_eq!(
+                        node.parent(),
+                        pair.parent(),
+                        "\nunpaired curleys:\n{}\n{:#?}\n",
+                        root.text(),
+                        root,
+                    );
+                    assert!(
+                        node.next_sibling().is_none() && pair.prev_sibling().is_none(),
+                        "\nfloating curlys at {:?}\nfile:\n{}\nerror:\n{}\n",
+                        node,
+                        root.text(),
+                        node.text(),
+                    );
+                }
+            }
+            _ => (),
+        }
+    }
+}
+
+fn validate_numeric_name(name_ref: Option<ast::NameRef>, errors: &mut Vec<SyntaxError>) {
+    if let Some(int_token) = int_token(name_ref) {
+        if int_token.text().chars().any(|c| !c.is_digit(10)) {
+            errors.push(SyntaxError::new(
+                "Tuple (struct) field access is only allowed through \
+                decimal integers with no underscores or suffix",
+                int_token.text_range(),
+            ));
+        }
+    }
+
+    fn int_token(name_ref: Option<ast::NameRef>) -> Option<SyntaxToken> {
+        name_ref?.syntax().first_child_or_token()?.into_token().filter(|it| it.kind() == INT_NUMBER)
+    }
+}
+
+fn validate_visibility(vis: ast::Visibility, errors: &mut Vec<SyntaxError>) {
+    let parent = match vis.syntax().parent() {
+        Some(it) => it,
+        None => return,
+    };
+    match parent.kind() {
+        FN | CONST | TYPE_ALIAS => (),
+        _ => return,
+    }
+
+    let impl_def = match parent.parent().and_then(|it| it.parent()).and_then(ast::Impl::cast) {
+        Some(it) => it,
+        None => return,
+    };
+    if impl_def.trait_().is_some() {
+        errors.push(SyntaxError::new("Unnecessary visibility qualifier", vis.syntax.text_range()));
+    }
+}
+
+fn validate_range_expr(expr: ast::RangeExpr, errors: &mut Vec<SyntaxError>) {
+    if expr.op_kind() == Some(ast::RangeOp::Inclusive) && expr.end().is_none() {
+        errors.push(SyntaxError::new(
+            "An inclusive range must have an end expression",
+            expr.syntax().text_range(),
+        ));
+    }
+}
+
+fn validate_path_keywords(segment: ast::PathSegment, errors: &mut Vec<SyntaxError>) {
+    use ast::PathSegmentKind;
+
+    let path = segment.parent_path();
+    let is_path_start = segment.coloncolon_token().is_none() && path.qualifier().is_none();
+
+    if let Some(token) = segment.self_token() {
+        if !is_path_start {
+            errors.push(SyntaxError::new(
+                "The `self` keyword is only allowed as the first segment of a path",
+                token.text_range(),
+            ));
+        }
+    } else if let Some(token) = segment.crate_token() {
+        if !is_path_start || use_prefix(path).is_some() {
+            errors.push(SyntaxError::new(
+                "The `crate` keyword is only allowed as the first segment of a path",
+                token.text_range(),
+            ));
+        }
+    } else if let Some(token) = segment.super_token() {
+        if !all_supers(&path) {
+            errors.push(SyntaxError::new(
+                "The `super` keyword may only be preceded by other `super`s",
+                token.text_range(),
+            ));
+            return;
+        }
+
+        let mut curr_path = path;
+        while let Some(prefix) = use_prefix(curr_path) {
+            if !all_supers(&prefix) {
+                errors.push(SyntaxError::new(
+                    "The `super` keyword may only be preceded by other `super`s",
+                    token.text_range(),
+                ));
+                return;
+            }
+            curr_path = prefix;
+        }
+    }
+
+    fn use_prefix(mut path: ast::Path) -> Option<ast::Path> {
+        for node in path.syntax().ancestors().skip(1) {
+            match_ast! {
+                match node {
+                    ast::UseTree(it) => if let Some(tree_path) = it.path() {
+                        // Even a top-level path exists within a `UseTree` so we must explicitly
+                        // allow our path but disallow anything else
+                        if tree_path != path {
+                            return Some(tree_path);
+                        }
+                    },
+                    ast::UseTreeList(_it) => continue,
+                    ast::Path(parent) => path = parent,
+                    _ => return None,
+                }
+            };
+        }
+        return None;
+    }
+
+    fn all_supers(path: &ast::Path) -> bool {
+        let segment = match path.segment() {
+            Some(it) => it,
+            None => return false,
+        };
+
+        if segment.kind() != Some(PathSegmentKind::SuperKw) {
+            return false;
+        }
+
+        if let Some(ref subpath) = path.qualifier() {
+            return all_supers(subpath);
+        }
+
+        return true;
+    }
+}
diff --git a/crates/syntax/src/validation/block.rs b/crates/syntax/src/validation/block.rs
new file mode 100644
index 00000000000..ad990146885
--- /dev/null
+++ b/crates/syntax/src/validation/block.rs
@@ -0,0 +1,22 @@
+//! Logic for validating block expressions i.e. `ast::BlockExpr`.
+
+use crate::{
+    ast::{self, AstNode, AttrsOwner},
+    SyntaxError,
+    SyntaxKind::*,
+};
+
+pub(crate) fn validate_block_expr(block: ast::BlockExpr, errors: &mut Vec<SyntaxError>) {
+    if let Some(parent) = block.syntax().parent() {
+        match parent.kind() {
+            FN | EXPR_STMT | BLOCK_EXPR => return,
+            _ => {}
+        }
+    }
+    errors.extend(block.attrs().map(|attr| {
+        SyntaxError::new(
+            "A block in this position cannot accept inner attributes",
+            attr.syntax().text_range(),
+        )
+    }))
+}
diff --git a/crates/syntax/test_data/accidentally_quadratic b/crates/syntax/test_data/accidentally_quadratic
new file mode 100644
index 00000000000..428f83a627b
--- /dev/null
+++ b/crates/syntax/test_data/accidentally_quadratic
@@ -0,0 +1,3980 @@
+#[doc = r" Register block"]
+#[repr(C)]
+pub struct RegisterBlock {
+    #[doc = "0x00 - Control Register"]
+    pub cr: CR,
+    #[doc = "0x04 - Error Status Register"]
+    pub es: ES,
+    _reserved0: [u8; 4usize],
+    #[doc = "0x0c - Enable Request Register"]
+    pub erq: ERQ,
+    _reserved1: [u8; 4usize],
+    #[doc = "0x14 - Enable Error Interrupt Register"]
+    pub eei: EEI,
+    #[doc = "0x18 - Clear Enable Error Interrupt Register"]
+    pub ceei: CEEI,
+    #[doc = "0x19 - Set Enable Error Interrupt Register"]
+    pub seei: SEEI,
+    #[doc = "0x1a - Clear Enable Request Register"]
+    pub cerq: CERQ,
+    #[doc = "0x1b - Set Enable Request Register"]
+    pub serq: SERQ,
+    #[doc = "0x1c - Clear DONE Status Bit Register"]
+    pub cdne: CDNE,
+    #[doc = "0x1d - Set START Bit Register"]
+    pub ssrt: SSRT,
+    #[doc = "0x1e - Clear Error Register"]
+    pub cerr: CERR,
+    #[doc = "0x1f - Clear Interrupt Request Register"]
+    pub cint: CINT,
+    _reserved2: [u8; 4usize],
+    #[doc = "0x24 - Interrupt Request Register"]
+    pub int: INT,
+    _reserved3: [u8; 4usize],
+    #[doc = "0x2c - Error Register"]
+    pub err: ERR,
+    _reserved4: [u8; 4usize],
+    #[doc = "0x34 - Hardware Request Status Register"]
+    pub hrs: HRS,
+    _reserved5: [u8; 12usize],
+    #[doc = "0x44 - Enable Asynchronous Request in Stop Register"]
+    pub ears: EARS,
+    _reserved6: [u8; 184usize],
+    #[doc = "0x100 - Channel n Priority Register"]
+    pub dchpri3: DCHPRI3,
+    #[doc = "0x101 - Channel n Priority Register"]
+    pub dchpri2: DCHPRI2,
+    #[doc = "0x102 - Channel n Priority Register"]
+    pub dchpri1: DCHPRI1,
+    #[doc = "0x103 - Channel n Priority Register"]
+    pub dchpri0: DCHPRI0,
+    #[doc = "0x104 - Channel n Priority Register"]
+    pub dchpri7: DCHPRI7,
+    #[doc = "0x105 - Channel n Priority Register"]
+    pub dchpri6: DCHPRI6,
+    #[doc = "0x106 - Channel n Priority Register"]
+    pub dchpri5: DCHPRI5,
+    #[doc = "0x107 - Channel n Priority Register"]
+    pub dchpri4: DCHPRI4,
+    #[doc = "0x108 - Channel n Priority Register"]
+    pub dchpri11: DCHPRI11,
+    #[doc = "0x109 - Channel n Priority Register"]
+    pub dchpri10: DCHPRI10,
+    #[doc = "0x10a - Channel n Priority Register"]
+    pub dchpri9: DCHPRI9,
+    #[doc = "0x10b - Channel n Priority Register"]
+    pub dchpri8: DCHPRI8,
+    #[doc = "0x10c - Channel n Priority Register"]
+    pub dchpri15: DCHPRI15,
+    #[doc = "0x10d - Channel n Priority Register"]
+    pub dchpri14: DCHPRI14,
+    #[doc = "0x10e - Channel n Priority Register"]
+    pub dchpri13: DCHPRI13,
+    #[doc = "0x10f - Channel n Priority Register"]
+    pub dchpri12: DCHPRI12,
+    #[doc = "0x110 - Channel n Priority Register"]
+    pub dchpri19: DCHPRI19,
+    #[doc = "0x111 - Channel n Priority Register"]
+    pub dchpri18: DCHPRI18,
+    #[doc = "0x112 - Channel n Priority Register"]
+    pub dchpri17: DCHPRI17,
+    #[doc = "0x113 - Channel n Priority Register"]
+    pub dchpri16: DCHPRI16,
+    #[doc = "0x114 - Channel n Priority Register"]
+    pub dchpri23: DCHPRI23,
+    #[doc = "0x115 - Channel n Priority Register"]
+    pub dchpri22: DCHPRI22,
+    #[doc = "0x116 - Channel n Priority Register"]
+    pub dchpri21: DCHPRI21,
+    #[doc = "0x117 - Channel n Priority Register"]
+    pub dchpri20: DCHPRI20,
+    #[doc = "0x118 - Channel n Priority Register"]
+    pub dchpri27: DCHPRI27,
+    #[doc = "0x119 - Channel n Priority Register"]
+    pub dchpri26: DCHPRI26,
+    #[doc = "0x11a - Channel n Priority Register"]
+    pub dchpri25: DCHPRI25,
+    #[doc = "0x11b - Channel n Priority Register"]
+    pub dchpri24: DCHPRI24,
+    #[doc = "0x11c - Channel n Priority Register"]
+    pub dchpri31: DCHPRI31,
+    #[doc = "0x11d - Channel n Priority Register"]
+    pub dchpri30: DCHPRI30,
+    #[doc = "0x11e - Channel n Priority Register"]
+    pub dchpri29: DCHPRI29,
+    #[doc = "0x11f - Channel n Priority Register"]
+    pub dchpri28: DCHPRI28,
+    _reserved7: [u8; 3808usize],
+    #[doc = "0x1000 - TCD Source Address"]
+    pub tcd0_saddr: TCD0_SADDR,
+    #[doc = "0x1004 - TCD Signed Source Address Offset"]
+    pub tcd0_soff: TCD0_SOFF,
+    #[doc = "0x1006 - TCD Transfer Attributes"]
+    pub tcd0_attr: TCD0_ATTR,
+    #[doc = "0x1008 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd0_nbytes_mlno: TCD0_NBYTES_MLNO,
+    #[doc = "0x100c - TCD Last Source Address Adjustment"]
+    pub tcd0_slast: TCD0_SLAST,
+    #[doc = "0x1010 - TCD Destination Address"]
+    pub tcd0_daddr: TCD0_DADDR,
+    #[doc = "0x1014 - TCD Signed Destination Address Offset"]
+    pub tcd0_doff: TCD0_DOFF,
+    #[doc = "0x1016 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd0_citer_elinkno: TCD0_CITER_ELINKNO,
+    #[doc = "0x1018 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd0_dlastsga: TCD0_DLASTSGA,
+    #[doc = "0x101c - TCD Control and Status"]
+    pub tcd0_csr: TCD0_CSR,
+    #[doc = "0x101e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd0_biter_elinkno: TCD0_BITER_ELINKNO,
+    #[doc = "0x1020 - TCD Source Address"]
+    pub tcd1_saddr: TCD1_SADDR,
+    #[doc = "0x1024 - TCD Signed Source Address Offset"]
+    pub tcd1_soff: TCD1_SOFF,
+    #[doc = "0x1026 - TCD Transfer Attributes"]
+    pub tcd1_attr: TCD1_ATTR,
+    #[doc = "0x1028 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd1_nbytes_mlno: TCD1_NBYTES_MLNO,
+    #[doc = "0x102c - TCD Last Source Address Adjustment"]
+    pub tcd1_slast: TCD1_SLAST,
+    #[doc = "0x1030 - TCD Destination Address"]
+    pub tcd1_daddr: TCD1_DADDR,
+    #[doc = "0x1034 - TCD Signed Destination Address Offset"]
+    pub tcd1_doff: TCD1_DOFF,
+    #[doc = "0x1036 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd1_citer_elinkno: TCD1_CITER_ELINKNO,
+    #[doc = "0x1038 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd1_dlastsga: TCD1_DLASTSGA,
+    #[doc = "0x103c - TCD Control and Status"]
+    pub tcd1_csr: TCD1_CSR,
+    #[doc = "0x103e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd1_biter_elinkno: TCD1_BITER_ELINKNO,
+    #[doc = "0x1040 - TCD Source Address"]
+    pub tcd2_saddr: TCD2_SADDR,
+    #[doc = "0x1044 - TCD Signed Source Address Offset"]
+    pub tcd2_soff: TCD2_SOFF,
+    #[doc = "0x1046 - TCD Transfer Attributes"]
+    pub tcd2_attr: TCD2_ATTR,
+    #[doc = "0x1048 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd2_nbytes_mlno: TCD2_NBYTES_MLNO,
+    #[doc = "0x104c - TCD Last Source Address Adjustment"]
+    pub tcd2_slast: TCD2_SLAST,
+    #[doc = "0x1050 - TCD Destination Address"]
+    pub tcd2_daddr: TCD2_DADDR,
+    #[doc = "0x1054 - TCD Signed Destination Address Offset"]
+    pub tcd2_doff: TCD2_DOFF,
+    #[doc = "0x1056 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd2_citer_elinkno: TCD2_CITER_ELINKNO,
+    #[doc = "0x1058 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd2_dlastsga: TCD2_DLASTSGA,
+    #[doc = "0x105c - TCD Control and Status"]
+    pub tcd2_csr: TCD2_CSR,
+    #[doc = "0x105e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd2_biter_elinkno: TCD2_BITER_ELINKNO,
+    #[doc = "0x1060 - TCD Source Address"]
+    pub tcd3_saddr: TCD3_SADDR,
+    #[doc = "0x1064 - TCD Signed Source Address Offset"]
+    pub tcd3_soff: TCD3_SOFF,
+    #[doc = "0x1066 - TCD Transfer Attributes"]
+    pub tcd3_attr: TCD3_ATTR,
+    #[doc = "0x1068 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd3_nbytes_mlno: TCD3_NBYTES_MLNO,
+    #[doc = "0x106c - TCD Last Source Address Adjustment"]
+    pub tcd3_slast: TCD3_SLAST,
+    #[doc = "0x1070 - TCD Destination Address"]
+    pub tcd3_daddr: TCD3_DADDR,
+    #[doc = "0x1074 - TCD Signed Destination Address Offset"]
+    pub tcd3_doff: TCD3_DOFF,
+    #[doc = "0x1076 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd3_citer_elinkno: TCD3_CITER_ELINKNO,
+    #[doc = "0x1078 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd3_dlastsga: TCD3_DLASTSGA,
+    #[doc = "0x107c - TCD Control and Status"]
+    pub tcd3_csr: TCD3_CSR,
+    #[doc = "0x107e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd3_biter_elinkno: TCD3_BITER_ELINKNO,
+    #[doc = "0x1080 - TCD Source Address"]
+    pub tcd4_saddr: TCD4_SADDR,
+    #[doc = "0x1084 - TCD Signed Source Address Offset"]
+    pub tcd4_soff: TCD4_SOFF,
+    #[doc = "0x1086 - TCD Transfer Attributes"]
+    pub tcd4_attr: TCD4_ATTR,
+    #[doc = "0x1088 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd4_nbytes_mlno: TCD4_NBYTES_MLNO,
+    #[doc = "0x108c - TCD Last Source Address Adjustment"]
+    pub tcd4_slast: TCD4_SLAST,
+    #[doc = "0x1090 - TCD Destination Address"]
+    pub tcd4_daddr: TCD4_DADDR,
+    #[doc = "0x1094 - TCD Signed Destination Address Offset"]
+    pub tcd4_doff: TCD4_DOFF,
+    #[doc = "0x1096 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd4_citer_elinkno: TCD4_CITER_ELINKNO,
+    #[doc = "0x1098 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd4_dlastsga: TCD4_DLASTSGA,
+    #[doc = "0x109c - TCD Control and Status"]
+    pub tcd4_csr: TCD4_CSR,
+    #[doc = "0x109e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd4_biter_elinkno: TCD4_BITER_ELINKNO,
+    #[doc = "0x10a0 - TCD Source Address"]
+    pub tcd5_saddr: TCD5_SADDR,
+    #[doc = "0x10a4 - TCD Signed Source Address Offset"]
+    pub tcd5_soff: TCD5_SOFF,
+    #[doc = "0x10a6 - TCD Transfer Attributes"]
+    pub tcd5_attr: TCD5_ATTR,
+    #[doc = "0x10a8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd5_nbytes_mlno: TCD5_NBYTES_MLNO,
+    #[doc = "0x10ac - TCD Last Source Address Adjustment"]
+    pub tcd5_slast: TCD5_SLAST,
+    #[doc = "0x10b0 - TCD Destination Address"]
+    pub tcd5_daddr: TCD5_DADDR,
+    #[doc = "0x10b4 - TCD Signed Destination Address Offset"]
+    pub tcd5_doff: TCD5_DOFF,
+    #[doc = "0x10b6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd5_citer_elinkno: TCD5_CITER_ELINKNO,
+    #[doc = "0x10b8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd5_dlastsga: TCD5_DLASTSGA,
+    #[doc = "0x10bc - TCD Control and Status"]
+    pub tcd5_csr: TCD5_CSR,
+    #[doc = "0x10be - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd5_biter_elinkno: TCD5_BITER_ELINKNO,
+    #[doc = "0x10c0 - TCD Source Address"]
+    pub tcd6_saddr: TCD6_SADDR,
+    #[doc = "0x10c4 - TCD Signed Source Address Offset"]
+    pub tcd6_soff: TCD6_SOFF,
+    #[doc = "0x10c6 - TCD Transfer Attributes"]
+    pub tcd6_attr: TCD6_ATTR,
+    #[doc = "0x10c8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd6_nbytes_mlno: TCD6_NBYTES_MLNO,
+    #[doc = "0x10cc - TCD Last Source Address Adjustment"]
+    pub tcd6_slast: TCD6_SLAST,
+    #[doc = "0x10d0 - TCD Destination Address"]
+    pub tcd6_daddr: TCD6_DADDR,
+    #[doc = "0x10d4 - TCD Signed Destination Address Offset"]
+    pub tcd6_doff: TCD6_DOFF,
+    #[doc = "0x10d6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd6_citer_elinkno: TCD6_CITER_ELINKNO,
+    #[doc = "0x10d8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd6_dlastsga: TCD6_DLASTSGA,
+    #[doc = "0x10dc - TCD Control and Status"]
+    pub tcd6_csr: TCD6_CSR,
+    #[doc = "0x10de - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd6_biter_elinkno: TCD6_BITER_ELINKNO,
+    #[doc = "0x10e0 - TCD Source Address"]
+    pub tcd7_saddr: TCD7_SADDR,
+    #[doc = "0x10e4 - TCD Signed Source Address Offset"]
+    pub tcd7_soff: TCD7_SOFF,
+    #[doc = "0x10e6 - TCD Transfer Attributes"]
+    pub tcd7_attr: TCD7_ATTR,
+    #[doc = "0x10e8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd7_nbytes_mlno: TCD7_NBYTES_MLNO,
+    #[doc = "0x10ec - TCD Last Source Address Adjustment"]
+    pub tcd7_slast: TCD7_SLAST,
+    #[doc = "0x10f0 - TCD Destination Address"]
+    pub tcd7_daddr: TCD7_DADDR,
+    #[doc = "0x10f4 - TCD Signed Destination Address Offset"]
+    pub tcd7_doff: TCD7_DOFF,
+    #[doc = "0x10f6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd7_citer_elinkno: TCD7_CITER_ELINKNO,
+    #[doc = "0x10f8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd7_dlastsga: TCD7_DLASTSGA,
+    #[doc = "0x10fc - TCD Control and Status"]
+    pub tcd7_csr: TCD7_CSR,
+    #[doc = "0x10fe - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd7_biter_elinkno: TCD7_BITER_ELINKNO,
+    #[doc = "0x1100 - TCD Source Address"]
+    pub tcd8_saddr: TCD8_SADDR,
+    #[doc = "0x1104 - TCD Signed Source Address Offset"]
+    pub tcd8_soff: TCD8_SOFF,
+    #[doc = "0x1106 - TCD Transfer Attributes"]
+    pub tcd8_attr: TCD8_ATTR,
+    #[doc = "0x1108 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd8_nbytes_mlno: TCD8_NBYTES_MLNO,
+    #[doc = "0x110c - TCD Last Source Address Adjustment"]
+    pub tcd8_slast: TCD8_SLAST,
+    #[doc = "0x1110 - TCD Destination Address"]
+    pub tcd8_daddr: TCD8_DADDR,
+    #[doc = "0x1114 - TCD Signed Destination Address Offset"]
+    pub tcd8_doff: TCD8_DOFF,
+    #[doc = "0x1116 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd8_citer_elinkno: TCD8_CITER_ELINKNO,
+    #[doc = "0x1118 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd8_dlastsga: TCD8_DLASTSGA,
+    #[doc = "0x111c - TCD Control and Status"]
+    pub tcd8_csr: TCD8_CSR,
+    #[doc = "0x111e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd8_biter_elinkno: TCD8_BITER_ELINKNO,
+    #[doc = "0x1120 - TCD Source Address"]
+    pub tcd9_saddr: TCD9_SADDR,
+    #[doc = "0x1124 - TCD Signed Source Address Offset"]
+    pub tcd9_soff: TCD9_SOFF,
+    #[doc = "0x1126 - TCD Transfer Attributes"]
+    pub tcd9_attr: TCD9_ATTR,
+    #[doc = "0x1128 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd9_nbytes_mlno: TCD9_NBYTES_MLNO,
+    #[doc = "0x112c - TCD Last Source Address Adjustment"]
+    pub tcd9_slast: TCD9_SLAST,
+    #[doc = "0x1130 - TCD Destination Address"]
+    pub tcd9_daddr: TCD9_DADDR,
+    #[doc = "0x1134 - TCD Signed Destination Address Offset"]
+    pub tcd9_doff: TCD9_DOFF,
+    #[doc = "0x1136 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd9_citer_elinkno: TCD9_CITER_ELINKNO,
+    #[doc = "0x1138 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd9_dlastsga: TCD9_DLASTSGA,
+    #[doc = "0x113c - TCD Control and Status"]
+    pub tcd9_csr: TCD9_CSR,
+    #[doc = "0x113e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd9_biter_elinkno: TCD9_BITER_ELINKNO,
+    #[doc = "0x1140 - TCD Source Address"]
+    pub tcd10_saddr: TCD10_SADDR,
+    #[doc = "0x1144 - TCD Signed Source Address Offset"]
+    pub tcd10_soff: TCD10_SOFF,
+    #[doc = "0x1146 - TCD Transfer Attributes"]
+    pub tcd10_attr: TCD10_ATTR,
+    #[doc = "0x1148 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd10_nbytes_mlno: TCD10_NBYTES_MLNO,
+    #[doc = "0x114c - TCD Last Source Address Adjustment"]
+    pub tcd10_slast: TCD10_SLAST,
+    #[doc = "0x1150 - TCD Destination Address"]
+    pub tcd10_daddr: TCD10_DADDR,
+    #[doc = "0x1154 - TCD Signed Destination Address Offset"]
+    pub tcd10_doff: TCD10_DOFF,
+    #[doc = "0x1156 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd10_citer_elinkno: TCD10_CITER_ELINKNO,
+    #[doc = "0x1158 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd10_dlastsga: TCD10_DLASTSGA,
+    #[doc = "0x115c - TCD Control and Status"]
+    pub tcd10_csr: TCD10_CSR,
+    #[doc = "0x115e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd10_biter_elinkno: TCD10_BITER_ELINKNO,
+    #[doc = "0x1160 - TCD Source Address"]
+    pub tcd11_saddr: TCD11_SADDR,
+    #[doc = "0x1164 - TCD Signed Source Address Offset"]
+    pub tcd11_soff: TCD11_SOFF,
+    #[doc = "0x1166 - TCD Transfer Attributes"]
+    pub tcd11_attr: TCD11_ATTR,
+    #[doc = "0x1168 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd11_nbytes_mlno: TCD11_NBYTES_MLNO,
+    #[doc = "0x116c - TCD Last Source Address Adjustment"]
+    pub tcd11_slast: TCD11_SLAST,
+    #[doc = "0x1170 - TCD Destination Address"]
+    pub tcd11_daddr: TCD11_DADDR,
+    #[doc = "0x1174 - TCD Signed Destination Address Offset"]
+    pub tcd11_doff: TCD11_DOFF,
+    #[doc = "0x1176 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd11_citer_elinkno: TCD11_CITER_ELINKNO,
+    #[doc = "0x1178 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd11_dlastsga: TCD11_DLASTSGA,
+    #[doc = "0x117c - TCD Control and Status"]
+    pub tcd11_csr: TCD11_CSR,
+    #[doc = "0x117e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd11_biter_elinkno: TCD11_BITER_ELINKNO,
+    #[doc = "0x1180 - TCD Source Address"]
+    pub tcd12_saddr: TCD12_SADDR,
+    #[doc = "0x1184 - TCD Signed Source Address Offset"]
+    pub tcd12_soff: TCD12_SOFF,
+    #[doc = "0x1186 - TCD Transfer Attributes"]
+    pub tcd12_attr: TCD12_ATTR,
+    #[doc = "0x1188 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd12_nbytes_mlno: TCD12_NBYTES_MLNO,
+    #[doc = "0x118c - TCD Last Source Address Adjustment"]
+    pub tcd12_slast: TCD12_SLAST,
+    #[doc = "0x1190 - TCD Destination Address"]
+    pub tcd12_daddr: TCD12_DADDR,
+    #[doc = "0x1194 - TCD Signed Destination Address Offset"]
+    pub tcd12_doff: TCD12_DOFF,
+    #[doc = "0x1196 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd12_citer_elinkno: TCD12_CITER_ELINKNO,
+    #[doc = "0x1198 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd12_dlastsga: TCD12_DLASTSGA,
+    #[doc = "0x119c - TCD Control and Status"]
+    pub tcd12_csr: TCD12_CSR,
+    #[doc = "0x119e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd12_biter_elinkno: TCD12_BITER_ELINKNO,
+    #[doc = "0x11a0 - TCD Source Address"]
+    pub tcd13_saddr: TCD13_SADDR,
+    #[doc = "0x11a4 - TCD Signed Source Address Offset"]
+    pub tcd13_soff: TCD13_SOFF,
+    #[doc = "0x11a6 - TCD Transfer Attributes"]
+    pub tcd13_attr: TCD13_ATTR,
+    #[doc = "0x11a8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd13_nbytes_mlno: TCD13_NBYTES_MLNO,
+    #[doc = "0x11ac - TCD Last Source Address Adjustment"]
+    pub tcd13_slast: TCD13_SLAST,
+    #[doc = "0x11b0 - TCD Destination Address"]
+    pub tcd13_daddr: TCD13_DADDR,
+    #[doc = "0x11b4 - TCD Signed Destination Address Offset"]
+    pub tcd13_doff: TCD13_DOFF,
+    #[doc = "0x11b6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd13_citer_elinkno: TCD13_CITER_ELINKNO,
+    #[doc = "0x11b8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd13_dlastsga: TCD13_DLASTSGA,
+    #[doc = "0x11bc - TCD Control and Status"]
+    pub tcd13_csr: TCD13_CSR,
+    #[doc = "0x11be - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd13_biter_elinkno: TCD13_BITER_ELINKNO,
+    #[doc = "0x11c0 - TCD Source Address"]
+    pub tcd14_saddr: TCD14_SADDR,
+    #[doc = "0x11c4 - TCD Signed Source Address Offset"]
+    pub tcd14_soff: TCD14_SOFF,
+    #[doc = "0x11c6 - TCD Transfer Attributes"]
+    pub tcd14_attr: TCD14_ATTR,
+    #[doc = "0x11c8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd14_nbytes_mlno: TCD14_NBYTES_MLNO,
+    #[doc = "0x11cc - TCD Last Source Address Adjustment"]
+    pub tcd14_slast: TCD14_SLAST,
+    #[doc = "0x11d0 - TCD Destination Address"]
+    pub tcd14_daddr: TCD14_DADDR,
+    #[doc = "0x11d4 - TCD Signed Destination Address Offset"]
+    pub tcd14_doff: TCD14_DOFF,
+    #[doc = "0x11d6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd14_citer_elinkno: TCD14_CITER_ELINKNO,
+    #[doc = "0x11d8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd14_dlastsga: TCD14_DLASTSGA,
+    #[doc = "0x11dc - TCD Control and Status"]
+    pub tcd14_csr: TCD14_CSR,
+    #[doc = "0x11de - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd14_biter_elinkno: TCD14_BITER_ELINKNO,
+    #[doc = "0x11e0 - TCD Source Address"]
+    pub tcd15_saddr: TCD15_SADDR,
+    #[doc = "0x11e4 - TCD Signed Source Address Offset"]
+    pub tcd15_soff: TCD15_SOFF,
+    #[doc = "0x11e6 - TCD Transfer Attributes"]
+    pub tcd15_attr: TCD15_ATTR,
+    #[doc = "0x11e8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd15_nbytes_mlno: TCD15_NBYTES_MLNO,
+    #[doc = "0x11ec - TCD Last Source Address Adjustment"]
+    pub tcd15_slast: TCD15_SLAST,
+    #[doc = "0x11f0 - TCD Destination Address"]
+    pub tcd15_daddr: TCD15_DADDR,
+    #[doc = "0x11f4 - TCD Signed Destination Address Offset"]
+    pub tcd15_doff: TCD15_DOFF,
+    #[doc = "0x11f6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd15_citer_elinkno: TCD15_CITER_ELINKNO,
+    #[doc = "0x11f8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd15_dlastsga: TCD15_DLASTSGA,
+    #[doc = "0x11fc - TCD Control and Status"]
+    pub tcd15_csr: TCD15_CSR,
+    #[doc = "0x11fe - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd15_biter_elinkno: TCD15_BITER_ELINKNO,
+    #[doc = "0x1200 - TCD Source Address"]
+    pub tcd16_saddr: TCD16_SADDR,
+    #[doc = "0x1204 - TCD Signed Source Address Offset"]
+    pub tcd16_soff: TCD16_SOFF,
+    #[doc = "0x1206 - TCD Transfer Attributes"]
+    pub tcd16_attr: TCD16_ATTR,
+    #[doc = "0x1208 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd16_nbytes_mlno: TCD16_NBYTES_MLNO,
+    #[doc = "0x120c - TCD Last Source Address Adjustment"]
+    pub tcd16_slast: TCD16_SLAST,
+    #[doc = "0x1210 - TCD Destination Address"]
+    pub tcd16_daddr: TCD16_DADDR,
+    #[doc = "0x1214 - TCD Signed Destination Address Offset"]
+    pub tcd16_doff: TCD16_DOFF,
+    #[doc = "0x1216 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd16_citer_elinkno: TCD16_CITER_ELINKNO,
+    #[doc = "0x1218 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd16_dlastsga: TCD16_DLASTSGA,
+    #[doc = "0x121c - TCD Control and Status"]
+    pub tcd16_csr: TCD16_CSR,
+    #[doc = "0x121e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd16_biter_elinkno: TCD16_BITER_ELINKNO,
+    #[doc = "0x1220 - TCD Source Address"]
+    pub tcd17_saddr: TCD17_SADDR,
+    #[doc = "0x1224 - TCD Signed Source Address Offset"]
+    pub tcd17_soff: TCD17_SOFF,
+    #[doc = "0x1226 - TCD Transfer Attributes"]
+    pub tcd17_attr: TCD17_ATTR,
+    #[doc = "0x1228 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd17_nbytes_mlno: TCD17_NBYTES_MLNO,
+    #[doc = "0x122c - TCD Last Source Address Adjustment"]
+    pub tcd17_slast: TCD17_SLAST,
+    #[doc = "0x1230 - TCD Destination Address"]
+    pub tcd17_daddr: TCD17_DADDR,
+    #[doc = "0x1234 - TCD Signed Destination Address Offset"]
+    pub tcd17_doff: TCD17_DOFF,
+    #[doc = "0x1236 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd17_citer_elinkno: TCD17_CITER_ELINKNO,
+    #[doc = "0x1238 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd17_dlastsga: TCD17_DLASTSGA,
+    #[doc = "0x123c - TCD Control and Status"]
+    pub tcd17_csr: TCD17_CSR,
+    #[doc = "0x123e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd17_biter_elinkno: TCD17_BITER_ELINKNO,
+    #[doc = "0x1240 - TCD Source Address"]
+    pub tcd18_saddr: TCD18_SADDR,
+    #[doc = "0x1244 - TCD Signed Source Address Offset"]
+    pub tcd18_soff: TCD18_SOFF,
+    #[doc = "0x1246 - TCD Transfer Attributes"]
+    pub tcd18_attr: TCD18_ATTR,
+    #[doc = "0x1248 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd18_nbytes_mlno: TCD18_NBYTES_MLNO,
+    #[doc = "0x124c - TCD Last Source Address Adjustment"]
+    pub tcd18_slast: TCD18_SLAST,
+    #[doc = "0x1250 - TCD Destination Address"]
+    pub tcd18_daddr: TCD18_DADDR,
+    #[doc = "0x1254 - TCD Signed Destination Address Offset"]
+    pub tcd18_doff: TCD18_DOFF,
+    #[doc = "0x1256 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd18_citer_elinkno: TCD18_CITER_ELINKNO,
+    #[doc = "0x1258 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd18_dlastsga: TCD18_DLASTSGA,
+    #[doc = "0x125c - TCD Control and Status"]
+    pub tcd18_csr: TCD18_CSR,
+    #[doc = "0x125e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd18_biter_elinkno: TCD18_BITER_ELINKNO,
+    #[doc = "0x1260 - TCD Source Address"]
+    pub tcd19_saddr: TCD19_SADDR,
+    #[doc = "0x1264 - TCD Signed Source Address Offset"]
+    pub tcd19_soff: TCD19_SOFF,
+    #[doc = "0x1266 - TCD Transfer Attributes"]
+    pub tcd19_attr: TCD19_ATTR,
+    #[doc = "0x1268 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd19_nbytes_mlno: TCD19_NBYTES_MLNO,
+    #[doc = "0x126c - TCD Last Source Address Adjustment"]
+    pub tcd19_slast: TCD19_SLAST,
+    #[doc = "0x1270 - TCD Destination Address"]
+    pub tcd19_daddr: TCD19_DADDR,
+    #[doc = "0x1274 - TCD Signed Destination Address Offset"]
+    pub tcd19_doff: TCD19_DOFF,
+    #[doc = "0x1276 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd19_citer_elinkno: TCD19_CITER_ELINKNO,
+    #[doc = "0x1278 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd19_dlastsga: TCD19_DLASTSGA,
+    #[doc = "0x127c - TCD Control and Status"]
+    pub tcd19_csr: TCD19_CSR,
+    #[doc = "0x127e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd19_biter_elinkno: TCD19_BITER_ELINKNO,
+    #[doc = "0x1280 - TCD Source Address"]
+    pub tcd20_saddr: TCD20_SADDR,
+    #[doc = "0x1284 - TCD Signed Source Address Offset"]
+    pub tcd20_soff: TCD20_SOFF,
+    #[doc = "0x1286 - TCD Transfer Attributes"]
+    pub tcd20_attr: TCD20_ATTR,
+    #[doc = "0x1288 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd20_nbytes_mlno: TCD20_NBYTES_MLNO,
+    #[doc = "0x128c - TCD Last Source Address Adjustment"]
+    pub tcd20_slast: TCD20_SLAST,
+    #[doc = "0x1290 - TCD Destination Address"]
+    pub tcd20_daddr: TCD20_DADDR,
+    #[doc = "0x1294 - TCD Signed Destination Address Offset"]
+    pub tcd20_doff: TCD20_DOFF,
+    #[doc = "0x1296 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd20_citer_elinkno: TCD20_CITER_ELINKNO,
+    #[doc = "0x1298 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd20_dlastsga: TCD20_DLASTSGA,
+    #[doc = "0x129c - TCD Control and Status"]
+    pub tcd20_csr: TCD20_CSR,
+    #[doc = "0x129e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd20_biter_elinkno: TCD20_BITER_ELINKNO,
+    #[doc = "0x12a0 - TCD Source Address"]
+    pub tcd21_saddr: TCD21_SADDR,
+    #[doc = "0x12a4 - TCD Signed Source Address Offset"]
+    pub tcd21_soff: TCD21_SOFF,
+    #[doc = "0x12a6 - TCD Transfer Attributes"]
+    pub tcd21_attr: TCD21_ATTR,
+    #[doc = "0x12a8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd21_nbytes_mlno: TCD21_NBYTES_MLNO,
+    #[doc = "0x12ac - TCD Last Source Address Adjustment"]
+    pub tcd21_slast: TCD21_SLAST,
+    #[doc = "0x12b0 - TCD Destination Address"]
+    pub tcd21_daddr: TCD21_DADDR,
+    #[doc = "0x12b4 - TCD Signed Destination Address Offset"]
+    pub tcd21_doff: TCD21_DOFF,
+    #[doc = "0x12b6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd21_citer_elinkno: TCD21_CITER_ELINKNO,
+    #[doc = "0x12b8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd21_dlastsga: TCD21_DLASTSGA,
+    #[doc = "0x12bc - TCD Control and Status"]
+    pub tcd21_csr: TCD21_CSR,
+    #[doc = "0x12be - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd21_biter_elinkno: TCD21_BITER_ELINKNO,
+    #[doc = "0x12c0 - TCD Source Address"]
+    pub tcd22_saddr: TCD22_SADDR,
+    #[doc = "0x12c4 - TCD Signed Source Address Offset"]
+    pub tcd22_soff: TCD22_SOFF,
+    #[doc = "0x12c6 - TCD Transfer Attributes"]
+    pub tcd22_attr: TCD22_ATTR,
+    #[doc = "0x12c8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd22_nbytes_mlno: TCD22_NBYTES_MLNO,
+    #[doc = "0x12cc - TCD Last Source Address Adjustment"]
+    pub tcd22_slast: TCD22_SLAST,
+    #[doc = "0x12d0 - TCD Destination Address"]
+    pub tcd22_daddr: TCD22_DADDR,
+    #[doc = "0x12d4 - TCD Signed Destination Address Offset"]
+    pub tcd22_doff: TCD22_DOFF,
+    #[doc = "0x12d6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd22_citer_elinkno: TCD22_CITER_ELINKNO,
+    #[doc = "0x12d8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd22_dlastsga: TCD22_DLASTSGA,
+    #[doc = "0x12dc - TCD Control and Status"]
+    pub tcd22_csr: TCD22_CSR,
+    #[doc = "0x12de - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd22_biter_elinkno: TCD22_BITER_ELINKNO,
+    #[doc = "0x12e0 - TCD Source Address"]
+    pub tcd23_saddr: TCD23_SADDR,
+    #[doc = "0x12e4 - TCD Signed Source Address Offset"]
+    pub tcd23_soff: TCD23_SOFF,
+    #[doc = "0x12e6 - TCD Transfer Attributes"]
+    pub tcd23_attr: TCD23_ATTR,
+    #[doc = "0x12e8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd23_nbytes_mlno: TCD23_NBYTES_MLNO,
+    #[doc = "0x12ec - TCD Last Source Address Adjustment"]
+    pub tcd23_slast: TCD23_SLAST,
+    #[doc = "0x12f0 - TCD Destination Address"]
+    pub tcd23_daddr: TCD23_DADDR,
+    #[doc = "0x12f4 - TCD Signed Destination Address Offset"]
+    pub tcd23_doff: TCD23_DOFF,
+    #[doc = "0x12f6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd23_citer_elinkno: TCD23_CITER_ELINKNO,
+    #[doc = "0x12f8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd23_dlastsga: TCD23_DLASTSGA,
+    #[doc = "0x12fc - TCD Control and Status"]
+    pub tcd23_csr: TCD23_CSR,
+    #[doc = "0x12fe - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd23_biter_elinkno: TCD23_BITER_ELINKNO,
+    #[doc = "0x1300 - TCD Source Address"]
+    pub tcd24_saddr: TCD24_SADDR,
+    #[doc = "0x1304 - TCD Signed Source Address Offset"]
+    pub tcd24_soff: TCD24_SOFF,
+    #[doc = "0x1306 - TCD Transfer Attributes"]
+    pub tcd24_attr: TCD24_ATTR,
+    #[doc = "0x1308 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd24_nbytes_mlno: TCD24_NBYTES_MLNO,
+    #[doc = "0x130c - TCD Last Source Address Adjustment"]
+    pub tcd24_slast: TCD24_SLAST,
+    #[doc = "0x1310 - TCD Destination Address"]
+    pub tcd24_daddr: TCD24_DADDR,
+    #[doc = "0x1314 - TCD Signed Destination Address Offset"]
+    pub tcd24_doff: TCD24_DOFF,
+    #[doc = "0x1316 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd24_citer_elinkno: TCD24_CITER_ELINKNO,
+    #[doc = "0x1318 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd24_dlastsga: TCD24_DLASTSGA,
+    #[doc = "0x131c - TCD Control and Status"]
+    pub tcd24_csr: TCD24_CSR,
+    #[doc = "0x131e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd24_biter_elinkno: TCD24_BITER_ELINKNO,
+    #[doc = "0x1320 - TCD Source Address"]
+    pub tcd25_saddr: TCD25_SADDR,
+    #[doc = "0x1324 - TCD Signed Source Address Offset"]
+    pub tcd25_soff: TCD25_SOFF,
+    #[doc = "0x1326 - TCD Transfer Attributes"]
+    pub tcd25_attr: TCD25_ATTR,
+    #[doc = "0x1328 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd25_nbytes_mlno: TCD25_NBYTES_MLNO,
+    #[doc = "0x132c - TCD Last Source Address Adjustment"]
+    pub tcd25_slast: TCD25_SLAST,
+    #[doc = "0x1330 - TCD Destination Address"]
+    pub tcd25_daddr: TCD25_DADDR,
+    #[doc = "0x1334 - TCD Signed Destination Address Offset"]
+    pub tcd25_doff: TCD25_DOFF,
+    #[doc = "0x1336 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd25_citer_elinkno: TCD25_CITER_ELINKNO,
+    #[doc = "0x1338 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd25_dlastsga: TCD25_DLASTSGA,
+    #[doc = "0x133c - TCD Control and Status"]
+    pub tcd25_csr: TCD25_CSR,
+    #[doc = "0x133e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd25_biter_elinkno: TCD25_BITER_ELINKNO,
+    #[doc = "0x1340 - TCD Source Address"]
+    pub tcd26_saddr: TCD26_SADDR,
+    #[doc = "0x1344 - TCD Signed Source Address Offset"]
+    pub tcd26_soff: TCD26_SOFF,
+    #[doc = "0x1346 - TCD Transfer Attributes"]
+    pub tcd26_attr: TCD26_ATTR,
+    #[doc = "0x1348 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd26_nbytes_mlno: TCD26_NBYTES_MLNO,
+    #[doc = "0x134c - TCD Last Source Address Adjustment"]
+    pub tcd26_slast: TCD26_SLAST,
+    #[doc = "0x1350 - TCD Destination Address"]
+    pub tcd26_daddr: TCD26_DADDR,
+    #[doc = "0x1354 - TCD Signed Destination Address Offset"]
+    pub tcd26_doff: TCD26_DOFF,
+    #[doc = "0x1356 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd26_citer_elinkno: TCD26_CITER_ELINKNO,
+    #[doc = "0x1358 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd26_dlastsga: TCD26_DLASTSGA,
+    #[doc = "0x135c - TCD Control and Status"]
+    pub tcd26_csr: TCD26_CSR,
+    #[doc = "0x135e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd26_biter_elinkno: TCD26_BITER_ELINKNO,
+    #[doc = "0x1360 - TCD Source Address"]
+    pub tcd27_saddr: TCD27_SADDR,
+    #[doc = "0x1364 - TCD Signed Source Address Offset"]
+    pub tcd27_soff: TCD27_SOFF,
+    #[doc = "0x1366 - TCD Transfer Attributes"]
+    pub tcd27_attr: TCD27_ATTR,
+    #[doc = "0x1368 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd27_nbytes_mlno: TCD27_NBYTES_MLNO,
+    #[doc = "0x136c - TCD Last Source Address Adjustment"]
+    pub tcd27_slast: TCD27_SLAST,
+    #[doc = "0x1370 - TCD Destination Address"]
+    pub tcd27_daddr: TCD27_DADDR,
+    #[doc = "0x1374 - TCD Signed Destination Address Offset"]
+    pub tcd27_doff: TCD27_DOFF,
+    #[doc = "0x1376 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd27_citer_elinkno: TCD27_CITER_ELINKNO,
+    #[doc = "0x1378 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd27_dlastsga: TCD27_DLASTSGA,
+    #[doc = "0x137c - TCD Control and Status"]
+    pub tcd27_csr: TCD27_CSR,
+    #[doc = "0x137e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd27_biter_elinkno: TCD27_BITER_ELINKNO,
+    #[doc = "0x1380 - TCD Source Address"]
+    pub tcd28_saddr: TCD28_SADDR,
+    #[doc = "0x1384 - TCD Signed Source Address Offset"]
+    pub tcd28_soff: TCD28_SOFF,
+    #[doc = "0x1386 - TCD Transfer Attributes"]
+    pub tcd28_attr: TCD28_ATTR,
+    #[doc = "0x1388 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd28_nbytes_mlno: TCD28_NBYTES_MLNO,
+    #[doc = "0x138c - TCD Last Source Address Adjustment"]
+    pub tcd28_slast: TCD28_SLAST,
+    #[doc = "0x1390 - TCD Destination Address"]
+    pub tcd28_daddr: TCD28_DADDR,
+    #[doc = "0x1394 - TCD Signed Destination Address Offset"]
+    pub tcd28_doff: TCD28_DOFF,
+    #[doc = "0x1396 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd28_citer_elinkno: TCD28_CITER_ELINKNO,
+    #[doc = "0x1398 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd28_dlastsga: TCD28_DLASTSGA,
+    #[doc = "0x139c - TCD Control and Status"]
+    pub tcd28_csr: TCD28_CSR,
+    #[doc = "0x139e - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd28_biter_elinkno: TCD28_BITER_ELINKNO,
+    #[doc = "0x13a0 - TCD Source Address"]
+    pub tcd29_saddr: TCD29_SADDR,
+    #[doc = "0x13a4 - TCD Signed Source Address Offset"]
+    pub tcd29_soff: TCD29_SOFF,
+    #[doc = "0x13a6 - TCD Transfer Attributes"]
+    pub tcd29_attr: TCD29_ATTR,
+    #[doc = "0x13a8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd29_nbytes_mlno: TCD29_NBYTES_MLNO,
+    #[doc = "0x13ac - TCD Last Source Address Adjustment"]
+    pub tcd29_slast: TCD29_SLAST,
+    #[doc = "0x13b0 - TCD Destination Address"]
+    pub tcd29_daddr: TCD29_DADDR,
+    #[doc = "0x13b4 - TCD Signed Destination Address Offset"]
+    pub tcd29_doff: TCD29_DOFF,
+    #[doc = "0x13b6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd29_citer_elinkno: TCD29_CITER_ELINKNO,
+    #[doc = "0x13b8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd29_dlastsga: TCD29_DLASTSGA,
+    #[doc = "0x13bc - TCD Control and Status"]
+    pub tcd29_csr: TCD29_CSR,
+    #[doc = "0x13be - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd29_biter_elinkno: TCD29_BITER_ELINKNO,
+    #[doc = "0x13c0 - TCD Source Address"]
+    pub tcd30_saddr: TCD30_SADDR,
+    #[doc = "0x13c4 - TCD Signed Source Address Offset"]
+    pub tcd30_soff: TCD30_SOFF,
+    #[doc = "0x13c6 - TCD Transfer Attributes"]
+    pub tcd30_attr: TCD30_ATTR,
+    #[doc = "0x13c8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd30_nbytes_mlno: TCD30_NBYTES_MLNO,
+    #[doc = "0x13cc - TCD Last Source Address Adjustment"]
+    pub tcd30_slast: TCD30_SLAST,
+    #[doc = "0x13d0 - TCD Destination Address"]
+    pub tcd30_daddr: TCD30_DADDR,
+    #[doc = "0x13d4 - TCD Signed Destination Address Offset"]
+    pub tcd30_doff: TCD30_DOFF,
+    #[doc = "0x13d6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd30_citer_elinkno: TCD30_CITER_ELINKNO,
+    #[doc = "0x13d8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd30_dlastsga: TCD30_DLASTSGA,
+    #[doc = "0x13dc - TCD Control and Status"]
+    pub tcd30_csr: TCD30_CSR,
+    #[doc = "0x13de - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd30_biter_elinkno: TCD30_BITER_ELINKNO,
+    #[doc = "0x13e0 - TCD Source Address"]
+    pub tcd31_saddr: TCD31_SADDR,
+    #[doc = "0x13e4 - TCD Signed Source Address Offset"]
+    pub tcd31_soff: TCD31_SOFF,
+    #[doc = "0x13e6 - TCD Transfer Attributes"]
+    pub tcd31_attr: TCD31_ATTR,
+    #[doc = "0x13e8 - TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+    pub tcd31_nbytes_mlno: TCD31_NBYTES_MLNO,
+    #[doc = "0x13ec - TCD Last Source Address Adjustment"]
+    pub tcd31_slast: TCD31_SLAST,
+    #[doc = "0x13f0 - TCD Destination Address"]
+    pub tcd31_daddr: TCD31_DADDR,
+    #[doc = "0x13f4 - TCD Signed Destination Address Offset"]
+    pub tcd31_doff: TCD31_DOFF,
+    #[doc = "0x13f6 - TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd31_citer_elinkno: TCD31_CITER_ELINKNO,
+    #[doc = "0x13f8 - TCD Last Destination Address Adjustment/Scatter Gather Address"]
+    pub tcd31_dlastsga: TCD31_DLASTSGA,
+    #[doc = "0x13fc - TCD Control and Status"]
+    pub tcd31_csr: TCD31_CSR,
+    #[doc = "0x13fe - TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+    pub tcd31_biter_elinkno: TCD31_BITER_ELINKNO,
+}
+#[doc = "Control Register"]
+pub struct CR {
+    register: VolatileCell<u32>,
+}
+#[doc = "Control Register"]
+pub mod cr;
+#[doc = "Error Status Register"]
+pub struct ES {
+    register: VolatileCell<u32>,
+}
+#[doc = "Error Status Register"]
+pub mod es;
+#[doc = "Enable Request Register"]
+pub struct ERQ {
+    register: VolatileCell<u32>,
+}
+#[doc = "Enable Request Register"]
+pub mod erq;
+#[doc = "Enable Error Interrupt Register"]
+pub struct EEI {
+    register: VolatileCell<u32>,
+}
+#[doc = "Enable Error Interrupt Register"]
+pub mod eei;
+#[doc = "Clear Enable Error Interrupt Register"]
+pub struct CEEI {
+    register: VolatileCell<u8>,
+}
+#[doc = "Clear Enable Error Interrupt Register"]
+pub mod ceei;
+#[doc = "Set Enable Error Interrupt Register"]
+pub struct SEEI {
+    register: VolatileCell<u8>,
+}
+#[doc = "Set Enable Error Interrupt Register"]
+pub mod seei;
+#[doc = "Clear Enable Request Register"]
+pub struct CERQ {
+    register: VolatileCell<u8>,
+}
+#[doc = "Clear Enable Request Register"]
+pub mod cerq;
+#[doc = "Set Enable Request Register"]
+pub struct SERQ {
+    register: VolatileCell<u8>,
+}
+#[doc = "Set Enable Request Register"]
+pub mod serq;
+#[doc = "Clear DONE Status Bit Register"]
+pub struct CDNE {
+    register: VolatileCell<u8>,
+}
+#[doc = "Clear DONE Status Bit Register"]
+pub mod cdne;
+#[doc = "Set START Bit Register"]
+pub struct SSRT {
+    register: VolatileCell<u8>,
+}
+#[doc = "Set START Bit Register"]
+pub mod ssrt;
+#[doc = "Clear Error Register"]
+pub struct CERR {
+    register: VolatileCell<u8>,
+}
+#[doc = "Clear Error Register"]
+pub mod cerr;
+#[doc = "Clear Interrupt Request Register"]
+pub struct CINT {
+    register: VolatileCell<u8>,
+}
+#[doc = "Clear Interrupt Request Register"]
+pub mod cint;
+#[doc = "Interrupt Request Register"]
+pub struct INT {
+    register: VolatileCell<u32>,
+}
+#[doc = "Interrupt Request Register"]
+pub mod int;
+#[doc = "Error Register"]
+pub struct ERR {
+    register: VolatileCell<u32>,
+}
+#[doc = "Error Register"]
+pub mod err;
+#[doc = "Hardware Request Status Register"]
+pub struct HRS {
+    register: VolatileCell<u32>,
+}
+#[doc = "Hardware Request Status Register"]
+pub mod hrs;
+#[doc = "Enable Asynchronous Request in Stop Register"]
+pub struct EARS {
+    register: VolatileCell<u32>,
+}
+#[doc = "Enable Asynchronous Request in Stop Register"]
+pub mod ears;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI3 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri3;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI2 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri2;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI1 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri1;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI0 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri0;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI7 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri7;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI6 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri6;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI5 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri5;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI4 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri4;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI11 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri11;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI10 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri10;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI9 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri9;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI8 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri8;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI15 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri15;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI14 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri14;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI13 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri13;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI12 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri12;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI19 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri19;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI18 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri18;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI17 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri17;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI16 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri16;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI23 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri23;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI22 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri22;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI21 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri21;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI20 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri20;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI27 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri27;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI26 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri26;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI25 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri25;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI24 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri24;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI31 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri31;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI30 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri30;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI29 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri29;
+#[doc = "Channel n Priority Register"]
+pub struct DCHPRI28 {
+    register: VolatileCell<u8>,
+}
+#[doc = "Channel n Priority Register"]
+pub mod dchpri28;
+#[doc = "TCD Source Address"]
+pub struct TCD0_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd0_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD0_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd0_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD0_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd0_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD0_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd0_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD0_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd0_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD0_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd0_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD0_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd0_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD0_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd0_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD0_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd0_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD0_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd0_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD0_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd0_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD0_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd0_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD0_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd0_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD0_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd0_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD0_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd0_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD1_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd1_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD1_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd1_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD1_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd1_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD1_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd1_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD1_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd1_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD1_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd1_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD1_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd1_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD1_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd1_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD1_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd1_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD1_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd1_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD1_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd1_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD1_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd1_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD1_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd1_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD1_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd1_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD1_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd1_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD2_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd2_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD2_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd2_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD2_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd2_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD2_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd2_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD2_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd2_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD2_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd2_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD2_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd2_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD2_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd2_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD2_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd2_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD2_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd2_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD2_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd2_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD2_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd2_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD2_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd2_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD2_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd2_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD2_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd2_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD3_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd3_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD3_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd3_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD3_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd3_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD3_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd3_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD3_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd3_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD3_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd3_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD3_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd3_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD3_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd3_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD3_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd3_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD3_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd3_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD3_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd3_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD3_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd3_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD3_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd3_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD3_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd3_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD3_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd3_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD4_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd4_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD4_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd4_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD4_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd4_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD4_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd4_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD4_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd4_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD4_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd4_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD4_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd4_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD4_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd4_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD4_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd4_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD4_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd4_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD4_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd4_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD4_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd4_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD4_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd4_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD4_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd4_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD4_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd4_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD5_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd5_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD5_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd5_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD5_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd5_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD5_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd5_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD5_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd5_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD5_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd5_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD5_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd5_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD5_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd5_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD5_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd5_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD5_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd5_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD5_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd5_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD5_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd5_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD5_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd5_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD5_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd5_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD5_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd5_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD6_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd6_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD6_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd6_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD6_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd6_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD6_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd6_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD6_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd6_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD6_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd6_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD6_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd6_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD6_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd6_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD6_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd6_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD6_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd6_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD6_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd6_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD6_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd6_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD6_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd6_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD6_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd6_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD6_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd6_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD7_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd7_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD7_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd7_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD7_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd7_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD7_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd7_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD7_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd7_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD7_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd7_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD7_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd7_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD7_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd7_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD7_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd7_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD7_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd7_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD7_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd7_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD7_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd7_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD7_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd7_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD7_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd7_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD7_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd7_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD8_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd8_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD8_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd8_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD8_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd8_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD8_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd8_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD8_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd8_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD8_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd8_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD8_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd8_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD8_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd8_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD8_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd8_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD8_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd8_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD8_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd8_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD8_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd8_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD8_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd8_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD8_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd8_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD8_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd8_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD9_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd9_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD9_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd9_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD9_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd9_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD9_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd9_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD9_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd9_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD9_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd9_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD9_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd9_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD9_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd9_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD9_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd9_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD9_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd9_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD9_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd9_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD9_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd9_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD9_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd9_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD9_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd9_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD9_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd9_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD10_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd10_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD10_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd10_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD10_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd10_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD10_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd10_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD10_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd10_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD10_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd10_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD10_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd10_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD10_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd10_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD10_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd10_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD10_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd10_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD10_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd10_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD10_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd10_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD10_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd10_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD10_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd10_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD10_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd10_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD11_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd11_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD11_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd11_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD11_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd11_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD11_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd11_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD11_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd11_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD11_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd11_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD11_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd11_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD11_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd11_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD11_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd11_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD11_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd11_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD11_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd11_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD11_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd11_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD11_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd11_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD11_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd11_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD11_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd11_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD12_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd12_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD12_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd12_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD12_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd12_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD12_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd12_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD12_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd12_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD12_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd12_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD12_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd12_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD12_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd12_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD12_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd12_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD12_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd12_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD12_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd12_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD12_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd12_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD12_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd12_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD12_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd12_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD12_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd12_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD13_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd13_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD13_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd13_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD13_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd13_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD13_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd13_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD13_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd13_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD13_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd13_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD13_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd13_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD13_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd13_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD13_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd13_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD13_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd13_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD13_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd13_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD13_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd13_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD13_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd13_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD13_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd13_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD13_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd13_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD14_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd14_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD14_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd14_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD14_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd14_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD14_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd14_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD14_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd14_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD14_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd14_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD14_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd14_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD14_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd14_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD14_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd14_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD14_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd14_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD14_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd14_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD14_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd14_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD14_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd14_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD14_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd14_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD14_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd14_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD15_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd15_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD15_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd15_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD15_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd15_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD15_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd15_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD15_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd15_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD15_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd15_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD15_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd15_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD15_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd15_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD15_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd15_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD15_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd15_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD15_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd15_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD15_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd15_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD15_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd15_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD15_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd15_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD15_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd15_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD16_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd16_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD16_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd16_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD16_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd16_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD16_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd16_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD16_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd16_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD16_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd16_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD16_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd16_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD16_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd16_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD16_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd16_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD16_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd16_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD16_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd16_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD16_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd16_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD16_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd16_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD16_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd16_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD16_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd16_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD17_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd17_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD17_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd17_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD17_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd17_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD17_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd17_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD17_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd17_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD17_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd17_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD17_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd17_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD17_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd17_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD17_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd17_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD17_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd17_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD17_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd17_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD17_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd17_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD17_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd17_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD17_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd17_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD17_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd17_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD18_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd18_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD18_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd18_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD18_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd18_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD18_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd18_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD18_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd18_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD18_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd18_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD18_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd18_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD18_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd18_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD18_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd18_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD18_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd18_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD18_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd18_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD18_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd18_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD18_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd18_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD18_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd18_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD18_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd18_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD19_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd19_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD19_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd19_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD19_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd19_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD19_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd19_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD19_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd19_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD19_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd19_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD19_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd19_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD19_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd19_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD19_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd19_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD19_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd19_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD19_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd19_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD19_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd19_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD19_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd19_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD19_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd19_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD19_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd19_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD20_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd20_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD20_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd20_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD20_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd20_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD20_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd20_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD20_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd20_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD20_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd20_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD20_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd20_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD20_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd20_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD20_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd20_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD20_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd20_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD20_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd20_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD20_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd20_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD20_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd20_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD20_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd20_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD20_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd20_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD21_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd21_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD21_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd21_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD21_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd21_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD21_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd21_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD21_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd21_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD21_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd21_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD21_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd21_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD21_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd21_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD21_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd21_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD21_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd21_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD21_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd21_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD21_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd21_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD21_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd21_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD21_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd21_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD21_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd21_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD22_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd22_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD22_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd22_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD22_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd22_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD22_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd22_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD22_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd22_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD22_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd22_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD22_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd22_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD22_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd22_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD22_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd22_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD22_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd22_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD22_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd22_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD22_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd22_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD22_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd22_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD22_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd22_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD22_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd22_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD23_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd23_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD23_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd23_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD23_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd23_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD23_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd23_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD23_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd23_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD23_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd23_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD23_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd23_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD23_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd23_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD23_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd23_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD23_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd23_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD23_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd23_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD23_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd23_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD23_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd23_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD23_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd23_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD23_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd23_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD24_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd24_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD24_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd24_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD24_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd24_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD24_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd24_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD24_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd24_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD24_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd24_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD24_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd24_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD24_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd24_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD24_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd24_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD24_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd24_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD24_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd24_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD24_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd24_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD24_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd24_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD24_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd24_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD24_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd24_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD25_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd25_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD25_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd25_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD25_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd25_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD25_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd25_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD25_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd25_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD25_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd25_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD25_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd25_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD25_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd25_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD25_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd25_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD25_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd25_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD25_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd25_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD25_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd25_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD25_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd25_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD25_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd25_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD25_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd25_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD26_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd26_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD26_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd26_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD26_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd26_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD26_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd26_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD26_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd26_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD26_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd26_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD26_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd26_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD26_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd26_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD26_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd26_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD26_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd26_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD26_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd26_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD26_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd26_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD26_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd26_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD26_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd26_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD26_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd26_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD27_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd27_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD27_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd27_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD27_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd27_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD27_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd27_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD27_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd27_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD27_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd27_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD27_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd27_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD27_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd27_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD27_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd27_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD27_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd27_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD27_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd27_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD27_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd27_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD27_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd27_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD27_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd27_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD27_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd27_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD28_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd28_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD28_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd28_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD28_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd28_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD28_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd28_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD28_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd28_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD28_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd28_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD28_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd28_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD28_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd28_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD28_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd28_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD28_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd28_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD28_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd28_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD28_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd28_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD28_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd28_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD28_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd28_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD28_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd28_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD29_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd29_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD29_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd29_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD29_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd29_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD29_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd29_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD29_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd29_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD29_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd29_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD29_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd29_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD29_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd29_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD29_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd29_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD29_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd29_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD29_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd29_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD29_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd29_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD29_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd29_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD29_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd29_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD29_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd29_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD30_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd30_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD30_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd30_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD30_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd30_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD30_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd30_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD30_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd30_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD30_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd30_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD30_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd30_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD30_DADDR {
+    register: VolatileCellz<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd30_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD30_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd30_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD30_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd30_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD30_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd30_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD30_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd30_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD30_CSR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd30_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD30_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd30_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD30_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd30_biter_elinkyes;
+#[doc = "TCD Source Address"]
+pub struct TCD31_SADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Source Address"]
+pub mod tcd31_saddr;
+#[doc = "TCD Signed Source Address Offset"]
+pub struct TCD31_SOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Source Address Offset"]
+pub mod tcd31_soff;
+#[doc = "TCD Transfer Attributes"]
+pub struct TCD31_ATTR {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Transfer Attributes"]
+pub mod tcd31_attr;
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub struct TCD31_NBYTES_MLNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Minor Byte Count (Minor Loop Mapping Disabled)"]
+pub mod tcd31_nbytes_mlno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub struct TCD31_NBYTES_MLOFFNO {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping Enabled and Offset Disabled)"]
+pub mod tcd31_nbytes_mloffno;
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub struct TCD31_NBYTES_MLOFFYES {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Signed Minor Loop Offset (Minor Loop Mapping and Offset Enabled)"]
+pub mod tcd31_nbytes_mloffyes;
+#[doc = "TCD Last Source Address Adjustment"]
+pub struct TCD31_SLAST {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Source Address Adjustment"]
+pub mod tcd31_slast;
+#[doc = "TCD Destination Address"]
+pub struct TCD31_DADDR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Destination Address"]
+pub mod tcd31_daddr;
+#[doc = "TCD Signed Destination Address Offset"]
+pub struct TCD31_DOFF {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Signed Destination Address Offset"]
+pub mod tcd31_doff;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD31_CITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd31_citer_elinkno;
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD31_CITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Current Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd31_citer_elinkyes;
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub struct TCD31_DLASTSGA {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Last Destination Address Adjustment/Scatter Gather Address"]
+pub mod tcd31_dlastsga;
+#[doc = "TCD Control and Status"]
+pub struct TCD31_CSR {
+    register: VolatileCell<u32>,
+}
+#[doc = "TCD Control and Status"]
+pub mod tcd31_csr;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub struct TCD31_BITER_ELINKNO {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Disabled)"]
+pub mod tcd31_biter_elinkno;
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub struct TCD31_BITER_ELINKYES {
+    register: VolatileCell<u16>,
+}
+#[doc = "TCD Beginning Minor Loop Link, Major Loop Count (Channel Linking Enabled)"]
+pub mod tcd31_biter_elinkyes;
diff --git a/crates/syntax/test_data/lexer/err/0001_unclosed_char_at_eof.rs b/crates/syntax/test_data/lexer/err/0001_unclosed_char_at_eof.rs
new file mode 100644
index 00000000000..ad2823b48f7
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0001_unclosed_char_at_eof.rs
@@ -0,0 +1 @@
+'
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0001_unclosed_char_at_eof.txt b/crates/syntax/test_data/lexer/err/0001_unclosed_char_at_eof.txt
new file mode 100644
index 00000000000..4d5ad74df57
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0001_unclosed_char_at_eof.txt
@@ -0,0 +1,2 @@
+CHAR 1 "\'"
+> error0..1 token("\'") msg(Missing trailing `'` symbol to terminate the character literal)
diff --git a/crates/syntax/test_data/lexer/err/0002_unclosed_char_with_ferris.rs b/crates/syntax/test_data/lexer/err/0002_unclosed_char_with_ferris.rs
new file mode 100644
index 00000000000..e264a415280
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0002_unclosed_char_with_ferris.rs
@@ -0,0 +1 @@
+'🦀
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0002_unclosed_char_with_ferris.txt b/crates/syntax/test_data/lexer/err/0002_unclosed_char_with_ferris.txt
new file mode 100644
index 00000000000..eafdb3c7c91
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0002_unclosed_char_with_ferris.txt
@@ -0,0 +1,2 @@
+CHAR 5 "\'🦀"
+> error0..5 token("\'🦀") msg(Missing trailing `'` symbol to terminate the character literal)
diff --git a/crates/syntax/test_data/lexer/err/0003_unclosed_char_with_ascii_escape.rs b/crates/syntax/test_data/lexer/err/0003_unclosed_char_with_ascii_escape.rs
new file mode 100644
index 00000000000..cf74b4dad3b
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0003_unclosed_char_with_ascii_escape.rs
@@ -0,0 +1 @@
+'\x7f
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0003_unclosed_char_with_ascii_escape.txt b/crates/syntax/test_data/lexer/err/0003_unclosed_char_with_ascii_escape.txt
new file mode 100644
index 00000000000..cc2b4866a17
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0003_unclosed_char_with_ascii_escape.txt
@@ -0,0 +1,2 @@
+CHAR 5 "\'\\x7f"
+> error0..5 token("\'\\x7f") msg(Missing trailing `'` symbol to terminate the character literal)
diff --git a/crates/syntax/test_data/lexer/err/0004_unclosed_char_with_unicode_escape.rs b/crates/syntax/test_data/lexer/err/0004_unclosed_char_with_unicode_escape.rs
new file mode 100644
index 00000000000..50be91f6852
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0004_unclosed_char_with_unicode_escape.rs
@@ -0,0 +1 @@
+'\u{20AA}
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0004_unclosed_char_with_unicode_escape.txt b/crates/syntax/test_data/lexer/err/0004_unclosed_char_with_unicode_escape.txt
new file mode 100644
index 00000000000..a6d422cb3d4
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0004_unclosed_char_with_unicode_escape.txt
@@ -0,0 +1,2 @@
+CHAR 9 "\'\\u{20AA}"
+> error0..9 token("\'\\u{20AA}") msg(Missing trailing `'` symbol to terminate the character literal)
diff --git a/crates/syntax/test_data/lexer/err/0005_unclosed_char_with_space.rs b/crates/syntax/test_data/lexer/err/0005_unclosed_char_with_space.rs
new file mode 100644
index 00000000000..309ecfe4786
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0005_unclosed_char_with_space.rs
@@ -0,0 +1 @@
+' 
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0005_unclosed_char_with_space.txt b/crates/syntax/test_data/lexer/err/0005_unclosed_char_with_space.txt
new file mode 100644
index 00000000000..47e7baa708a
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0005_unclosed_char_with_space.txt
@@ -0,0 +1,2 @@
+CHAR 2 "\' "
+> error0..2 token("\' ") msg(Missing trailing `'` symbol to terminate the character literal)
diff --git a/crates/syntax/test_data/lexer/err/0006_unclosed_char_with_slash.rs b/crates/syntax/test_data/lexer/err/0006_unclosed_char_with_slash.rs
new file mode 100644
index 00000000000..6ba258b1093
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0006_unclosed_char_with_slash.rs
@@ -0,0 +1 @@
+'\
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0006_unclosed_char_with_slash.txt b/crates/syntax/test_data/lexer/err/0006_unclosed_char_with_slash.txt
new file mode 100644
index 00000000000..511029d8078
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0006_unclosed_char_with_slash.txt
@@ -0,0 +1,2 @@
+CHAR 2 "\'\\"
+> error0..2 token("\'\\") msg(Missing trailing `'` symbol to terminate the character literal)
diff --git a/crates/syntax/test_data/lexer/err/0007_unclosed_char_with_slash_n.rs b/crates/syntax/test_data/lexer/err/0007_unclosed_char_with_slash_n.rs
new file mode 100644
index 00000000000..78bef7e3eb2
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0007_unclosed_char_with_slash_n.rs
@@ -0,0 +1 @@
+'\n
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0007_unclosed_char_with_slash_n.txt b/crates/syntax/test_data/lexer/err/0007_unclosed_char_with_slash_n.txt
new file mode 100644
index 00000000000..d2ba5742c67
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0007_unclosed_char_with_slash_n.txt
@@ -0,0 +1,2 @@
+CHAR 3 "\'\\n"
+> error0..3 token("\'\\n") msg(Missing trailing `'` symbol to terminate the character literal)
diff --git a/crates/syntax/test_data/lexer/err/0008_unclosed_char_with_slash_single_quote.rs b/crates/syntax/test_data/lexer/err/0008_unclosed_char_with_slash_single_quote.rs
new file mode 100644
index 00000000000..a0e722065bd
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0008_unclosed_char_with_slash_single_quote.rs
@@ -0,0 +1 @@
+'\'
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0008_unclosed_char_with_slash_single_quote.txt b/crates/syntax/test_data/lexer/err/0008_unclosed_char_with_slash_single_quote.txt
new file mode 100644
index 00000000000..ae9a7f0e2a7
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0008_unclosed_char_with_slash_single_quote.txt
@@ -0,0 +1,2 @@
+CHAR 3 "\'\\\'"
+> error0..3 token("\'\\\'") msg(Missing trailing `'` symbol to terminate the character literal)
diff --git a/crates/syntax/test_data/lexer/err/0009_unclosed_byte_at_eof.rs b/crates/syntax/test_data/lexer/err/0009_unclosed_byte_at_eof.rs
new file mode 100644
index 00000000000..795dc7e25c5
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0009_unclosed_byte_at_eof.rs
@@ -0,0 +1 @@
+b'
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0009_unclosed_byte_at_eof.txt b/crates/syntax/test_data/lexer/err/0009_unclosed_byte_at_eof.txt
new file mode 100644
index 00000000000..ff15045920f
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0009_unclosed_byte_at_eof.txt
@@ -0,0 +1,2 @@
+BYTE 2 "b\'"
+> error0..2 token("b\'") msg(Missing trailing `'` symbol to terminate the byte literal)
diff --git a/crates/syntax/test_data/lexer/err/0010_unclosed_byte_with_ferris.rs b/crates/syntax/test_data/lexer/err/0010_unclosed_byte_with_ferris.rs
new file mode 100644
index 00000000000..c9230dc24ea
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0010_unclosed_byte_with_ferris.rs
@@ -0,0 +1 @@
+b'🦀
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0010_unclosed_byte_with_ferris.txt b/crates/syntax/test_data/lexer/err/0010_unclosed_byte_with_ferris.txt
new file mode 100644
index 00000000000..34f7bd6d407
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0010_unclosed_byte_with_ferris.txt
@@ -0,0 +1,2 @@
+BYTE 6 "b\'🦀"
+> error0..6 token("b\'🦀") msg(Missing trailing `'` symbol to terminate the byte literal)
diff --git a/crates/syntax/test_data/lexer/err/0011_unclosed_byte_with_ascii_escape.rs b/crates/syntax/test_data/lexer/err/0011_unclosed_byte_with_ascii_escape.rs
new file mode 100644
index 00000000000..d146a8090d1
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0011_unclosed_byte_with_ascii_escape.rs
@@ -0,0 +1 @@
+b'\x7f
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0011_unclosed_byte_with_ascii_escape.txt b/crates/syntax/test_data/lexer/err/0011_unclosed_byte_with_ascii_escape.txt
new file mode 100644
index 00000000000..c964d0f00a5
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0011_unclosed_byte_with_ascii_escape.txt
@@ -0,0 +1,2 @@
+BYTE 6 "b\'\\x7f"
+> error0..6 token("b\'\\x7f") msg(Missing trailing `'` symbol to terminate the byte literal)
diff --git a/crates/syntax/test_data/lexer/err/0012_unclosed_byte_with_unicode_escape.rs b/crates/syntax/test_data/lexer/err/0012_unclosed_byte_with_unicode_escape.rs
new file mode 100644
index 00000000000..a3dec7c255d
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0012_unclosed_byte_with_unicode_escape.rs
@@ -0,0 +1 @@
+b'\u{20AA}
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0012_unclosed_byte_with_unicode_escape.txt b/crates/syntax/test_data/lexer/err/0012_unclosed_byte_with_unicode_escape.txt
new file mode 100644
index 00000000000..cc65fb86f97
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0012_unclosed_byte_with_unicode_escape.txt
@@ -0,0 +1,2 @@
+BYTE 10 "b\'\\u{20AA}"
+> error0..10 token("b\'\\u{20AA}") msg(Missing trailing `'` symbol to terminate the byte literal)
diff --git a/crates/syntax/test_data/lexer/err/0013_unclosed_byte_with_space.rs b/crates/syntax/test_data/lexer/err/0013_unclosed_byte_with_space.rs
new file mode 100644
index 00000000000..93b7f9c87c9
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0013_unclosed_byte_with_space.rs
@@ -0,0 +1 @@
+b' 
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0013_unclosed_byte_with_space.txt b/crates/syntax/test_data/lexer/err/0013_unclosed_byte_with_space.txt
new file mode 100644
index 00000000000..800834a144f
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0013_unclosed_byte_with_space.txt
@@ -0,0 +1,2 @@
+BYTE 3 "b\' "
+> error0..3 token("b\' ") msg(Missing trailing `'` symbol to terminate the byte literal)
diff --git a/crates/syntax/test_data/lexer/err/0014_unclosed_byte_with_slash.rs b/crates/syntax/test_data/lexer/err/0014_unclosed_byte_with_slash.rs
new file mode 100644
index 00000000000..abffa5037c0
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0014_unclosed_byte_with_slash.rs
@@ -0,0 +1 @@
+b'\
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0014_unclosed_byte_with_slash.txt b/crates/syntax/test_data/lexer/err/0014_unclosed_byte_with_slash.txt
new file mode 100644
index 00000000000..7b85ee64634
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0014_unclosed_byte_with_slash.txt
@@ -0,0 +1,2 @@
+BYTE 3 "b\'\\"
+> error0..3 token("b\'\\") msg(Missing trailing `'` symbol to terminate the byte literal)
diff --git a/crates/syntax/test_data/lexer/err/0015_unclosed_byte_with_slash_n.rs b/crates/syntax/test_data/lexer/err/0015_unclosed_byte_with_slash_n.rs
new file mode 100644
index 00000000000..4f46836a935
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0015_unclosed_byte_with_slash_n.rs
@@ -0,0 +1 @@
+b'\n
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0015_unclosed_byte_with_slash_n.txt b/crates/syntax/test_data/lexer/err/0015_unclosed_byte_with_slash_n.txt
new file mode 100644
index 00000000000..4b9a63117b5
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0015_unclosed_byte_with_slash_n.txt
@@ -0,0 +1,2 @@
+BYTE 4 "b\'\\n"
+> error0..4 token("b\'\\n") msg(Missing trailing `'` symbol to terminate the byte literal)
diff --git a/crates/syntax/test_data/lexer/err/0016_unclosed_byte_with_slash_single_quote.rs b/crates/syntax/test_data/lexer/err/0016_unclosed_byte_with_slash_single_quote.rs
new file mode 100644
index 00000000000..645b641eedb
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0016_unclosed_byte_with_slash_single_quote.rs
@@ -0,0 +1 @@
+b'\'
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0016_unclosed_byte_with_slash_single_quote.txt b/crates/syntax/test_data/lexer/err/0016_unclosed_byte_with_slash_single_quote.txt
new file mode 100644
index 00000000000..fe337f8d325
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0016_unclosed_byte_with_slash_single_quote.txt
@@ -0,0 +1,2 @@
+BYTE 4 "b\'\\\'"
+> error0..4 token("b\'\\\'") msg(Missing trailing `'` symbol to terminate the byte literal)
diff --git a/crates/syntax/test_data/lexer/err/0017_unclosed_string_at_eof.rs b/crates/syntax/test_data/lexer/err/0017_unclosed_string_at_eof.rs
new file mode 100644
index 00000000000..9d68933c44f
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0017_unclosed_string_at_eof.rs
@@ -0,0 +1 @@
+"
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0017_unclosed_string_at_eof.txt b/crates/syntax/test_data/lexer/err/0017_unclosed_string_at_eof.txt
new file mode 100644
index 00000000000..d11a8d880ea
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0017_unclosed_string_at_eof.txt
@@ -0,0 +1,2 @@
+STRING 1 "\""
+> error0..1 token("\"") msg(Missing trailing `"` symbol to terminate the string literal)
diff --git a/crates/syntax/test_data/lexer/err/0018_unclosed_string_with_ferris.rs b/crates/syntax/test_data/lexer/err/0018_unclosed_string_with_ferris.rs
new file mode 100644
index 00000000000..d439b8d2a1d
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0018_unclosed_string_with_ferris.rs
@@ -0,0 +1 @@
+"🦀
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0018_unclosed_string_with_ferris.txt b/crates/syntax/test_data/lexer/err/0018_unclosed_string_with_ferris.txt
new file mode 100644
index 00000000000..167f942d12c
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0018_unclosed_string_with_ferris.txt
@@ -0,0 +1,2 @@
+STRING 5 "\"🦀"
+> error0..5 token("\"🦀") msg(Missing trailing `"` symbol to terminate the string literal)
diff --git a/crates/syntax/test_data/lexer/err/0019_unclosed_string_with_ascii_escape.rs b/crates/syntax/test_data/lexer/err/0019_unclosed_string_with_ascii_escape.rs
new file mode 100644
index 00000000000..56186a34444
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0019_unclosed_string_with_ascii_escape.rs
@@ -0,0 +1 @@
+"\x7f
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0019_unclosed_string_with_ascii_escape.txt b/crates/syntax/test_data/lexer/err/0019_unclosed_string_with_ascii_escape.txt
new file mode 100644
index 00000000000..224c653d26d
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0019_unclosed_string_with_ascii_escape.txt
@@ -0,0 +1,2 @@
+STRING 5 "\"\\x7f"
+> error0..5 token("\"\\x7f") msg(Missing trailing `"` symbol to terminate the string literal)
diff --git a/crates/syntax/test_data/lexer/err/0020_unclosed_string_with_unicode_escape.rs b/crates/syntax/test_data/lexer/err/0020_unclosed_string_with_unicode_escape.rs
new file mode 100644
index 00000000000..ed24095c3d4
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0020_unclosed_string_with_unicode_escape.rs
@@ -0,0 +1 @@
+"\u{20AA}
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0020_unclosed_string_with_unicode_escape.txt b/crates/syntax/test_data/lexer/err/0020_unclosed_string_with_unicode_escape.txt
new file mode 100644
index 00000000000..48975bbcbc4
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0020_unclosed_string_with_unicode_escape.txt
@@ -0,0 +1,2 @@
+STRING 9 "\"\\u{20AA}"
+> error0..9 token("\"\\u{20AA}") msg(Missing trailing `"` symbol to terminate the string literal)
diff --git a/crates/syntax/test_data/lexer/err/0021_unclosed_string_with_space.rs b/crates/syntax/test_data/lexer/err/0021_unclosed_string_with_space.rs
new file mode 100644
index 00000000000..72cdc841fbd
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0021_unclosed_string_with_space.rs
@@ -0,0 +1 @@
+" 
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0021_unclosed_string_with_space.txt b/crates/syntax/test_data/lexer/err/0021_unclosed_string_with_space.txt
new file mode 100644
index 00000000000..a823cca7a48
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0021_unclosed_string_with_space.txt
@@ -0,0 +1,2 @@
+STRING 2 "\" "
+> error0..2 token("\" ") msg(Missing trailing `"` symbol to terminate the string literal)
diff --git a/crates/syntax/test_data/lexer/err/0022_unclosed_string_with_slash.rs b/crates/syntax/test_data/lexer/err/0022_unclosed_string_with_slash.rs
new file mode 100644
index 00000000000..00a25840087
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0022_unclosed_string_with_slash.rs
@@ -0,0 +1 @@
+"\
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0022_unclosed_string_with_slash.txt b/crates/syntax/test_data/lexer/err/0022_unclosed_string_with_slash.txt
new file mode 100644
index 00000000000..0914f001f55
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0022_unclosed_string_with_slash.txt
@@ -0,0 +1,2 @@
+STRING 2 "\"\\"
+> error0..2 token("\"\\") msg(Missing trailing `"` symbol to terminate the string literal)
diff --git a/crates/syntax/test_data/lexer/err/0023_unclosed_string_with_slash_n.rs b/crates/syntax/test_data/lexer/err/0023_unclosed_string_with_slash_n.rs
new file mode 100644
index 00000000000..a0c29b8cff7
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0023_unclosed_string_with_slash_n.rs
@@ -0,0 +1 @@
+"\n
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0023_unclosed_string_with_slash_n.txt b/crates/syntax/test_data/lexer/err/0023_unclosed_string_with_slash_n.txt
new file mode 100644
index 00000000000..5674b55fdfa
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0023_unclosed_string_with_slash_n.txt
@@ -0,0 +1,2 @@
+STRING 3 "\"\\n"
+> error0..3 token("\"\\n") msg(Missing trailing `"` symbol to terminate the string literal)
diff --git a/crates/syntax/test_data/lexer/err/0024_unclosed_string_with_slash_double_quote.rs b/crates/syntax/test_data/lexer/err/0024_unclosed_string_with_slash_double_quote.rs
new file mode 100644
index 00000000000..403c2d6ddc6
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0024_unclosed_string_with_slash_double_quote.rs
@@ -0,0 +1 @@
+"\"
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0024_unclosed_string_with_slash_double_quote.txt b/crates/syntax/test_data/lexer/err/0024_unclosed_string_with_slash_double_quote.txt
new file mode 100644
index 00000000000..4c9a774e466
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0024_unclosed_string_with_slash_double_quote.txt
@@ -0,0 +1,2 @@
+STRING 3 "\"\\\""
+> error0..3 token("\"\\\"") msg(Missing trailing `"` symbol to terminate the string literal)
diff --git a/crates/syntax/test_data/lexer/err/0025_unclosed_byte_string_at_eof.rs b/crates/syntax/test_data/lexer/err/0025_unclosed_byte_string_at_eof.rs
new file mode 100644
index 00000000000..36f4f432187
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0025_unclosed_byte_string_at_eof.rs
@@ -0,0 +1 @@
+b"
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0025_unclosed_byte_string_at_eof.txt b/crates/syntax/test_data/lexer/err/0025_unclosed_byte_string_at_eof.txt
new file mode 100644
index 00000000000..04e6b0aa4f1
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0025_unclosed_byte_string_at_eof.txt
@@ -0,0 +1,2 @@
+BYTE_STRING 2 "b\""
+> error0..2 token("b\"") msg(Missing trailing `"` symbol to terminate the byte string literal)
diff --git a/crates/syntax/test_data/lexer/err/0026_unclosed_byte_string_with_ferris.rs b/crates/syntax/test_data/lexer/err/0026_unclosed_byte_string_with_ferris.rs
new file mode 100644
index 00000000000..3c23a037228
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0026_unclosed_byte_string_with_ferris.rs
@@ -0,0 +1 @@
+b"🦀
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0026_unclosed_byte_string_with_ferris.txt b/crates/syntax/test_data/lexer/err/0026_unclosed_byte_string_with_ferris.txt
new file mode 100644
index 00000000000..0576a0609a8
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0026_unclosed_byte_string_with_ferris.txt
@@ -0,0 +1,2 @@
+BYTE_STRING 6 "b\"🦀"
+> error0..6 token("b\"🦀") msg(Missing trailing `"` symbol to terminate the byte string literal)
diff --git a/crates/syntax/test_data/lexer/err/0027_unclosed_byte_string_with_ascii_escape.rs b/crates/syntax/test_data/lexer/err/0027_unclosed_byte_string_with_ascii_escape.rs
new file mode 100644
index 00000000000..836c112c157
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0027_unclosed_byte_string_with_ascii_escape.rs
@@ -0,0 +1 @@
+b"\x7f
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0027_unclosed_byte_string_with_ascii_escape.txt b/crates/syntax/test_data/lexer/err/0027_unclosed_byte_string_with_ascii_escape.txt
new file mode 100644
index 00000000000..541a013d853
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0027_unclosed_byte_string_with_ascii_escape.txt
@@ -0,0 +1,2 @@
+BYTE_STRING 6 "b\"\\x7f"
+> error0..6 token("b\"\\x7f") msg(Missing trailing `"` symbol to terminate the byte string literal)
diff --git a/crates/syntax/test_data/lexer/err/0028_unclosed_byte_string_with_unicode_escape.rs b/crates/syntax/test_data/lexer/err/0028_unclosed_byte_string_with_unicode_escape.rs
new file mode 100644
index 00000000000..1c6df1d00e4
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0028_unclosed_byte_string_with_unicode_escape.rs
@@ -0,0 +1 @@
+b"\u{20AA}
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0028_unclosed_byte_string_with_unicode_escape.txt b/crates/syntax/test_data/lexer/err/0028_unclosed_byte_string_with_unicode_escape.txt
new file mode 100644
index 00000000000..71b0fb2118c
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0028_unclosed_byte_string_with_unicode_escape.txt
@@ -0,0 +1,2 @@
+BYTE_STRING 10 "b\"\\u{20AA}"
+> error0..10 token("b\"\\u{20AA}") msg(Missing trailing `"` symbol to terminate the byte string literal)
diff --git a/crates/syntax/test_data/lexer/err/0029_unclosed_byte_string_with_space.rs b/crates/syntax/test_data/lexer/err/0029_unclosed_byte_string_with_space.rs
new file mode 100644
index 00000000000..d6898541e62
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0029_unclosed_byte_string_with_space.rs
@@ -0,0 +1 @@
+b" 
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0029_unclosed_byte_string_with_space.txt b/crates/syntax/test_data/lexer/err/0029_unclosed_byte_string_with_space.txt
new file mode 100644
index 00000000000..bd5058bc118
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0029_unclosed_byte_string_with_space.txt
@@ -0,0 +1,2 @@
+BYTE_STRING 3 "b\" "
+> error0..3 token("b\" ") msg(Missing trailing `"` symbol to terminate the byte string literal)
diff --git a/crates/syntax/test_data/lexer/err/0030_unclosed_byte_string_with_slash.rs b/crates/syntax/test_data/lexer/err/0030_unclosed_byte_string_with_slash.rs
new file mode 100644
index 00000000000..cce6615381d
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0030_unclosed_byte_string_with_slash.rs
@@ -0,0 +1 @@
+b"\
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0030_unclosed_byte_string_with_slash.txt b/crates/syntax/test_data/lexer/err/0030_unclosed_byte_string_with_slash.txt
new file mode 100644
index 00000000000..7f94f10ba15
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0030_unclosed_byte_string_with_slash.txt
@@ -0,0 +1,2 @@
+BYTE_STRING 3 "b\"\\"
+> error0..3 token("b\"\\") msg(Missing trailing `"` symbol to terminate the byte string literal)
diff --git a/crates/syntax/test_data/lexer/err/0031_unclosed_byte_string_with_slash_n.rs b/crates/syntax/test_data/lexer/err/0031_unclosed_byte_string_with_slash_n.rs
new file mode 100644
index 00000000000..5e680aabb7b
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0031_unclosed_byte_string_with_slash_n.rs
@@ -0,0 +1 @@
+b"\n
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0031_unclosed_byte_string_with_slash_n.txt b/crates/syntax/test_data/lexer/err/0031_unclosed_byte_string_with_slash_n.txt
new file mode 100644
index 00000000000..9c3c089d724
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0031_unclosed_byte_string_with_slash_n.txt
@@ -0,0 +1,2 @@
+BYTE_STRING 4 "b\"\\n"
+> error0..4 token("b\"\\n") msg(Missing trailing `"` symbol to terminate the byte string literal)
diff --git a/crates/syntax/test_data/lexer/err/0032_unclosed_byte_string_with_slash_double_quote.rs b/crates/syntax/test_data/lexer/err/0032_unclosed_byte_string_with_slash_double_quote.rs
new file mode 100644
index 00000000000..f2ff58ba9a8
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0032_unclosed_byte_string_with_slash_double_quote.rs
@@ -0,0 +1 @@
+b"\"
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0032_unclosed_byte_string_with_slash_double_quote.txt b/crates/syntax/test_data/lexer/err/0032_unclosed_byte_string_with_slash_double_quote.txt
new file mode 100644
index 00000000000..884b12c8ee0
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0032_unclosed_byte_string_with_slash_double_quote.txt
@@ -0,0 +1,2 @@
+BYTE_STRING 4 "b\"\\\""
+> error0..4 token("b\"\\\"") msg(Missing trailing `"` symbol to terminate the byte string literal)
diff --git a/crates/syntax/test_data/lexer/err/0033_unclosed_raw_string_at_eof.rs b/crates/syntax/test_data/lexer/err/0033_unclosed_raw_string_at_eof.rs
new file mode 100644
index 00000000000..557c59b6251
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0033_unclosed_raw_string_at_eof.rs
@@ -0,0 +1 @@
+r##"
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0033_unclosed_raw_string_at_eof.txt b/crates/syntax/test_data/lexer/err/0033_unclosed_raw_string_at_eof.txt
new file mode 100644
index 00000000000..6fd59ccc027
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0033_unclosed_raw_string_at_eof.txt
@@ -0,0 +1,2 @@
+RAW_STRING 4 "r##\""
+> error0..4 token("r##\"") msg(Missing trailing `"` with `#` symbols to terminate the raw string literal)
diff --git a/crates/syntax/test_data/lexer/err/0034_unclosed_raw_string_with_ferris.rs b/crates/syntax/test_data/lexer/err/0034_unclosed_raw_string_with_ferris.rs
new file mode 100644
index 00000000000..bd046e4bb91
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0034_unclosed_raw_string_with_ferris.rs
@@ -0,0 +1 @@
+r##"🦀
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0034_unclosed_raw_string_with_ferris.txt b/crates/syntax/test_data/lexer/err/0034_unclosed_raw_string_with_ferris.txt
new file mode 100644
index 00000000000..8d9ca0e8f12
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0034_unclosed_raw_string_with_ferris.txt
@@ -0,0 +1,2 @@
+RAW_STRING 8 "r##\"🦀"
+> error0..8 token("r##\"🦀") msg(Missing trailing `"` with `#` symbols to terminate the raw string literal)
diff --git a/crates/syntax/test_data/lexer/err/0035_unclosed_raw_string_with_ascii_escape.rs b/crates/syntax/test_data/lexer/err/0035_unclosed_raw_string_with_ascii_escape.rs
new file mode 100644
index 00000000000..5bec883dc7a
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0035_unclosed_raw_string_with_ascii_escape.rs
@@ -0,0 +1 @@
+r##"\x7f
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0035_unclosed_raw_string_with_ascii_escape.txt b/crates/syntax/test_data/lexer/err/0035_unclosed_raw_string_with_ascii_escape.txt
new file mode 100644
index 00000000000..a906380c718
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0035_unclosed_raw_string_with_ascii_escape.txt
@@ -0,0 +1,2 @@
+RAW_STRING 8 "r##\"\\x7f"
+> error0..8 token("r##\"\\x7f") msg(Missing trailing `"` with `#` symbols to terminate the raw string literal)
diff --git a/crates/syntax/test_data/lexer/err/0036_unclosed_raw_string_with_unicode_escape.rs b/crates/syntax/test_data/lexer/err/0036_unclosed_raw_string_with_unicode_escape.rs
new file mode 100644
index 00000000000..bf05c39134b
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0036_unclosed_raw_string_with_unicode_escape.rs
@@ -0,0 +1 @@
+r##"\u{20AA}
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0036_unclosed_raw_string_with_unicode_escape.txt b/crates/syntax/test_data/lexer/err/0036_unclosed_raw_string_with_unicode_escape.txt
new file mode 100644
index 00000000000..5667c614995
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0036_unclosed_raw_string_with_unicode_escape.txt
@@ -0,0 +1,2 @@
+RAW_STRING 12 "r##\"\\u{20AA}"
+> error0..12 token("r##\"\\u{20AA}") msg(Missing trailing `"` with `#` symbols to terminate the raw string literal)
diff --git a/crates/syntax/test_data/lexer/err/0037_unclosed_raw_string_with_space.rs b/crates/syntax/test_data/lexer/err/0037_unclosed_raw_string_with_space.rs
new file mode 100644
index 00000000000..f104bae4f2c
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0037_unclosed_raw_string_with_space.rs
@@ -0,0 +1 @@
+r##" 
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0037_unclosed_raw_string_with_space.txt b/crates/syntax/test_data/lexer/err/0037_unclosed_raw_string_with_space.txt
new file mode 100644
index 00000000000..141c8268e80
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0037_unclosed_raw_string_with_space.txt
@@ -0,0 +1,2 @@
+RAW_STRING 5 "r##\" "
+> error0..5 token("r##\" ") msg(Missing trailing `"` with `#` symbols to terminate the raw string literal)
diff --git a/crates/syntax/test_data/lexer/err/0038_unclosed_raw_string_with_slash.rs b/crates/syntax/test_data/lexer/err/0038_unclosed_raw_string_with_slash.rs
new file mode 100644
index 00000000000..9242077b8b7
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0038_unclosed_raw_string_with_slash.rs
@@ -0,0 +1 @@
+r##"\
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0038_unclosed_raw_string_with_slash.txt b/crates/syntax/test_data/lexer/err/0038_unclosed_raw_string_with_slash.txt
new file mode 100644
index 00000000000..f61d4cc915e
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0038_unclosed_raw_string_with_slash.txt
@@ -0,0 +1,2 @@
+RAW_STRING 5 "r##\"\\"
+> error0..5 token("r##\"\\") msg(Missing trailing `"` with `#` symbols to terminate the raw string literal)
diff --git a/crates/syntax/test_data/lexer/err/0039_unclosed_raw_string_with_slash_n.rs b/crates/syntax/test_data/lexer/err/0039_unclosed_raw_string_with_slash_n.rs
new file mode 100644
index 00000000000..db1c16f2ba5
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0039_unclosed_raw_string_with_slash_n.rs
@@ -0,0 +1 @@
+r##"\n
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0039_unclosed_raw_string_with_slash_n.txt b/crates/syntax/test_data/lexer/err/0039_unclosed_raw_string_with_slash_n.txt
new file mode 100644
index 00000000000..12e2c0fc038
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0039_unclosed_raw_string_with_slash_n.txt
@@ -0,0 +1,2 @@
+RAW_STRING 6 "r##\"\\n"
+> error0..6 token("r##\"\\n") msg(Missing trailing `"` with `#` symbols to terminate the raw string literal)
diff --git a/crates/syntax/test_data/lexer/err/0040_unclosed_raw_byte_string_at_eof.rs b/crates/syntax/test_data/lexer/err/0040_unclosed_raw_byte_string_at_eof.rs
new file mode 100644
index 00000000000..ae5bae62230
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0040_unclosed_raw_byte_string_at_eof.rs
@@ -0,0 +1 @@
+br##"
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0040_unclosed_raw_byte_string_at_eof.txt b/crates/syntax/test_data/lexer/err/0040_unclosed_raw_byte_string_at_eof.txt
new file mode 100644
index 00000000000..fe12cb5fc6d
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0040_unclosed_raw_byte_string_at_eof.txt
@@ -0,0 +1,2 @@
+RAW_BYTE_STRING 5 "br##\""
+> error0..5 token("br##\"") msg(Missing trailing `"` with `#` symbols to terminate the raw byte string literal)
diff --git a/crates/syntax/test_data/lexer/err/0041_unclosed_raw_byte_string_with_ferris.rs b/crates/syntax/test_data/lexer/err/0041_unclosed_raw_byte_string_with_ferris.rs
new file mode 100644
index 00000000000..9ef01207a17
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0041_unclosed_raw_byte_string_with_ferris.rs
@@ -0,0 +1 @@
+br##"🦀
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0041_unclosed_raw_byte_string_with_ferris.txt b/crates/syntax/test_data/lexer/err/0041_unclosed_raw_byte_string_with_ferris.txt
new file mode 100644
index 00000000000..5be2a7861b4
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0041_unclosed_raw_byte_string_with_ferris.txt
@@ -0,0 +1,2 @@
+RAW_BYTE_STRING 9 "br##\"🦀"
+> error0..9 token("br##\"🦀") msg(Missing trailing `"` with `#` symbols to terminate the raw byte string literal)
diff --git a/crates/syntax/test_data/lexer/err/0042_unclosed_raw_byte_string_with_ascii_escape.rs b/crates/syntax/test_data/lexer/err/0042_unclosed_raw_byte_string_with_ascii_escape.rs
new file mode 100644
index 00000000000..d50270afe1e
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0042_unclosed_raw_byte_string_with_ascii_escape.rs
@@ -0,0 +1 @@
+br##"\x7f
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0042_unclosed_raw_byte_string_with_ascii_escape.txt b/crates/syntax/test_data/lexer/err/0042_unclosed_raw_byte_string_with_ascii_escape.txt
new file mode 100644
index 00000000000..6cbe08d07ed
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0042_unclosed_raw_byte_string_with_ascii_escape.txt
@@ -0,0 +1,2 @@
+RAW_BYTE_STRING 9 "br##\"\\x7f"
+> error0..9 token("br##\"\\x7f") msg(Missing trailing `"` with `#` symbols to terminate the raw byte string literal)
diff --git a/crates/syntax/test_data/lexer/err/0043_unclosed_raw_byte_string_with_unicode_escape.rs b/crates/syntax/test_data/lexer/err/0043_unclosed_raw_byte_string_with_unicode_escape.rs
new file mode 100644
index 00000000000..90e299a1a97
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0043_unclosed_raw_byte_string_with_unicode_escape.rs
@@ -0,0 +1 @@
+br##"\u{20AA}
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0043_unclosed_raw_byte_string_with_unicode_escape.txt b/crates/syntax/test_data/lexer/err/0043_unclosed_raw_byte_string_with_unicode_escape.txt
new file mode 100644
index 00000000000..f56a4f98480
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0043_unclosed_raw_byte_string_with_unicode_escape.txt
@@ -0,0 +1,2 @@
+RAW_BYTE_STRING 13 "br##\"\\u{20AA}"
+> error0..13 token("br##\"\\u{20AA}") msg(Missing trailing `"` with `#` symbols to terminate the raw byte string literal)
diff --git a/crates/syntax/test_data/lexer/err/0044_unclosed_raw_byte_string_with_space.rs b/crates/syntax/test_data/lexer/err/0044_unclosed_raw_byte_string_with_space.rs
new file mode 100644
index 00000000000..14c602fd2b3
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0044_unclosed_raw_byte_string_with_space.rs
@@ -0,0 +1 @@
+br##" 
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0044_unclosed_raw_byte_string_with_space.txt b/crates/syntax/test_data/lexer/err/0044_unclosed_raw_byte_string_with_space.txt
new file mode 100644
index 00000000000..3d32ce34ea5
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0044_unclosed_raw_byte_string_with_space.txt
@@ -0,0 +1,2 @@
+RAW_BYTE_STRING 6 "br##\" "
+> error0..6 token("br##\" ") msg(Missing trailing `"` with `#` symbols to terminate the raw byte string literal)
diff --git a/crates/syntax/test_data/lexer/err/0045_unclosed_raw_byte_string_with_slash.rs b/crates/syntax/test_data/lexer/err/0045_unclosed_raw_byte_string_with_slash.rs
new file mode 100644
index 00000000000..0b3c015d74d
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0045_unclosed_raw_byte_string_with_slash.rs
@@ -0,0 +1 @@
+br##"\
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0045_unclosed_raw_byte_string_with_slash.txt b/crates/syntax/test_data/lexer/err/0045_unclosed_raw_byte_string_with_slash.txt
new file mode 100644
index 00000000000..320fea17700
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0045_unclosed_raw_byte_string_with_slash.txt
@@ -0,0 +1,2 @@
+RAW_BYTE_STRING 6 "br##\"\\"
+> error0..6 token("br##\"\\") msg(Missing trailing `"` with `#` symbols to terminate the raw byte string literal)
diff --git a/crates/syntax/test_data/lexer/err/0046_unclosed_raw_byte_string_with_slash_n.rs b/crates/syntax/test_data/lexer/err/0046_unclosed_raw_byte_string_with_slash_n.rs
new file mode 100644
index 00000000000..0d8b0e7ab04
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0046_unclosed_raw_byte_string_with_slash_n.rs
@@ -0,0 +1 @@
+br##"\n
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0046_unclosed_raw_byte_string_with_slash_n.txt b/crates/syntax/test_data/lexer/err/0046_unclosed_raw_byte_string_with_slash_n.txt
new file mode 100644
index 00000000000..b3a56380cbd
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0046_unclosed_raw_byte_string_with_slash_n.txt
@@ -0,0 +1,2 @@
+RAW_BYTE_STRING 7 "br##\"\\n"
+> error0..7 token("br##\"\\n") msg(Missing trailing `"` with `#` symbols to terminate the raw byte string literal)
diff --git a/crates/syntax/test_data/lexer/err/0047_unstarted_raw_string_at_eof.rs b/crates/syntax/test_data/lexer/err/0047_unstarted_raw_string_at_eof.rs
new file mode 100644
index 00000000000..eddf8d08094
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0047_unstarted_raw_string_at_eof.rs
@@ -0,0 +1 @@
+r##
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0047_unstarted_raw_string_at_eof.txt b/crates/syntax/test_data/lexer/err/0047_unstarted_raw_string_at_eof.txt
new file mode 100644
index 00000000000..5af1e2d97ff
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0047_unstarted_raw_string_at_eof.txt
@@ -0,0 +1,2 @@
+RAW_STRING 3 "r##"
+> error0..3 token("r##") msg(Missing `"` symbol after `#` symbols to begin the raw string literal)
diff --git a/crates/syntax/test_data/lexer/err/0048_unstarted_raw_byte_string_at_eof.rs b/crates/syntax/test_data/lexer/err/0048_unstarted_raw_byte_string_at_eof.rs
new file mode 100644
index 00000000000..7e8cadf4f49
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0048_unstarted_raw_byte_string_at_eof.rs
@@ -0,0 +1 @@
+br##
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0048_unstarted_raw_byte_string_at_eof.txt b/crates/syntax/test_data/lexer/err/0048_unstarted_raw_byte_string_at_eof.txt
new file mode 100644
index 00000000000..aec7afd9278
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0048_unstarted_raw_byte_string_at_eof.txt
@@ -0,0 +1,2 @@
+RAW_BYTE_STRING 4 "br##"
+> error0..4 token("br##") msg(Missing `"` symbol after `#` symbols to begin the raw byte string literal)
diff --git a/crates/syntax/test_data/lexer/err/0049_unstarted_raw_string_with_ascii.rs b/crates/syntax/test_data/lexer/err/0049_unstarted_raw_string_with_ascii.rs
new file mode 100644
index 00000000000..534668a9b66
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0049_unstarted_raw_string_with_ascii.rs
@@ -0,0 +1 @@
+r## I lack a quote!
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0049_unstarted_raw_string_with_ascii.txt b/crates/syntax/test_data/lexer/err/0049_unstarted_raw_string_with_ascii.txt
new file mode 100644
index 00000000000..e22fe5374f0
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0049_unstarted_raw_string_with_ascii.txt
@@ -0,0 +1,10 @@
+RAW_STRING 4 "r## "
+IDENT 1 "I"
+WHITESPACE 1 " "
+IDENT 4 "lack"
+WHITESPACE 1 " "
+IDENT 1 "a"
+WHITESPACE 1 " "
+IDENT 5 "quote"
+BANG 1 "!"
+> error0..4 token("r## ") msg(Missing `"` symbol after `#` symbols to begin the raw string literal)
diff --git a/crates/syntax/test_data/lexer/err/0050_unstarted_raw_byte_string_with_ascii.rs b/crates/syntax/test_data/lexer/err/0050_unstarted_raw_byte_string_with_ascii.rs
new file mode 100644
index 00000000000..d9b55455ac4
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0050_unstarted_raw_byte_string_with_ascii.rs
@@ -0,0 +1 @@
+br## I lack a quote!
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0050_unstarted_raw_byte_string_with_ascii.txt b/crates/syntax/test_data/lexer/err/0050_unstarted_raw_byte_string_with_ascii.txt
new file mode 100644
index 00000000000..d74ea4c2796
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0050_unstarted_raw_byte_string_with_ascii.txt
@@ -0,0 +1,10 @@
+RAW_BYTE_STRING 5 "br## "
+IDENT 1 "I"
+WHITESPACE 1 " "
+IDENT 4 "lack"
+WHITESPACE 1 " "
+IDENT 1 "a"
+WHITESPACE 1 " "
+IDENT 5 "quote"
+BANG 1 "!"
+> error0..5 token("br## ") msg(Missing `"` symbol after `#` symbols to begin the raw byte string literal)
diff --git a/crates/syntax/test_data/lexer/err/0051_unclosed_block_comment_at_eof.rs b/crates/syntax/test_data/lexer/err/0051_unclosed_block_comment_at_eof.rs
new file mode 100644
index 00000000000..22e83649f7d
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0051_unclosed_block_comment_at_eof.rs
@@ -0,0 +1 @@
+/*
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/err/0051_unclosed_block_comment_at_eof.txt b/crates/syntax/test_data/lexer/err/0051_unclosed_block_comment_at_eof.txt
new file mode 100644
index 00000000000..2a256e9dffd
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0051_unclosed_block_comment_at_eof.txt
@@ -0,0 +1,2 @@
+COMMENT 2 "/*"
+> error0..2 token("/*") msg(Missing trailing `*/` symbols to terminate the block comment)
diff --git a/crates/syntax/test_data/lexer/err/0052_unclosed_block_comment_with_content.rs b/crates/syntax/test_data/lexer/err/0052_unclosed_block_comment_with_content.rs
new file mode 100644
index 00000000000..c45c2844dbc
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0052_unclosed_block_comment_with_content.rs
@@ -0,0 +1 @@
+/* comment
diff --git a/crates/syntax/test_data/lexer/err/0052_unclosed_block_comment_with_content.txt b/crates/syntax/test_data/lexer/err/0052_unclosed_block_comment_with_content.txt
new file mode 100644
index 00000000000..8e8490302a5
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0052_unclosed_block_comment_with_content.txt
@@ -0,0 +1,2 @@
+COMMENT 11 "/* comment\n"
+> error0..11 token("/* comment\n") msg(Missing trailing `*/` symbols to terminate the block comment)
diff --git a/crates/syntax/test_data/lexer/err/0053_unclosed_nested_block_comment_entirely.rs b/crates/syntax/test_data/lexer/err/0053_unclosed_nested_block_comment_entirely.rs
new file mode 100644
index 00000000000..3fcfc96600a
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0053_unclosed_nested_block_comment_entirely.rs
@@ -0,0 +1 @@
+/* /* /*
diff --git a/crates/syntax/test_data/lexer/err/0053_unclosed_nested_block_comment_entirely.txt b/crates/syntax/test_data/lexer/err/0053_unclosed_nested_block_comment_entirely.txt
new file mode 100644
index 00000000000..b7d28fc05d5
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0053_unclosed_nested_block_comment_entirely.txt
@@ -0,0 +1,2 @@
+COMMENT 9 "/* /* /*\n"
+> error0..9 token("/* /* /*\n") msg(Missing trailing `*/` symbols to terminate the block comment)
diff --git a/crates/syntax/test_data/lexer/err/0054_unclosed_nested_block_comment_partially.rs b/crates/syntax/test_data/lexer/err/0054_unclosed_nested_block_comment_partially.rs
new file mode 100644
index 00000000000..26c898f019d
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0054_unclosed_nested_block_comment_partially.rs
@@ -0,0 +1 @@
+/** /*! /* comment */ */
diff --git a/crates/syntax/test_data/lexer/err/0054_unclosed_nested_block_comment_partially.txt b/crates/syntax/test_data/lexer/err/0054_unclosed_nested_block_comment_partially.txt
new file mode 100644
index 00000000000..4742d2c12ca
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0054_unclosed_nested_block_comment_partially.txt
@@ -0,0 +1,2 @@
+COMMENT 25 "/** /*! /* comment */ */\n"
+> error0..25 token("/** /*! /* comment */ */\n") msg(Missing trailing `*/` symbols to terminate the block comment)
diff --git a/crates/syntax/test_data/lexer/err/0055_empty_int.rs b/crates/syntax/test_data/lexer/err/0055_empty_int.rs
new file mode 100644
index 00000000000..aa2a9fdca17
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0055_empty_int.rs
@@ -0,0 +1,17 @@
+0b
+0o
+0x
+
+0b_
+0o_
+0x_
+
+0bnoDigit
+0onoDigit
+0xnoDigit
+
+0xG
+0xg
+
+0x_g
+0x_G
diff --git a/crates/syntax/test_data/lexer/err/0055_empty_int.txt b/crates/syntax/test_data/lexer/err/0055_empty_int.txt
new file mode 100644
index 00000000000..bcd094b6ef7
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0055_empty_int.txt
@@ -0,0 +1,39 @@
+INT_NUMBER 2 "0b"
+WHITESPACE 1 "\n"
+INT_NUMBER 2 "0o"
+WHITESPACE 1 "\n"
+INT_NUMBER 2 "0x"
+WHITESPACE 2 "\n\n"
+INT_NUMBER 3 "0b_"
+WHITESPACE 1 "\n"
+INT_NUMBER 3 "0o_"
+WHITESPACE 1 "\n"
+INT_NUMBER 3 "0x_"
+WHITESPACE 2 "\n\n"
+INT_NUMBER 9 "0bnoDigit"
+WHITESPACE 1 "\n"
+INT_NUMBER 9 "0onoDigit"
+WHITESPACE 1 "\n"
+INT_NUMBER 9 "0xnoDigit"
+WHITESPACE 2 "\n\n"
+INT_NUMBER 3 "0xG"
+WHITESPACE 1 "\n"
+INT_NUMBER 3 "0xg"
+WHITESPACE 2 "\n\n"
+INT_NUMBER 4 "0x_g"
+WHITESPACE 1 "\n"
+INT_NUMBER 4 "0x_G"
+WHITESPACE 1 "\n"
+> error0..2 token("0b") msg(Missing digits after the integer base prefix)
+> error3..5 token("0o") msg(Missing digits after the integer base prefix)
+> error6..8 token("0x") msg(Missing digits after the integer base prefix)
+> error10..13 token("0b_") msg(Missing digits after the integer base prefix)
+> error14..17 token("0o_") msg(Missing digits after the integer base prefix)
+> error18..21 token("0x_") msg(Missing digits after the integer base prefix)
+> error23..32 token("0bnoDigit") msg(Missing digits after the integer base prefix)
+> error33..42 token("0onoDigit") msg(Missing digits after the integer base prefix)
+> error43..52 token("0xnoDigit") msg(Missing digits after the integer base prefix)
+> error54..57 token("0xG") msg(Missing digits after the integer base prefix)
+> error58..61 token("0xg") msg(Missing digits after the integer base prefix)
+> error63..67 token("0x_g") msg(Missing digits after the integer base prefix)
+> error68..72 token("0x_G") msg(Missing digits after the integer base prefix)
diff --git a/crates/syntax/test_data/lexer/err/0056_empty_exponent.rs b/crates/syntax/test_data/lexer/err/0056_empty_exponent.rs
new file mode 100644
index 00000000000..286584c887f
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0056_empty_exponent.rs
@@ -0,0 +1,22 @@
+0e
+0E
+
+42e+
+42e-
+42E+
+42E-
+
+42.e+
+42.e-
+42.E+
+42.E-
+
+42.2e+
+42.2e-
+42.2E+
+42.2E-
+
+42.2e+f32
+42.2e-f32
+42.2E+f32
+42.2E-f32
diff --git a/crates/syntax/test_data/lexer/err/0056_empty_exponent.txt b/crates/syntax/test_data/lexer/err/0056_empty_exponent.txt
new file mode 100644
index 00000000000..6a645a6a44c
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0056_empty_exponent.txt
@@ -0,0 +1,62 @@
+FLOAT_NUMBER 2 "0e"
+WHITESPACE 1 "\n"
+FLOAT_NUMBER 2 "0E"
+WHITESPACE 2 "\n\n"
+FLOAT_NUMBER 4 "42e+"
+WHITESPACE 1 "\n"
+FLOAT_NUMBER 4 "42e-"
+WHITESPACE 1 "\n"
+FLOAT_NUMBER 4 "42E+"
+WHITESPACE 1 "\n"
+FLOAT_NUMBER 4 "42E-"
+WHITESPACE 2 "\n\n"
+INT_NUMBER 2 "42"
+DOT 1 "."
+IDENT 1 "e"
+PLUS 1 "+"
+WHITESPACE 1 "\n"
+INT_NUMBER 2 "42"
+DOT 1 "."
+IDENT 1 "e"
+MINUS 1 "-"
+WHITESPACE 1 "\n"
+INT_NUMBER 2 "42"
+DOT 1 "."
+IDENT 1 "E"
+PLUS 1 "+"
+WHITESPACE 1 "\n"
+INT_NUMBER 2 "42"
+DOT 1 "."
+IDENT 1 "E"
+MINUS 1 "-"
+WHITESPACE 2 "\n\n"
+FLOAT_NUMBER 6 "42.2e+"
+WHITESPACE 1 "\n"
+FLOAT_NUMBER 6 "42.2e-"
+WHITESPACE 1 "\n"
+FLOAT_NUMBER 6 "42.2E+"
+WHITESPACE 1 "\n"
+FLOAT_NUMBER 6 "42.2E-"
+WHITESPACE 2 "\n\n"
+FLOAT_NUMBER 9 "42.2e+f32"
+WHITESPACE 1 "\n"
+FLOAT_NUMBER 9 "42.2e-f32"
+WHITESPACE 1 "\n"
+FLOAT_NUMBER 9 "42.2E+f32"
+WHITESPACE 1 "\n"
+FLOAT_NUMBER 9 "42.2E-f32"
+WHITESPACE 1 "\n"
+> error0..2 token("0e") msg(Missing digits after the exponent symbol)
+> error3..5 token("0E") msg(Missing digits after the exponent symbol)
+> error7..11 token("42e+") msg(Missing digits after the exponent symbol)
+> error12..16 token("42e-") msg(Missing digits after the exponent symbol)
+> error17..21 token("42E+") msg(Missing digits after the exponent symbol)
+> error22..26 token("42E-") msg(Missing digits after the exponent symbol)
+> error53..59 token("42.2e+") msg(Missing digits after the exponent symbol)
+> error60..66 token("42.2e-") msg(Missing digits after the exponent symbol)
+> error67..73 token("42.2E+") msg(Missing digits after the exponent symbol)
+> error74..80 token("42.2E-") msg(Missing digits after the exponent symbol)
+> error82..91 token("42.2e+f32") msg(Missing digits after the exponent symbol)
+> error92..101 token("42.2e-f32") msg(Missing digits after the exponent symbol)
+> error102..111 token("42.2E+f32") msg(Missing digits after the exponent symbol)
+> error112..121 token("42.2E-f32") msg(Missing digits after the exponent symbol)
diff --git a/crates/syntax/test_data/lexer/err/0057_lifetime_strarts_with_a_number.rs b/crates/syntax/test_data/lexer/err/0057_lifetime_strarts_with_a_number.rs
new file mode 100644
index 00000000000..a7698a404a8
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0057_lifetime_strarts_with_a_number.rs
@@ -0,0 +1,2 @@
+'1
+'1lifetime
diff --git a/crates/syntax/test_data/lexer/err/0057_lifetime_strarts_with_a_number.txt b/crates/syntax/test_data/lexer/err/0057_lifetime_strarts_with_a_number.txt
new file mode 100644
index 00000000000..e138bcebcdc
--- /dev/null
+++ b/crates/syntax/test_data/lexer/err/0057_lifetime_strarts_with_a_number.txt
@@ -0,0 +1,6 @@
+LIFETIME 2 "\'1"
+WHITESPACE 1 "\n"
+LIFETIME 10 "\'1lifetime"
+WHITESPACE 1 "\n"
+> error0..2 token("\'1") msg(Lifetime name cannot start with a number)
+> error3..13 token("\'1lifetime") msg(Lifetime name cannot start with a number)
diff --git a/crates/syntax/test_data/lexer/ok/0001_hello.rs b/crates/syntax/test_data/lexer/ok/0001_hello.rs
new file mode 100644
index 00000000000..95d09f2b101
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0001_hello.rs
@@ -0,0 +1 @@
+hello world
\ No newline at end of file
diff --git a/crates/syntax/test_data/lexer/ok/0001_hello.txt b/crates/syntax/test_data/lexer/ok/0001_hello.txt
new file mode 100644
index 00000000000..27a5940a9c1
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0001_hello.txt
@@ -0,0 +1,3 @@
+IDENT 5 "hello"
+WHITESPACE 1 " "
+IDENT 5 "world"
diff --git a/crates/syntax/test_data/lexer/ok/0002_whitespace.rs b/crates/syntax/test_data/lexer/ok/0002_whitespace.rs
new file mode 100644
index 00000000000..08fce1418a7
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0002_whitespace.rs
@@ -0,0 +1,4 @@
+a b  c
+d
+
+e	f
diff --git a/crates/syntax/test_data/lexer/ok/0002_whitespace.txt b/crates/syntax/test_data/lexer/ok/0002_whitespace.txt
new file mode 100644
index 00000000000..01d260918ee
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0002_whitespace.txt
@@ -0,0 +1,12 @@
+IDENT 1 "a"
+WHITESPACE 1 " "
+IDENT 1 "b"
+WHITESPACE 2 "  "
+IDENT 1 "c"
+WHITESPACE 1 "\n"
+IDENT 1 "d"
+WHITESPACE 2 "\n\n"
+IDENT 1 "e"
+WHITESPACE 1 "\t"
+IDENT 1 "f"
+WHITESPACE 1 "\n"
diff --git a/crates/syntax/test_data/lexer/ok/0003_ident.rs b/crates/syntax/test_data/lexer/ok/0003_ident.rs
new file mode 100644
index 00000000000..c05c9c009d7
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0003_ident.rs
@@ -0,0 +1 @@
+foo foo_ _foo _ __ x привет
diff --git a/crates/syntax/test_data/lexer/ok/0003_ident.txt b/crates/syntax/test_data/lexer/ok/0003_ident.txt
new file mode 100644
index 00000000000..4a0d5c05312
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0003_ident.txt
@@ -0,0 +1,14 @@
+IDENT 3 "foo"
+WHITESPACE 1 " "
+IDENT 4 "foo_"
+WHITESPACE 1 " "
+IDENT 4 "_foo"
+WHITESPACE 1 " "
+UNDERSCORE 1 "_"
+WHITESPACE 1 " "
+IDENT 2 "__"
+WHITESPACE 1 " "
+IDENT 1 "x"
+WHITESPACE 1 " "
+IDENT 12 "привет"
+WHITESPACE 1 "\n"
diff --git a/crates/syntax/test_data/lexer/ok/0004_numbers.rs b/crates/syntax/test_data/lexer/ok/0004_numbers.rs
new file mode 100644
index 00000000000..bc761c235d8
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0004_numbers.rs
@@ -0,0 +1,9 @@
+0 00 0_ 0. 0z
+01790 0b1790 0o1790 0x1790aAbBcCdDeEfF 001279 0_1279 0.1279 0e1279 0E1279
+0..2
+0.foo()
+0e+1
+0.e+1
+0.0E-2
+0___0.10000____0000e+111__
+1i64 92.0f32 11__s
diff --git a/crates/syntax/test_data/lexer/ok/0004_numbers.txt b/crates/syntax/test_data/lexer/ok/0004_numbers.txt
new file mode 100644
index 00000000000..e19fc5789e3
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0004_numbers.txt
@@ -0,0 +1,57 @@
+INT_NUMBER 1 "0"
+WHITESPACE 1 " "
+INT_NUMBER 2 "00"
+WHITESPACE 1 " "
+INT_NUMBER 2 "0_"
+WHITESPACE 1 " "
+FLOAT_NUMBER 2 "0."
+WHITESPACE 1 " "
+INT_NUMBER 2 "0z"
+WHITESPACE 1 "\n"
+INT_NUMBER 5 "01790"
+WHITESPACE 1 " "
+INT_NUMBER 6 "0b1790"
+WHITESPACE 1 " "
+INT_NUMBER 6 "0o1790"
+WHITESPACE 1 " "
+INT_NUMBER 18 "0x1790aAbBcCdDeEfF"
+WHITESPACE 1 " "
+INT_NUMBER 6 "001279"
+WHITESPACE 1 " "
+INT_NUMBER 6 "0_1279"
+WHITESPACE 1 " "
+FLOAT_NUMBER 6 "0.1279"
+WHITESPACE 1 " "
+FLOAT_NUMBER 6 "0e1279"
+WHITESPACE 1 " "
+FLOAT_NUMBER 6 "0E1279"
+WHITESPACE 1 "\n"
+INT_NUMBER 1 "0"
+DOT 1 "."
+DOT 1 "."
+INT_NUMBER 1 "2"
+WHITESPACE 1 "\n"
+INT_NUMBER 1 "0"
+DOT 1 "."
+IDENT 3 "foo"
+L_PAREN 1 "("
+R_PAREN 1 ")"
+WHITESPACE 1 "\n"
+FLOAT_NUMBER 4 "0e+1"
+WHITESPACE 1 "\n"
+INT_NUMBER 1 "0"
+DOT 1 "."
+IDENT 1 "e"
+PLUS 1 "+"
+INT_NUMBER 1 "1"
+WHITESPACE 1 "\n"
+FLOAT_NUMBER 6 "0.0E-2"
+WHITESPACE 1 "\n"
+FLOAT_NUMBER 26 "0___0.10000____0000e+111__"
+WHITESPACE 1 "\n"
+INT_NUMBER 4 "1i64"
+WHITESPACE 1 " "
+FLOAT_NUMBER 7 "92.0f32"
+WHITESPACE 1 " "
+INT_NUMBER 5 "11__s"
+WHITESPACE 1 "\n"
diff --git a/crates/syntax/test_data/lexer/ok/0005_symbols.rs b/crates/syntax/test_data/lexer/ok/0005_symbols.rs
new file mode 100644
index 00000000000..487569b5ae3
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0005_symbols.rs
@@ -0,0 +1,6 @@
+; , ( ) { } [ ] < > @ # ~ ? $ & | + * / ^ %
+. .. ... ..=
+: ::
+= =>
+! !=
+- ->
diff --git a/crates/syntax/test_data/lexer/ok/0005_symbols.txt b/crates/syntax/test_data/lexer/ok/0005_symbols.txt
new file mode 100644
index 00000000000..2049c2f1d66
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0005_symbols.txt
@@ -0,0 +1,77 @@
+SEMICOLON 1 ";"
+WHITESPACE 1 " "
+COMMA 1 ","
+WHITESPACE 1 " "
+L_PAREN 1 "("
+WHITESPACE 1 " "
+R_PAREN 1 ")"
+WHITESPACE 1 " "
+L_CURLY 1 "{"
+WHITESPACE 1 " "
+R_CURLY 1 "}"
+WHITESPACE 1 " "
+L_BRACK 1 "["
+WHITESPACE 1 " "
+R_BRACK 1 "]"
+WHITESPACE 1 " "
+L_ANGLE 1 "<"
+WHITESPACE 1 " "
+R_ANGLE 1 ">"
+WHITESPACE 1 " "
+AT 1 "@"
+WHITESPACE 1 " "
+POUND 1 "#"
+WHITESPACE 1 " "
+TILDE 1 "~"
+WHITESPACE 1 " "
+QUESTION 1 "?"
+WHITESPACE 1 " "
+DOLLAR 1 "$"
+WHITESPACE 1 " "
+AMP 1 "&"
+WHITESPACE 1 " "
+PIPE 1 "|"
+WHITESPACE 1 " "
+PLUS 1 "+"
+WHITESPACE 1 " "
+STAR 1 "*"
+WHITESPACE 1 " "
+SLASH 1 "/"
+WHITESPACE 1 " "
+CARET 1 "^"
+WHITESPACE 1 " "
+PERCENT 1 "%"
+WHITESPACE 1 "\n"
+DOT 1 "."
+WHITESPACE 1 " "
+DOT 1 "."
+DOT 1 "."
+WHITESPACE 1 " "
+DOT 1 "."
+DOT 1 "."
+DOT 1 "."
+WHITESPACE 1 " "
+DOT 1 "."
+DOT 1 "."
+EQ 1 "="
+WHITESPACE 1 "\n"
+COLON 1 ":"
+WHITESPACE 1 " "
+COLON 1 ":"
+COLON 1 ":"
+WHITESPACE 1 "\n"
+EQ 1 "="
+WHITESPACE 1 " "
+EQ 1 "="
+R_ANGLE 1 ">"
+WHITESPACE 1 "\n"
+BANG 1 "!"
+WHITESPACE 1 " "
+BANG 1 "!"
+EQ 1 "="
+WHITESPACE 1 "\n"
+MINUS 1 "-"
+WHITESPACE 1 " "
+MINUS 1 "-"
+R_ANGLE 1 ">"
+WHITESPACE 1 "\n"
diff --git a/crates/syntax/test_data/lexer/ok/0006_chars.rs b/crates/syntax/test_data/lexer/ok/0006_chars.rs
new file mode 100644
index 00000000000..454ee0a5f61
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0006_chars.rs
@@ -0,0 +1 @@
+'x' ' ' '0' 'hello' '\x7f' '\n' '\\' '\''
diff --git a/crates/syntax/test_data/lexer/ok/0006_chars.txt b/crates/syntax/test_data/lexer/ok/0006_chars.txt
new file mode 100644
index 00000000000..950954fbc88
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0006_chars.txt
@@ -0,0 +1,16 @@
+CHAR 3 "\'x\'"
+WHITESPACE 1 " "
+CHAR 3 "\' \'"
+WHITESPACE 1 " "
+CHAR 3 "\'0\'"
+WHITESPACE 1 " "
+CHAR 7 "\'hello\'"
+WHITESPACE 1 " "
+CHAR 6 "\'\\x7f\'"
+WHITESPACE 1 " "
+CHAR 4 "\'\\n\'"
+WHITESPACE 1 " "
+CHAR 4 "\'\\\\\'"
+WHITESPACE 1 " "
+CHAR 4 "\'\\\'\'"
+WHITESPACE 1 "\n"
diff --git a/crates/syntax/test_data/lexer/ok/0007_lifetimes.rs b/crates/syntax/test_data/lexer/ok/0007_lifetimes.rs
new file mode 100644
index 00000000000..b764f1dce3c
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0007_lifetimes.rs
@@ -0,0 +1 @@
+'a 'foo 'foo_bar_baz '_
diff --git a/crates/syntax/test_data/lexer/ok/0007_lifetimes.txt b/crates/syntax/test_data/lexer/ok/0007_lifetimes.txt
new file mode 100644
index 00000000000..005c29100a0
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0007_lifetimes.txt
@@ -0,0 +1,8 @@
+LIFETIME 2 "\'a"
+WHITESPACE 1 " "
+LIFETIME 4 "\'foo"
+WHITESPACE 1 " "
+LIFETIME 12 "\'foo_bar_baz"
+WHITESPACE 1 " "
+LIFETIME 2 "\'_"
+WHITESPACE 1 "\n"
diff --git a/crates/syntax/test_data/lexer/ok/0008_byte_strings.rs b/crates/syntax/test_data/lexer/ok/0008_byte_strings.rs
new file mode 100644
index 00000000000..b54930f5e69
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0008_byte_strings.rs
@@ -0,0 +1,3 @@
+b'' b'x' b"foo" br""
+b''suf b""ix br""br
+b'\n' b'\\' b'\'' b'hello'
diff --git a/crates/syntax/test_data/lexer/ok/0008_byte_strings.txt b/crates/syntax/test_data/lexer/ok/0008_byte_strings.txt
new file mode 100644
index 00000000000..bc03b51a8ab
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0008_byte_strings.txt
@@ -0,0 +1,22 @@
+BYTE 3 "b\'\'"
+WHITESPACE 1 " "
+BYTE 4 "b\'x\'"
+WHITESPACE 1 " "
+BYTE_STRING 6 "b\"foo\""
+WHITESPACE 1 " "
+RAW_BYTE_STRING 4 "br\"\""
+WHITESPACE 1 "\n"
+BYTE 6 "b\'\'suf"
+WHITESPACE 1 " "
+BYTE_STRING 5 "b\"\"ix"
+WHITESPACE 1 " "
+RAW_BYTE_STRING 6 "br\"\"br"
+WHITESPACE 1 "\n"
+BYTE 5 "b\'\\n\'"
+WHITESPACE 1 " "
+BYTE 5 "b\'\\\\\'"
+WHITESPACE 1 " "
+BYTE 5 "b\'\\\'\'"
+WHITESPACE 1 " "
+BYTE 8 "b\'hello\'"
+WHITESPACE 1 "\n"
diff --git a/crates/syntax/test_data/lexer/ok/0009_strings.rs b/crates/syntax/test_data/lexer/ok/0009_strings.rs
new file mode 100644
index 00000000000..4ddb5bffccc
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0009_strings.rs
@@ -0,0 +1,2 @@
+"hello" r"world" "\n\"\\no escape" "multi
+line"
diff --git a/crates/syntax/test_data/lexer/ok/0009_strings.txt b/crates/syntax/test_data/lexer/ok/0009_strings.txt
new file mode 100644
index 00000000000..4cb4d711d67
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0009_strings.txt
@@ -0,0 +1,8 @@
+STRING 7 "\"hello\""
+WHITESPACE 1 " "
+RAW_STRING 8 "r\"world\""
+WHITESPACE 1 " "
+STRING 17 "\"\\n\\\"\\\\no escape\""
+WHITESPACE 1 " "
+STRING 12 "\"multi\nline\""
+WHITESPACE 1 "\n"
diff --git a/crates/syntax/test_data/lexer/ok/0010_single_line_comments.rs b/crates/syntax/test_data/lexer/ok/0010_single_line_comments.rs
new file mode 100644
index 00000000000..4b6653f9cc9
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0010_single_line_comments.rs
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+// hello
+//! World
+//!! Inner line doc
+/// Outer line doc
+//// Just a comment
+
+//
+//!
+//!!
+///
+////
diff --git a/crates/syntax/test_data/lexer/ok/0010_single_line_comments.txt b/crates/syntax/test_data/lexer/ok/0010_single_line_comments.txt
new file mode 100644
index 00000000000..98a3818c06c
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0010_single_line_comments.txt
@@ -0,0 +1,22 @@
+SHEBANG 19 "#!/usr/bin/env bash"
+WHITESPACE 1 "\n"
+COMMENT 8 "// hello"
+WHITESPACE 1 "\n"
+COMMENT 9 "//! World"
+WHITESPACE 1 "\n"
+COMMENT 19 "//!! Inner line doc"
+WHITESPACE 1 "\n"
+COMMENT 18 "/// Outer line doc"
+WHITESPACE 1 "\n"
+COMMENT 19 "//// Just a comment"
+WHITESPACE 2 "\n\n"
+COMMENT 2 "//"
+WHITESPACE 1 "\n"
+COMMENT 3 "//!"
+WHITESPACE 1 "\n"
+COMMENT 4 "//!!"
+WHITESPACE 1 "\n"
+COMMENT 3 "///"
+WHITESPACE 1 "\n"
+COMMENT 4 "////"
+WHITESPACE 1 "\n"
diff --git a/crates/syntax/test_data/lexer/ok/0011_keywords.rs b/crates/syntax/test_data/lexer/ok/0011_keywords.rs
new file mode 100644
index 00000000000..1e91bff4e7d
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0011_keywords.rs
@@ -0,0 +1,3 @@
+async fn use struct trait enum impl true false as extern crate
+mod pub self super in where for loop while if match const
+static mut type ref let else move return
diff --git a/crates/syntax/test_data/lexer/ok/0011_keywords.txt b/crates/syntax/test_data/lexer/ok/0011_keywords.txt
new file mode 100644
index 00000000000..22c00eefb62
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0011_keywords.txt
@@ -0,0 +1,64 @@
+ASYNC_KW 5 "async"
+WHITESPACE 1 " "
+FN_KW 2 "fn"
+WHITESPACE 1 " "
+USE_KW 3 "use"
+WHITESPACE 1 " "
+STRUCT_KW 6 "struct"
+WHITESPACE 1 " "
+TRAIT_KW 5 "trait"
+WHITESPACE 1 " "
+ENUM_KW 4 "enum"
+WHITESPACE 1 " "
+IMPL_KW 4 "impl"
+WHITESPACE 1 " "
+TRUE_KW 4 "true"
+WHITESPACE 1 " "
+FALSE_KW 5 "false"
+WHITESPACE 1 " "
+AS_KW 2 "as"
+WHITESPACE 1 " "
+EXTERN_KW 6 "extern"
+WHITESPACE 1 " "
+CRATE_KW 5 "crate"
+WHITESPACE 1 "\n"
+MOD_KW 3 "mod"
+WHITESPACE 1 " "
+PUB_KW 3 "pub"
+WHITESPACE 1 " "
+SELF_KW 4 "self"
+WHITESPACE 1 " "
+SUPER_KW 5 "super"
+WHITESPACE 1 " "
+IN_KW 2 "in"
+WHITESPACE 1 " "
+WHERE_KW 5 "where"
+WHITESPACE 1 " "
+FOR_KW 3 "for"
+WHITESPACE 1 " "
+LOOP_KW 4 "loop"
+WHITESPACE 1 " "
+WHILE_KW 5 "while"
+WHITESPACE 1 " "
+IF_KW 2 "if"
+WHITESPACE 1 " "
+MATCH_KW 5 "match"
+WHITESPACE 1 " "
+CONST_KW 5 "const"
+WHITESPACE 1 "\n"
+STATIC_KW 6 "static"
+WHITESPACE 1 " "
+MUT_KW 3 "mut"
+WHITESPACE 1 " "
+TYPE_KW 4 "type"
+WHITESPACE 1 " "
+REF_KW 3 "ref"
+WHITESPACE 1 " "
+LET_KW 3 "let"
+WHITESPACE 1 " "
+ELSE_KW 4 "else"
+WHITESPACE 1 " "
+MOVE_KW 4 "move"
+WHITESPACE 1 " "
+RETURN_KW 6 "return"
+WHITESPACE 1 "\n"
diff --git a/crates/syntax/test_data/lexer/ok/0012_block_comment.rs b/crates/syntax/test_data/lexer/ok/0012_block_comment.rs
new file mode 100644
index 00000000000..b880a59d952
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0012_block_comment.rs
@@ -0,0 +1,3 @@
+/* */
+/**/
+/* /* */ */
diff --git a/crates/syntax/test_data/lexer/ok/0012_block_comment.txt b/crates/syntax/test_data/lexer/ok/0012_block_comment.txt
new file mode 100644
index 00000000000..2618e287e63
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0012_block_comment.txt
@@ -0,0 +1,6 @@
+COMMENT 5 "/* */"
+WHITESPACE 1 "\n"
+COMMENT 4 "/**/"
+WHITESPACE 1 "\n"
+COMMENT 11 "/* /* */ */"
+WHITESPACE 1 "\n"
diff --git a/crates/syntax/test_data/lexer/ok/0013_raw_strings.rs b/crates/syntax/test_data/lexer/ok/0013_raw_strings.rs
new file mode 100644
index 00000000000..e5ed0b693b3
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0013_raw_strings.rs
@@ -0,0 +1 @@
+r###"this is a r##"raw"## string"###
diff --git a/crates/syntax/test_data/lexer/ok/0013_raw_strings.txt b/crates/syntax/test_data/lexer/ok/0013_raw_strings.txt
new file mode 100644
index 00000000000..9cf0957d1e6
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0013_raw_strings.txt
@@ -0,0 +1,2 @@
+RAW_STRING 36 "r###\"this is a r##\"raw\"## string\"###"
+WHITESPACE 1 "\n"
diff --git a/crates/syntax/test_data/lexer/ok/0014_raw_ident.rs b/crates/syntax/test_data/lexer/ok/0014_raw_ident.rs
new file mode 100644
index 00000000000..b40a1b6a248
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0014_raw_ident.rs
@@ -0,0 +1 @@
+r#raw_ident
diff --git a/crates/syntax/test_data/lexer/ok/0014_raw_ident.txt b/crates/syntax/test_data/lexer/ok/0014_raw_ident.txt
new file mode 100644
index 00000000000..484689693ba
--- /dev/null
+++ b/crates/syntax/test_data/lexer/ok/0014_raw_ident.txt
@@ -0,0 +1,2 @@
+IDENT 11 "r#raw_ident"
+WHITESPACE 1 "\n"
diff --git a/crates/syntax/test_data/parser/err/0000_struct_field_missing_comma.rast b/crates/syntax/test_data/parser/err/0000_struct_field_missing_comma.rast
new file mode 100644
index 00000000000..bbbf496c82d
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0000_struct_field_missing_comma.rast
@@ -0,0 +1,34 @@
+SOURCE_FILE@0..34
+  STRUCT@0..34
+    STRUCT_KW@0..6 "struct"
+    WHITESPACE@6..7 " "
+    NAME@7..8
+      IDENT@7..8 "S"
+    WHITESPACE@8..9 " "
+    RECORD_FIELD_LIST@9..34
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      RECORD_FIELD@15..21
+        NAME@15..16
+          IDENT@15..16 "a"
+        COLON@16..17 ":"
+        WHITESPACE@17..18 " "
+        PATH_TYPE@18..21
+          PATH@18..21
+            PATH_SEGMENT@18..21
+              NAME_REF@18..21
+                IDENT@18..21 "u32"
+      WHITESPACE@21..26 "\n    "
+      RECORD_FIELD@26..32
+        NAME@26..27
+          IDENT@26..27 "b"
+        COLON@27..28 ":"
+        WHITESPACE@28..29 " "
+        PATH_TYPE@29..32
+          PATH@29..32
+            PATH_SEGMENT@29..32
+              NAME_REF@29..32
+                IDENT@29..32 "u32"
+      WHITESPACE@32..33 "\n"
+      R_CURLY@33..34 "}"
+error 21..21: expected COMMA
diff --git a/crates/syntax/test_data/parser/err/0000_struct_field_missing_comma.rs b/crates/syntax/test_data/parser/err/0000_struct_field_missing_comma.rs
new file mode 100644
index 00000000000..fe5030d893f
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0000_struct_field_missing_comma.rs
@@ -0,0 +1,4 @@
+struct S {
+    a: u32
+    b: u32
+}
\ No newline at end of file
diff --git a/crates/syntax/test_data/parser/err/0001_item_recovery_in_file.rast b/crates/syntax/test_data/parser/err/0001_item_recovery_in_file.rast
new file mode 100644
index 00000000000..6dc73bfdbae
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0001_item_recovery_in_file.rast
@@ -0,0 +1,18 @@
+SOURCE_FILE@0..21
+  ERROR@0..2
+    IF_KW@0..2 "if"
+  WHITESPACE@2..3 " "
+  ERROR@3..8
+    MATCH_KW@3..8 "match"
+  WHITESPACE@8..10 "\n\n"
+  STRUCT@10..21
+    STRUCT_KW@10..16 "struct"
+    WHITESPACE@16..17 " "
+    NAME@17..18
+      IDENT@17..18 "S"
+    WHITESPACE@18..19 " "
+    RECORD_FIELD_LIST@19..21
+      L_CURLY@19..20 "{"
+      R_CURLY@20..21 "}"
+error 0..0: expected an item
+error 3..3: expected an item
diff --git a/crates/syntax/test_data/parser/err/0001_item_recovery_in_file.rs b/crates/syntax/test_data/parser/err/0001_item_recovery_in_file.rs
new file mode 100644
index 00000000000..98f23de1f22
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0001_item_recovery_in_file.rs
@@ -0,0 +1,3 @@
+if match
+
+struct S {}
\ No newline at end of file
diff --git a/crates/syntax/test_data/parser/err/0002_duplicate_shebang.rast b/crates/syntax/test_data/parser/err/0002_duplicate_shebang.rast
new file mode 100644
index 00000000000..4cfd1bce4b1
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0002_duplicate_shebang.rast
@@ -0,0 +1,39 @@
+SOURCE_FILE@0..42
+  SHEBANG@0..20 "#!/use/bin/env rusti"
+  WHITESPACE@20..21 "\n"
+  ATTR@21..23
+    POUND@21..22 "#"
+    BANG@22..23 "!"
+  ERROR@23..24
+    SLASH@23..24 "/"
+  USE@24..28
+    USE_KW@24..27 "use"
+    ERROR@27..28
+      SLASH@27..28 "/"
+  MACRO_CALL@28..31
+    PATH@28..31
+      PATH_SEGMENT@28..31
+        NAME_REF@28..31
+          IDENT@28..31 "bin"
+  ERROR@31..32
+    SLASH@31..32 "/"
+  MACRO_CALL@32..41
+    PATH@32..35
+      PATH_SEGMENT@32..35
+        NAME_REF@32..35
+          IDENT@32..35 "env"
+    WHITESPACE@35..36 " "
+    NAME@36..41
+      IDENT@36..41 "rusti"
+  WHITESPACE@41..42 "\n"
+error 23..23: expected `[`
+error 23..23: expected an item
+error 27..27: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
+error 28..28: expected SEMICOLON
+error 31..31: expected BANG
+error 31..31: expected `{`, `[`, `(`
+error 31..31: expected SEMICOLON
+error 31..31: expected an item
+error 35..35: expected BANG
+error 41..41: expected `{`, `[`, `(`
+error 41..41: expected SEMICOLON
diff --git a/crates/syntax/test_data/parser/err/0002_duplicate_shebang.rs b/crates/syntax/test_data/parser/err/0002_duplicate_shebang.rs
new file mode 100644
index 00000000000..48a3a3980ba
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0002_duplicate_shebang.rs
@@ -0,0 +1,2 @@
+#!/use/bin/env rusti
+#!/use/bin/env rusti
diff --git a/crates/syntax/test_data/parser/err/0003_C++_semicolon.rast b/crates/syntax/test_data/parser/err/0003_C++_semicolon.rast
new file mode 100644
index 00000000000..7763fad840b
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0003_C++_semicolon.rast
@@ -0,0 +1,39 @@
+SOURCE_FILE@0..40
+  STRUCT@0..39
+    STRUCT_KW@0..6 "struct"
+    WHITESPACE@6..7 " "
+    NAME@7..8
+      IDENT@7..8 "S"
+    WHITESPACE@8..9 " "
+    RECORD_FIELD_LIST@9..39
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      RECORD_FIELD@15..21
+        NAME@15..16
+          IDENT@15..16 "a"
+        COLON@16..17 ":"
+        WHITESPACE@17..18 " "
+        PATH_TYPE@18..21
+          PATH@18..21
+            PATH_SEGMENT@18..21
+              NAME_REF@18..21
+                IDENT@18..21 "i32"
+      COMMA@21..22 ","
+      WHITESPACE@22..27 "\n    "
+      RECORD_FIELD@27..36
+        NAME@27..28
+          IDENT@27..28 "b"
+        COLON@28..29 ":"
+        WHITESPACE@29..30 " "
+        PATH_TYPE@30..36
+          PATH@30..36
+            PATH_SEGMENT@30..36
+              NAME_REF@30..36
+                IDENT@30..36 "String"
+      COMMA@36..37 ","
+      WHITESPACE@37..38 "\n"
+      R_CURLY@38..39 "}"
+  ERROR@39..40
+    SEMICOLON@39..40 ";"
+error 39..39: expected item, found `;`
+consider removing this semicolon
diff --git a/crates/syntax/test_data/parser/err/0003_C++_semicolon.rs b/crates/syntax/test_data/parser/err/0003_C++_semicolon.rs
new file mode 100644
index 00000000000..009312270fe
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0003_C++_semicolon.rs
@@ -0,0 +1,4 @@
+struct S {
+    a: i32,
+    b: String,
+};
\ No newline at end of file
diff --git a/crates/syntax/test_data/parser/err/0004_use_path_bad_segment.rast b/crates/syntax/test_data/parser/err/0004_use_path_bad_segment.rast
new file mode 100644
index 00000000000..9a0f4665efc
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0004_use_path_bad_segment.rast
@@ -0,0 +1,15 @@
+SOURCE_FILE@0..12
+  USE@0..12
+    USE_KW@0..3 "use"
+    WHITESPACE@3..4 " "
+    USE_TREE@4..11
+      PATH@4..11
+        PATH@4..7
+          PATH_SEGMENT@4..7
+            NAME_REF@4..7
+              IDENT@4..7 "foo"
+        COLON2@7..9 "::"
+        ERROR@9..11
+          INT_NUMBER@9..11 "92"
+    SEMICOLON@11..12 ";"
+error 9..9: expected identifier
diff --git a/crates/syntax/test_data/parser/err/0004_use_path_bad_segment.rs b/crates/syntax/test_data/parser/err/0004_use_path_bad_segment.rs
new file mode 100644
index 00000000000..060e65d06d2
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0004_use_path_bad_segment.rs
@@ -0,0 +1 @@
+use foo::92;
\ No newline at end of file
diff --git a/crates/syntax/test_data/parser/err/0005_attribute_recover.rast b/crates/syntax/test_data/parser/err/0005_attribute_recover.rast
new file mode 100644
index 00000000000..4845a6563cb
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0005_attribute_recover.rast
@@ -0,0 +1,59 @@
+SOURCE_FILE@0..54
+  FN@0..31
+    ATTR@0..18
+      POUND@0..1 "#"
+      L_BRACK@1..2 "["
+      PATH@2..5
+        PATH_SEGMENT@2..5
+          NAME_REF@2..5
+            IDENT@2..5 "foo"
+      TOKEN_TREE@5..17
+        L_PAREN@5..6 "("
+        IDENT@6..9 "foo"
+        COMMA@9..10 ","
+        WHITESPACE@10..11 " "
+        PLUS@11..12 "+"
+        COMMA@12..13 ","
+        WHITESPACE@13..14 " "
+        INT_NUMBER@14..16 "92"
+        R_PAREN@16..17 ")"
+      R_BRACK@17..18 "]"
+    WHITESPACE@18..19 "\n"
+    FN_KW@19..21 "fn"
+    WHITESPACE@21..22 " "
+    NAME@22..25
+      IDENT@22..25 "foo"
+    PARAM_LIST@25..27
+      L_PAREN@25..26 "("
+      R_PAREN@26..27 ")"
+    WHITESPACE@27..28 " "
+    BLOCK_EXPR@28..31
+      L_CURLY@28..29 "{"
+      WHITESPACE@29..30 "\n"
+      R_CURLY@30..31 "}"
+  WHITESPACE@31..34 "\n\n\n"
+  ATTR@34..53
+    POUND@34..35 "#"
+    L_BRACK@35..36 "["
+    PATH@36..39
+      PATH_SEGMENT@36..39
+        NAME_REF@36..39
+          IDENT@36..39 "foo"
+    TOKEN_TREE@39..53
+      L_PAREN@39..40 "("
+      WHITESPACE@40..41 "\n"
+      FN_KW@41..43 "fn"
+      WHITESPACE@43..44 " "
+      IDENT@44..47 "foo"
+      TOKEN_TREE@47..49
+        L_PAREN@47..48 "("
+        R_PAREN@48..49 ")"
+      WHITESPACE@49..50 " "
+      TOKEN_TREE@50..53
+        L_CURLY@50..51 "{"
+        WHITESPACE@51..52 "\n"
+        R_CURLY@52..53 "}"
+  WHITESPACE@53..54 "\n"
+error 53..53: expected R_PAREN
+error 53..53: expected `]`
+error 53..53: expected an item
diff --git a/crates/syntax/test_data/parser/err/0005_attribute_recover.rs b/crates/syntax/test_data/parser/err/0005_attribute_recover.rs
new file mode 100644
index 00000000000..de7f8162839
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0005_attribute_recover.rs
@@ -0,0 +1,8 @@
+#[foo(foo, +, 92)]
+fn foo() {
+}
+
+
+#[foo(
+fn foo() {
+}
diff --git a/crates/syntax/test_data/parser/err/0006_named_field_recovery.rast b/crates/syntax/test_data/parser/err/0006_named_field_recovery.rast
new file mode 100644
index 00000000000..5f85c3943ab
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0006_named_field_recovery.rast
@@ -0,0 +1,74 @@
+SOURCE_FILE@0..74
+  STRUCT@0..73
+    STRUCT_KW@0..6 "struct"
+    WHITESPACE@6..7 " "
+    NAME@7..8
+      IDENT@7..8 "S"
+    WHITESPACE@8..9 " "
+    RECORD_FIELD_LIST@9..73
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      RECORD_FIELD@15..21
+        NAME@15..16
+          IDENT@15..16 "f"
+        COLON@16..17 ":"
+        WHITESPACE@17..18 " "
+        PATH_TYPE@18..21
+          PATH@18..21
+            PATH_SEGMENT@18..21
+              NAME_REF@18..21
+                IDENT@18..21 "u32"
+      COMMA@21..22 ","
+      WHITESPACE@22..27 "\n    "
+      VISIBILITY@27..30
+        PUB_KW@27..30 "pub"
+      WHITESPACE@30..31 " "
+      ERROR@31..33
+        INT_NUMBER@31..33 "92"
+      WHITESPACE@33..38 "\n    "
+      ERROR@38..39
+        PLUS@38..39 "+"
+      WHITESPACE@39..40 " "
+      ERROR@40..41
+        MINUS@40..41 "-"
+      WHITESPACE@41..42 " "
+      ERROR@42..43
+        STAR@42..43 "*"
+      WHITESPACE@43..48 "\n    "
+      RECORD_FIELD@48..58
+        VISIBILITY@48..51
+          PUB_KW@48..51 "pub"
+        WHITESPACE@51..52 " "
+        NAME@52..53
+          IDENT@52..53 "x"
+        COLON@53..54 ":"
+        WHITESPACE@54..55 " "
+        PATH_TYPE@55..58
+          PATH@55..58
+            PATH_SEGMENT@55..58
+              NAME_REF@55..58
+                IDENT@55..58 "u32"
+      COMMA@58..59 ","
+      WHITESPACE@59..64 "\n    "
+      RECORD_FIELD@64..70
+        NAME@64..65
+          IDENT@64..65 "z"
+        COLON@65..66 ":"
+        WHITESPACE@66..67 " "
+        PATH_TYPE@67..70
+          PATH@67..70
+            PATH_SEGMENT@67..70
+              NAME_REF@67..70
+                IDENT@67..70 "f64"
+      COMMA@70..71 ","
+      WHITESPACE@71..72 "\n"
+      R_CURLY@72..73 "}"
+  WHITESPACE@73..74 "\n"
+error 31..31: expected field declaration
+error 33..33: expected COMMA
+error 38..38: expected field declaration
+error 39..39: expected COMMA
+error 40..40: expected field declaration
+error 41..41: expected COMMA
+error 42..42: expected field declaration
+error 43..43: expected COMMA
diff --git a/crates/syntax/test_data/parser/err/0006_named_field_recovery.rs b/crates/syntax/test_data/parser/err/0006_named_field_recovery.rs
new file mode 100644
index 00000000000..8069c111b4b
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0006_named_field_recovery.rs
@@ -0,0 +1,7 @@
+struct S {
+    f: u32,
+    pub 92
+    + - *
+    pub x: u32,
+    z: f64,
+}
diff --git a/crates/syntax/test_data/parser/err/0007_stray_curly_in_file.rast b/crates/syntax/test_data/parser/err/0007_stray_curly_in_file.rast
new file mode 100644
index 00000000000..560bfd75186
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0007_stray_curly_in_file.rast
@@ -0,0 +1,32 @@
+SOURCE_FILE@0..31
+  ERROR@0..1
+    R_CURLY@0..1 "}"
+  WHITESPACE@1..3 "\n\n"
+  STRUCT@3..12
+    STRUCT_KW@3..9 "struct"
+    WHITESPACE@9..10 " "
+    NAME@10..11
+      IDENT@10..11 "S"
+    SEMICOLON@11..12 ";"
+  WHITESPACE@12..14 "\n\n"
+  ERROR@14..15
+    R_CURLY@14..15 "}"
+  WHITESPACE@15..17 "\n\n"
+  FN@17..27
+    FN_KW@17..19 "fn"
+    WHITESPACE@19..20 " "
+    NAME@20..23
+      IDENT@20..23 "foo"
+    PARAM_LIST@23..25
+      L_PAREN@23..24 "("
+      R_PAREN@24..25 ")"
+    BLOCK_EXPR@25..27
+      L_CURLY@25..26 "{"
+      R_CURLY@26..27 "}"
+  WHITESPACE@27..29 "\n\n"
+  ERROR@29..30
+    R_CURLY@29..30 "}"
+  WHITESPACE@30..31 "\n"
+error 0..0: unmatched `}`
+error 14..14: unmatched `}`
+error 29..29: unmatched `}`
diff --git a/crates/syntax/test_data/parser/err/0007_stray_curly_in_file.rs b/crates/syntax/test_data/parser/err/0007_stray_curly_in_file.rs
new file mode 100644
index 00000000000..dc869fb785e
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0007_stray_curly_in_file.rs
@@ -0,0 +1,9 @@
+}
+
+struct S;
+
+}
+
+fn foo(){}
+
+}
diff --git a/crates/syntax/test_data/parser/err/0008_item_block_recovery.rast b/crates/syntax/test_data/parser/err/0008_item_block_recovery.rast
new file mode 100644
index 00000000000..1e9637c26d5
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0008_item_block_recovery.rast
@@ -0,0 +1,77 @@
+SOURCE_FILE@0..95
+  FN@0..12
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..12
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..11 "\n"
+      R_CURLY@11..12 "}"
+  WHITESPACE@12..14 "\n\n"
+  MACRO_CALL@14..19
+    PATH@14..17
+      PATH_SEGMENT@14..17
+        NAME_REF@14..17
+          IDENT@14..17 "bar"
+    TOKEN_TREE@17..19
+      L_PAREN@17..18 "("
+      R_PAREN@18..19 ")"
+  WHITESPACE@19..20 " "
+  ERROR@20..80
+    L_CURLY@20..21 "{"
+    WHITESPACE@21..26 "\n    "
+    IF_EXPR@26..78
+      IF_KW@26..28 "if"
+      WHITESPACE@28..29 " "
+      CONDITION@29..33
+        LITERAL@29..33
+          TRUE_KW@29..33 "true"
+      WHITESPACE@33..34 " "
+      BLOCK_EXPR@34..51
+        L_CURLY@34..35 "{"
+        WHITESPACE@35..44 "\n        "
+        LITERAL@44..45
+          INT_NUMBER@44..45 "1"
+        WHITESPACE@45..50 "\n    "
+        R_CURLY@50..51 "}"
+      WHITESPACE@51..52 " "
+      ELSE_KW@52..56 "else"
+      WHITESPACE@56..57 " "
+      BLOCK_EXPR@57..78
+        L_CURLY@57..58 "{"
+        WHITESPACE@58..67 "\n        "
+        BIN_EXPR@67..72
+          LITERAL@67..68
+            INT_NUMBER@67..68 "2"
+          WHITESPACE@68..69 " "
+          PLUS@69..70 "+"
+          WHITESPACE@70..71 " "
+          LITERAL@71..72
+            INT_NUMBER@71..72 "3"
+        WHITESPACE@72..77 "\n    "
+        R_CURLY@77..78 "}"
+    WHITESPACE@78..79 "\n"
+    R_CURLY@79..80 "}"
+  WHITESPACE@80..82 "\n\n"
+  FN@82..94
+    FN_KW@82..84 "fn"
+    WHITESPACE@84..85 " "
+    NAME@85..88
+      IDENT@85..88 "baz"
+    PARAM_LIST@88..90
+      L_PAREN@88..89 "("
+      R_PAREN@89..90 ")"
+    WHITESPACE@90..91 " "
+    BLOCK_EXPR@91..94
+      L_CURLY@91..92 "{"
+      WHITESPACE@92..93 "\n"
+      R_CURLY@93..94 "}"
+  WHITESPACE@94..95 "\n"
+error 17..17: expected BANG
+error 19..19: expected SEMICOLON
+error 20..20: expected an item
diff --git a/crates/syntax/test_data/parser/err/0008_item_block_recovery.rs b/crates/syntax/test_data/parser/err/0008_item_block_recovery.rs
new file mode 100644
index 00000000000..9fcac19b5ce
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0008_item_block_recovery.rs
@@ -0,0 +1,13 @@
+fn foo() {
+}
+
+bar() {
+    if true {
+        1
+    } else {
+        2 + 3
+    }
+}
+
+fn baz() {
+}
diff --git a/crates/syntax/test_data/parser/err/0009_broken_struct_type_parameter.rast b/crates/syntax/test_data/parser/err/0009_broken_struct_type_parameter.rast
new file mode 100644
index 00000000000..dacf71aa165
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0009_broken_struct_type_parameter.rast
@@ -0,0 +1,58 @@
+SOURCE_FILE@0..43
+  STRUCT@0..11
+    STRUCT_KW@0..6 "struct"
+    WHITESPACE@6..7 " "
+    NAME@7..8
+      IDENT@7..8 "S"
+    GENERIC_PARAM_LIST@8..11
+      L_ANGLE@8..9 "<"
+      ERROR@9..11
+        INT_NUMBER@9..11 "90"
+  WHITESPACE@11..12 " "
+  ERROR@12..13
+    PLUS@12..13 "+"
+  WHITESPACE@13..14 " "
+  ERROR@14..15
+    INT_NUMBER@14..15 "2"
+  ERROR@15..16
+    R_ANGLE@15..16 ">"
+  WHITESPACE@16..17 " "
+  ERROR@17..31
+    L_CURLY@17..18 "{"
+    WHITESPACE@18..23 "\n    "
+    EXPR_STMT@23..24
+      PATH_EXPR@23..24
+        PATH@23..24
+          PATH_SEGMENT@23..24
+            NAME_REF@23..24
+              IDENT@23..24 "f"
+    EXPR_STMT@24..25
+      ERROR@24..25
+        COLON@24..25 ":"
+    WHITESPACE@25..26 " "
+    PATH_EXPR@26..29
+      PATH@26..29
+        PATH_SEGMENT@26..29
+          NAME_REF@26..29
+            IDENT@26..29 "u32"
+    WHITESPACE@29..30 "\n"
+    R_CURLY@30..31 "}"
+  WHITESPACE@31..33 "\n\n"
+  STRUCT@33..42
+    STRUCT_KW@33..39 "struct"
+    WHITESPACE@39..40 " "
+    NAME@40..41
+      IDENT@40..41 "T"
+    SEMICOLON@41..42 ";"
+  WHITESPACE@42..43 "\n"
+error 9..9: expected type parameter
+error 11..11: expected COMMA
+error 11..11: expected R_ANGLE
+error 11..11: expected `;`, `{`, or `(`
+error 12..12: expected an item
+error 14..14: expected an item
+error 15..15: expected an item
+error 17..17: expected an item
+error 24..24: expected SEMICOLON
+error 24..24: expected expression
+error 25..25: expected SEMICOLON
diff --git a/crates/syntax/test_data/parser/err/0009_broken_struct_type_parameter.rs b/crates/syntax/test_data/parser/err/0009_broken_struct_type_parameter.rs
new file mode 100644
index 00000000000..0dd30d0bd68
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0009_broken_struct_type_parameter.rs
@@ -0,0 +1,5 @@
+struct S<90 + 2> {
+    f: u32
+}
+
+struct T;
diff --git a/crates/syntax/test_data/parser/err/0010_unsafe_lambda_block.rast b/crates/syntax/test_data/parser/err/0010_unsafe_lambda_block.rast
new file mode 100644
index 00000000000..e0f1d0c2749
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0010_unsafe_lambda_block.rast
@@ -0,0 +1,44 @@
+SOURCE_FILE@0..42
+  FN@0..41
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..41
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      EXPR_STMT@16..24
+        CLOSURE_EXPR@16..24
+          PARAM_LIST@16..18
+            PIPE@16..17 "|"
+            PIPE@17..18 "|"
+          WHITESPACE@18..19 " "
+          RET_TYPE@19..24
+            THIN_ARROW@19..21 "->"
+            WHITESPACE@21..22 " "
+            TUPLE_TYPE@22..24
+              L_PAREN@22..23 "("
+              R_PAREN@23..24 ")"
+      WHITESPACE@24..25 " "
+      EXPR_STMT@25..39
+        EFFECT_EXPR@25..38
+          UNSAFE_KW@25..31 "unsafe"
+          WHITESPACE@31..32 " "
+          BLOCK_EXPR@32..38
+            L_CURLY@32..33 "{"
+            WHITESPACE@33..34 " "
+            TUPLE_EXPR@34..36
+              L_PAREN@34..35 "("
+              R_PAREN@35..36 ")"
+            WHITESPACE@36..37 " "
+            R_CURLY@37..38 "}"
+        SEMICOLON@38..39 ";"
+      WHITESPACE@39..40 "\n"
+      R_CURLY@40..41 "}"
+  WHITESPACE@41..42 "\n"
+error 24..24: expected a block
+error 24..24: expected SEMICOLON
diff --git a/crates/syntax/test_data/parser/err/0010_unsafe_lambda_block.rs b/crates/syntax/test_data/parser/err/0010_unsafe_lambda_block.rs
new file mode 100644
index 00000000000..9857752824a
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0010_unsafe_lambda_block.rs
@@ -0,0 +1,3 @@
+fn main() {
+    || -> () unsafe { () };
+}
diff --git a/crates/syntax/test_data/parser/err/0011_extern_struct.rast b/crates/syntax/test_data/parser/err/0011_extern_struct.rast
new file mode 100644
index 00000000000..b02d390af9b
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0011_extern_struct.rast
@@ -0,0 +1,13 @@
+SOURCE_FILE@0..19
+  ERROR@0..6
+    ABI@0..6
+      EXTERN_KW@0..6 "extern"
+  WHITESPACE@6..7 " "
+  STRUCT@7..18
+    STRUCT_KW@7..13 "struct"
+    WHITESPACE@13..14 " "
+    NAME@14..17
+      IDENT@14..17 "Foo"
+    SEMICOLON@17..18 ";"
+  WHITESPACE@18..19 "\n"
+error 6..6: expected existential, fn, trait or impl
diff --git a/crates/syntax/test_data/parser/err/0011_extern_struct.rs b/crates/syntax/test_data/parser/err/0011_extern_struct.rs
new file mode 100644
index 00000000000..c1bd0a2d1be
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0011_extern_struct.rs
@@ -0,0 +1 @@
+extern struct Foo;
diff --git a/crates/syntax/test_data/parser/err/0012_broken_lambda.rast b/crates/syntax/test_data/parser/err/0012_broken_lambda.rast
new file mode 100644
index 00000000000..f31c2763398
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0012_broken_lambda.rast
@@ -0,0 +1,387 @@
+SOURCE_FILE@0..389
+  FN@0..389
+    VISIBILITY@0..10
+      PUB_KW@0..3
+      L_PAREN@3..4
+      SUPER_KW@4..9
+      R_PAREN@9..10
+    WHITESPACE@10..11
+    FN_KW@11..13
+    WHITESPACE@13..14
+    NAME@14..21
+      IDENT@14..21 "process"
+    GENERIC_PARAM_LIST@21..38
+      L_ANGLE@21..22
+      LIFETIME_PARAM@22..24
+        LIFETIME@22..24 "'a"
+      COMMA@24..25
+      WHITESPACE@25..26
+      TYPE_PARAM@26..37
+        NAME@26..27
+          IDENT@26..27 "S"
+        COLON@27..28
+        WHITESPACE@28..29
+        PATH@29..37
+          PATH_SEGMENT@29..37
+            NAME_REF@29..33
+              IDENT@29..33 "Sink"
+            GENERIC_ARG_LIST@33..37
+              L_ANGLE@33..34
+              LIFETIME_ARG@34..36
+                LIFETIME@34..36 "'a"
+              R_ANGLE@36..37
+      R_ANGLE@37..38
+    PARAM_LIST@38..93
+      L_PAREN@38..39
+      PARAM@39..54
+        IDENT_PAT@39..46
+          NAME@39..46
+            IDENT@39..46 "builder"
+        COLON@46..47
+        WHITESPACE@47..48
+        REF_TYPE@48..54
+          AMP@48..49
+          MUT_KW@49..52
+          WHITESPACE@52..53
+          PATH_TYPE@53..54
+            PATH@53..54
+              PATH_SEGMENT@53..54
+                NAME_REF@53..54
+                  IDENT@53..54 "S"
+      COMMA@54..55
+      WHITESPACE@55..56
+      PARAM@56..72
+        IDENT_PAT@56..62
+          NAME@56..62
+            IDENT@56..62 "tokens"
+        COLON@62..63
+        WHITESPACE@63..64
+        REF_TYPE@64..72
+          AMP@64..65
+          SLICE_TYPE@65..72
+            L_BRACK@65..66
+            PATH_TYPE@66..71
+              PATH@66..71
+                PATH_SEGMENT@66..71
+                  NAME_REF@66..71
+                    IDENT@66..71 "Token"
+            R_BRACK@71..72
+      COMMA@72..73
+      WHITESPACE@73..74
+      PARAM@74..92
+        IDENT_PAT@74..80
+          NAME@74..80
+            IDENT@74..80 "events"
+        COLON@80..81
+        WHITESPACE@81..82
+        PATH_TYPE@82..92
+          PATH@82..92
+            PATH_SEGMENT@82..92
+              NAME_REF@82..85
+                IDENT@82..85 "Vec"
+              GENERIC_ARG_LIST@85..92
+                L_ANGLE@85..86
+                TYPE_ARG@86..91
+                  PATH_TYPE@86..91
+                    PATH@86..91
+                      PATH_SEGMENT@86..91
+                        NAME_REF@86..91
+                          IDENT@86..91 "Event"
+                R_ANGLE@91..92
+      R_PAREN@92..93
+    WHITESPACE@93..94
+    BLOCK_EXPR@94..389
+      L_CURLY@94..95
+      WHITESPACE@95..100
+      LET_STMT@100..125
+        LET_KW@100..103
+        WHITESPACE@103..104
+        IDENT_PAT@104..120
+          MUT_KW@104..107
+          WHITESPACE@107..108
+          NAME@108..120
+            IDENT@108..120 "next_tok_idx"
+        WHITESPACE@120..121
+        EQ@121..122
+        WHITESPACE@122..123
+        LITERAL@123..124
+          INT_NUMBER@123..124 "0"
+        SEMICOLON@124..125
+      WHITESPACE@125..130
+      LET_STMT@130..389
+        LET_KW@130..133
+        WHITESPACE@133..134
+        IDENT_PAT@134..140
+          NAME@134..140
+            IDENT@134..140 "eat_ws"
+        WHITESPACE@140..141
+        EQ@141..142
+        WHITESPACE@142..143
+        CLOSURE_EXPR@143..389
+          PARAM_LIST@143..388
+            PIPE@143..144
+            PARAM@144..159
+              IDENT_PAT@144..147
+                NAME@144..147
+                  IDENT@144..147 "idx"
+              COLON@147..148
+              WHITESPACE@148..149
+              REF_TYPE@149..159
+                AMP@149..150
+                MUT_KW@150..153
+                WHITESPACE@153..154
+                PATH_TYPE@154..159
+                  PATH@154..159
+                    PATH_SEGMENT@154..159
+                      NAME_REF@154..159
+                        IDENT@154..159 "usize"
+            COMMA@159..160
+            WHITESPACE@160..161
+            PARAM@161..167
+              REF_PAT@161..167
+                AMP@161..162
+                MUT_KW@162..165
+                WHITESPACE@165..166
+                err: `expected pattern`
+                ERROR@166..167
+                  PIPE@166..167
+                  err: `expected COMMA`
+            WHITESPACE@167..168
+            err: `expected pattern`
+            PARAM@168..169
+              ERROR@168..169
+                L_CURLY@168..169
+                err: `expected COMMA`
+            WHITESPACE@169..178
+            err: `expected pattern`
+            PARAM@178..183
+              ERROR@178..183
+                WHILE_KW@178..183
+                err: `expected COMMA`
+            WHITESPACE@183..184
+            err: `expected pattern`
+            PARAM@184..187
+              ERROR@184..187
+                LET_KW@184..187
+                err: `expected COMMA`
+            WHITESPACE@187..188
+            PARAM@188..199
+              TUPLE_STRUCT_PAT@188..199
+                PATH@188..192
+                  PATH_SEGMENT@188..192
+                    NAME_REF@188..192
+                      IDENT@188..192 "Some"
+                L_PAREN@192..193
+                IDENT_PAT@193..198
+                  NAME@193..198
+                    IDENT@193..198 "token"
+                R_PAREN@198..199
+                err: `expected COMMA`
+            WHITESPACE@199..200
+            err: `expected pattern`
+            PARAM@200..201
+              ERROR@200..201
+                EQ@200..201
+                err: `expected COMMA`
+            WHITESPACE@201..202
+            PARAM@202..208
+              IDENT_PAT@202..208
+                NAME@202..208
+                  IDENT@202..208 "tokens"
+                  err: `expected COMMA`
+                  err: `expected pattern`
+            PARAM@208..209
+              ERROR@208..209
+                DOT@208..209
+                err: `expected COMMA`
+            PARAM@209..218
+              TUPLE_STRUCT_PAT@209..218
+                PATH@209..212
+                  PATH_SEGMENT@209..212
+                    NAME_REF@209..212
+                      IDENT@209..212 "get"
+                L_PAREN@212..213
+                err: `expected pattern`
+                ERROR@213..214
+                  STAR@213..214
+                  err: `expected COMMA`
+                IDENT_PAT@214..217
+                  NAME@214..217
+                    IDENT@214..217 "idx"
+                R_PAREN@217..218
+                err: `expected COMMA`
+            WHITESPACE@218..219
+            err: `expected pattern`
+            PARAM@219..220
+              ERROR@219..220
+                L_CURLY@219..220
+                err: `expected COMMA`
+            WHITESPACE@220..233
+            err: `expected pattern`
+            PARAM@233..235
+              ERROR@233..235
+                IF_KW@233..235
+                err: `expected COMMA`
+            WHITESPACE@235..236
+            err: `expected pattern`
+            PARAM@236..237
+              ERROR@236..237
+                BANG@236..237
+                err: `expected COMMA`
+            PARAM@237..242
+              IDENT_PAT@237..242
+                NAME@237..242
+                  IDENT@237..242 "token"
+                  err: `expected COMMA`
+                  err: `expected pattern`
+            PARAM@242..243
+              ERROR@242..243
+                DOT@242..243
+                err: `expected COMMA`
+            PARAM@243..247
+              IDENT_PAT@243..247
+                NAME@243..247
+                  IDENT@243..247 "kind"
+                  err: `expected COMMA`
+                  err: `expected pattern`
+            PARAM@247..248
+              ERROR@247..248
+                DOT@247..248
+                err: `expected COMMA`
+            PARAM@248..259
+              TUPLE_STRUCT_PAT@248..259
+                PATH@248..257
+                  PATH_SEGMENT@248..257
+                    NAME_REF@248..257
+                      IDENT@248..257 "is_trivia"
+                L_PAREN@257..258
+                R_PAREN@258..259
+                err: `expected COMMA`
+            WHITESPACE@259..260
+            err: `expected pattern`
+            PARAM@260..261
+              ERROR@260..261
+                L_CURLY@260..261
+                err: `expected COMMA`
+            WHITESPACE@261..278
+            PARAM@278..283
+              IDENT_PAT@278..283
+                NAME@278..283
+                  IDENT@278..283 "break"
+                  err: `expected COMMA`
+                  err: `expected pattern`
+            PARAM@283..284
+              ERROR@283..284
+                SEMICOLON@283..284
+                err: `expected COMMA`
+            WHITESPACE@284..297
+            err: `expected pattern`
+            PARAM@297..298
+              ERROR@297..298
+                R_CURLY@297..298
+                err: `expected COMMA`
+            WHITESPACE@298..311
+            PARAM@311..318
+              IDENT_PAT@311..318
+                NAME@311..318
+                  IDENT@311..318 "builder"
+                  err: `expected COMMA`
+                  err: `expected pattern`
+            PARAM@318..319
+              ERROR@318..319
+                DOT@318..319
+                err: `expected COMMA`
+            PARAM@319..346
+              TUPLE_STRUCT_PAT@319..346
+                PATH@319..323
+                  PATH_SEGMENT@319..323
+                    NAME_REF@319..323
+                      IDENT@319..323 "leaf"
+                L_PAREN@323..324
+                IDENT_PAT@324..329
+                  NAME@324..329
+                    IDENT@324..329 "token"
+                    err: `expected COMMA`
+                    err: `expected pattern`
+                ERROR@329..330
+                  DOT@329..330
+                  err: `expected COMMA`
+                IDENT_PAT@330..334
+                  NAME@330..334
+                    IDENT@330..334 "kind"
+                COMMA@334..335
+                WHITESPACE@335..336
+                IDENT_PAT@336..341
+                  NAME@336..341
+                    IDENT@336..341 "token"
+                    err: `expected COMMA`
+                    err: `expected pattern`
+                ERROR@341..342
+                  DOT@341..342
+                  err: `expected COMMA`
+                IDENT_PAT@342..345
+                  NAME@342..345
+                    IDENT@342..345 "len"
+                R_PAREN@345..346
+                err: `expected COMMA`
+                err: `expected pattern`
+            PARAM@346..347
+              ERROR@346..347
+                SEMICOLON@346..347
+                err: `expected COMMA`
+            WHITESPACE@347..360
+            err: `expected pattern`
+            PARAM@360..361
+              ERROR@360..361
+                STAR@360..361
+                err: `expected COMMA`
+            PARAM@361..364
+              IDENT_PAT@361..364
+                NAME@361..364
+                  IDENT@361..364 "idx"
+                  err: `expected COMMA`
+            WHITESPACE@364..365
+            err: `expected pattern`
+            PARAM@365..366
+              ERROR@365..366
+                PLUS@365..366
+                err: `expected COMMA`
+                err: `expected pattern`
+            PARAM@366..367
+              ERROR@366..367
+                EQ@366..367
+                err: `expected COMMA`
+            WHITESPACE@367..368
+            PARAM@368..369
+              LITERAL@368..369
+                INT_NUMBER@368..369 "1"
+                err: `expected COMMA`
+            WHITESPACE@369..378
+            err: `expected pattern`
+            PARAM@378..379
+              ERROR@378..379
+                R_CURLY@378..379
+                err: `expected COMMA`
+            WHITESPACE@379..384
+            err: `expected pattern`
+            PARAM@384..385
+              ERROR@384..385
+                R_CURLY@384..385
+                err: `expected COMMA`
+                err: `expected pattern`
+            PARAM@385..386
+              ERROR@385..386
+                SEMICOLON@385..386
+                err: `expected COMMA`
+            WHITESPACE@386..387
+            err: `expected pattern`
+            PARAM@387..388
+              ERROR@387..388
+                R_CURLY@387..388
+                err: `expected COMMA`
+                err: `expected PIPE`
+          WHITESPACE@388..389
+          err: `expected expression`
+          err: `expected SEMI`
+          err: `expected R_CURLY`
+          ERROR@389..389
diff --git a/crates/syntax/test_data/parser/err/0013_invalid_type.rast b/crates/syntax/test_data/parser/err/0013_invalid_type.rast
new file mode 100644
index 00000000000..f48ab6e7124
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0013_invalid_type.rast
@@ -0,0 +1,89 @@
+SOURCE_FILE@0..86
+  STRUCT@0..72
+    VISIBILITY@0..3
+      PUB_KW@0..3 "pub"
+    WHITESPACE@3..4 " "
+    STRUCT_KW@4..10 "struct"
+    WHITESPACE@10..11 " "
+    NAME@11..16
+      IDENT@11..16 "Cache"
+    TUPLE_FIELD_LIST@16..72
+      L_PAREN@16..17 "("
+      WHITESPACE@17..22 "\n    "
+      TUPLE_FIELD@22..68
+        PATH_TYPE@22..68
+          PATH@22..68
+            PATH_SEGMENT@22..68
+              NAME_REF@22..29
+                IDENT@22..29 "RefCell"
+              GENERIC_ARG_LIST@29..68
+                L_ANGLE@29..30 "<"
+                TYPE_ARG@30..68
+                  PATH_TYPE@30..68
+                    PATH@30..68
+                      PATH_SEGMENT@30..68
+                        NAME_REF@30..37
+                          IDENT@30..37 "HashMap"
+                        GENERIC_ARG_LIST@37..68
+                          L_ANGLE@37..38 "<"
+                          WHITESPACE@38..47 "\n        "
+                          TYPE_ARG@47..53
+                            PATH_TYPE@47..53
+                              PATH@47..53
+                                PATH_SEGMENT@47..53
+                                  NAME_REF@47..53
+                                    IDENT@47..53 "TypeId"
+                          COMMA@53..54 ","
+                          WHITESPACE@54..63 "\n        "
+                          TYPE_ARG@63..68
+                            PATH_TYPE@63..68
+                              PATH@63..68
+                                PATH_SEGMENT@63..68
+                                  NAME_REF@63..66
+                                    IDENT@63..66 "Box"
+                                  GENERIC_ARG_LIST@66..68
+                                    L_ANGLE@66..67 "<"
+                                    TYPE_ARG@67..68
+                                      ERROR@67..68
+                                        AT@67..68 "@"
+      WHITESPACE@68..69 " "
+      TUPLE_FIELD@69..72
+        PATH_TYPE@69..72
+          PATH@69..72
+            PATH_SEGMENT@69..72
+              NAME_REF@69..72
+                IDENT@69..72 "Any"
+      ERROR@72..72
+  ERROR@72..73
+    R_ANGLE@72..73 ">"
+  ERROR@73..74
+    COMMA@73..74 ","
+  WHITESPACE@74..79 "\n    "
+  ERROR@79..80
+    R_ANGLE@79..80 ">"
+  ERROR@80..81
+    R_ANGLE@80..81 ">"
+  WHITESPACE@81..82 "\n"
+  ERROR@82..83
+    R_PAREN@82..83 ")"
+  ERROR@83..84
+    SEMICOLON@83..84 ";"
+  WHITESPACE@84..86 "\n\n"
+error 67..67: expected type
+error 68..68: expected COMMA
+error 68..68: expected R_ANGLE
+error 68..68: expected COMMA
+error 68..68: expected R_ANGLE
+error 68..68: expected COMMA
+error 68..68: expected R_ANGLE
+error 68..68: expected COMMA
+error 72..72: expected COMMA
+error 72..72: expected a type
+error 72..72: expected R_PAREN
+error 72..72: expected SEMICOLON
+error 72..72: expected an item
+error 73..73: expected an item
+error 79..79: expected an item
+error 80..80: expected an item
+error 82..82: expected an item
+error 83..83: expected an item
diff --git a/crates/syntax/test_data/parser/err/0013_invalid_type.rs b/crates/syntax/test_data/parser/err/0013_invalid_type.rs
new file mode 100644
index 00000000000..20dde3bc30f
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0013_invalid_type.rs
@@ -0,0 +1,7 @@
+pub struct Cache(
+    RefCell<HashMap<
+        TypeId,
+        Box<@ Any>,
+    >>
+);
+
diff --git a/crates/syntax/test_data/parser/err/0014_where_no_bounds.rast b/crates/syntax/test_data/parser/err/0014_where_no_bounds.rast
new file mode 100644
index 00000000000..a1f39b22a52
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0014_where_no_bounds.rast
@@ -0,0 +1,31 @@
+SOURCE_FILE@0..23
+  FN@0..22
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    GENERIC_PARAM_LIST@6..9
+      L_ANGLE@6..7 "<"
+      TYPE_PARAM@7..8
+        NAME@7..8
+          IDENT@7..8 "T"
+      R_ANGLE@8..9 ">"
+    PARAM_LIST@9..11
+      L_PAREN@9..10 "("
+      R_PAREN@10..11 ")"
+    WHITESPACE@11..12 " "
+    WHERE_CLAUSE@12..19
+      WHERE_KW@12..17 "where"
+      WHITESPACE@17..18 " "
+      WHERE_PRED@18..19
+        PATH_TYPE@18..19
+          PATH@18..19
+            PATH_SEGMENT@18..19
+              NAME_REF@18..19
+                IDENT@18..19 "T"
+    WHITESPACE@19..20 " "
+    BLOCK_EXPR@20..22
+      L_CURLY@20..21 "{"
+      R_CURLY@21..22 "}"
+  WHITESPACE@22..23 "\n"
+error 19..19: expected colon
diff --git a/crates/syntax/test_data/parser/err/0014_where_no_bounds.rs b/crates/syntax/test_data/parser/err/0014_where_no_bounds.rs
new file mode 100644
index 00000000000..75c1d2f9861
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0014_where_no_bounds.rs
@@ -0,0 +1 @@
+fn foo<T>() where T {}
diff --git a/crates/syntax/test_data/parser/err/0015_curly_in_params.rast b/crates/syntax/test_data/parser/err/0015_curly_in_params.rast
new file mode 100644
index 00000000000..a3c25b450a9
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0015_curly_in_params.rast
@@ -0,0 +1,24 @@
+SOURCE_FILE@0..14
+  FN@0..7
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..7
+      L_PAREN@6..7 "("
+  ERROR@7..8
+    R_CURLY@7..8 "}"
+  ERROR@8..9
+    R_PAREN@8..9 ")"
+  WHITESPACE@9..10 " "
+  ERROR@10..13
+    L_CURLY@10..11 "{"
+    WHITESPACE@11..12 "\n"
+    R_CURLY@12..13 "}"
+  WHITESPACE@13..14 "\n"
+error 7..7: expected value parameter
+error 7..7: expected R_PAREN
+error 7..7: expected a block
+error 7..7: unmatched `}`
+error 8..8: expected an item
+error 10..10: expected an item
diff --git a/crates/syntax/test_data/parser/err/0015_curly_in_params.rs b/crates/syntax/test_data/parser/err/0015_curly_in_params.rs
new file mode 100644
index 00000000000..156e70251a1
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0015_curly_in_params.rs
@@ -0,0 +1,2 @@
+fn foo(}) {
+}
diff --git a/crates/syntax/test_data/parser/err/0016_missing_semi.rast b/crates/syntax/test_data/parser/err/0016_missing_semi.rast
new file mode 100644
index 00000000000..66157c3dce9
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0016_missing_semi.rast
@@ -0,0 +1,43 @@
+SOURCE_FILE@0..56
+  FN@0..55
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..55
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..38
+        CALL_EXPR@15..38
+          PATH_EXPR@15..18
+            PATH@15..18
+              PATH_SEGMENT@15..18
+                NAME_REF@15..18
+                  IDENT@15..18 "foo"
+          ARG_LIST@18..38
+            L_PAREN@18..19 "("
+            WHITESPACE@19..28 "\n        "
+            LITERAL@28..29
+              INT_NUMBER@28..29 "1"
+            COMMA@29..30 ","
+            WHITESPACE@30..31 " "
+            LITERAL@31..32
+              INT_NUMBER@31..32 "2"
+            WHITESPACE@32..37 "\n    "
+            R_PAREN@37..38 ")"
+      WHITESPACE@38..43 "\n    "
+      EXPR_STMT@43..53
+        RETURN_EXPR@43..52
+          RETURN_KW@43..49 "return"
+          WHITESPACE@49..50 " "
+          LITERAL@50..52
+            INT_NUMBER@50..52 "92"
+        SEMICOLON@52..53 ";"
+      WHITESPACE@53..54 "\n"
+      R_CURLY@54..55 "}"
+  WHITESPACE@55..56 "\n"
+error 38..38: expected SEMICOLON
diff --git a/crates/syntax/test_data/parser/err/0016_missing_semi.rs b/crates/syntax/test_data/parser/err/0016_missing_semi.rs
new file mode 100644
index 00000000000..9ae85768619
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0016_missing_semi.rs
@@ -0,0 +1,6 @@
+fn foo() {
+    foo(
+        1, 2
+    )
+    return 92;
+}
diff --git a/crates/syntax/test_data/parser/err/0017_incomplete_binexpr.rast b/crates/syntax/test_data/parser/err/0017_incomplete_binexpr.rast
new file mode 100644
index 00000000000..fe094f61c17
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0017_incomplete_binexpr.rast
@@ -0,0 +1,46 @@
+SOURCE_FILE@0..47
+  FN@0..46
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..16
+      L_PAREN@6..7 "("
+      PARAM@7..15
+        IDENT_PAT@7..10
+          NAME@7..10
+            IDENT@7..10 "foo"
+        COLON@10..11 ":"
+        WHITESPACE@11..12 " "
+        PATH_TYPE@12..15
+          PATH@12..15
+            PATH_SEGMENT@12..15
+              NAME_REF@12..15
+                IDENT@12..15 "i32"
+      R_PAREN@15..16 ")"
+    WHITESPACE@16..17 " "
+    BLOCK_EXPR@17..46
+      L_CURLY@17..18 "{"
+      WHITESPACE@18..23 "\n    "
+      LET_STMT@23..36
+        LET_KW@23..26 "let"
+        WHITESPACE@26..27 " "
+        IDENT_PAT@27..30
+          NAME@27..30
+            IDENT@27..30 "bar"
+        WHITESPACE@30..31 " "
+        EQ@31..32 "="
+        WHITESPACE@32..33 " "
+        LITERAL@33..35
+          INT_NUMBER@33..35 "92"
+        SEMICOLON@35..36 ";"
+      WHITESPACE@36..41 "\n    "
+      BIN_EXPR@41..44
+        LITERAL@41..42
+          INT_NUMBER@41..42 "1"
+        WHITESPACE@42..43 " "
+        PLUS@43..44 "+"
+      WHITESPACE@44..45 "\n"
+      R_CURLY@45..46 "}"
+  WHITESPACE@46..47 "\n"
+error 44..44: expected expression
diff --git a/crates/syntax/test_data/parser/err/0017_incomplete_binexpr.rs b/crates/syntax/test_data/parser/err/0017_incomplete_binexpr.rs
new file mode 100644
index 00000000000..17bd4977777
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0017_incomplete_binexpr.rs
@@ -0,0 +1,4 @@
+fn foo(foo: i32) {
+    let bar = 92;
+    1 +
+}
diff --git a/crates/syntax/test_data/parser/err/0018_incomplete_fn.rast b/crates/syntax/test_data/parser/err/0018_incomplete_fn.rast
new file mode 100644
index 00000000000..72939fc981a
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0018_incomplete_fn.rast
@@ -0,0 +1,131 @@
+SOURCE_FILE@0..183
+  IMPL@0..182
+    IMPL_KW@0..4 "impl"
+    WHITESPACE@4..5 " "
+    PATH_TYPE@5..13
+      PATH@5..13
+        PATH_SEGMENT@5..13
+          NAME_REF@5..13
+            IDENT@5..13 "FnScopes"
+    WHITESPACE@13..14 " "
+    ASSOC_ITEM_LIST@14..182
+      L_CURLY@14..15 "{"
+      WHITESPACE@15..20 "\n    "
+      FN@20..161
+        FN_KW@20..22 "fn"
+        WHITESPACE@22..23 " "
+        NAME@23..32
+          IDENT@23..32 "new_scope"
+        PARAM_LIST@32..35
+          L_PAREN@32..33 "("
+          PARAM@33..34
+            REF_PAT@33..34
+              AMP@33..34 "&"
+          R_PAREN@34..35 ")"
+        WHITESPACE@35..36 " "
+        RET_TYPE@36..46
+          THIN_ARROW@36..38 "->"
+          WHITESPACE@38..39 " "
+          PATH_TYPE@39..46
+            PATH@39..46
+              PATH_SEGMENT@39..46
+                NAME_REF@39..46
+                  IDENT@39..46 "ScopeId"
+        WHITESPACE@46..47 " "
+        BLOCK_EXPR@47..161
+          L_CURLY@47..48 "{"
+          WHITESPACE@48..57 "\n        "
+          LET_STMT@57..85
+            LET_KW@57..60 "let"
+            WHITESPACE@60..61 " "
+            IDENT_PAT@61..64
+              NAME@61..64
+                IDENT@61..64 "res"
+            WHITESPACE@64..65 " "
+            EQ@65..66 "="
+            WHITESPACE@66..67 " "
+            METHOD_CALL_EXPR@67..84
+              FIELD_EXPR@67..78
+                PATH_EXPR@67..71
+                  PATH@67..71
+                    PATH_SEGMENT@67..71
+                      SELF_KW@67..71 "self"
+                DOT@71..72 "."
+                NAME_REF@72..78
+                  IDENT@72..78 "scopes"
+              DOT@78..79 "."
+              NAME_REF@79..82
+                IDENT@79..82 "len"
+              ARG_LIST@82..84
+                L_PAREN@82..83 "("
+                R_PAREN@83..84 ")"
+            SEMICOLON@84..85 ";"
+          WHITESPACE@85..94 "\n        "
+          METHOD_CALL_EXPR@94..155
+            FIELD_EXPR@94..105
+              PATH_EXPR@94..98
+                PATH@94..98
+                  PATH_SEGMENT@94..98
+                    SELF_KW@94..98 "self"
+              DOT@98..99 "."
+              NAME_REF@99..105
+                IDENT@99..105 "scopes"
+            DOT@105..106 "."
+            NAME_REF@106..110
+              IDENT@106..110 "push"
+            ARG_LIST@110..155
+              L_PAREN@110..111 "("
+              RECORD_EXPR@111..154
+                PATH@111..120
+                  PATH_SEGMENT@111..120
+                    NAME_REF@111..120
+                      IDENT@111..120 "ScopeData"
+                WHITESPACE@120..121 " "
+                RECORD_EXPR_FIELD_LIST@121..154
+                  L_CURLY@121..122 "{"
+                  WHITESPACE@122..123 " "
+                  RECORD_EXPR_FIELD@123..135
+                    NAME_REF@123..129
+                      IDENT@123..129 "parent"
+                    COLON@129..130 ":"
+                    WHITESPACE@130..131 " "
+                    PATH_EXPR@131..135
+                      PATH@131..135
+                        PATH_SEGMENT@131..135
+                          NAME_REF@131..135
+                            IDENT@131..135 "None"
+                  COMMA@135..136 ","
+                  WHITESPACE@136..137 " "
+                  RECORD_EXPR_FIELD@137..152
+                    NAME_REF@137..144
+                      IDENT@137..144 "entries"
+                    COLON@144..145 ":"
+                    WHITESPACE@145..146 " "
+                    MACRO_CALL@146..152
+                      PATH@146..149
+                        PATH_SEGMENT@146..149
+                          NAME_REF@146..149
+                            IDENT@146..149 "vec"
+                      BANG@149..150 "!"
+                      TOKEN_TREE@150..152
+                        L_BRACK@150..151 "["
+                        R_BRACK@151..152 "]"
+                  WHITESPACE@152..153 " "
+                  R_CURLY@153..154 "}"
+              R_PAREN@154..155 ")"
+          WHITESPACE@155..160 "\n    "
+          R_CURLY@160..161 "}"
+      WHITESPACE@161..167 "\n\n    "
+      FN@167..180
+        FN_KW@167..169 "fn"
+        WHITESPACE@169..170 " "
+        NAME@170..180
+          IDENT@170..180 "set_parent"
+      WHITESPACE@180..181 "\n"
+      R_CURLY@181..182 "}"
+  WHITESPACE@182..183 "\n"
+error 34..34: expected pattern
+error 34..34: expected COLON
+error 34..34: expected type
+error 180..180: expected function arguments
+error 180..180: expected a block
diff --git a/crates/syntax/test_data/parser/err/0018_incomplete_fn.rs b/crates/syntax/test_data/parser/err/0018_incomplete_fn.rs
new file mode 100644
index 00000000000..fe604006c9e
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0018_incomplete_fn.rs
@@ -0,0 +1,8 @@
+impl FnScopes {
+    fn new_scope(&) -> ScopeId {
+        let res = self.scopes.len();
+        self.scopes.push(ScopeData { parent: None, entries: vec![] })
+    }
+
+    fn set_parent
+}
diff --git a/crates/syntax/test_data/parser/err/0019_let_recover.rast b/crates/syntax/test_data/parser/err/0019_let_recover.rast
new file mode 100644
index 00000000000..72c05bd964a
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0019_let_recover.rast
@@ -0,0 +1,103 @@
+SOURCE_FILE@0..139
+  FN@0..138
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..138
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      LET_STMT@15..24
+        LET_KW@15..18 "let"
+        WHITESPACE@18..19 " "
+        IDENT_PAT@19..22
+          NAME@19..22
+            IDENT@19..22 "foo"
+        WHITESPACE@22..23 " "
+        EQ@23..24 "="
+      WHITESPACE@24..29 "\n    "
+      LET_STMT@29..41
+        LET_KW@29..32 "let"
+        WHITESPACE@32..33 " "
+        IDENT_PAT@33..36
+          NAME@33..36
+            IDENT@33..36 "bar"
+        WHITESPACE@36..37 " "
+        EQ@37..38 "="
+        WHITESPACE@38..39 " "
+        LITERAL@39..40
+          INT_NUMBER@39..40 "1"
+        SEMICOLON@40..41 ";"
+      WHITESPACE@41..46 "\n    "
+      LET_STMT@46..49
+        LET_KW@46..49 "let"
+      WHITESPACE@49..54 "\n    "
+      LET_STMT@54..67
+        LET_KW@54..57 "let"
+        WHITESPACE@57..58 " "
+        IDENT_PAT@58..61
+          NAME@58..61
+            IDENT@58..61 "baz"
+        WHITESPACE@61..62 " "
+        EQ@62..63 "="
+        WHITESPACE@63..64 " "
+        LITERAL@64..66
+          INT_NUMBER@64..66 "92"
+        SEMICOLON@66..67 ";"
+      WHITESPACE@67..72 "\n    "
+      LET_STMT@72..75
+        LET_KW@72..75 "let"
+      WHITESPACE@75..80 "\n    "
+      EXPR_STMT@80..90
+        IF_EXPR@80..90
+          IF_KW@80..82 "if"
+          WHITESPACE@82..83 " "
+          CONDITION@83..87
+            LITERAL@83..87
+              TRUE_KW@83..87 "true"
+          WHITESPACE@87..88 " "
+          BLOCK_EXPR@88..90
+            L_CURLY@88..89 "{"
+            R_CURLY@89..90 "}"
+      WHITESPACE@90..95 "\n    "
+      LET_STMT@95..98
+        LET_KW@95..98 "let"
+      WHITESPACE@98..103 "\n    "
+      EXPR_STMT@103..116
+        WHILE_EXPR@103..116
+          WHILE_KW@103..108 "while"
+          WHITESPACE@108..109 " "
+          CONDITION@109..113
+            LITERAL@109..113
+              TRUE_KW@109..113 "true"
+          WHITESPACE@113..114 " "
+          BLOCK_EXPR@114..116
+            L_CURLY@114..115 "{"
+            R_CURLY@115..116 "}"
+      WHITESPACE@116..121 "\n    "
+      LET_STMT@121..124
+        LET_KW@121..124 "let"
+      WHITESPACE@124..129 "\n    "
+      LOOP_EXPR@129..136
+        LOOP_KW@129..133 "loop"
+        WHITESPACE@133..134 " "
+        BLOCK_EXPR@134..136
+          L_CURLY@134..135 "{"
+          R_CURLY@135..136 "}"
+      WHITESPACE@136..137 "\n"
+      R_CURLY@137..138 "}"
+  WHITESPACE@138..139 "\n"
+error 24..24: expected expression
+error 24..24: expected SEMICOLON
+error 49..49: expected pattern
+error 49..49: expected SEMICOLON
+error 75..75: expected pattern
+error 75..75: expected SEMICOLON
+error 98..98: expected pattern
+error 98..98: expected SEMICOLON
+error 124..124: expected pattern
+error 124..124: expected SEMICOLON
diff --git a/crates/syntax/test_data/parser/err/0019_let_recover.rs b/crates/syntax/test_data/parser/err/0019_let_recover.rs
new file mode 100644
index 00000000000..48bf3d68bd3
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0019_let_recover.rs
@@ -0,0 +1,12 @@
+fn foo() {
+    let foo =
+    let bar = 1;
+    let
+    let baz = 92;
+    let
+    if true {}
+    let
+    while true {}
+    let
+    loop {}
+}
diff --git a/crates/syntax/test_data/parser/err/0020_fn_recover.rast b/crates/syntax/test_data/parser/err/0020_fn_recover.rast
new file mode 100644
index 00000000000..6f6feba5a83
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0020_fn_recover.rast
@@ -0,0 +1,20 @@
+SOURCE_FILE@0..16
+  FN@0..2
+    FN_KW@0..2 "fn"
+  WHITESPACE@2..4 "\n\n"
+  FN@4..15
+    FN_KW@4..6 "fn"
+    WHITESPACE@6..7 " "
+    NAME@7..10
+      IDENT@7..10 "foo"
+    PARAM_LIST@10..12
+      L_PAREN@10..11 "("
+      R_PAREN@11..12 ")"
+    WHITESPACE@12..13 " "
+    BLOCK_EXPR@13..15
+      L_CURLY@13..14 "{"
+      R_CURLY@14..15 "}"
+  WHITESPACE@15..16 "\n"
+error 2..2: expected a name
+error 2..2: expected function arguments
+error 2..2: expected a block
diff --git a/crates/syntax/test_data/parser/err/0020_fn_recover.rs b/crates/syntax/test_data/parser/err/0020_fn_recover.rs
new file mode 100644
index 00000000000..3393b668b41
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0020_fn_recover.rs
@@ -0,0 +1,3 @@
+fn
+
+fn foo() {}
diff --git a/crates/syntax/test_data/parser/err/0021_incomplete_param.rast b/crates/syntax/test_data/parser/err/0021_incomplete_param.rast
new file mode 100644
index 00000000000..b3284553770
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0021_incomplete_param.rast
@@ -0,0 +1,34 @@
+SOURCE_FILE@0..22
+  FN@0..21
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..17
+      L_PAREN@6..7 "("
+      PARAM@7..13
+        IDENT_PAT@7..8
+          NAME@7..8
+            IDENT@7..8 "x"
+        COLON@8..9 ":"
+        WHITESPACE@9..10 " "
+        PATH_TYPE@10..13
+          PATH@10..13
+            PATH_SEGMENT@10..13
+              NAME_REF@10..13
+                IDENT@10..13 "i32"
+      COMMA@13..14 ","
+      WHITESPACE@14..15 " "
+      PARAM@15..16
+        IDENT_PAT@15..16
+          NAME@15..16
+            IDENT@15..16 "y"
+      R_PAREN@16..17 ")"
+    WHITESPACE@17..18 " "
+    BLOCK_EXPR@18..21
+      L_CURLY@18..19 "{"
+      WHITESPACE@19..20 "\n"
+      R_CURLY@20..21 "}"
+  WHITESPACE@21..22 "\n"
+error 16..16: expected COLON
+error 16..16: expected type
diff --git a/crates/syntax/test_data/parser/err/0021_incomplete_param.rs b/crates/syntax/test_data/parser/err/0021_incomplete_param.rs
new file mode 100644
index 00000000000..7a6c264f6d7
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0021_incomplete_param.rs
@@ -0,0 +1,2 @@
+fn foo(x: i32, y) {
+}
diff --git a/crates/syntax/test_data/parser/err/0022_bad_exprs.rast b/crates/syntax/test_data/parser/err/0022_bad_exprs.rast
new file mode 100644
index 00000000000..71fb19783ad
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0022_bad_exprs.rast
@@ -0,0 +1,180 @@
+SOURCE_FILE@0..112
+  FN@0..33
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..4
+      IDENT@3..4 "a"
+    PARAM_LIST@4..6
+      L_PAREN@4..5 "("
+      R_PAREN@5..6 ")"
+    WHITESPACE@6..7 " "
+    BLOCK_EXPR@7..33
+      L_CURLY@7..8 "{"
+      WHITESPACE@8..9 " "
+      EXPR_STMT@9..17
+        ARRAY_EXPR@9..17
+          L_BRACK@9..10 "["
+          LITERAL@10..11
+            INT_NUMBER@10..11 "1"
+          COMMA@11..12 ","
+          WHITESPACE@12..13 " "
+          LITERAL@13..14
+            INT_NUMBER@13..14 "2"
+          COMMA@14..15 ","
+          WHITESPACE@15..16 " "
+          ERROR@16..17
+            AT@16..17 "@"
+      EXPR_STMT@17..18
+        ERROR@17..18
+          COMMA@17..18 ","
+      WHITESPACE@18..19 " "
+      STRUCT@19..26
+        STRUCT_KW@19..25 "struct"
+        ERROR@25..26
+          COMMA@25..26 ","
+      WHITESPACE@26..27 " "
+      LET_STMT@27..31
+        LET_KW@27..30 "let"
+        ERROR@30..31
+          R_BRACK@30..31 "]"
+      WHITESPACE@31..32 " "
+      R_CURLY@32..33 "}"
+  WHITESPACE@33..34 "\n"
+  FN@34..68
+    FN_KW@34..36 "fn"
+    WHITESPACE@36..37 " "
+    NAME@37..38
+      IDENT@37..38 "b"
+    PARAM_LIST@38..40
+      L_PAREN@38..39 "("
+      R_PAREN@39..40 ")"
+    WHITESPACE@40..41 " "
+    BLOCK_EXPR@41..68
+      L_CURLY@41..42 "{"
+      WHITESPACE@42..43 " "
+      EXPR_STMT@43..54
+        CALL_EXPR@43..54
+          PATH_EXPR@43..46
+            PATH@43..46
+              PATH_SEGMENT@43..46
+                NAME_REF@43..46
+                  IDENT@43..46 "foo"
+          ARG_LIST@46..54
+            L_PAREN@46..47 "("
+            LITERAL@47..48
+              INT_NUMBER@47..48 "1"
+            COMMA@48..49 ","
+            WHITESPACE@49..50 " "
+            LITERAL@50..51
+              INT_NUMBER@50..51 "2"
+            COMMA@51..52 ","
+            WHITESPACE@52..53 " "
+            ERROR@53..54
+              AT@53..54 "@"
+      EXPR_STMT@54..55
+        ERROR@54..55
+          COMMA@54..55 ","
+      WHITESPACE@55..56 " "
+      IMPL@56..60
+        IMPL_KW@56..60 "impl"
+      EXPR_STMT@60..61
+        ERROR@60..61
+          COMMA@60..61 ","
+      WHITESPACE@61..62 " "
+      LET_STMT@62..65
+        LET_KW@62..65 "let"
+      ERROR@65..66
+        R_PAREN@65..66 ")"
+      WHITESPACE@66..67 " "
+      R_CURLY@67..68 "}"
+  WHITESPACE@68..69 "\n"
+  FN@69..111
+    FN_KW@69..71 "fn"
+    WHITESPACE@71..72 " "
+    NAME@72..73
+      IDENT@72..73 "c"
+    PARAM_LIST@73..75
+      L_PAREN@73..74 "("
+      R_PAREN@74..75 ")"
+    WHITESPACE@75..76 " "
+    BLOCK_EXPR@76..111
+      L_CURLY@76..77 "{"
+      WHITESPACE@77..78 " "
+      EXPR_STMT@78..93
+        METHOD_CALL_EXPR@78..93
+          PATH_EXPR@78..81
+            PATH@78..81
+              PATH_SEGMENT@78..81
+                NAME_REF@78..81
+                  IDENT@78..81 "foo"
+          DOT@81..82 "."
+          NAME_REF@82..85
+            IDENT@82..85 "bar"
+          ARG_LIST@85..93
+            L_PAREN@85..86 "("
+            LITERAL@86..87
+              INT_NUMBER@86..87 "1"
+            COMMA@87..88 ","
+            WHITESPACE@88..89 " "
+            LITERAL@89..90
+              INT_NUMBER@89..90 "2"
+            COMMA@90..91 ","
+            WHITESPACE@91..92 " "
+            ERROR@92..93
+              AT@92..93 "@"
+      EXPR_STMT@93..94
+        ERROR@93..94
+          COMMA@93..94 ","
+      WHITESPACE@94..95 " "
+      EXPR_STMT@95..96
+        ERROR@95..96
+          R_BRACK@95..96 "]"
+      EXPR_STMT@96..97
+        ERROR@96..97
+          COMMA@96..97 ","
+      WHITESPACE@97..98 " "
+      TRAIT@98..104
+        TRAIT_KW@98..103 "trait"
+        ERROR@103..104
+          COMMA@103..104 ","
+      WHITESPACE@104..105 " "
+      LET_STMT@105..108
+        LET_KW@105..108 "let"
+      ERROR@108..109
+        R_PAREN@108..109 ")"
+      WHITESPACE@109..110 " "
+      R_CURLY@110..111 "}"
+  WHITESPACE@111..112 "\n"
+error 16..16: expected expression
+error 17..17: expected R_BRACK
+error 17..17: expected SEMICOLON
+error 17..17: expected expression
+error 18..18: expected SEMICOLON
+error 25..25: expected a name
+error 26..26: expected `;`, `{`, or `(`
+error 30..30: expected pattern
+error 31..31: expected SEMICOLON
+error 53..53: expected expression
+error 54..54: expected SEMICOLON
+error 54..54: expected expression
+error 55..55: expected SEMICOLON
+error 60..60: expected type
+error 60..60: expected `{`
+error 60..60: expected expression
+error 61..61: expected SEMICOLON
+error 65..65: expected pattern
+error 65..65: expected SEMICOLON
+error 65..65: expected expression
+error 92..92: expected expression
+error 93..93: expected SEMICOLON
+error 93..93: expected expression
+error 94..94: expected SEMICOLON
+error 95..95: expected expression
+error 96..96: expected SEMICOLON
+error 96..96: expected expression
+error 97..97: expected SEMICOLON
+error 103..103: expected a name
+error 104..104: expected `{`
+error 108..108: expected pattern
+error 108..108: expected SEMICOLON
+error 108..108: expected expression
diff --git a/crates/syntax/test_data/parser/err/0022_bad_exprs.rs b/crates/syntax/test_data/parser/err/0022_bad_exprs.rs
new file mode 100644
index 00000000000..cd2d493a10c
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0022_bad_exprs.rs
@@ -0,0 +1,3 @@
+fn a() { [1, 2, @, struct, let] }
+fn b() { foo(1, 2, @, impl, let) }
+fn c() { foo.bar(1, 2, @, ], trait, let) }
diff --git a/crates/syntax/test_data/parser/err/0023_mismatched_paren.rast b/crates/syntax/test_data/parser/err/0023_mismatched_paren.rast
new file mode 100644
index 00000000000..5ffefd74290
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0023_mismatched_paren.rast
@@ -0,0 +1,43 @@
+SOURCE_FILE@0..94
+  FN@0..55
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..55
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      MACRO_CALL@16..49
+        PATH@16..19
+          PATH_SEGMENT@16..19
+            NAME_REF@16..19
+              IDENT@16..19 "foo"
+        BANG@19..20 "!"
+        WHITESPACE@20..21 " "
+        TOKEN_TREE@21..49
+          L_PAREN@21..22 "("
+          WHITESPACE@22..31 "\n        "
+          IDENT@31..34 "bar"
+          COMMA@34..35 ","
+          WHITESPACE@35..36 " "
+          STRING@36..41 "\"baz\""
+          COMMA@41..42 ","
+          WHITESPACE@42..43 " "
+          INT_NUMBER@43..44 "1"
+          COMMA@44..45 ","
+          WHITESPACE@45..46 " "
+          FLOAT_NUMBER@46..49 "2.0"
+      WHITESPACE@49..54 "\n    "
+      R_CURLY@54..55 "}"
+  WHITESPACE@55..56 " "
+  COMMENT@56..91 "//~ ERROR incorrect c ..."
+  WHITESPACE@91..92 "\n"
+  ERROR@92..93
+    R_CURLY@92..93 "}"
+  WHITESPACE@93..94 "\n"
+error 49..49: unmatched `}`
+error 92..92: unmatched `}`
diff --git a/crates/syntax/test_data/parser/err/0023_mismatched_paren.rs b/crates/syntax/test_data/parser/err/0023_mismatched_paren.rs
new file mode 100644
index 00000000000..0206d563ea7
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0023_mismatched_paren.rs
@@ -0,0 +1,5 @@
+fn main() {
+    foo! (
+        bar, "baz", 1, 2.0
+    } //~ ERROR incorrect close delimiter
+}
diff --git a/crates/syntax/test_data/parser/err/0024_many_type_parens.rast b/crates/syntax/test_data/parser/err/0024_many_type_parens.rast
new file mode 100644
index 00000000000..e3be6b22e11
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0024_many_type_parens.rast
@@ -0,0 +1,319 @@
+SOURCE_FILE@0..240
+  FN@0..53
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..4
+      IDENT@3..4 "f"
+    GENERIC_PARAM_LIST@4..48
+      L_ANGLE@4..5 "<"
+      TYPE_PARAM@5..47
+        NAME@5..6
+          IDENT@5..6 "T"
+        COLON@6..7 ":"
+        WHITESPACE@7..8 " "
+        TYPE_BOUND_LIST@8..47
+          TYPE_BOUND@8..14
+            L_PAREN@8..9 "("
+            PATH_TYPE@9..13
+              PATH@9..13
+                PATH_SEGMENT@9..13
+                  NAME_REF@9..13
+                    IDENT@9..13 "Copy"
+            R_PAREN@13..14 ")"
+          WHITESPACE@14..15 " "
+          PLUS@15..16 "+"
+          WHITESPACE@16..17 " "
+          TYPE_BOUND@17..25
+            L_PAREN@17..18 "("
+            QUESTION@18..19 "?"
+            PATH_TYPE@19..24
+              PATH@19..24
+                PATH_SEGMENT@19..24
+                  NAME_REF@19..24
+                    IDENT@19..24 "Sized"
+            R_PAREN@24..25 ")"
+          WHITESPACE@25..26 " "
+          PLUS@26..27 "+"
+          WHITESPACE@27..28 " "
+          TYPE_BOUND@28..47
+            L_PAREN@28..29 "("
+            FOR_TYPE@29..46
+              FOR_KW@29..32 "for"
+              GENERIC_PARAM_LIST@32..36
+                L_ANGLE@32..33 "<"
+                LIFETIME_PARAM@33..35
+                  LIFETIME@33..35 "\'a"
+                R_ANGLE@35..36 ">"
+              WHITESPACE@36..37 " "
+              PATH_TYPE@37..46
+                PATH@37..46
+                  PATH_SEGMENT@37..46
+                    NAME_REF@37..42
+                      IDENT@37..42 "Trait"
+                    GENERIC_ARG_LIST@42..46
+                      L_ANGLE@42..43 "<"
+                      LIFETIME_ARG@43..45
+                        LIFETIME@43..45 "\'a"
+                      R_ANGLE@45..46 ">"
+            R_PAREN@46..47 ")"
+      R_ANGLE@47..48 ">"
+    PARAM_LIST@48..50
+      L_PAREN@48..49 "("
+      R_PAREN@49..50 ")"
+    WHITESPACE@50..51 " "
+    BLOCK_EXPR@51..53
+      L_CURLY@51..52 "{"
+      R_CURLY@52..53 "}"
+  WHITESPACE@53..55 "\n\n"
+  FN@55..239
+    FN_KW@55..57 "fn"
+    WHITESPACE@57..58 " "
+    NAME@58..62
+      IDENT@58..62 "main"
+    PARAM_LIST@62..64
+      L_PAREN@62..63 "("
+      R_PAREN@63..64 ")"
+    WHITESPACE@64..65 " "
+    BLOCK_EXPR@65..239
+      L_CURLY@65..66 "{"
+      WHITESPACE@66..71 "\n    "
+      LET_STMT@71..121
+        LET_KW@71..74 "let"
+        WHITESPACE@74..75 " "
+        WILDCARD_PAT@75..76
+          UNDERSCORE@75..76 "_"
+        COLON@76..77 ":"
+        WHITESPACE@77..78 " "
+        DYN_TRAIT_TYPE@78..121
+          TYPE_BOUND_LIST@78..121
+            TYPE_BOUND@78..88
+              PATH_TYPE@78..88
+                PATH@78..88
+                  PATH_SEGMENT@78..88
+                    NAME_REF@78..81
+                      IDENT@78..81 "Box"
+                    GENERIC_ARG_LIST@81..88
+                      L_ANGLE@81..82 "<"
+                      TYPE_ARG@82..88
+                        PAREN_TYPE@82..88
+                          L_PAREN@82..83 "("
+                          PATH_TYPE@83..87
+                            PATH@83..87
+                              PATH_SEGMENT@83..87
+                                NAME_REF@83..87
+                                  IDENT@83..87 "Copy"
+                          R_PAREN@87..88 ")"
+            WHITESPACE@88..89 " "
+            PLUS@89..90 "+"
+            WHITESPACE@90..91 " "
+            TYPE_BOUND@91..99
+              L_PAREN@91..92 "("
+              QUESTION@92..93 "?"
+              PATH_TYPE@93..98
+                PATH@93..98
+                  PATH_SEGMENT@93..98
+                    NAME_REF@93..98
+                      IDENT@93..98 "Sized"
+              R_PAREN@98..99 ")"
+            WHITESPACE@99..100 " "
+            PLUS@100..101 "+"
+            WHITESPACE@101..102 " "
+            TYPE_BOUND@102..121
+              L_PAREN@102..103 "("
+              FOR_TYPE@103..120
+                FOR_KW@103..106 "for"
+                GENERIC_PARAM_LIST@106..110
+                  L_ANGLE@106..107 "<"
+                  LIFETIME_PARAM@107..109
+                    LIFETIME@107..109 "\'a"
+                  R_ANGLE@109..110 ">"
+                WHITESPACE@110..111 " "
+                PATH_TYPE@111..120
+                  PATH@111..120
+                    PATH_SEGMENT@111..120
+                      NAME_REF@111..116
+                        IDENT@111..116 "Trait"
+                      GENERIC_ARG_LIST@116..120
+                        L_ANGLE@116..117 "<"
+                        LIFETIME_ARG@117..119
+                          LIFETIME@117..119 "\'a"
+                        R_ANGLE@119..120 ">"
+              R_PAREN@120..121 ")"
+      EXPR_STMT@121..123
+        ERROR@121..122
+          R_ANGLE@121..122 ">"
+        SEMICOLON@122..123 ";"
+      WHITESPACE@123..128 "\n    "
+      LET_STMT@128..141
+        LET_KW@128..131 "let"
+        WHITESPACE@131..132 " "
+        WILDCARD_PAT@132..133
+          UNDERSCORE@132..133 "_"
+        COLON@133..134 ":"
+        WHITESPACE@134..135 " "
+        PATH_TYPE@135..141
+          PATH@135..141
+            PATH_SEGMENT@135..141
+              NAME_REF@135..138
+                IDENT@135..138 "Box"
+              GENERIC_ARG_LIST@138..141
+                L_ANGLE@138..139 "<"
+                TYPE_ARG@139..141
+                  PAREN_TYPE@139..141
+                    L_PAREN@139..140 "("
+                    ERROR@140..141
+                      QUESTION@140..141 "?"
+      EXPR_STMT@141..146
+        PATH_EXPR@141..146
+          PATH@141..146
+            PATH_SEGMENT@141..146
+              NAME_REF@141..146
+                IDENT@141..146 "Sized"
+      EXPR_STMT@146..147
+        ERROR@146..147
+          R_PAREN@146..147 ")"
+      WHITESPACE@147..148 " "
+      EXPR_STMT@148..149
+        ERROR@148..149
+          PLUS@148..149 "+"
+      WHITESPACE@149..150 " "
+      EXPR_STMT@150..180
+        TUPLE_EXPR@150..180
+          L_PAREN@150..151 "("
+          FOR_EXPR@151..180
+            FOR_KW@151..154 "for"
+            PATH_PAT@154..158
+              PATH@154..158
+                PATH_SEGMENT@154..158
+                  L_ANGLE@154..155 "<"
+                  ERROR@155..157
+                    LIFETIME@155..157 "\'a"
+                  R_ANGLE@157..158 ">"
+            WHITESPACE@158..159 " "
+            BIN_EXPR@159..180
+              BIN_EXPR@159..178
+                BIN_EXPR@159..169
+                  BIN_EXPR@159..167
+                    PATH_EXPR@159..164
+                      PATH@159..164
+                        PATH_SEGMENT@159..164
+                          NAME_REF@159..164
+                            IDENT@159..164 "Trait"
+                    L_ANGLE@164..165 "<"
+                    ERROR@165..167
+                      LIFETIME@165..167 "\'a"
+                  R_ANGLE@167..168 ">"
+                  ERROR@168..169
+                    R_PAREN@168..169 ")"
+                WHITESPACE@169..170 " "
+                PLUS@170..171 "+"
+                WHITESPACE@171..172 " "
+                PAREN_EXPR@172..178
+                  L_PAREN@172..173 "("
+                  PATH_EXPR@173..177
+                    PATH@173..177
+                      PATH_SEGMENT@173..177
+                        NAME_REF@173..177
+                          IDENT@173..177 "Copy"
+                  R_PAREN@177..178 ")"
+              R_ANGLE@178..179 ">"
+              ERROR@179..180
+                SEMICOLON@179..180 ";"
+      WHITESPACE@180..185 "\n    "
+      LET_STMT@185..235
+        LET_KW@185..188 "let"
+        WHITESPACE@188..189 " "
+        WILDCARD_PAT@189..190
+          UNDERSCORE@189..190 "_"
+        COLON@190..191 ":"
+        WHITESPACE@191..192 " "
+        DYN_TRAIT_TYPE@192..235
+          TYPE_BOUND_LIST@192..235
+            TYPE_BOUND@192..215
+              PATH_TYPE@192..215
+                PATH@192..215
+                  PATH_SEGMENT@192..215
+                    NAME_REF@192..195
+                      IDENT@192..195 "Box"
+                    GENERIC_ARG_LIST@195..215
+                      L_ANGLE@195..196 "<"
+                      TYPE_ARG@196..215
+                        PAREN_TYPE@196..215
+                          L_PAREN@196..197 "("
+                          FOR_TYPE@197..214
+                            FOR_KW@197..200 "for"
+                            GENERIC_PARAM_LIST@200..204
+                              L_ANGLE@200..201 "<"
+                              LIFETIME_PARAM@201..203
+                                LIFETIME@201..203 "\'a"
+                              R_ANGLE@203..204 ">"
+                            WHITESPACE@204..205 " "
+                            PATH_TYPE@205..214
+                              PATH@205..214
+                                PATH_SEGMENT@205..214
+                                  NAME_REF@205..210
+                                    IDENT@205..210 "Trait"
+                                  GENERIC_ARG_LIST@210..214
+                                    L_ANGLE@210..211 "<"
+                                    LIFETIME_ARG@211..213
+                                      LIFETIME@211..213 "\'a"
+                                    R_ANGLE@213..214 ">"
+                          R_PAREN@214..215 ")"
+            WHITESPACE@215..216 " "
+            PLUS@216..217 "+"
+            WHITESPACE@217..218 " "
+            TYPE_BOUND@218..224
+              L_PAREN@218..219 "("
+              PATH_TYPE@219..223
+                PATH@219..223
+                  PATH_SEGMENT@219..223
+                    NAME_REF@219..223
+                      IDENT@219..223 "Copy"
+              R_PAREN@223..224 ")"
+            WHITESPACE@224..225 " "
+            PLUS@225..226 "+"
+            WHITESPACE@226..227 " "
+            TYPE_BOUND@227..235
+              L_PAREN@227..228 "("
+              QUESTION@228..229 "?"
+              PATH_TYPE@229..234
+                PATH@229..234
+                  PATH_SEGMENT@229..234
+                    NAME_REF@229..234
+                      IDENT@229..234 "Sized"
+              R_PAREN@234..235 ")"
+      EXPR_STMT@235..237
+        ERROR@235..236
+          R_ANGLE@235..236 ">"
+        SEMICOLON@236..237 ";"
+      WHITESPACE@237..238 "\n"
+      R_CURLY@238..239 "}"
+  WHITESPACE@239..240 "\n"
+error 88..88: expected COMMA
+error 88..88: expected R_ANGLE
+error 121..121: expected SEMICOLON
+error 121..121: expected expression
+error 140..140: expected type
+error 141..141: expected R_PAREN
+error 141..141: expected COMMA
+error 141..141: expected R_ANGLE
+error 141..141: expected SEMICOLON
+error 146..146: expected SEMICOLON
+error 146..146: expected expression
+error 147..147: expected SEMICOLON
+error 148..148: expected expression
+error 149..149: expected SEMICOLON
+error 155..155: expected type
+error 158..158: expected IN_KW
+error 165..165: expected expression
+error 168..168: expected expression
+error 179..179: expected expression
+error 180..180: expected a block
+error 180..180: expected COMMA
+error 180..180: expected expression
+error 180..180: expected R_PAREN
+error 180..180: expected SEMICOLON
+error 215..215: expected COMMA
+error 215..215: expected R_ANGLE
+error 235..235: expected SEMICOLON
+error 235..235: expected expression
diff --git a/crates/syntax/test_data/parser/err/0024_many_type_parens.rs b/crates/syntax/test_data/parser/err/0024_many_type_parens.rs
new file mode 100644
index 00000000000..6c2e95c0296
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0024_many_type_parens.rs
@@ -0,0 +1,7 @@
+fn f<T: (Copy) + (?Sized) + (for<'a> Trait<'a>)>() {}
+
+fn main() {
+    let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>;
+    let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Copy)>;
+    let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
+}
diff --git a/crates/syntax/test_data/parser/err/0025_nope.rast b/crates/syntax/test_data/parser/err/0025_nope.rast
new file mode 100644
index 00000000000..83fc9fe776c
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0025_nope.rast
@@ -0,0 +1,202 @@
+SOURCE_FILE@0..575
+  FN@0..574
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..574
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      ENUM@16..152
+        ENUM_KW@16..20 "enum"
+        WHITESPACE@20..21 " "
+        NAME@21..25
+          IDENT@21..25 "Test"
+        WHITESPACE@25..26 " "
+        VARIANT_LIST@26..152
+          L_CURLY@26..27 "{"
+          WHITESPACE@27..36 "\n        "
+          VARIANT@36..40
+            NAME@36..40
+              IDENT@36..40 "Var1"
+          COMMA@40..41 ","
+          WHITESPACE@41..50 "\n        "
+          VARIANT@50..62
+            NAME@50..54
+              IDENT@50..54 "Var2"
+            TUPLE_FIELD_LIST@54..62
+              L_PAREN@54..55 "("
+              TUPLE_FIELD@55..61
+                PATH_TYPE@55..61
+                  PATH@55..61
+                    PATH_SEGMENT@55..61
+                      NAME_REF@55..61
+                        IDENT@55..61 "String"
+              R_PAREN@61..62 ")"
+          COMMA@62..63 ","
+          WHITESPACE@63..72 "\n        "
+          VARIANT@72..145
+            NAME@72..76
+              IDENT@72..76 "Var3"
+            WHITESPACE@76..77 " "
+            RECORD_FIELD_LIST@77..145
+              L_CURLY@77..78 "{"
+              WHITESPACE@78..91 "\n            "
+              RECORD_FIELD@91..95
+                NAME@91..94
+                  IDENT@91..94 "abc"
+                COLON@94..95 ":"
+              WHITESPACE@95..96 " "
+              ERROR@96..98
+                L_CURLY@96..97 "{"
+                R_CURLY@97..98 "}"
+              ERROR@98..99
+                COMMA@98..99 ","
+              WHITESPACE@99..100 " "
+              COMMENT@100..135 "//~ ERROR: expected t ..."
+              WHITESPACE@135..144 "\n        "
+              R_CURLY@144..145 "}"
+          COMMA@145..146 ","
+          WHITESPACE@146..151 "\n    "
+          R_CURLY@151..152 "}"
+      WHITESPACE@152..158 "\n\n    "
+      COMMENT@158..171 "// recover..."
+      WHITESPACE@171..176 "\n    "
+      LET_STMT@176..186
+        LET_KW@176..179 "let"
+        WHITESPACE@179..180 " "
+        IDENT_PAT@180..181
+          NAME@180..181
+            IDENT@180..181 "a"
+        WHITESPACE@181..182 " "
+        EQ@182..183 "="
+        WHITESPACE@183..184 " "
+        LITERAL@184..185
+          INT_NUMBER@184..185 "1"
+        SEMICOLON@185..186 ";"
+      WHITESPACE@186..191 "\n    "
+      ENUM@191..223
+        ENUM_KW@191..195 "enum"
+        WHITESPACE@195..196 " "
+        NAME@196..201
+          IDENT@196..201 "Test2"
+        WHITESPACE@201..202 " "
+        VARIANT_LIST@202..223
+          L_CURLY@202..203 "{"
+          WHITESPACE@203..212 "\n        "
+          VARIANT@212..216
+            NAME@212..216
+              IDENT@212..216 "Fine"
+          COMMA@216..217 ","
+          WHITESPACE@217..222 "\n    "
+          R_CURLY@222..223 "}"
+      WHITESPACE@223..229 "\n\n    "
+      ENUM@229..300
+        ENUM_KW@229..233 "enum"
+        WHITESPACE@233..234 " "
+        NAME@234..239
+          IDENT@234..239 "Test3"
+        WHITESPACE@239..240 " "
+        VARIANT_LIST@240..300
+          L_CURLY@240..241 "{"
+          WHITESPACE@241..250 "\n        "
+          VARIANT@250..293
+            NAME@250..259
+              IDENT@250..259 "StillFine"
+            WHITESPACE@259..260 " "
+            RECORD_FIELD_LIST@260..293
+              L_CURLY@260..261 "{"
+              WHITESPACE@261..274 "\n            "
+              RECORD_FIELD@274..282
+                NAME@274..277
+                  IDENT@274..277 "def"
+                COLON@277..278 ":"
+                WHITESPACE@278..279 " "
+                PATH_TYPE@279..282
+                  PATH@279..282
+                    PATH_SEGMENT@279..282
+                      NAME_REF@279..282
+                        IDENT@279..282 "i32"
+              COMMA@282..283 ","
+              WHITESPACE@283..292 "\n        "
+              R_CURLY@292..293 "}"
+          COMMA@293..294 ","
+          WHITESPACE@294..299 "\n    "
+          R_CURLY@299..300 "}"
+      WHITESPACE@300..306 "\n\n    "
+      EXPR_STMT@306..459
+        BLOCK_EXPR@306..459
+          L_CURLY@306..307 "{"
+          WHITESPACE@307..316 "\n        "
+          ENUM@316..453
+            COMMENT@316..329 "// fail again"
+            WHITESPACE@329..338 "\n        "
+            ENUM_KW@338..342 "enum"
+            WHITESPACE@342..343 " "
+            NAME@343..348
+              IDENT@343..348 "Test4"
+            WHITESPACE@348..349 " "
+            VARIANT_LIST@349..453
+              L_CURLY@349..350 "{"
+              WHITESPACE@350..363 "\n            "
+              VARIANT@363..372
+                NAME@363..367
+                  IDENT@363..367 "Nope"
+                TUPLE_FIELD_LIST@367..372
+                  L_PAREN@367..368 "("
+                  TUPLE_FIELD@368..371
+                    PATH_TYPE@368..371
+                      PATH@368..371
+                        PATH_SEGMENT@368..371
+                          NAME_REF@368..371
+                            IDENT@368..371 "i32"
+                  WHITESPACE@371..372 " "
+                  ERROR@372..372
+              ERROR@372..374
+                L_CURLY@372..373 "{"
+                R_CURLY@373..374 "}"
+              ERROR@374..375
+                R_PAREN@374..375 ")"
+              WHITESPACE@375..376 " "
+              COMMENT@376..396 "//~ ERROR: found `{`"
+              WHITESPACE@396..422 "\n                     ..."
+              COMMENT@422..443 "//~^ ERROR: found `{`"
+              WHITESPACE@443..452 "\n        "
+              R_CURLY@452..453 "}"
+          WHITESPACE@453..458 "\n    "
+          R_CURLY@458..459 "}"
+      WHITESPACE@459..464 "\n    "
+      COMMENT@464..486 "// still recover later"
+      WHITESPACE@486..491 "\n    "
+      LET_STMT@491..510
+        LET_KW@491..494 "let"
+        WHITESPACE@494..495 " "
+        IDENT_PAT@495..505
+          NAME@495..505
+            IDENT@495..505 "bad_syntax"
+        WHITESPACE@505..506 " "
+        EQ@506..507 "="
+        WHITESPACE@507..508 " "
+        ERROR@508..509
+          UNDERSCORE@508..509 "_"
+        SEMICOLON@509..510 ";"
+      WHITESPACE@510..511 " "
+      COMMENT@511..572 "//~ ERROR: expected e ..."
+      WHITESPACE@572..573 "\n"
+      R_CURLY@573..574 "}"
+  WHITESPACE@574..575 "\n"
+error 95..95: expected type
+error 95..95: expected COMMA
+error 96..96: expected field
+error 98..98: expected field declaration
+error 371..371: expected COMMA
+error 372..372: expected a type
+error 372..372: expected R_PAREN
+error 372..372: expected COMMA
+error 372..372: expected enum variant
+error 374..374: expected enum variant
+error 508..508: expected expression
diff --git a/crates/syntax/test_data/parser/err/0025_nope.rs b/crates/syntax/test_data/parser/err/0025_nope.rs
new file mode 100644
index 00000000000..28726ed5138
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0025_nope.rs
@@ -0,0 +1,31 @@
+fn main() {
+    enum Test {
+        Var1,
+        Var2(String),
+        Var3 {
+            abc: {}, //~ ERROR: expected type, found `{`
+        },
+    }
+
+    // recover...
+    let a = 1;
+    enum Test2 {
+        Fine,
+    }
+
+    enum Test3 {
+        StillFine {
+            def: i32,
+        },
+    }
+
+    {
+        // fail again
+        enum Test4 {
+            Nope(i32 {}) //~ ERROR: found `{`
+                         //~^ ERROR: found `{`
+        }
+    }
+    // still recover later
+    let bad_syntax = _; //~ ERROR: expected expression, found reserved identifier `_`
+}
diff --git a/crates/syntax/test_data/parser/err/0026_imp_recovery.rast b/crates/syntax/test_data/parser/err/0026_imp_recovery.rast
new file mode 100644
index 00000000000..1b08c834eb8
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0026_imp_recovery.rast
@@ -0,0 +1,49 @@
+SOURCE_FILE@0..38
+  IMPL@0..14
+    IMPL_KW@0..4 "impl"
+    GENERIC_PARAM_LIST@4..14
+      L_ANGLE@4..5 "<"
+      TYPE_PARAM@5..13
+        NAME@5..6
+          IDENT@5..6 "T"
+        COLON@6..7 ":"
+        WHITESPACE@7..8 " "
+        TYPE_BOUND_LIST@8..13
+          TYPE_BOUND@8..13
+            PATH_TYPE@8..13
+              PATH@8..13
+                PATH_SEGMENT@8..13
+                  NAME_REF@8..13
+                    IDENT@8..13 "Clone"
+      R_ANGLE@13..14 ">"
+  WHITESPACE@14..15 "\n"
+  IMPL@15..37
+    IMPL_KW@15..19 "impl"
+    GENERIC_PARAM_LIST@19..22
+      L_ANGLE@19..20 "<"
+      TYPE_PARAM@20..21
+        NAME@20..21
+          IDENT@20..21 "T"
+      R_ANGLE@21..22 ">"
+    WHITESPACE@22..23 " "
+    PATH_TYPE@23..34
+      PATH@23..34
+        PATH_SEGMENT@23..34
+          NAME_REF@23..31
+            IDENT@23..31 "OnceCell"
+          GENERIC_ARG_LIST@31..34
+            L_ANGLE@31..32 "<"
+            TYPE_ARG@32..33
+              PATH_TYPE@32..33
+                PATH@32..33
+                  PATH_SEGMENT@32..33
+                    NAME_REF@32..33
+                      IDENT@32..33 "T"
+            R_ANGLE@33..34 ">"
+    WHITESPACE@34..35 " "
+    ASSOC_ITEM_LIST@35..37
+      L_CURLY@35..36 "{"
+      R_CURLY@36..37 "}"
+  WHITESPACE@37..38 "\n"
+error 14..14: expected trait or type
+error 14..14: expected `{`
diff --git a/crates/syntax/test_data/parser/err/0026_imp_recovery.rs b/crates/syntax/test_data/parser/err/0026_imp_recovery.rs
new file mode 100644
index 00000000000..829ca1c4be9
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0026_imp_recovery.rs
@@ -0,0 +1,2 @@
+impl<T: Clone>
+impl<T> OnceCell<T> {}
diff --git a/crates/syntax/test_data/parser/err/0027_incomplere_where_for.rast b/crates/syntax/test_data/parser/err/0027_incomplere_where_for.rast
new file mode 100644
index 00000000000..a8e42e6eaae
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0027_incomplere_where_for.rast
@@ -0,0 +1,27 @@
+SOURCE_FILE@0..30
+  FN@0..29
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..13 "\n    "
+    WHERE_CLAUSE@13..26
+      WHERE_KW@13..18 "where"
+      WHITESPACE@18..19 " "
+      WHERE_PRED@19..26
+        FOR_KW@19..22 "for"
+        GENERIC_PARAM_LIST@22..26
+          L_ANGLE@22..23 "<"
+          LIFETIME_PARAM@23..25
+            LIFETIME@23..25 "\'a"
+          R_ANGLE@25..26 ">"
+    WHITESPACE@26..27 "\n"
+    BLOCK_EXPR@27..29
+      L_CURLY@27..28 "{"
+      R_CURLY@28..29 "}"
+  WHITESPACE@29..30 "\n"
+error 26..26: expected type
+error 26..26: expected colon
diff --git a/crates/syntax/test_data/parser/err/0027_incomplere_where_for.rs b/crates/syntax/test_data/parser/err/0027_incomplere_where_for.rs
new file mode 100644
index 00000000000..2792c20843a
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0027_incomplere_where_for.rs
@@ -0,0 +1,3 @@
+fn foo()
+    where for<'a>
+{}
diff --git a/crates/syntax/test_data/parser/err/0029_field_completion.rast b/crates/syntax/test_data/parser/err/0029_field_completion.rast
new file mode 100644
index 00000000000..c6402cdd847
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0029_field_completion.rast
@@ -0,0 +1,35 @@
+SOURCE_FILE@0..24
+  FN@0..23
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..12
+      L_PAREN@6..7 "("
+      PARAM@7..11
+        IDENT_PAT@7..8
+          NAME@7..8
+            IDENT@7..8 "a"
+        COLON@8..9 ":"
+        WHITESPACE@9..10 " "
+        PATH_TYPE@10..11
+          PATH@10..11
+            PATH_SEGMENT@10..11
+              NAME_REF@10..11
+                IDENT@10..11 "A"
+      R_PAREN@11..12 ")"
+    WHITESPACE@12..13 " "
+    BLOCK_EXPR@13..23
+      L_CURLY@13..14 "{"
+      WHITESPACE@14..19 "\n    "
+      FIELD_EXPR@19..21
+        PATH_EXPR@19..20
+          PATH@19..20
+            PATH_SEGMENT@19..20
+              NAME_REF@19..20
+                IDENT@19..20 "a"
+        DOT@20..21 "."
+      WHITESPACE@21..22 "\n"
+      R_CURLY@22..23 "}"
+  WHITESPACE@23..24 "\n"
+error 21..21: expected field name or number
diff --git a/crates/syntax/test_data/parser/err/0029_field_completion.rs b/crates/syntax/test_data/parser/err/0029_field_completion.rs
new file mode 100644
index 00000000000..a7cdc17bb11
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0029_field_completion.rs
@@ -0,0 +1,3 @@
+fn foo(a: A) {
+    a.
+}
diff --git a/crates/syntax/test_data/parser/err/0031_block_inner_attrs.rast b/crates/syntax/test_data/parser/err/0031_block_inner_attrs.rast
new file mode 100644
index 00000000000..a443b37db17
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0031_block_inner_attrs.rast
@@ -0,0 +1,121 @@
+SOURCE_FILE@0..350
+  FN@0..349
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..8
+      IDENT@3..8 "block"
+    PARAM_LIST@8..10
+      L_PAREN@8..9 "("
+      R_PAREN@9..10 ")"
+    WHITESPACE@10..11 " "
+    BLOCK_EXPR@11..349
+      L_CURLY@11..12 "{"
+      WHITESPACE@12..17 "\n    "
+      LET_STMT@17..129
+        LET_KW@17..20 "let"
+        WHITESPACE@20..21 " "
+        IDENT_PAT@21..26
+          NAME@21..26
+            IDENT@21..26 "inner"
+        WHITESPACE@26..27 " "
+        EQ@27..28 "="
+        WHITESPACE@28..29 " "
+        BLOCK_EXPR@29..128
+          L_CURLY@29..30 "{"
+          WHITESPACE@30..39 "\n        "
+          ATTR@39..83
+            POUND@39..40 "#"
+            BANG@40..41 "!"
+            L_BRACK@41..42 "["
+            PATH@42..45
+              PATH_SEGMENT@42..45
+                NAME_REF@42..45
+                  IDENT@42..45 "doc"
+            TOKEN_TREE@45..82
+              L_PAREN@45..46 "("
+              STRING@46..81 "\"Inner attributes not ..."
+              R_PAREN@81..82 ")"
+            R_BRACK@82..83 "]"
+          WHITESPACE@83..92 "\n        "
+          COMMENT@92..122 "//! Nor are ModuleDoc ..."
+          WHITESPACE@122..127 "\n    "
+          R_CURLY@127..128 "}"
+        SEMICOLON@128..129 ";"
+      WHITESPACE@129..134 "\n    "
+      EXPR_STMT@134..257
+        IF_EXPR@134..257
+          IF_KW@134..136 "if"
+          WHITESPACE@136..137 " "
+          CONDITION@137..141
+            LITERAL@137..141
+              TRUE_KW@137..141 "true"
+          WHITESPACE@141..142 " "
+          BLOCK_EXPR@142..257
+            L_CURLY@142..143 "{"
+            WHITESPACE@143..152 "\n        "
+            ATTR@152..171
+              POUND@152..153 "#"
+              BANG@153..154 "!"
+              L_BRACK@154..155 "["
+              PATH@155..158
+                PATH_SEGMENT@155..158
+                  NAME_REF@155..158
+                    IDENT@155..158 "doc"
+              TOKEN_TREE@158..170
+                L_PAREN@158..159 "("
+                STRING@159..169 "\"Nor here\""
+                R_PAREN@169..170 ")"
+              R_BRACK@170..171 "]"
+            WHITESPACE@171..180 "\n        "
+            ATTR@180..212
+              POUND@180..181 "#"
+              BANG@181..182 "!"
+              L_BRACK@182..183 "["
+              PATH@183..186
+                PATH_SEGMENT@183..186
+                  NAME_REF@183..186
+                    IDENT@183..186 "doc"
+              TOKEN_TREE@186..211
+                L_PAREN@186..187 "("
+                STRING@187..210 "\"We error on each attr\""
+                R_PAREN@210..211 ")"
+              R_BRACK@211..212 "]"
+            WHITESPACE@212..221 "\n        "
+            COMMENT@221..251 "//! Nor are ModuleDoc ..."
+            WHITESPACE@251..256 "\n    "
+            R_CURLY@256..257 "}"
+      WHITESPACE@257..262 "\n    "
+      WHILE_EXPR@262..347
+        WHILE_KW@262..267 "while"
+        WHITESPACE@267..268 " "
+        CONDITION@268..272
+          LITERAL@268..272
+            TRUE_KW@268..272 "true"
+        WHITESPACE@272..273 " "
+        BLOCK_EXPR@273..347
+          L_CURLY@273..274 "{"
+          WHITESPACE@274..283 "\n        "
+          ATTR@283..302
+            POUND@283..284 "#"
+            BANG@284..285 "!"
+            L_BRACK@285..286 "["
+            PATH@286..289
+              PATH_SEGMENT@286..289
+                NAME_REF@286..289
+                  IDENT@286..289 "doc"
+            TOKEN_TREE@289..301
+              L_PAREN@289..290 "("
+              STRING@290..300 "\"Nor here\""
+              R_PAREN@300..301 ")"
+            R_BRACK@301..302 "]"
+          WHITESPACE@302..311 "\n        "
+          COMMENT@311..341 "//! Nor are ModuleDoc ..."
+          WHITESPACE@341..346 "\n    "
+          R_CURLY@346..347 "}"
+      WHITESPACE@347..348 "\n"
+      R_CURLY@348..349 "}"
+  WHITESPACE@349..350 "\n"
+error 39..83: A block in this position cannot accept inner attributes
+error 152..171: A block in this position cannot accept inner attributes
+error 180..212: A block in this position cannot accept inner attributes
+error 283..302: A block in this position cannot accept inner attributes
diff --git a/crates/syntax/test_data/parser/err/0031_block_inner_attrs.rs b/crates/syntax/test_data/parser/err/0031_block_inner_attrs.rs
new file mode 100644
index 00000000000..6a04f2d0aae
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0031_block_inner_attrs.rs
@@ -0,0 +1,15 @@
+fn block() {
+    let inner = {
+        #![doc("Inner attributes not allowed here")]
+        //! Nor are ModuleDoc comments
+    };
+    if true {
+        #![doc("Nor here")]
+        #![doc("We error on each attr")]
+        //! Nor are ModuleDoc comments
+    }
+    while true {
+        #![doc("Nor here")]
+        //! Nor are ModuleDoc comments
+    }
+}
diff --git a/crates/syntax/test_data/parser/err/0032_match_arms_inner_attrs.rast b/crates/syntax/test_data/parser/err/0032_match_arms_inner_attrs.rast
new file mode 100644
index 00000000000..672dd054ac5
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0032_match_arms_inner_attrs.rast
@@ -0,0 +1,203 @@
+SOURCE_FILE@0..293
+  FN@0..292
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..292
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..101
+        MATCH_EXPR@15..101
+          MATCH_KW@15..20 "match"
+          WHITESPACE@20..21 " "
+          TUPLE_EXPR@21..23
+            L_PAREN@21..22 "("
+            R_PAREN@22..23 ")"
+          WHITESPACE@23..24 " "
+          MATCH_ARM_LIST@24..101
+            L_CURLY@24..25 "{"
+            WHITESPACE@25..34 "\n        "
+            MATCH_ARM@34..41
+              WILDCARD_PAT@34..35
+                UNDERSCORE@34..35 "_"
+              WHITESPACE@35..36 " "
+              FAT_ARROW@36..38 "=>"
+              WHITESPACE@38..39 " "
+              TUPLE_EXPR@39..41
+                L_PAREN@39..40 "("
+                R_PAREN@40..41 ")"
+            COMMA@41..42 ","
+            WHITESPACE@42..51 "\n        "
+            MATCH_ARM@51..78
+              ATTR@51..52
+                POUND@51..52 "#"
+              ERROR@52..53
+                BANG@52..53 "!"
+              ARRAY_EXPR@53..78
+                L_BRACK@53..54 "["
+                CALL_EXPR@54..77
+                  PATH_EXPR@54..57
+                    PATH@54..57
+                      PATH_SEGMENT@54..57
+                        NAME_REF@54..57
+                          IDENT@54..57 "doc"
+                  ARG_LIST@57..77
+                    L_PAREN@57..58 "("
+                    LITERAL@58..76
+                      STRING@58..76 "\"Not allowed here\""
+                    R_PAREN@76..77 ")"
+                R_BRACK@77..78 "]"
+            WHITESPACE@78..87 "\n        "
+            MATCH_ARM@87..94
+              WILDCARD_PAT@87..88
+                UNDERSCORE@87..88 "_"
+              WHITESPACE@88..89 " "
+              FAT_ARROW@89..91 "=>"
+              WHITESPACE@91..92 " "
+              TUPLE_EXPR@92..94
+                L_PAREN@92..93 "("
+                R_PAREN@93..94 ")"
+            COMMA@94..95 ","
+            WHITESPACE@95..100 "\n    "
+            R_CURLY@100..101 "}"
+      WHITESPACE@101..107 "\n\n    "
+      EXPR_STMT@107..185
+        MATCH_EXPR@107..185
+          MATCH_KW@107..112 "match"
+          WHITESPACE@112..113 " "
+          TUPLE_EXPR@113..115
+            L_PAREN@113..114 "("
+            R_PAREN@114..115 ")"
+          WHITESPACE@115..116 " "
+          MATCH_ARM_LIST@116..185
+            L_CURLY@116..117 "{"
+            WHITESPACE@117..126 "\n        "
+            MATCH_ARM@126..133
+              WILDCARD_PAT@126..127
+                UNDERSCORE@126..127 "_"
+              WHITESPACE@127..128 " "
+              FAT_ARROW@128..130 "=>"
+              WHITESPACE@130..131 " "
+              TUPLE_EXPR@131..133
+                L_PAREN@131..132 "("
+                R_PAREN@132..133 ")"
+            COMMA@133..134 ","
+            WHITESPACE@134..143 "\n        "
+            MATCH_ARM@143..150
+              WILDCARD_PAT@143..144
+                UNDERSCORE@143..144 "_"
+              WHITESPACE@144..145 " "
+              FAT_ARROW@145..147 "=>"
+              WHITESPACE@147..148 " "
+              TUPLE_EXPR@148..150
+                L_PAREN@148..149 "("
+                R_PAREN@149..150 ")"
+            COMMA@150..151 ","
+            WHITESPACE@151..160 "\n        "
+            MATCH_ARM@160..179
+              ATTR@160..161
+                POUND@160..161 "#"
+              ERROR@161..162
+                BANG@161..162 "!"
+              ARRAY_EXPR@162..179
+                L_BRACK@162..163 "["
+                CALL_EXPR@163..178
+                  PATH_EXPR@163..166
+                    PATH@163..166
+                      PATH_SEGMENT@163..166
+                        NAME_REF@163..166
+                          IDENT@163..166 "doc"
+                  ARG_LIST@166..178
+                    L_PAREN@166..167 "("
+                    LITERAL@167..177
+                      STRING@167..177 "\"Nor here\""
+                    R_PAREN@177..178 ")"
+                R_BRACK@178..179 "]"
+            WHITESPACE@179..184 "\n    "
+            R_CURLY@184..185 "}"
+      WHITESPACE@185..191 "\n\n    "
+      MATCH_EXPR@191..290
+        MATCH_KW@191..196 "match"
+        WHITESPACE@196..197 " "
+        TUPLE_EXPR@197..199
+          L_PAREN@197..198 "("
+          R_PAREN@198..199 ")"
+        WHITESPACE@199..200 " "
+        MATCH_ARM_LIST@200..290
+          L_CURLY@200..201 "{"
+          WHITESPACE@201..210 "\n        "
+          MATCH_ARM@210..250
+            ATTR@210..222
+              POUND@210..211 "#"
+              L_BRACK@211..212 "["
+              PATH@212..215
+                PATH_SEGMENT@212..215
+                  NAME_REF@212..215
+                    IDENT@212..215 "cfg"
+              TOKEN_TREE@215..221
+                L_PAREN@215..216 "("
+                IDENT@216..220 "test"
+                R_PAREN@220..221 ")"
+              R_BRACK@221..222 "]"
+            WHITESPACE@222..231 "\n        "
+            ATTR@231..232
+              POUND@231..232 "#"
+            ERROR@232..233
+              BANG@232..233 "!"
+            ARRAY_EXPR@233..250
+              L_BRACK@233..234 "["
+              CALL_EXPR@234..249
+                PATH_EXPR@234..237
+                  PATH@234..237
+                    PATH_SEGMENT@234..237
+                      NAME_REF@234..237
+                        IDENT@234..237 "doc"
+                ARG_LIST@237..249
+                  L_PAREN@237..238 "("
+                  LITERAL@238..248
+                    STRING@238..248 "\"Nor here\""
+                  R_PAREN@248..249 ")"
+              R_BRACK@249..250 "]"
+          WHITESPACE@250..259 "\n        "
+          MATCH_ARM@259..266
+            WILDCARD_PAT@259..260
+              UNDERSCORE@259..260 "_"
+            WHITESPACE@260..261 " "
+            FAT_ARROW@261..263 "=>"
+            WHITESPACE@263..264 " "
+            TUPLE_EXPR@264..266
+              L_PAREN@264..265 "("
+              R_PAREN@265..266 ")"
+          COMMA@266..267 ","
+          WHITESPACE@267..276 "\n        "
+          MATCH_ARM@276..283
+            WILDCARD_PAT@276..277
+              UNDERSCORE@276..277 "_"
+            WHITESPACE@277..278 " "
+            FAT_ARROW@278..280 "=>"
+            WHITESPACE@280..281 " "
+            TUPLE_EXPR@281..283
+              L_PAREN@281..282 "("
+              R_PAREN@282..283 ")"
+          COMMA@283..284 ","
+          WHITESPACE@284..289 "\n    "
+          R_CURLY@289..290 "}"
+      WHITESPACE@290..291 "\n"
+      R_CURLY@291..292 "}"
+  WHITESPACE@292..293 "\n"
+error 52..52: expected `[`
+error 52..52: expected pattern
+error 53..53: expected FAT_ARROW
+error 78..78: expected COMMA
+error 161..161: expected `[`
+error 161..161: expected pattern
+error 162..162: expected FAT_ARROW
+error 232..232: expected `[`
+error 232..232: expected pattern
+error 233..233: expected FAT_ARROW
+error 250..250: expected COMMA
diff --git a/crates/syntax/test_data/parser/err/0032_match_arms_inner_attrs.rs b/crates/syntax/test_data/parser/err/0032_match_arms_inner_attrs.rs
new file mode 100644
index 00000000000..06aa4777043
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0032_match_arms_inner_attrs.rs
@@ -0,0 +1,20 @@
+fn foo() {
+    match () {
+        _ => (),
+        #![doc("Not allowed here")]
+        _ => (),
+    }
+
+    match () {
+        _ => (),
+        _ => (),
+        #![doc("Nor here")]
+    }
+
+    match () {
+        #[cfg(test)]
+        #![doc("Nor here")]
+        _ => (),
+        _ => (),
+    }
+}
diff --git a/crates/syntax/test_data/parser/err/0033_match_arms_outer_attrs.rast b/crates/syntax/test_data/parser/err/0033_match_arms_outer_attrs.rast
new file mode 100644
index 00000000000..33bb085e918
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0033_match_arms_outer_attrs.rast
@@ -0,0 +1,66 @@
+SOURCE_FILE@0..89
+  FN@0..88
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..88
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      MATCH_EXPR@15..86
+        MATCH_KW@15..20 "match"
+        WHITESPACE@20..21 " "
+        TUPLE_EXPR@21..23
+          L_PAREN@21..22 "("
+          R_PAREN@22..23 ")"
+        WHITESPACE@23..24 " "
+        MATCH_ARM_LIST@24..86
+          L_CURLY@24..25 "{"
+          WHITESPACE@25..34 "\n        "
+          MATCH_ARM@34..41
+            WILDCARD_PAT@34..35
+              UNDERSCORE@34..35 "_"
+            WHITESPACE@35..36 " "
+            FAT_ARROW@36..38 "=>"
+            WHITESPACE@38..39 " "
+            TUPLE_EXPR@39..41
+              L_PAREN@39..40 "("
+              R_PAREN@40..41 ")"
+          COMMA@41..42 ","
+          WHITESPACE@42..51 "\n        "
+          MATCH_ARM@51..58
+            WILDCARD_PAT@51..52
+              UNDERSCORE@51..52 "_"
+            WHITESPACE@52..53 " "
+            FAT_ARROW@53..55 "=>"
+            WHITESPACE@55..56 " "
+            TUPLE_EXPR@56..58
+              L_PAREN@56..57 "("
+              R_PAREN@57..58 ")"
+          COMMA@58..59 ","
+          WHITESPACE@59..68 "\n        "
+          MATCH_ARM@68..80
+            ATTR@68..80
+              POUND@68..69 "#"
+              L_BRACK@69..70 "["
+              PATH@70..73
+                PATH_SEGMENT@70..73
+                  NAME_REF@70..73
+                    IDENT@70..73 "cfg"
+              TOKEN_TREE@73..79
+                L_PAREN@73..74 "("
+                IDENT@74..78 "test"
+                R_PAREN@78..79 ")"
+              R_BRACK@79..80 "]"
+          WHITESPACE@80..85 "\n    "
+          R_CURLY@85..86 "}"
+      WHITESPACE@86..87 "\n"
+      R_CURLY@87..88 "}"
+  WHITESPACE@88..89 "\n"
+error 80..80: expected pattern
+error 80..80: expected FAT_ARROW
+error 80..80: expected expression
diff --git a/crates/syntax/test_data/parser/err/0033_match_arms_outer_attrs.rs b/crates/syntax/test_data/parser/err/0033_match_arms_outer_attrs.rs
new file mode 100644
index 00000000000..4635222da28
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0033_match_arms_outer_attrs.rs
@@ -0,0 +1,7 @@
+fn foo() {
+    match () {
+        _ => (),
+        _ => (),
+        #[cfg(test)]
+    }
+}
diff --git a/crates/syntax/test_data/parser/err/0034_bad_box_pattern.rast b/crates/syntax/test_data/parser/err/0034_bad_box_pattern.rast
new file mode 100644
index 00000000000..d9d49bfb5ff
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0034_bad_box_pattern.rast
@@ -0,0 +1,95 @@
+SOURCE_FILE@0..91
+  FN@0..89
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..89
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      LET_STMT@16..27
+        LET_KW@16..19 "let"
+        WHITESPACE@19..20 " "
+        IDENT_PAT@20..27
+          REF_KW@20..23 "ref"
+          WHITESPACE@23..24 " "
+          ERROR@24..27
+            BOX_KW@24..27 "box"
+      WHITESPACE@27..28 " "
+      EXPR_STMT@28..35
+        BIN_EXPR@28..34
+          PATH_EXPR@28..29
+            PATH@28..29
+              PATH_SEGMENT@28..29
+                NAME_REF@28..29
+                  IDENT@28..29 "i"
+          WHITESPACE@29..30 " "
+          EQ@30..31 "="
+          WHITESPACE@31..32 " "
+          TUPLE_EXPR@32..34
+            L_PAREN@32..33 "("
+            R_PAREN@33..34 ")"
+        SEMICOLON@34..35 ";"
+      WHITESPACE@35..40 "\n    "
+      LET_STMT@40..51
+        LET_KW@40..43 "let"
+        WHITESPACE@43..44 " "
+        IDENT_PAT@44..51
+          MUT_KW@44..47 "mut"
+          WHITESPACE@47..48 " "
+          ERROR@48..51
+            BOX_KW@48..51 "box"
+      WHITESPACE@51..52 " "
+      EXPR_STMT@52..59
+        BIN_EXPR@52..58
+          PATH_EXPR@52..53
+            PATH@52..53
+              PATH_SEGMENT@52..53
+                NAME_REF@52..53
+                  IDENT@52..53 "i"
+          WHITESPACE@53..54 " "
+          EQ@54..55 "="
+          WHITESPACE@55..56 " "
+          TUPLE_EXPR@56..58
+            L_PAREN@56..57 "("
+            R_PAREN@57..58 ")"
+        SEMICOLON@58..59 ";"
+      WHITESPACE@59..64 "\n    "
+      LET_STMT@64..79
+        LET_KW@64..67 "let"
+        WHITESPACE@67..68 " "
+        IDENT_PAT@68..79
+          REF_KW@68..71 "ref"
+          WHITESPACE@71..72 " "
+          MUT_KW@72..75 "mut"
+          WHITESPACE@75..76 " "
+          ERROR@76..79
+            BOX_KW@76..79 "box"
+      WHITESPACE@79..80 " "
+      EXPR_STMT@80..87
+        BIN_EXPR@80..86
+          PATH_EXPR@80..81
+            PATH@80..81
+              PATH_SEGMENT@80..81
+                NAME_REF@80..81
+                  IDENT@80..81 "i"
+          WHITESPACE@81..82 " "
+          EQ@82..83 "="
+          WHITESPACE@83..84 " "
+          TUPLE_EXPR@84..86
+            L_PAREN@84..85 "("
+            R_PAREN@85..86 ")"
+        SEMICOLON@86..87 ";"
+      WHITESPACE@87..88 "\n"
+      R_CURLY@88..89 "}"
+  WHITESPACE@89..91 "\n\n"
+error 24..24: expected a name
+error 27..27: expected SEMICOLON
+error 48..48: expected a name
+error 51..51: expected SEMICOLON
+error 76..76: expected a name
+error 79..79: expected SEMICOLON
diff --git a/crates/syntax/test_data/parser/err/0034_bad_box_pattern.rs b/crates/syntax/test_data/parser/err/0034_bad_box_pattern.rs
new file mode 100644
index 00000000000..d3fa2e468cc
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0034_bad_box_pattern.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let ref box i = ();
+    let mut box i = ();
+    let ref mut box i = ();
+}
+
diff --git a/crates/syntax/test_data/parser/err/0035_use_recover.rast b/crates/syntax/test_data/parser/err/0035_use_recover.rast
new file mode 100644
index 00000000000..2f03709ebad
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0035_use_recover.rast
@@ -0,0 +1,53 @@
+SOURCE_FILE@0..48
+  USE@0..13
+    USE_KW@0..3 "use"
+    WHITESPACE@3..4 " "
+    USE_TREE@4..12
+      PATH@4..12
+        PATH@4..7
+          PATH_SEGMENT@4..7
+            NAME_REF@4..7
+              IDENT@4..7 "foo"
+        COLON2@7..9 "::"
+        PATH_SEGMENT@9..12
+          NAME_REF@9..12
+            IDENT@9..12 "bar"
+    SEMICOLON@12..13 ";"
+  WHITESPACE@13..14 "\n"
+  USE@14..17
+    USE_KW@14..17 "use"
+  WHITESPACE@17..18 "\n"
+  USE@18..33
+    USE_KW@18..21 "use"
+    WHITESPACE@21..22 " "
+    USE_TREE@22..32
+      PATH@22..32
+        PATH@22..27
+          PATH_SEGMENT@22..27
+            CRATE_KW@22..27 "crate"
+        COLON2@27..29 "::"
+        PATH_SEGMENT@29..32
+          NAME_REF@29..32
+            IDENT@29..32 "baz"
+    SEMICOLON@32..33 ";"
+  WHITESPACE@33..34 "\n"
+  USE@34..37
+    USE_KW@34..37 "use"
+  WHITESPACE@37..38 "\n"
+  FN@38..47
+    FN_KW@38..40 "fn"
+    WHITESPACE@40..41 " "
+    NAME@41..42
+      IDENT@41..42 "f"
+    PARAM_LIST@42..44
+      L_PAREN@42..43 "("
+      R_PAREN@43..44 ")"
+    WHITESPACE@44..45 " "
+    BLOCK_EXPR@45..47
+      L_CURLY@45..46 "{"
+      R_CURLY@46..47 "}"
+  WHITESPACE@47..48 "\n"
+error 17..17: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
+error 17..17: expected SEMICOLON
+error 37..37: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
+error 37..37: expected SEMICOLON
diff --git a/crates/syntax/test_data/parser/err/0035_use_recover.rs b/crates/syntax/test_data/parser/err/0035_use_recover.rs
new file mode 100644
index 00000000000..4a266812628
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0035_use_recover.rs
@@ -0,0 +1,5 @@
+use foo::bar;
+use
+use crate::baz;
+use
+fn f() {}
diff --git a/crates/syntax/test_data/parser/err/0036_partial_use.rast b/crates/syntax/test_data/parser/err/0036_partial_use.rast
new file mode 100644
index 00000000000..ef6172f8a1a
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0036_partial_use.rast
@@ -0,0 +1,51 @@
+SOURCE_FILE@0..37
+  USE@0..36
+    USE_KW@0..3 "use"
+    WHITESPACE@3..4 " "
+    USE_TREE@4..36
+      PATH@4..7
+        PATH_SEGMENT@4..7
+          NAME_REF@4..7
+            IDENT@4..7 "std"
+      COLON2@7..9 "::"
+      USE_TREE_LIST@9..36
+        L_CURLY@9..10 "{"
+        USE_TREE@10..22
+          PATH@10..22
+            PATH@10..15
+              PATH_SEGMENT@10..15
+                NAME_REF@10..15
+                  IDENT@10..15 "error"
+            COLON2@15..17 "::"
+            PATH_SEGMENT@17..22
+              NAME_REF@17..22
+                IDENT@17..22 "Error"
+        ERROR@22..23
+          SEMICOLON@22..23 ";"
+        WHITESPACE@23..24 "\n"
+        ERROR@24..27
+          USE_KW@24..27 "use"
+        WHITESPACE@27..28 " "
+        USE_TREE@28..35
+          PATH@28..35
+            PATH@28..31
+              PATH_SEGMENT@28..31
+                NAME_REF@28..31
+                  IDENT@28..31 "std"
+            COLON2@31..33 "::"
+            PATH_SEGMENT@33..35
+              NAME_REF@33..35
+                IDENT@33..35 "io"
+        ERROR@35..36
+          SEMICOLON@35..36 ";"
+  WHITESPACE@36..37 "\n"
+error 22..22: expected COMMA
+error 22..22: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
+error 23..23: expected COMMA
+error 24..24: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
+error 27..27: expected COMMA
+error 35..35: expected COMMA
+error 35..35: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
+error 36..36: expected COMMA
+error 36..36: expected R_CURLY
+error 36..36: expected SEMICOLON
diff --git a/crates/syntax/test_data/parser/err/0036_partial_use.rs b/crates/syntax/test_data/parser/err/0036_partial_use.rs
new file mode 100644
index 00000000000..d521a5bb2de
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0036_partial_use.rs
@@ -0,0 +1,2 @@
+use std::{error::Error;
+use std::io;
diff --git a/crates/syntax/test_data/parser/err/0037_visibility_in_traits.rast b/crates/syntax/test_data/parser/err/0037_visibility_in_traits.rast
new file mode 100644
index 00000000000..faf87d6e5cc
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0037_visibility_in_traits.rast
@@ -0,0 +1,97 @@
+SOURCE_FILE@0..118
+  IMPL@0..117
+    IMPL_KW@0..4 "impl"
+    WHITESPACE@4..5 " "
+    PATH_TYPE@5..6
+      PATH@5..6
+        PATH_SEGMENT@5..6
+          NAME_REF@5..6
+            IDENT@5..6 "T"
+    WHITESPACE@6..7 " "
+    FOR_KW@7..10 "for"
+    WHITESPACE@10..11 " "
+    TUPLE_TYPE@11..13
+      L_PAREN@11..12 "("
+      R_PAREN@12..13 ")"
+    WHITESPACE@13..14 " "
+    ASSOC_ITEM_LIST@14..117
+      L_CURLY@14..15 "{"
+      WHITESPACE@15..20 "\n    "
+      FN@20..31
+        FN_KW@20..22 "fn"
+        WHITESPACE@22..23 " "
+        NAME@23..26
+          IDENT@23..26 "foo"
+        PARAM_LIST@26..28
+          L_PAREN@26..27 "("
+          R_PAREN@27..28 ")"
+        WHITESPACE@28..29 " "
+        BLOCK_EXPR@29..31
+          L_CURLY@29..30 "{"
+          R_CURLY@30..31 "}"
+      WHITESPACE@31..36 "\n    "
+      FN@36..51
+        VISIBILITY@36..39
+          PUB_KW@36..39 "pub"
+        WHITESPACE@39..40 " "
+        FN_KW@40..42 "fn"
+        WHITESPACE@42..43 " "
+        NAME@43..46
+          IDENT@43..46 "bar"
+        PARAM_LIST@46..48
+          L_PAREN@46..47 "("
+          R_PAREN@47..48 ")"
+        WHITESPACE@48..49 " "
+        BLOCK_EXPR@49..51
+          L_CURLY@49..50 "{"
+          R_CURLY@50..51 "}"
+      WHITESPACE@51..56 "\n    "
+      TYPE_ALIAS@56..81
+        VISIBILITY@56..66
+          PUB_KW@56..59 "pub"
+          L_PAREN@59..60 "("
+          CRATE_KW@60..65 "crate"
+          R_PAREN@65..66 ")"
+        WHITESPACE@66..67 " "
+        TYPE_KW@67..71 "type"
+        WHITESPACE@71..72 " "
+        NAME@72..75
+          IDENT@72..75 "Baz"
+        WHITESPACE@75..76 " "
+        EQ@76..77 "="
+        WHITESPACE@77..78 " "
+        TUPLE_TYPE@78..80
+          L_PAREN@78..79 "("
+          R_PAREN@79..80 ")"
+        SEMICOLON@80..81 ";"
+      WHITESPACE@81..86 "\n    "
+      CONST@86..115
+        VISIBILITY@86..96
+          PUB_KW@86..89 "pub"
+          L_PAREN@89..90 "("
+          CRATE_KW@90..95 "crate"
+          R_PAREN@95..96 ")"
+        WHITESPACE@96..97 " "
+        CONST_KW@97..102 "const"
+        WHITESPACE@102..103 " "
+        NAME@103..104
+          IDENT@103..104 "C"
+        COLON@104..105 ":"
+        WHITESPACE@105..106 " "
+        PATH_TYPE@106..109
+          PATH@106..109
+            PATH_SEGMENT@106..109
+              NAME_REF@106..109
+                IDENT@106..109 "i32"
+        WHITESPACE@109..110 " "
+        EQ@110..111 "="
+        WHITESPACE@111..112 " "
+        LITERAL@112..114
+          INT_NUMBER@112..114 "92"
+        SEMICOLON@114..115 ";"
+      WHITESPACE@115..116 "\n"
+      R_CURLY@116..117 "}"
+  WHITESPACE@117..118 "\n"
+error 36..39: Unnecessary visibility qualifier
+error 56..66: Unnecessary visibility qualifier
+error 86..96: Unnecessary visibility qualifier
diff --git a/crates/syntax/test_data/parser/err/0037_visibility_in_traits.rs b/crates/syntax/test_data/parser/err/0037_visibility_in_traits.rs
new file mode 100644
index 00000000000..a43e7ef10c1
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0037_visibility_in_traits.rs
@@ -0,0 +1,6 @@
+impl T for () {
+    fn foo() {}
+    pub fn bar() {}
+    pub(crate) type Baz = ();
+    pub(crate) const C: i32 = 92;
+}
diff --git a/crates/syntax/test_data/parser/err/0038_endless_inclusive_range.rast b/crates/syntax/test_data/parser/err/0038_endless_inclusive_range.rast
new file mode 100644
index 00000000000..bed7ad6c332
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0038_endless_inclusive_range.rast
@@ -0,0 +1,29 @@
+SOURCE_FILE@0..33
+  FN@0..32
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..32
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      EXPR_STMT@16..21
+        RANGE_EXPR@16..20
+          LITERAL@16..17
+            INT_NUMBER@16..17 "0"
+          DOT2EQ@17..20 "..="
+        SEMICOLON@20..21 ";"
+      WHITESPACE@21..26 "\n    "
+      EXPR_STMT@26..30
+        RANGE_EXPR@26..29
+          DOT2EQ@26..29 "..="
+        SEMICOLON@29..30 ";"
+      WHITESPACE@30..31 "\n"
+      R_CURLY@31..32 "}"
+  WHITESPACE@32..33 "\n"
+error 16..20: An inclusive range must have an end expression
+error 26..29: An inclusive range must have an end expression
diff --git a/crates/syntax/test_data/parser/err/0038_endless_inclusive_range.rs b/crates/syntax/test_data/parser/err/0038_endless_inclusive_range.rs
new file mode 100644
index 00000000000..0b4ed7a2bc2
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0038_endless_inclusive_range.rs
@@ -0,0 +1,4 @@
+fn main() {
+    0..=;
+    ..=;
+}
diff --git a/crates/syntax/test_data/parser/err/0039_lambda_recovery.rast b/crates/syntax/test_data/parser/err/0039_lambda_recovery.rast
new file mode 100644
index 00000000000..a9c5b70fd3d
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0039_lambda_recovery.rast
@@ -0,0 +1,82 @@
+SOURCE_FILE@0..83
+  FN@0..82
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    RET_TYPE@9..15
+      THIN_ARROW@9..11 "->"
+      WHITESPACE@11..12 " "
+      PATH_TYPE@12..15
+        PATH@12..15
+          PATH_SEGMENT@12..15
+            NAME_REF@12..15
+              IDENT@12..15 "i32"
+    WHITESPACE@15..16 " "
+    BLOCK_EXPR@16..82
+      L_CURLY@16..17 "{"
+      WHITESPACE@17..22 "\n    "
+      EXPR_STMT@22..80
+        METHOD_CALL_EXPR@22..79
+          METHOD_CALL_EXPR@22..57
+            METHOD_CALL_EXPR@22..38
+              ARRAY_EXPR@22..31
+                L_BRACK@22..23 "["
+                LITERAL@23..24
+                  INT_NUMBER@23..24 "1"
+                COMMA@24..25 ","
+                WHITESPACE@25..26 " "
+                LITERAL@26..27
+                  INT_NUMBER@26..27 "2"
+                COMMA@27..28 ","
+                WHITESPACE@28..29 " "
+                LITERAL@29..30
+                  INT_NUMBER@29..30 "3"
+                R_BRACK@30..31 "]"
+              DOT@31..32 "."
+              NAME_REF@32..36
+                IDENT@32..36 "iter"
+              ARG_LIST@36..38
+                L_PAREN@36..37 "("
+                R_PAREN@37..38 ")"
+            WHITESPACE@38..47 "\n        "
+            DOT@47..48 "."
+            NAME_REF@48..51
+              IDENT@48..51 "map"
+            ARG_LIST@51..57
+              L_PAREN@51..52 "("
+              CLOSURE_EXPR@52..56
+                PARAM_LIST@52..56
+                  PIPE@52..53 "|"
+                  PARAM@53..55
+                    IDENT_PAT@53..55
+                      NAME@53..55
+                        IDENT@53..55 "it"
+                  PIPE@55..56 "|"
+              R_PAREN@56..57 ")"
+          WHITESPACE@57..66 "\n        "
+          DOT@66..67 "."
+          NAME_REF@67..70
+            IDENT@67..70 "max"
+          GENERIC_ARG_LIST@70..77
+            COLON2@70..72 "::"
+            L_ANGLE@72..73 "<"
+            TYPE_ARG@73..76
+              PATH_TYPE@73..76
+                PATH@73..76
+                  PATH_SEGMENT@73..76
+                    NAME_REF@73..76
+                      IDENT@73..76 "i32"
+            R_ANGLE@76..77 ">"
+          ARG_LIST@77..79
+            L_PAREN@77..78 "("
+            R_PAREN@78..79 ")"
+        SEMICOLON@79..80 ";"
+      WHITESPACE@80..81 "\n"
+      R_CURLY@81..82 "}"
+  WHITESPACE@82..83 "\n"
+error 56..56: expected expression
diff --git a/crates/syntax/test_data/parser/err/0039_lambda_recovery.rs b/crates/syntax/test_data/parser/err/0039_lambda_recovery.rs
new file mode 100644
index 00000000000..a2f74bd879a
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0039_lambda_recovery.rs
@@ -0,0 +1,5 @@
+fn foo() -> i32 {
+    [1, 2, 3].iter()
+        .map(|it|)
+        .max::<i32>();
+}
diff --git a/crates/syntax/test_data/parser/err/0040_illegal_crate_kw_location.rast b/crates/syntax/test_data/parser/err/0040_illegal_crate_kw_location.rast
new file mode 100644
index 00000000000..284c8715b35
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0040_illegal_crate_kw_location.rast
@@ -0,0 +1,91 @@
+SOURCE_FILE@0..98
+  USE@0..12
+    USE_KW@0..3 "use"
+    WHITESPACE@3..4 " "
+    USE_TREE@4..11
+      PATH@4..11
+        PATH_SEGMENT@4..11
+          COLON2@4..6 "::"
+          CRATE_KW@6..11 "crate"
+    SEMICOLON@11..12 ";"
+  WHITESPACE@12..13 "\n"
+  USE@13..54
+    USE_KW@13..16 "use"
+    WHITESPACE@16..17 " "
+    USE_TREE@17..53
+      USE_TREE_LIST@17..53
+        L_CURLY@17..18 "{"
+        USE_TREE@18..23
+          PATH@18..23
+            PATH_SEGMENT@18..23
+              CRATE_KW@18..23 "crate"
+        COMMA@23..24 ","
+        WHITESPACE@24..25 " "
+        USE_TREE@25..52
+          PATH@25..28
+            PATH_SEGMENT@25..28
+              NAME_REF@25..28
+                IDENT@25..28 "foo"
+          COLON2@28..30 "::"
+          USE_TREE_LIST@30..52
+            L_CURLY@30..31 "{"
+            USE_TREE@31..51
+              PATH@31..51
+                PATH@31..46
+                  PATH@31..41
+                    PATH@31..36
+                      PATH_SEGMENT@31..36
+                        CRATE_KW@31..36 "crate"
+                    COLON2@36..38 "::"
+                    PATH_SEGMENT@38..41
+                      NAME_REF@38..41
+                        IDENT@38..41 "foo"
+                  COLON2@41..43 "::"
+                  PATH_SEGMENT@43..46
+                    NAME_REF@43..46
+                      IDENT@43..46 "bar"
+                COLON2@46..48 "::"
+                PATH_SEGMENT@48..51
+                  NAME_REF@48..51
+                    IDENT@48..51 "baz"
+            R_CURLY@51..52 "}"
+        R_CURLY@52..53 "}"
+    SEMICOLON@53..54 ";"
+  WHITESPACE@54..55 "\n"
+  USE@55..72
+    USE_KW@55..58 "use"
+    WHITESPACE@58..59 " "
+    USE_TREE@59..71
+      PATH@59..71
+        PATH@59..64
+          PATH_SEGMENT@59..64
+            NAME_REF@59..64
+              IDENT@59..64 "hello"
+        COLON2@64..66 "::"
+        PATH_SEGMENT@66..71
+          CRATE_KW@66..71 "crate"
+    SEMICOLON@71..72 ";"
+  WHITESPACE@72..73 "\n"
+  USE@73..97
+    USE_KW@73..76 "use"
+    WHITESPACE@76..77 " "
+    USE_TREE@77..96
+      PATH@77..96
+        PATH@77..89
+          PATH@77..82
+            PATH_SEGMENT@77..82
+              NAME_REF@77..82
+                IDENT@77..82 "hello"
+          COLON2@82..84 "::"
+          PATH_SEGMENT@84..89
+            CRATE_KW@84..89 "crate"
+        COLON2@89..91 "::"
+        PATH_SEGMENT@91..96
+          NAME_REF@91..96
+            IDENT@91..96 "there"
+    SEMICOLON@96..97 ";"
+  WHITESPACE@97..98 "\n"
+error 6..11: The `crate` keyword is only allowed as the first segment of a path
+error 31..36: The `crate` keyword is only allowed as the first segment of a path
+error 66..71: The `crate` keyword is only allowed as the first segment of a path
+error 84..89: The `crate` keyword is only allowed as the first segment of a path
diff --git a/crates/syntax/test_data/parser/err/0040_illegal_crate_kw_location.rs b/crates/syntax/test_data/parser/err/0040_illegal_crate_kw_location.rs
new file mode 100644
index 00000000000..508def2c7ef
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0040_illegal_crate_kw_location.rs
@@ -0,0 +1,4 @@
+use ::crate;
+use {crate, foo::{crate::foo::bar::baz}};
+use hello::crate;
+use hello::crate::there;
diff --git a/crates/syntax/test_data/parser/err/0041_illegal_super_keyword_location.rast b/crates/syntax/test_data/parser/err/0041_illegal_super_keyword_location.rast
new file mode 100644
index 00000000000..2049a9d724f
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0041_illegal_super_keyword_location.rast
@@ -0,0 +1,70 @@
+SOURCE_FILE@0..67
+  USE@0..12
+    USE_KW@0..3 "use"
+    WHITESPACE@3..4 " "
+    USE_TREE@4..11
+      PATH@4..11
+        PATH_SEGMENT@4..11
+          COLON2@4..6 "::"
+          SUPER_KW@6..11 "super"
+    SEMICOLON@11..12 ";"
+  WHITESPACE@12..13 "\n"
+  USE@13..26
+    USE_KW@13..16 "use"
+    WHITESPACE@16..17 " "
+    USE_TREE@17..25
+      PATH@17..25
+        PATH@17..18
+          PATH_SEGMENT@17..18
+            NAME_REF@17..18
+              IDENT@17..18 "a"
+        COLON2@18..20 "::"
+        PATH_SEGMENT@20..25
+          SUPER_KW@20..25 "super"
+    SEMICOLON@25..26 ";"
+  WHITESPACE@26..27 "\n"
+  USE@27..47
+    USE_KW@27..30 "use"
+    WHITESPACE@30..31 " "
+    USE_TREE@31..46
+      PATH@31..46
+        PATH@31..39
+          PATH@31..36
+            PATH_SEGMENT@31..36
+              SUPER_KW@31..36 "super"
+          COLON2@36..38 "::"
+          PATH_SEGMENT@38..39
+            NAME_REF@38..39
+              IDENT@38..39 "a"
+        COLON2@39..41 "::"
+        PATH_SEGMENT@41..46
+          SUPER_KW@41..46 "super"
+    SEMICOLON@46..47 ";"
+  WHITESPACE@47..48 "\n"
+  USE@48..66
+    USE_KW@48..51 "use"
+    WHITESPACE@51..52 " "
+    USE_TREE@52..65
+      PATH@52..53
+        PATH_SEGMENT@52..53
+          NAME_REF@52..53
+            IDENT@52..53 "a"
+      COLON2@53..55 "::"
+      USE_TREE_LIST@55..65
+        L_CURLY@55..56 "{"
+        USE_TREE@56..64
+          PATH@56..64
+            PATH@56..61
+              PATH_SEGMENT@56..61
+                SUPER_KW@56..61 "super"
+            COLON2@61..63 "::"
+            PATH_SEGMENT@63..64
+              NAME_REF@63..64
+                IDENT@63..64 "b"
+        R_CURLY@64..65 "}"
+    SEMICOLON@65..66 ";"
+  WHITESPACE@66..67 "\n"
+error 6..11: The `super` keyword may only be preceded by other `super`s
+error 20..25: The `super` keyword may only be preceded by other `super`s
+error 41..46: The `super` keyword may only be preceded by other `super`s
+error 56..61: The `super` keyword may only be preceded by other `super`s
diff --git a/crates/syntax/test_data/parser/err/0041_illegal_super_keyword_location.rs b/crates/syntax/test_data/parser/err/0041_illegal_super_keyword_location.rs
new file mode 100644
index 00000000000..bd4d5804263
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0041_illegal_super_keyword_location.rs
@@ -0,0 +1,4 @@
+use ::super;
+use a::super;
+use super::a::super;
+use a::{super::b};
diff --git a/crates/syntax/test_data/parser/err/0042_illegal_self_keyword_location.rast b/crates/syntax/test_data/parser/err/0042_illegal_self_keyword_location.rast
new file mode 100644
index 00000000000..deadf56b4b5
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0042_illegal_self_keyword_location.rast
@@ -0,0 +1,27 @@
+SOURCE_FILE@0..25
+  USE@0..11
+    USE_KW@0..3 "use"
+    WHITESPACE@3..4 " "
+    USE_TREE@4..10
+      PATH@4..10
+        PATH_SEGMENT@4..10
+          COLON2@4..6 "::"
+          SELF_KW@6..10 "self"
+    SEMICOLON@10..11 ";"
+  WHITESPACE@11..12 "\n"
+  USE@12..24
+    USE_KW@12..15 "use"
+    WHITESPACE@15..16 " "
+    USE_TREE@16..23
+      PATH@16..23
+        PATH@16..17
+          PATH_SEGMENT@16..17
+            NAME_REF@16..17
+              IDENT@16..17 "a"
+        COLON2@17..19 "::"
+        PATH_SEGMENT@19..23
+          SELF_KW@19..23 "self"
+    SEMICOLON@23..24 ";"
+  WHITESPACE@24..25 "\n"
+error 6..10: The `self` keyword is only allowed as the first segment of a path
+error 19..23: The `self` keyword is only allowed as the first segment of a path
diff --git a/crates/syntax/test_data/parser/err/0042_illegal_self_keyword_location.rs b/crates/syntax/test_data/parser/err/0042_illegal_self_keyword_location.rs
new file mode 100644
index 00000000000..b9e1d7d8be2
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0042_illegal_self_keyword_location.rs
@@ -0,0 +1,2 @@
+use ::self;
+use a::self;
diff --git a/crates/syntax/test_data/parser/err/0043_weird_blocks.rast b/crates/syntax/test_data/parser/err/0043_weird_blocks.rast
new file mode 100644
index 00000000000..df29017e7f2
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0043_weird_blocks.rast
@@ -0,0 +1,71 @@
+SOURCE_FILE@0..83
+  FN@0..82
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..82
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      EXPR_STMT@16..29
+        BLOCK_EXPR@16..29
+          L_CURLY@16..17 "{"
+          WHITESPACE@17..18 " "
+          ERROR@18..24
+            UNSAFE_KW@18..24 "unsafe"
+          WHITESPACE@24..25 " "
+          LITERAL@25..27
+            INT_NUMBER@25..27 "92"
+          WHITESPACE@27..28 " "
+          R_CURLY@28..29 "}"
+      WHITESPACE@29..34 "\n    "
+      EXPR_STMT@34..46
+        BLOCK_EXPR@34..46
+          L_CURLY@34..35 "{"
+          WHITESPACE@35..36 " "
+          ERROR@36..41
+            ASYNC_KW@36..41 "async"
+          WHITESPACE@41..42 " "
+          LITERAL@42..44
+            INT_NUMBER@42..44 "92"
+          WHITESPACE@44..45 " "
+          R_CURLY@45..46 "}"
+      WHITESPACE@46..51 "\n    "
+      EXPR_STMT@51..61
+        BLOCK_EXPR@51..61
+          L_CURLY@51..52 "{"
+          WHITESPACE@52..53 " "
+          EXPR_STMT@53..56
+            EFFECT_EXPR@53..56
+              TRY_KW@53..56 "try"
+          WHITESPACE@56..57 " "
+          LITERAL@57..59
+            INT_NUMBER@57..59 "92"
+          WHITESPACE@59..60 " "
+          R_CURLY@60..61 "}"
+      WHITESPACE@61..66 "\n    "
+      BLOCK_EXPR@66..80
+        L_CURLY@66..67 "{"
+        WHITESPACE@67..68 " "
+        EXPR_STMT@68..75
+          ERROR@68..75
+            LABEL@68..75
+              LIFETIME@68..74 "\'label"
+              COLON@74..75 ":"
+        WHITESPACE@75..76 " "
+        LITERAL@76..78
+          INT_NUMBER@76..78 "92"
+        WHITESPACE@78..79 " "
+        R_CURLY@79..80 "}"
+      WHITESPACE@80..81 "\n"
+      R_CURLY@81..82 "}"
+  WHITESPACE@82..83 "\n"
+error 24..24: expected existential, fn, trait or impl
+error 41..41: expected existential, fn, trait or impl
+error 56..56: expected a block
+error 75..75: expected a loop
+error 75..75: expected SEMICOLON
diff --git a/crates/syntax/test_data/parser/err/0043_weird_blocks.rs b/crates/syntax/test_data/parser/err/0043_weird_blocks.rs
new file mode 100644
index 00000000000..8fa324c1a14
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0043_weird_blocks.rs
@@ -0,0 +1,6 @@
+fn main() {
+    { unsafe 92 }
+    { async 92 }
+    { try 92 }
+    { 'label: 92 }
+}
diff --git a/crates/syntax/test_data/parser/err/0044_unexpected_for_type.rast b/crates/syntax/test_data/parser/err/0044_unexpected_for_type.rast
new file mode 100644
index 00000000000..71aa864943f
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0044_unexpected_for_type.rast
@@ -0,0 +1,240 @@
+SOURCE_FILE@0..239
+  TYPE_ALIAS@0..30
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..11
+      IDENT@5..11 "ForRef"
+    WHITESPACE@11..12 " "
+    EQ@12..13 "="
+    WHITESPACE@13..14 " "
+    FOR_TYPE@14..29
+      FOR_KW@14..17 "for"
+      GENERIC_PARAM_LIST@17..21
+        L_ANGLE@17..18 "<"
+        LIFETIME_PARAM@18..20
+          LIFETIME@18..20 "\'a"
+        R_ANGLE@20..21 ">"
+      WHITESPACE@21..22 " "
+      REF_TYPE@22..29
+        AMP@22..23 "&"
+        LIFETIME@23..25 "\'a"
+        WHITESPACE@25..26 " "
+        PATH_TYPE@26..29
+          PATH@26..29
+            PATH_SEGMENT@26..29
+              NAME_REF@26..29
+                IDENT@26..29 "u32"
+    SEMICOLON@29..30 ";"
+  WHITESPACE@30..31 "\n"
+  TYPE_ALIAS@31..64
+    TYPE_KW@31..35 "type"
+    WHITESPACE@35..36 " "
+    NAME@36..42
+      IDENT@36..42 "ForTup"
+    WHITESPACE@42..43 " "
+    EQ@43..44 "="
+    WHITESPACE@44..45 " "
+    FOR_TYPE@45..63
+      FOR_KW@45..48 "for"
+      GENERIC_PARAM_LIST@48..52
+        L_ANGLE@48..49 "<"
+        LIFETIME_PARAM@49..51
+          LIFETIME@49..51 "\'a"
+        R_ANGLE@51..52 ">"
+      WHITESPACE@52..53 " "
+      TUPLE_TYPE@53..63
+        L_PAREN@53..54 "("
+        REF_TYPE@54..61
+          AMP@54..55 "&"
+          LIFETIME@55..57 "\'a"
+          WHITESPACE@57..58 " "
+          PATH_TYPE@58..61
+            PATH@58..61
+              PATH_SEGMENT@58..61
+                NAME_REF@58..61
+                  IDENT@58..61 "u32"
+        COMMA@61..62 ","
+        R_PAREN@62..63 ")"
+    SEMICOLON@63..64 ";"
+  WHITESPACE@64..65 "\n"
+  TYPE_ALIAS@65..95
+    TYPE_KW@65..69 "type"
+    WHITESPACE@69..70 " "
+    NAME@70..78
+      IDENT@70..78 "ForSlice"
+    WHITESPACE@78..79 " "
+    EQ@79..80 "="
+    WHITESPACE@80..81 " "
+    FOR_TYPE@81..94
+      FOR_KW@81..84 "for"
+      GENERIC_PARAM_LIST@84..88
+        L_ANGLE@84..85 "<"
+        LIFETIME_PARAM@85..87
+          LIFETIME@85..87 "\'a"
+        R_ANGLE@87..88 ">"
+      WHITESPACE@88..89 " "
+      SLICE_TYPE@89..94
+        L_BRACK@89..90 "["
+        PATH_TYPE@90..93
+          PATH@90..93
+            PATH_SEGMENT@90..93
+              NAME_REF@90..93
+                IDENT@90..93 "u32"
+        R_BRACK@93..94 "]"
+    SEMICOLON@94..95 ";"
+  WHITESPACE@95..96 "\n"
+  TYPE_ALIAS@96..149
+    TYPE_KW@96..100 "type"
+    WHITESPACE@100..101 " "
+    NAME@101..109
+      IDENT@101..109 "ForForFn"
+    WHITESPACE@109..110 " "
+    EQ@110..111 "="
+    WHITESPACE@111..112 " "
+    FOR_TYPE@112..148
+      FOR_KW@112..115 "for"
+      GENERIC_PARAM_LIST@115..119
+        L_ANGLE@115..116 "<"
+        LIFETIME_PARAM@116..118
+          LIFETIME@116..118 "\'a"
+        R_ANGLE@118..119 ">"
+      WHITESPACE@119..120 " "
+      FOR_TYPE@120..148
+        FOR_KW@120..123 "for"
+        GENERIC_PARAM_LIST@123..127
+          L_ANGLE@123..124 "<"
+          LIFETIME_PARAM@124..126
+            LIFETIME@124..126 "\'b"
+          R_ANGLE@126..127 ">"
+        WHITESPACE@127..128 " "
+        FN_PTR_TYPE@128..148
+          FN_KW@128..130 "fn"
+          PARAM_LIST@130..148
+            L_PAREN@130..131 "("
+            PARAM@131..138
+              REF_TYPE@131..138
+                AMP@131..132 "&"
+                LIFETIME@132..134 "\'a"
+                WHITESPACE@134..135 " "
+                PATH_TYPE@135..138
+                  PATH@135..138
+                    PATH_SEGMENT@135..138
+                      NAME_REF@135..138
+                        IDENT@135..138 "i32"
+            COMMA@138..139 ","
+            WHITESPACE@139..140 " "
+            PARAM@140..147
+              REF_TYPE@140..147
+                AMP@140..141 "&"
+                LIFETIME@141..143 "\'b"
+                WHITESPACE@143..144 " "
+                PATH_TYPE@144..147
+                  PATH@144..147
+                    PATH_SEGMENT@144..147
+                      NAME_REF@144..147
+                        IDENT@144..147 "i32"
+            R_PAREN@147..148 ")"
+    SEMICOLON@148..149 ";"
+  WHITESPACE@149..150 "\n"
+  FN@150..238
+    FN_KW@150..152 "fn"
+    WHITESPACE@152..153 " "
+    NAME@153..164
+      IDENT@153..164 "for_for_for"
+    GENERIC_PARAM_LIST@164..167
+      L_ANGLE@164..165 "<"
+      TYPE_PARAM@165..166
+        NAME@165..166
+          IDENT@165..166 "T"
+      R_ANGLE@166..167 ">"
+    PARAM_LIST@167..169
+      L_PAREN@167..168 "("
+      R_PAREN@168..169 ")"
+    WHITESPACE@169..170 "\n"
+    WHERE_CLAUSE@170..234
+      WHERE_KW@170..175 "where"
+      WHITESPACE@175..180 "\n    "
+      WHERE_PRED@180..233
+        FOR_KW@180..183 "for"
+        GENERIC_PARAM_LIST@183..187
+          L_ANGLE@183..184 "<"
+          LIFETIME_PARAM@184..186
+            LIFETIME@184..186 "\'a"
+          R_ANGLE@186..187 ">"
+        WHITESPACE@187..188 " "
+        FOR_TYPE@188..227
+          FOR_KW@188..191 "for"
+          GENERIC_PARAM_LIST@191..195
+            L_ANGLE@191..192 "<"
+            LIFETIME_PARAM@192..194
+              LIFETIME@192..194 "\'b"
+            R_ANGLE@194..195 ">"
+          WHITESPACE@195..196 " "
+          FOR_TYPE@196..227
+            FOR_KW@196..199 "for"
+            GENERIC_PARAM_LIST@199..203
+              L_ANGLE@199..200 "<"
+              LIFETIME_PARAM@200..202
+                LIFETIME@200..202 "\'c"
+              R_ANGLE@202..203 ">"
+            WHITESPACE@203..204 " "
+            FN_PTR_TYPE@204..227
+              FN_KW@204..206 "fn"
+              PARAM_LIST@206..227
+                L_PAREN@206..207 "("
+                PARAM@207..212
+                  REF_TYPE@207..212
+                    AMP@207..208 "&"
+                    LIFETIME@208..210 "\'a"
+                    WHITESPACE@210..211 " "
+                    PATH_TYPE@211..212
+                      PATH@211..212
+                        PATH_SEGMENT@211..212
+                          NAME_REF@211..212
+                            IDENT@211..212 "T"
+                COMMA@212..213 ","
+                WHITESPACE@213..214 " "
+                PARAM@214..219
+                  REF_TYPE@214..219
+                    AMP@214..215 "&"
+                    LIFETIME@215..217 "\'b"
+                    WHITESPACE@217..218 " "
+                    PATH_TYPE@218..219
+                      PATH@218..219
+                        PATH_SEGMENT@218..219
+                          NAME_REF@218..219
+                            IDENT@218..219 "T"
+                COMMA@219..220 ","
+                WHITESPACE@220..221 " "
+                PARAM@221..226
+                  REF_TYPE@221..226
+                    AMP@221..222 "&"
+                    LIFETIME@222..224 "\'c"
+                    WHITESPACE@224..225 " "
+                    PATH_TYPE@225..226
+                      PATH@225..226
+                        PATH_SEGMENT@225..226
+                          NAME_REF@225..226
+                            IDENT@225..226 "T"
+                R_PAREN@226..227 ")"
+        COLON@227..228 ":"
+        WHITESPACE@228..229 " "
+        TYPE_BOUND_LIST@229..233
+          TYPE_BOUND@229..233
+            PATH_TYPE@229..233
+              PATH@229..233
+                PATH_SEGMENT@229..233
+                  NAME_REF@229..233
+                    IDENT@229..233 "Copy"
+      COMMA@233..234 ","
+    WHITESPACE@234..235 "\n"
+    BLOCK_EXPR@235..238
+      L_CURLY@235..236 "{"
+      WHITESPACE@236..237 "\n"
+      R_CURLY@237..238 "}"
+  WHITESPACE@238..239 "\n"
+error 21..21: expected a function pointer or path
+error 52..52: expected a function pointer or path
+error 88..88: expected a function pointer or path
+error 119..119: expected a function pointer or path
+error 195..195: expected a function pointer or path
diff --git a/crates/syntax/test_data/parser/err/0044_unexpected_for_type.rs b/crates/syntax/test_data/parser/err/0044_unexpected_for_type.rs
new file mode 100644
index 00000000000..0e9f8ccb4f8
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0044_unexpected_for_type.rs
@@ -0,0 +1,9 @@
+type ForRef = for<'a> &'a u32;
+type ForTup = for<'a> (&'a u32,);
+type ForSlice = for<'a> [u32];
+type ForForFn = for<'a> for<'b> fn(&'a i32, &'b i32);
+fn for_for_for<T>()
+where
+    for<'a> for<'b> for<'c> fn(&'a T, &'b T, &'c T): Copy,
+{
+}
diff --git a/crates/syntax/test_data/parser/err/0045_item_modifiers.rast b/crates/syntax/test_data/parser/err/0045_item_modifiers.rast
new file mode 100644
index 00000000000..a6e6552a99e
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0045_item_modifiers.rast
@@ -0,0 +1,45 @@
+SOURCE_FILE@0..50
+  ERROR@0..6
+    UNSAFE_KW@0..6 "unsafe"
+  WHITESPACE@6..7 " "
+  FN@7..24
+    ASYNC_KW@7..12 "async"
+    WHITESPACE@12..13 " "
+    FN_KW@13..15 "fn"
+    WHITESPACE@15..16 " "
+    NAME@16..19
+      IDENT@16..19 "foo"
+    PARAM_LIST@19..21
+      L_PAREN@19..20 "("
+      R_PAREN@20..21 ")"
+    WHITESPACE@21..22 " "
+    BLOCK_EXPR@22..24
+      L_CURLY@22..23 "{"
+      R_CURLY@23..24 "}"
+  WHITESPACE@24..25 "\n"
+  CONST@25..46
+    UNSAFE_KW@25..31 "unsafe"
+    WHITESPACE@31..32 " "
+    CONST_KW@32..37 "const"
+    WHITESPACE@37..38 " "
+    ERROR@38..40
+      FN_KW@38..40 "fn"
+    WHITESPACE@40..41 " "
+    PATH_TYPE@41..46
+      PATH@41..46
+        PATH_SEGMENT@41..46
+          NAME_REF@41..44
+            IDENT@41..44 "bar"
+          PARAM_LIST@44..46
+            L_PAREN@44..45 "("
+            R_PAREN@45..46 ")"
+  WHITESPACE@46..47 " "
+  ERROR@47..49
+    L_CURLY@47..48 "{"
+    R_CURLY@48..49 "}"
+  WHITESPACE@49..50 "\n"
+error 6..6: expected existential, fn, trait or impl
+error 38..38: expected a name
+error 40..40: expected COLON
+error 46..46: expected SEMICOLON
+error 47..47: expected an item
diff --git a/crates/syntax/test_data/parser/err/0045_item_modifiers.rs b/crates/syntax/test_data/parser/err/0045_item_modifiers.rs
new file mode 100644
index 00000000000..731e58013bd
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0045_item_modifiers.rs
@@ -0,0 +1,2 @@
+unsafe async fn foo() {}
+unsafe const fn bar() {}
diff --git a/crates/syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rast b/crates/syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rast
new file mode 100644
index 00000000000..5df7507e2de
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rast
@@ -0,0 +1 @@
+ERROR
diff --git a/crates/syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rs b/crates/syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rs
new file mode 100644
index 00000000000..ca49acb079e
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rs
@@ -0,0 +1 @@
+1 +
diff --git a/crates/syntax/test_data/parser/fragments/expr/ok/0000_add.rast b/crates/syntax/test_data/parser/fragments/expr/ok/0000_add.rast
new file mode 100644
index 00000000000..fa78a02a6bf
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/expr/ok/0000_add.rast
@@ -0,0 +1,8 @@
+BIN_EXPR@0..5
+  LITERAL@0..1
+    INT_NUMBER@0..1 "1"
+  WHITESPACE@1..2 " "
+  PLUS@2..3 "+"
+  WHITESPACE@3..4 " "
+  LITERAL@4..5
+    INT_NUMBER@4..5 "2"
diff --git a/crates/syntax/test_data/parser/fragments/expr/ok/0000_add.rs b/crates/syntax/test_data/parser/fragments/expr/ok/0000_add.rs
new file mode 100644
index 00000000000..e0ef5840209
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/expr/ok/0000_add.rs
@@ -0,0 +1 @@
+1 + 2
diff --git a/crates/syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rast b/crates/syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rast
new file mode 100644
index 00000000000..5df7507e2de
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rast
@@ -0,0 +1 @@
+ERROR
diff --git a/crates/syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rs b/crates/syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rs
new file mode 100644
index 00000000000..dc32389bbb7
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rs
@@ -0,0 +1 @@
+fn fn foo() {}
diff --git a/crates/syntax/test_data/parser/fragments/item/ok/0000_fn.rast b/crates/syntax/test_data/parser/fragments/item/ok/0000_fn.rast
new file mode 100644
index 00000000000..93c429e128c
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/item/ok/0000_fn.rast
@@ -0,0 +1,12 @@
+FN@0..11
+  FN_KW@0..2 "fn"
+  WHITESPACE@2..3 " "
+  NAME@3..6
+    IDENT@3..6 "foo"
+  PARAM_LIST@6..8
+    L_PAREN@6..7 "("
+    R_PAREN@7..8 ")"
+  WHITESPACE@8..9 " "
+  BLOCK_EXPR@9..11
+    L_CURLY@9..10 "{"
+    R_CURLY@10..11 "}"
diff --git a/crates/syntax/test_data/parser/fragments/item/ok/0000_fn.rs b/crates/syntax/test_data/parser/fragments/item/ok/0000_fn.rs
new file mode 100644
index 00000000000..8f3b7ef112a
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/item/ok/0000_fn.rs
@@ -0,0 +1 @@
+fn foo() {}
diff --git a/crates/syntax/test_data/parser/fragments/path/err/0000_reserved_word.rast b/crates/syntax/test_data/parser/fragments/path/err/0000_reserved_word.rast
new file mode 100644
index 00000000000..5df7507e2de
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/path/err/0000_reserved_word.rast
@@ -0,0 +1 @@
+ERROR
diff --git a/crates/syntax/test_data/parser/fragments/path/err/0000_reserved_word.rs b/crates/syntax/test_data/parser/fragments/path/err/0000_reserved_word.rs
new file mode 100644
index 00000000000..2046de04929
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/path/err/0000_reserved_word.rs
@@ -0,0 +1 @@
+struct
diff --git a/crates/syntax/test_data/parser/fragments/path/err/0001_expression.rast b/crates/syntax/test_data/parser/fragments/path/err/0001_expression.rast
new file mode 100644
index 00000000000..5df7507e2de
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/path/err/0001_expression.rast
@@ -0,0 +1 @@
+ERROR
diff --git a/crates/syntax/test_data/parser/fragments/path/err/0001_expression.rs b/crates/syntax/test_data/parser/fragments/path/err/0001_expression.rs
new file mode 100644
index 00000000000..745e8d376f7
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/path/err/0001_expression.rs
@@ -0,0 +1 @@
+a + b
diff --git a/crates/syntax/test_data/parser/fragments/path/ok/0000_single_ident.rast b/crates/syntax/test_data/parser/fragments/path/ok/0000_single_ident.rast
new file mode 100644
index 00000000000..0c5d4360fa8
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/path/ok/0000_single_ident.rast
@@ -0,0 +1,4 @@
+PATH@0..3
+  PATH_SEGMENT@0..3
+    NAME_REF@0..3
+      IDENT@0..3 "foo"
diff --git a/crates/syntax/test_data/parser/fragments/path/ok/0000_single_ident.rs b/crates/syntax/test_data/parser/fragments/path/ok/0000_single_ident.rs
new file mode 100644
index 00000000000..257cc5642cb
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/path/ok/0000_single_ident.rs
@@ -0,0 +1 @@
+foo
diff --git a/crates/syntax/test_data/parser/fragments/path/ok/0001_multipart.rast b/crates/syntax/test_data/parser/fragments/path/ok/0001_multipart.rast
new file mode 100644
index 00000000000..4a2b45e6a96
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/path/ok/0001_multipart.rast
@@ -0,0 +1,14 @@
+PATH@0..13
+  PATH@0..8
+    PATH@0..3
+      PATH_SEGMENT@0..3
+        NAME_REF@0..3
+          IDENT@0..3 "foo"
+    COLON2@3..5 "::"
+    PATH_SEGMENT@5..8
+      NAME_REF@5..8
+        IDENT@5..8 "bar"
+  COLON2@8..10 "::"
+  PATH_SEGMENT@10..13
+    NAME_REF@10..13
+      IDENT@10..13 "baz"
diff --git a/crates/syntax/test_data/parser/fragments/path/ok/0001_multipart.rs b/crates/syntax/test_data/parser/fragments/path/ok/0001_multipart.rs
new file mode 100644
index 00000000000..81e0b21cd41
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/path/ok/0001_multipart.rs
@@ -0,0 +1 @@
+foo::bar::baz
diff --git a/crates/syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rast b/crates/syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rast
new file mode 100644
index 00000000000..5df7507e2de
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rast
@@ -0,0 +1 @@
+ERROR
diff --git a/crates/syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rs b/crates/syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rs
new file mode 100644
index 00000000000..ae26fc45566
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rs
@@ -0,0 +1 @@
+fn
diff --git a/crates/syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rast b/crates/syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rast
new file mode 100644
index 00000000000..5df7507e2de
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rast
@@ -0,0 +1 @@
+ERROR
diff --git a/crates/syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rs b/crates/syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rs
new file mode 100644
index 00000000000..61a391d0846
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rs
@@ -0,0 +1 @@
+Some(x
diff --git a/crates/syntax/test_data/parser/fragments/pattern/ok/0000_enum.rast b/crates/syntax/test_data/parser/fragments/pattern/ok/0000_enum.rast
new file mode 100644
index 00000000000..dcf102339aa
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/pattern/ok/0000_enum.rast
@@ -0,0 +1,10 @@
+TUPLE_STRUCT_PAT@0..7
+  PATH@0..4
+    PATH_SEGMENT@0..4
+      NAME_REF@0..4
+        IDENT@0..4 "Some"
+  L_PAREN@4..5 "("
+  IDENT_PAT@5..6
+    NAME@5..6
+      IDENT@5..6 "x"
+  R_PAREN@6..7 ")"
diff --git a/crates/syntax/test_data/parser/fragments/pattern/ok/0000_enum.rs b/crates/syntax/test_data/parser/fragments/pattern/ok/0000_enum.rs
new file mode 100644
index 00000000000..87114dd7881
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/pattern/ok/0000_enum.rs
@@ -0,0 +1 @@
+Some(x)
diff --git a/crates/syntax/test_data/parser/fragments/type/err/0000_missing_close.rast b/crates/syntax/test_data/parser/fragments/type/err/0000_missing_close.rast
new file mode 100644
index 00000000000..5df7507e2de
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/type/err/0000_missing_close.rast
@@ -0,0 +1 @@
+ERROR
diff --git a/crates/syntax/test_data/parser/fragments/type/err/0000_missing_close.rs b/crates/syntax/test_data/parser/fragments/type/err/0000_missing_close.rs
new file mode 100644
index 00000000000..caa4d7c0927
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/type/err/0000_missing_close.rs
@@ -0,0 +1 @@
+Result<Foo, Bar
diff --git a/crates/syntax/test_data/parser/fragments/type/ok/0000_result.rast b/crates/syntax/test_data/parser/fragments/type/ok/0000_result.rast
new file mode 100644
index 00000000000..38c15b5815e
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/type/ok/0000_result.rast
@@ -0,0 +1,22 @@
+PATH_TYPE@0..16
+  PATH@0..16
+    PATH_SEGMENT@0..16
+      NAME_REF@0..6
+        IDENT@0..6 "Result"
+      GENERIC_ARG_LIST@6..16
+        L_ANGLE@6..7 "<"
+        TYPE_ARG@7..10
+          PATH_TYPE@7..10
+            PATH@7..10
+              PATH_SEGMENT@7..10
+                NAME_REF@7..10
+                  IDENT@7..10 "Foo"
+        COMMA@10..11 ","
+        WHITESPACE@11..12 " "
+        TYPE_ARG@12..15
+          PATH_TYPE@12..15
+            PATH@12..15
+              PATH_SEGMENT@12..15
+                NAME_REF@12..15
+                  IDENT@12..15 "Bar"
+        R_ANGLE@15..16 ">"
diff --git a/crates/syntax/test_data/parser/fragments/type/ok/0000_result.rs b/crates/syntax/test_data/parser/fragments/type/ok/0000_result.rs
new file mode 100644
index 00000000000..b50b3bb3bfd
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/type/ok/0000_result.rs
@@ -0,0 +1 @@
+Result<Foo, Bar>
diff --git a/crates/syntax/test_data/parser/fuzz-failures/0000.rs b/crates/syntax/test_data/parser/fuzz-failures/0000.rs
new file mode 100644
index 00000000000..f1d0dc34382
--- /dev/null
+++ b/crates/syntax/test_data/parser/fuzz-failures/0000.rs
@@ -0,0 +1,199 @@
+//! An experimental implementation of [Rust RFC#2256 lrs);
+        let root = SyntaxNode::new_owned(root);
+        validate_block_structure(root.borrowed());
+        File { root }
+    }
+    pub fn parse(text: &str) -> File {
+        let tokens = tokenize(&text);
+        let (green, errors) = parser_impl::parse_with::<syntax_node::GreenBuilder>(
+            text, &tokens, grammar::root,
+        );
+        File::new(green, errors)
+    }
+    pub fn reparse(&self, edit: &AtomTextEdit) -> File {
+        self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit))
+    }
+    pub fn incremental_reparse(&self, edit: &AtomTextEdit) -> Option<File> {
+        let (node, reparser) = find_reparsable_node(self.syntax(), edit.delete)?;
+        let text = replace_range(
+            node.text().to_string(),
+            edit.delete - node.range().start(),
+            &edit.insert,
+        );
+        let tokens = tokenize(&text);
+        if !is_balanced(&tokens) {
+            return None;
+        }
+        let (green, new_errors) = parser_impl::parse_with::<syntax_node::GreenBuilder>(
+            &te2t, &tokens, reparser,
+        );
+        let green_root = node.replace_with(green);
+        let errors = merge_errors(self.errors(), new_errors, node, edit);
+        Some(File::new(green_root, errors))
+    }
+    fn full_reparse(&self, edit: &AtomTextEdit) -> File {
+        let text = replace_range(self.syntax().text().to_string(), edit.delete, &edit.insert);
+        File::parse(&text)
+    }
+    pub fn ast(&self) -> ast::Root {
+        ast::Root::cast(self.syntax()).unwrap()
+    }
+    pub fn syntax(&self) -> SyntaxNodeRef {
+        self.root.brroowed()
+    }
+    mp_tree(root),
+                    );
+                    assert!(
+                        node.next_sibling().is_none() && pair.prev_sibling().is_none(),
+                        "\nfloating curlys at {:?}\nfile:\n{}\nerror:\n{}\n",
+                        node,
+                        root.text(),
+                        node.text(),
+                    );
+                }
+            }
+            _ => (),
+        }
+    }
+}
+
+#[derive(Debug, Clone)]
+pub struct AtomTextEdit {
+    pub delete: TextRange,
+    pub insert: String,
+}
+
+impl AtomTextEdit {
+    pub fn replace(range: TextRange, replace_with: String) -> AtomTextEdit {
+        AtomTextEdit { delete: range, insert: replace_with }
+    }
+
+    pub fn delete(range: TextRange) -> AtomTextEdit {
+        AtomTextEdit::replace(range, String::new())
+    }
+
+    pub fn insert(offset: TextUnit, text: String) -> AtomTextEdit {
+        AtomTextEdit::replace(TextRange::offset_len(offset, 0.into()), text)
+    }
+}
+
+fn find_reparsable_node(node: SyntaxNodeRef, range: TextRange) -> Option<(SyntaxNodeRef, fn(&mut Parser))> {
+    let node = algo::find_covering_node(node, range);
+    return algo::ancestors(node)
+        .filter_map(|node| reparser(node).map(|r| (node, r)))
+        .next();
+
+    fn reparser(node: SyntaxNodeRef) -> Option<fn(&mut Parser)> {
+        let res = match node.kind() {
+            BLOCK => grammar::block,
+            RECORD_FIELD_LIST => grammar::record_field_list,
+            _ => return None,
+        };
+        Some(res)
+    }
+}
+
+pub /*(meh)*/ fn replace_range(mut text: String, range: TextRange, replace_with: &str) -> String {
+    let start = u32::from(range.start()) as usize;
+    let end = u32::from(range.end()) as usize;
+    text.replace_range(start..end, replace_with);
+    text
+}
+
+fn is_balanced(tokens: &[Token]) -> bool {
+    if tokens.len() == 0
+       || tokens.first().unwrap().kind != L_CURLY
+       || tokens.last().unwrap().kind != R_CURLY {
+        return false
+    }
+    let mut balance = 0usize;
+    for t in tokens.iter() {
+        match t.kind {
+            L_CURLYt {
+    pub delete: TextRange,
+    pub insert: String,
+}
+
+impl AtomTextEdit {
+    pub fn replace(range: TextRange, replace_with: String) -> AtomTextEdit {
+        AtomTextEdit { delete: range, insert: replace_with }
+    }
+
+    pub fn delete(range: TextRange) -> AtomTextEdit {
+        AtomTextEdit::replace(range, String::new())
+    }
+
+    pub fn insert(offset: TextUnit, text: String) -> AtomTextEdit {
+        AtomTextEdit::replace(TextRange::offset_len(offset, 0.into()), text)
+    }
+}
+
+fn find_reparsable_node(node: SyntaxNodeRef, range: TextRange) -> Option<(SyntaxNodeRef, fn(&mut Parser))> {
+    let node = algo::find_covering_node(node, range);
+    return algo::ancestors(node)
+        .filter_map(|node| reparser(node).map(|r| (node, r)))
+        .next();
+
+    fn reparser(node: SyntaxNodeRef) -> Option<fn(&mut Parser)> {
+        let res = match node.kind() {
+     ;
+    let end = u32::from(range.end()) as usize;
+    text.replaT => grammar::record_field_list,
+            _ => return None,
+        };
+        Some(res)
+    }
+}
+
+pub /*(meh)*/ fn replace_range(mut text: String, range: TextRange, replace_with: &str) -> String {
+    let start = u32::from(range.start()) as usize;
+    let end = u32::from(range.end()) as usize;
+    text.replace_range(start..end, replace_with);
+    text
+}
+
+fn is_balanced(tokens: &[Token]) -> bool {
+    if tokens.len() == 0
+       || tokens.first().unwrap().kind != L_CURLY
+       || tokens.last().unwrap().kind != R_CURLY {
+        return false
+    }
+    let mut balance = 0usize;
+    for t in tokens.iter() {
+        match t.kind {
+            L_CURLY => balance += 1,
+            R_CURLY => balance = match balance.checked_sub(1) {
+                Some(b) => b,
+                None => return false,
+            },
+            _ => (),
+        }
+    }
+    balance == 0
+}
+
+fn merge_errors(
+    old_errors: Vec<SyntaxError>,
+    new_errors: Vec<SyntaxError>,
+    old_node: SyntaxNodeRef,
+    edit: &AtomTextEdit,
+) -> Vec<SyntaxError> {
+    let mut res = Vec::new();
+    for e in old_errors {
+        if e.offset < old_node.range().start() {
+            res.push(e)
+        } else if e.offset > old_node.range().end() {
+            res.push(SyntaxError {
+                msg: e.msg,
+                offset: e.offset + TextUnit::of_str(&edit.insert) - edit.delete.len(),
+            })
+        }
+    }
+    for e in new_errors {
+        res.push(SyntaxError {
+            msg: e.msg,
+            offset: e.offset + old_node.range().start(),
+        })
+    }
+    res
+}
diff --git a/crates/syntax/test_data/parser/fuzz-failures/0001.rs b/crates/syntax/test_data/parser/fuzz-failures/0001.rs
new file mode 100644
index 00000000000..f1148058efd
--- /dev/null
+++ b/crates/syntax/test_data/parser/fuzz-failures/0001.rs
@@ -0,0 +1,106 @@
+use syntax::{
+    File, TextRange, SyntaxNodeRef, TextUnit,
+    SyntaxKind::*,
+    algo::{find_leaf_at_offset, LeafAtOffset, find_covering_node, ancestors, Direction, siblings},
+};
+
+pub fn extend_selection(file: &File, range: TextRange) -> Option<TextRange> {
+    let syntax = file.syntax();
+    extend(syntax.borrowed(), range)
+}
+
+pub(crate) fn extend(root: SyntaxNodeRef, range: TextRange) -> Option<TextRange> {
+    if range.is_empty() {
+        let offset = range.start();
+        let mut leaves = find_leaf_at_offset(root, offset);
+        if leaves.clone().all(|it| it.kind() == WHITESPACE) {
+            return Some(extend_ws(root, leaves.next()?, offset));
+        }
+        let leaf = match leaves {
+            LeafAtOffset::None => return None,
+            LeafAtOffset::Single(l) => l,
+            LeafAtOffset::Between(l, r) => pick_best(l, r),
+        };
+        return Some(leaf.range());
+    };
+    let node = find_covering_node(root, range);
+    if node.kind() == COMMENT && range == node.range() {
+        if let Some(range) = extend_comments(node) {
+            return Some(range);
+        }
+    }
+
+    match ancestors(node).skip_while(|n| n.range() == range).next() {
+        None => None,
+        Some(parent) => Some(parent.range()),
+    }
+}
+
+fn extend_ws(root: SyntaxNodeRef, ws: SyntaxNodeRef, offset: TextUnit) -> TextRange {
+    let ws_text = ws.leaf_text().unwrap();
+    let suffix = TextRange::from_to(offset, ws.range().end()) - ws.range().start();
+    let prefix = TextRange::from_to(ws.range().start(), offset) - ws.range().start();
+    let ws_suffix = &ws_text.as_str()[suffix];
+    let ws_prefix = &ws_text.as_str()[prefix];
+    if ws_text.contains("\n") && !ws_suffix.contains("\n") {
+        if let Some(node) = ws.next_sibling() {
+            let start = match ws_prefix.rfind('\n') {
+                Some(idx) => ws.range().start() + TextUnit::from((idx + 1) as u32),
+                None => node.range().start()
+            };
+            let end = if root.text().char_at(node.range().end()) == Some('\n') {
+                node.range().end() + TextUnit::of_char('\n')
+            } else {
+                node.range().end()
+            };
+            return TextRange::from_to(start, end);
+        }
+    }
+    ws.range()
+}
+
+fn pick_best<'a>(l: SyntaxNodeRef<'a>, r: Syntd[axNodeRef<'a>) -> SyntaxNodeRef<'a> {
+    return if priority(r) > priority(l) { r } else { l };
+    fn priority(n: SyntaxNodeRef) -> usize {
+        match n.kind() {
+            WHITESPACE => 0,
+            IDENT | SELF_KW | SUPER_KW | CRATE_KW => 2,
+            _ => 1,
+        }
+    }
+}
+
+fn extend_comments(node: SyntaxNodeRef) -> Option<TextRange> {
+    let left = adj_com[ments(node, Direction::Backward);
+    let right = adj_comments(node, Direction::Forward);
+    if left != right {
+        Some(TextRange::from_to(
+            left.range().start(),
+            right.range().end(),
+        ))
+    } else {
+        None
+    }
+}
+
+fn adj_comments(node: SyntaxNodeRef, dir: Direction) -> SyntaxNodeRef {
+    let mut res = node;
+    for node in siblings(node, dir) {
+        match node.kind() {
+            COMMENT => res = node,
+            WHITESPACE if !node.leaf_text().unwrap().as_str().contains("\n\n") => (),
+            _ => break
+        }
+    }
+    res
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use test_utils::extract_offset;
+
+    fn do_check(before: &str, afters: &[&str]) {
+        let (cursor, before) = extract_offset(before);
+        let file = File::parse(&before);
+        let mut range = TextRange::of
diff --git a/crates/syntax/test_data/parser/fuzz-failures/0002.rs b/crates/syntax/test_data/parser/fuzz-failures/0002.rs
new file mode 100644
index 00000000000..f35dc728948
--- /dev/null
+++ b/crates/syntax/test_data/parser/fuzz-failures/0002.rs
@@ -0,0 +1 @@
+!('\
\ No newline at end of file
diff --git a/crates/syntax/test_data/parser/fuzz-failures/0003.rs b/crates/syntax/test_data/parser/fuzz-failures/0003.rs
new file mode 100644
index 00000000000..0f59c472269
--- /dev/null
+++ b/crates/syntax/test_data/parser/fuzz-failures/0003.rs
@@ -0,0 +1 @@
+if'\xɿ
\ No newline at end of file
diff --git a/crates/syntax/test_data/parser/fuzz-failures/0004.rs b/crates/syntax/test_data/parser/fuzz-failures/0004.rs
new file mode 100644
index 00000000000..003290f52f6
--- /dev/null
+++ b/crates/syntax/test_data/parser/fuzz-failures/0004.rs
@@ -0,0 +1 @@
+b"\xʿ
\ No newline at end of file
diff --git a/crates/syntax/test_data/parser/inline/err/0001_array_type_missing_semi.rast b/crates/syntax/test_data/parser/inline/err/0001_array_type_missing_semi.rast
new file mode 100644
index 00000000000..0b9bbec0776
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0001_array_type_missing_semi.rast
@@ -0,0 +1,27 @@
+SOURCE_FILE@0..18
+  TYPE_ALIAS@0..12
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "T"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    SLICE_TYPE@9..12
+      L_BRACK@9..10 "["
+      TUPLE_TYPE@10..12
+        L_PAREN@10..11 "("
+        R_PAREN@11..12 ")"
+  WHITESPACE@12..13 " "
+  ERROR@13..15
+    INT_NUMBER@13..15 "92"
+  ERROR@15..16
+    R_BRACK@15..16 "]"
+  ERROR@16..17
+    SEMICOLON@16..17 ";"
+  WHITESPACE@17..18 "\n"
+error 12..12: expected `;` or `]`
+error 12..12: expected SEMICOLON
+error 13..13: expected an item
+error 15..15: expected an item
+error 16..16: expected an item
diff --git a/crates/syntax/test_data/parser/inline/err/0001_array_type_missing_semi.rs b/crates/syntax/test_data/parser/inline/err/0001_array_type_missing_semi.rs
new file mode 100644
index 00000000000..a9485144320
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0001_array_type_missing_semi.rs
@@ -0,0 +1 @@
+type T = [() 92];
diff --git a/crates/syntax/test_data/parser/inline/err/0002_misplaced_label_err.rast b/crates/syntax/test_data/parser/inline/err/0002_misplaced_label_err.rast
new file mode 100644
index 00000000000..a4271fc87ab
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0002_misplaced_label_err.rast
@@ -0,0 +1,28 @@
+SOURCE_FILE@0..30
+  FN@0..29
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..29
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      EXPR_STMT@16..22
+        ERROR@16..22
+          LABEL@16..22
+            LIFETIME@16..21 "\'loop"
+            COLON@21..22 ":"
+      WHITESPACE@22..23 " "
+      IMPL@23..27
+        IMPL_KW@23..27 "impl"
+      WHITESPACE@27..28 "\n"
+      R_CURLY@28..29 "}"
+  WHITESPACE@29..30 "\n"
+error 22..22: expected a loop
+error 22..22: expected SEMICOLON
+error 27..27: expected type
+error 27..27: expected `{`
diff --git a/crates/syntax/test_data/parser/inline/err/0002_misplaced_label_err.rs b/crates/syntax/test_data/parser/inline/err/0002_misplaced_label_err.rs
new file mode 100644
index 00000000000..a2164c5105c
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0002_misplaced_label_err.rs
@@ -0,0 +1,3 @@
+fn main() {
+    'loop: impl
+}
diff --git a/crates/syntax/test_data/parser/inline/err/0003_pointer_type_no_mutability.rast b/crates/syntax/test_data/parser/inline/err/0003_pointer_type_no_mutability.rast
new file mode 100644
index 00000000000..0d8bf6dd6b6
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0003_pointer_type_no_mutability.rast
@@ -0,0 +1,17 @@
+SOURCE_FILE@0..14
+  TYPE_ALIAS@0..13
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "T"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    PTR_TYPE@9..12
+      STAR@9..10 "*"
+      TUPLE_TYPE@10..12
+        L_PAREN@10..11 "("
+        R_PAREN@11..12 ")"
+    SEMICOLON@12..13 ";"
+  WHITESPACE@13..14 "\n"
+error 10..10: expected mut or const in raw pointer type (use `*mut T` or `*const T` as appropriate)
diff --git a/crates/syntax/test_data/parser/inline/err/0003_pointer_type_no_mutability.rs b/crates/syntax/test_data/parser/inline/err/0003_pointer_type_no_mutability.rs
new file mode 100644
index 00000000000..fae70513133
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0003_pointer_type_no_mutability.rs
@@ -0,0 +1 @@
+type T = *();
diff --git a/crates/syntax/test_data/parser/inline/err/0004_impl_type.rast b/crates/syntax/test_data/parser/inline/err/0004_impl_type.rast
new file mode 100644
index 00000000000..29d6b397402
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0004_impl_type.rast
@@ -0,0 +1,79 @@
+SOURCE_FILE@0..87
+  IMPL@0..12
+    IMPL_KW@0..4 "impl"
+    WHITESPACE@4..5 " "
+    PATH_TYPE@5..9
+      PATH@5..9
+        PATH_SEGMENT@5..9
+          NAME_REF@5..9
+            IDENT@5..9 "Type"
+    WHITESPACE@9..10 " "
+    ASSOC_ITEM_LIST@10..12
+      L_CURLY@10..11 "{"
+      R_CURLY@11..12 "}"
+  WHITESPACE@12..13 "\n"
+  IMPL@13..33
+    IMPL_KW@13..17 "impl"
+    WHITESPACE@17..18 " "
+    PATH_TYPE@18..24
+      PATH@18..24
+        PATH_SEGMENT@18..24
+          NAME_REF@18..24
+            IDENT@18..24 "Trait1"
+    WHITESPACE@24..25 " "
+    FOR_KW@25..28 "for"
+    WHITESPACE@28..29 " "
+    PATH_TYPE@29..30
+      PATH@29..30
+        PATH_SEGMENT@29..30
+          NAME_REF@29..30
+            IDENT@29..30 "T"
+    WHITESPACE@30..31 " "
+    ASSOC_ITEM_LIST@31..33
+      L_CURLY@31..32 "{"
+      R_CURLY@32..33 "}"
+  WHITESPACE@33..34 "\n"
+  IMPL@34..38
+    IMPL_KW@34..38 "impl"
+  WHITESPACE@38..39 " "
+  IMPL@39..54
+    IMPL_KW@39..43 "impl"
+    WHITESPACE@43..44 " "
+    PATH_TYPE@44..51
+      PATH@44..51
+        PATH_SEGMENT@44..51
+          NAME_REF@44..51
+            IDENT@44..51 "NotType"
+    WHITESPACE@51..52 " "
+    ASSOC_ITEM_LIST@52..54
+      L_CURLY@52..53 "{"
+      R_CURLY@53..54 "}"
+  WHITESPACE@54..55 "\n"
+  IMPL@55..70
+    IMPL_KW@55..59 "impl"
+    WHITESPACE@59..60 " "
+    PATH_TYPE@60..66
+      PATH@60..66
+        PATH_SEGMENT@60..66
+          NAME_REF@60..66
+            IDENT@60..66 "Trait2"
+    WHITESPACE@66..67 " "
+    FOR_KW@67..70 "for"
+  WHITESPACE@70..71 " "
+  IMPL@71..86
+    IMPL_KW@71..75 "impl"
+    WHITESPACE@75..76 " "
+    PATH_TYPE@76..83
+      PATH@76..83
+        PATH_SEGMENT@76..83
+          NAME_REF@76..83
+            IDENT@76..83 "NotType"
+    WHITESPACE@83..84 " "
+    ASSOC_ITEM_LIST@84..86
+      L_CURLY@84..85 "{"
+      R_CURLY@85..86 "}"
+  WHITESPACE@86..87 "\n"
+error 38..38: expected trait or type
+error 38..38: expected `{`
+error 70..70: expected trait or type
+error 70..70: expected `{`
diff --git a/crates/syntax/test_data/parser/inline/err/0004_impl_type.rs b/crates/syntax/test_data/parser/inline/err/0004_impl_type.rs
new file mode 100644
index 00000000000..b8c7b65e31d
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0004_impl_type.rs
@@ -0,0 +1,4 @@
+impl Type {}
+impl Trait1 for T {}
+impl impl NotType {}
+impl Trait2 for impl NotType {}
diff --git a/crates/syntax/test_data/parser/inline/err/0005_fn_pointer_type_missing_fn.rast b/crates/syntax/test_data/parser/inline/err/0005_fn_pointer_type_missing_fn.rast
new file mode 100644
index 00000000000..776022fd936
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0005_fn_pointer_type_missing_fn.rast
@@ -0,0 +1,23 @@
+SOURCE_FILE@0..20
+  TYPE_ALIAS@0..15
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "F"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    UNSAFE_KW@9..15 "unsafe"
+  WHITESPACE@15..16 " "
+  ERROR@16..17
+    L_PAREN@16..17 "("
+  ERROR@17..18
+    R_PAREN@17..18 ")"
+  ERROR@18..19
+    SEMICOLON@18..19 ";"
+  WHITESPACE@19..20 "\n"
+error 15..15: expected `fn`
+error 15..15: expected SEMICOLON
+error 16..16: expected an item
+error 17..17: expected an item
+error 18..18: expected an item
diff --git a/crates/syntax/test_data/parser/inline/err/0005_fn_pointer_type_missing_fn.rs b/crates/syntax/test_data/parser/inline/err/0005_fn_pointer_type_missing_fn.rs
new file mode 100644
index 00000000000..f014914ff9f
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0005_fn_pointer_type_missing_fn.rs
@@ -0,0 +1 @@
+type F = unsafe ();
diff --git a/crates/syntax/test_data/parser/inline/err/0006_unsafe_block_in_mod.rast b/crates/syntax/test_data/parser/inline/err/0006_unsafe_block_in_mod.rast
new file mode 100644
index 00000000000..cc0f8bcaf9f
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0006_unsafe_block_in_mod.rast
@@ -0,0 +1,35 @@
+SOURCE_FILE@0..33
+  FN@0..10
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    BLOCK_EXPR@8..10
+      L_CURLY@8..9 "{"
+      R_CURLY@9..10 "}"
+  WHITESPACE@10..11 " "
+  ERROR@11..17
+    UNSAFE_KW@11..17 "unsafe"
+  WHITESPACE@17..18 " "
+  ERROR@18..21
+    L_CURLY@18..19 "{"
+    WHITESPACE@19..20 " "
+    R_CURLY@20..21 "}"
+  WHITESPACE@21..22 " "
+  FN@22..32
+    FN_KW@22..24 "fn"
+    WHITESPACE@24..25 " "
+    NAME@25..28
+      IDENT@25..28 "bar"
+    PARAM_LIST@28..30
+      L_PAREN@28..29 "("
+      R_PAREN@29..30 ")"
+    BLOCK_EXPR@30..32
+      L_CURLY@30..31 "{"
+      R_CURLY@31..32 "}"
+  WHITESPACE@32..33 "\n"
+error 11..11: expected an item
+error 18..18: expected an item
diff --git a/crates/syntax/test_data/parser/inline/err/0006_unsafe_block_in_mod.rs b/crates/syntax/test_data/parser/inline/err/0006_unsafe_block_in_mod.rs
new file mode 100644
index 00000000000..26141e90491
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0006_unsafe_block_in_mod.rs
@@ -0,0 +1 @@
+fn foo(){} unsafe { } fn bar(){}
diff --git a/crates/syntax/test_data/parser/inline/err/0007_async_without_semicolon.rast b/crates/syntax/test_data/parser/inline/err/0007_async_without_semicolon.rast
new file mode 100644
index 00000000000..2c9570678ed
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0007_async_without_semicolon.rast
@@ -0,0 +1,31 @@
+SOURCE_FILE@0..30
+  FN@0..29
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..29
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..11 " "
+      LET_STMT@11..27
+        LET_KW@11..14 "let"
+        WHITESPACE@14..15 " "
+        WILDCARD_PAT@15..16
+          UNDERSCORE@15..16 "_"
+        WHITESPACE@16..17 " "
+        EQ@17..18 "="
+        WHITESPACE@18..19 " "
+        EFFECT_EXPR@19..27
+          ASYNC_KW@19..24 "async"
+          WHITESPACE@24..25 " "
+          BLOCK_EXPR@25..27
+            L_CURLY@25..26 "{"
+            R_CURLY@26..27 "}"
+      WHITESPACE@27..28 " "
+      R_CURLY@28..29 "}"
+  WHITESPACE@29..30 "\n"
+error 27..27: expected SEMICOLON
diff --git a/crates/syntax/test_data/parser/inline/err/0007_async_without_semicolon.rs b/crates/syntax/test_data/parser/inline/err/0007_async_without_semicolon.rs
new file mode 100644
index 00000000000..9a423248c27
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0007_async_without_semicolon.rs
@@ -0,0 +1 @@
+fn foo() { let _ = async {} }
diff --git a/crates/syntax/test_data/parser/inline/err/0008_pub_expr.rast b/crates/syntax/test_data/parser/inline/err/0008_pub_expr.rast
new file mode 100644
index 00000000000..63a10127dd9
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0008_pub_expr.rast
@@ -0,0 +1,25 @@
+SOURCE_FILE@0..21
+  FN@0..20
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..20
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..11 " "
+      ERROR@11..14
+        VISIBILITY@11..14
+          PUB_KW@11..14 "pub"
+      WHITESPACE@14..15 " "
+      EXPR_STMT@15..18
+        LITERAL@15..17
+          INT_NUMBER@15..17 "92"
+        SEMICOLON@17..18 ";"
+      WHITESPACE@18..19 " "
+      R_CURLY@19..20 "}"
+  WHITESPACE@20..21 "\n"
+error 14..14: expected an item
diff --git a/crates/syntax/test_data/parser/inline/err/0008_pub_expr.rs b/crates/syntax/test_data/parser/inline/err/0008_pub_expr.rs
new file mode 100644
index 00000000000..2976f68625f
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0008_pub_expr.rs
@@ -0,0 +1 @@
+fn foo() { pub 92; }
diff --git a/crates/syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.rast b/crates/syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.rast
new file mode 100644
index 00000000000..8fd8d5e593a
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.rast
@@ -0,0 +1,58 @@
+SOURCE_FILE@0..48
+  FN@0..47
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..47
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..14 "\n   "
+      EXPR_STMT@14..25
+        ATTR@14..18
+          POUND@14..15 "#"
+          L_BRACK@15..16 "["
+          PATH@16..17
+            PATH_SEGMENT@16..17
+              NAME_REF@16..17
+                IDENT@16..17 "A"
+          R_BRACK@17..18 "]"
+        WHITESPACE@18..19 " "
+        BIN_EXPR@19..24
+          LITERAL@19..20
+            INT_NUMBER@19..20 "1"
+          WHITESPACE@20..21 " "
+          PLUS@21..22 "+"
+          WHITESPACE@22..23 " "
+          LITERAL@23..24
+            INT_NUMBER@23..24 "2"
+        SEMICOLON@24..25 ";"
+      WHITESPACE@25..29 "\n   "
+      EXPR_STMT@29..45
+        ATTR@29..33
+          POUND@29..30 "#"
+          L_BRACK@30..31 "["
+          PATH@31..32
+            PATH_SEGMENT@31..32
+              NAME_REF@31..32
+                IDENT@31..32 "B"
+          R_BRACK@32..33 "]"
+        WHITESPACE@33..34 " "
+        IF_EXPR@34..44
+          IF_KW@34..36 "if"
+          WHITESPACE@36..37 " "
+          CONDITION@37..41
+            LITERAL@37..41
+              TRUE_KW@37..41 "true"
+          WHITESPACE@41..42 " "
+          BLOCK_EXPR@42..44
+            L_CURLY@42..43 "{"
+            R_CURLY@43..44 "}"
+        SEMICOLON@44..45 ";"
+      WHITESPACE@45..46 "\n"
+      R_CURLY@46..47 "}"
+  WHITESPACE@47..48 "\n"
+error 24..24: attributes are not allowed on BIN_EXPR
diff --git a/crates/syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.rs b/crates/syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.rs
new file mode 100644
index 00000000000..d725a07ce96
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.rs
@@ -0,0 +1,4 @@
+fn foo() {
+   #[A] 1 + 2;
+   #[B] if true {};
+}
diff --git a/crates/syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.rast b/crates/syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.rast
new file mode 100644
index 00000000000..fa14e1e6de5
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.rast
@@ -0,0 +1,52 @@
+SOURCE_FILE@0..47
+  FN@0..46
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..46
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..20
+        FIELD_EXPR@15..19
+          PATH_EXPR@15..16
+            PATH@15..16
+              PATH_SEGMENT@15..16
+                NAME_REF@15..16
+                  IDENT@15..16 "x"
+          DOT@16..17 "."
+          FLOAT_NUMBER@17..19 "0."
+        SEMICOLON@19..20 ";"
+      WHITESPACE@20..25 "\n    "
+      EXPR_STMT@25..32
+        FIELD_EXPR@25..31
+          PATH_EXPR@25..26
+            PATH@25..26
+              PATH_SEGMENT@25..26
+                NAME_REF@25..26
+                  IDENT@25..26 "x"
+          DOT@26..27 "."
+          NAME_REF@27..31
+            INT_NUMBER@27..31 "1i32"
+        SEMICOLON@31..32 ";"
+      WHITESPACE@32..37 "\n    "
+      EXPR_STMT@37..44
+        FIELD_EXPR@37..43
+          PATH_EXPR@37..38
+            PATH@37..38
+              PATH_SEGMENT@37..38
+                NAME_REF@37..38
+                  IDENT@37..38 "x"
+          DOT@38..39 "."
+          NAME_REF@39..43
+            INT_NUMBER@39..43 "0x01"
+        SEMICOLON@43..44 ";"
+      WHITESPACE@44..45 "\n"
+      R_CURLY@45..46 "}"
+  WHITESPACE@46..47 "\n"
+error 27..31: Tuple (struct) field access is only allowed through decimal integers with no underscores or suffix
+error 39..43: Tuple (struct) field access is only allowed through decimal integers with no underscores or suffix
diff --git a/crates/syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.rs b/crates/syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.rs
new file mode 100644
index 00000000000..30cc4913899
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.rs
@@ -0,0 +1,5 @@
+fn foo() {
+    x.0.;
+    x.1i32;
+    x.0x01;
+}
diff --git a/crates/syntax/test_data/parser/inline/err/0013_static_underscore.rast b/crates/syntax/test_data/parser/inline/err/0013_static_underscore.rast
new file mode 100644
index 00000000000..8d761b90741
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0013_static_underscore.rast
@@ -0,0 +1,21 @@
+SOURCE_FILE@0..19
+  STATIC@0..18
+    STATIC_KW@0..6 "static"
+    WHITESPACE@6..7 " "
+    ERROR@7..8
+      UNDERSCORE@7..8 "_"
+    COLON@8..9 ":"
+    WHITESPACE@9..10 " "
+    PATH_TYPE@10..13
+      PATH@10..13
+        PATH_SEGMENT@10..13
+          NAME_REF@10..13
+            IDENT@10..13 "i32"
+    WHITESPACE@13..14 " "
+    EQ@14..15 "="
+    WHITESPACE@15..16 " "
+    LITERAL@16..17
+      INT_NUMBER@16..17 "5"
+    SEMICOLON@17..18 ";"
+  WHITESPACE@18..19 "\n"
+error 7..7: expected a name
diff --git a/crates/syntax/test_data/parser/inline/err/0013_static_underscore.rs b/crates/syntax/test_data/parser/inline/err/0013_static_underscore.rs
new file mode 100644
index 00000000000..df8cecb4326
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0013_static_underscore.rs
@@ -0,0 +1 @@
+static _: i32 = 5;
diff --git a/crates/syntax/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rast b/crates/syntax/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rast
new file mode 100644
index 00000000000..a81c442c0d8
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rast
@@ -0,0 +1,48 @@
+SOURCE_FILE@0..45
+  FN@0..44
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..44
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      RECORD_EXPR@16..42
+        PATH@16..17
+          PATH_SEGMENT@16..17
+            NAME_REF@16..17
+              IDENT@16..17 "S"
+        WHITESPACE@17..18 " "
+        RECORD_EXPR_FIELD_LIST@18..42
+          L_CURLY@18..19 "{"
+          WHITESPACE@19..20 " "
+          RECORD_EXPR_FIELD@20..40
+            NAME_REF@20..25
+              IDENT@20..25 "field"
+            WHITESPACE@25..26 " "
+            RANGE_EXPR@26..40
+              DOT2@26..28 ".."
+              CALL_EXPR@28..40
+                PATH_EXPR@28..38
+                  PATH@28..38
+                    PATH@28..29
+                      PATH_SEGMENT@28..29
+                        NAME_REF@28..29
+                          IDENT@28..29 "S"
+                    COLON2@29..31 "::"
+                    PATH_SEGMENT@31..38
+                      NAME_REF@31..38
+                        IDENT@31..38 "default"
+                ARG_LIST@38..40
+                  L_PAREN@38..39 "("
+                  R_PAREN@39..40 ")"
+          WHITESPACE@40..41 " "
+          R_CURLY@41..42 "}"
+      WHITESPACE@42..43 "\n"
+      R_CURLY@43..44 "}"
+  WHITESPACE@44..45 "\n"
+error 25..25: expected COLON
diff --git a/crates/syntax/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rs b/crates/syntax/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rs
new file mode 100644
index 00000000000..a4e5b2f6933
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rs
@@ -0,0 +1,3 @@
+fn main() {
+    S { field ..S::default() }
+}
diff --git a/crates/syntax/test_data/parser/inline/err/0015_empty_segment.rast b/crates/syntax/test_data/parser/inline/err/0015_empty_segment.rast
new file mode 100644
index 00000000000..2f59d0606c0
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0015_empty_segment.rast
@@ -0,0 +1,15 @@
+SOURCE_FILE@0..13
+  USE@0..12
+    USE_KW@0..3 "use"
+    WHITESPACE@3..4 " "
+    USE_TREE@4..12
+      PATH@4..12
+        PATH@4..9
+          PATH_SEGMENT@4..9
+            CRATE_KW@4..9 "crate"
+        COLON2@9..11 "::"
+        ERROR@11..12
+          SEMICOLON@11..12 ";"
+  WHITESPACE@12..13 "\n"
+error 11..11: expected identifier
+error 12..12: expected SEMICOLON
diff --git a/crates/syntax/test_data/parser/inline/err/0015_empty_segment.rs b/crates/syntax/test_data/parser/inline/err/0015_empty_segment.rs
new file mode 100644
index 00000000000..7510664e102
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/err/0015_empty_segment.rs
@@ -0,0 +1 @@
+use crate::;
diff --git a/crates/syntax/test_data/parser/inline/ok/0001_trait_item_list.rast b/crates/syntax/test_data/parser/inline/ok/0001_trait_item_list.rast
new file mode 100644
index 00000000000..c7289e4008a
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0001_trait_item_list.rast
@@ -0,0 +1,71 @@
+SOURCE_FILE@0..83
+  IMPL@0..82
+    IMPL_KW@0..4 "impl"
+    WHITESPACE@4..5 " "
+    PATH_TYPE@5..6
+      PATH@5..6
+        PATH_SEGMENT@5..6
+          NAME_REF@5..6
+            IDENT@5..6 "F"
+    WHITESPACE@6..7 " "
+    ASSOC_ITEM_LIST@7..82
+      L_CURLY@7..8 "{"
+      WHITESPACE@8..13 "\n    "
+      TYPE_ALIAS@13..27
+        TYPE_KW@13..17 "type"
+        WHITESPACE@17..18 " "
+        NAME@18..19
+          IDENT@18..19 "A"
+        COLON@19..20 ":"
+        WHITESPACE@20..21 " "
+        TYPE_BOUND_LIST@21..26
+          TYPE_BOUND@21..26
+            PATH_TYPE@21..26
+              PATH@21..26
+                PATH_SEGMENT@21..26
+                  NAME_REF@21..26
+                    IDENT@21..26 "Clone"
+        SEMICOLON@26..27 ";"
+      WHITESPACE@27..32 "\n    "
+      CONST@32..45
+        CONST_KW@32..37 "const"
+        WHITESPACE@37..38 " "
+        NAME@38..39
+          IDENT@38..39 "B"
+        COLON@39..40 ":"
+        WHITESPACE@40..41 " "
+        PATH_TYPE@41..44
+          PATH@41..44
+            PATH_SEGMENT@41..44
+              NAME_REF@41..44
+                IDENT@41..44 "i32"
+        SEMICOLON@44..45 ";"
+      WHITESPACE@45..50 "\n    "
+      FN@50..61
+        FN_KW@50..52 "fn"
+        WHITESPACE@52..53 " "
+        NAME@53..56
+          IDENT@53..56 "foo"
+        PARAM_LIST@56..58
+          L_PAREN@56..57 "("
+          R_PAREN@57..58 ")"
+        WHITESPACE@58..59 " "
+        BLOCK_EXPR@59..61
+          L_CURLY@59..60 "{"
+          R_CURLY@60..61 "}"
+      WHITESPACE@61..66 "\n    "
+      FN@66..80
+        FN_KW@66..68 "fn"
+        WHITESPACE@68..69 " "
+        NAME@69..72
+          IDENT@69..72 "bar"
+        PARAM_LIST@72..79
+          L_PAREN@72..73 "("
+          SELF_PARAM@73..78
+            AMP@73..74 "&"
+            SELF_KW@74..78 "self"
+          R_PAREN@78..79 ")"
+        SEMICOLON@79..80 ";"
+      WHITESPACE@80..81 "\n"
+      R_CURLY@81..82 "}"
+  WHITESPACE@82..83 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0001_trait_item_list.rs b/crates/syntax/test_data/parser/inline/ok/0001_trait_item_list.rs
new file mode 100644
index 00000000000..a5ec3239f8f
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0001_trait_item_list.rs
@@ -0,0 +1,6 @@
+impl F {
+    type A: Clone;
+    const B: i32;
+    fn foo() {}
+    fn bar(&self);
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0002_use_tree_list.rast b/crates/syntax/test_data/parser/inline/ok/0002_use_tree_list.rast
new file mode 100644
index 00000000000..1e80dd7e27f
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0002_use_tree_list.rast
@@ -0,0 +1,136 @@
+SOURCE_FILE@0..249
+  USE@0..58
+    USE_KW@0..3 "use"
+    WHITESPACE@3..4 " "
+    USE_TREE@4..57
+      USE_TREE_LIST@4..57
+        L_CURLY@4..5 "{"
+        USE_TREE@5..28
+          PATH@5..28
+            PATH@5..22
+              PATH@5..16
+                PATH@5..10
+                  PATH_SEGMENT@5..10
+                    CRATE_KW@5..10 "crate"
+                COLON2@10..12 "::"
+                PATH_SEGMENT@12..16
+                  NAME_REF@12..16
+                    IDENT@12..16 "path"
+              COLON2@16..18 "::"
+              PATH_SEGMENT@18..22
+                NAME_REF@18..22
+                  IDENT@18..22 "from"
+            COLON2@22..24 "::"
+            PATH_SEGMENT@24..28
+              NAME_REF@24..28
+                IDENT@24..28 "root"
+        COMMA@28..29 ","
+        WHITESPACE@29..30 " "
+        USE_TREE@30..56
+          PATH@30..56
+            PATH@30..44
+              PATH@30..38
+                PATH@30..32
+                  PATH_SEGMENT@30..32
+                    NAME_REF@30..32
+                      IDENT@30..32 "or"
+                COLON2@32..34 "::"
+                PATH_SEGMENT@34..38
+                  NAME_REF@34..38
+                    IDENT@34..38 "path"
+              COLON2@38..40 "::"
+              PATH_SEGMENT@40..44
+                NAME_REF@40..44
+                  IDENT@40..44 "from"
+            COLON2@44..46 "::"
+            PATH_SEGMENT@46..56
+              NAME_REF@46..56
+                IDENT@46..56 "crate_name"
+        R_CURLY@56..57 "}"
+    SEMICOLON@57..58 ";"
+  WHITESPACE@58..59 " "
+  COMMENT@59..97 "// Rust 2018 (with a  ..."
+  WHITESPACE@97..98 "\n"
+  USE@98..121
+    USE_KW@98..101 "use"
+    WHITESPACE@101..102 " "
+    USE_TREE@102..120
+      USE_TREE_LIST@102..120
+        L_CURLY@102..103 "{"
+        USE_TREE@103..119
+          PATH@103..119
+            PATH@103..113
+              PATH@103..107
+                PATH_SEGMENT@103..107
+                  NAME_REF@103..107
+                    IDENT@103..107 "path"
+              COLON2@107..109 "::"
+              PATH_SEGMENT@109..113
+                NAME_REF@109..113
+                  IDENT@109..113 "from"
+            COLON2@113..115 "::"
+            PATH_SEGMENT@115..119
+              NAME_REF@115..119
+                IDENT@115..119 "root"
+        R_CURLY@119..120 "}"
+    SEMICOLON@120..121 ";"
+  WHITESPACE@121..122 " "
+  COMMENT@122..134 "// Rust 2015"
+  WHITESPACE@134..135 "\n"
+  USE@135..166
+    USE_KW@135..138 "use"
+    WHITESPACE@138..139 " "
+    USE_TREE@139..165
+      COLON2@139..141 "::"
+      USE_TREE_LIST@141..165
+        L_CURLY@141..142 "{"
+        USE_TREE@142..164
+          PATH@142..164
+            PATH@142..158
+              PATH@142..146
+                PATH_SEGMENT@142..146
+                  NAME_REF@142..146
+                    IDENT@142..146 "some"
+              COLON2@146..148 "::"
+              PATH_SEGMENT@148..158
+                NAME_REF@148..158
+                  IDENT@148..158 "arbritrary"
+            COLON2@158..160 "::"
+            PATH_SEGMENT@160..164
+              NAME_REF@160..164
+                IDENT@160..164 "path"
+        R_CURLY@164..165 "}"
+    SEMICOLON@165..166 ";"
+  WHITESPACE@166..167 " "
+  COMMENT@167..179 "// Rust 2015"
+  WHITESPACE@179..180 "\n"
+  USE@180..205
+    USE_KW@180..183 "use"
+    WHITESPACE@183..184 " "
+    USE_TREE@184..204
+      COLON2@184..186 "::"
+      USE_TREE_LIST@186..204
+        L_CURLY@186..187 "{"
+        USE_TREE@187..203
+          USE_TREE_LIST@187..203
+            L_CURLY@187..188 "{"
+            USE_TREE@188..202
+              USE_TREE_LIST@188..202
+                L_CURLY@188..189 "{"
+                USE_TREE@189..201
+                  PATH@189..201
+                    PATH@189..193
+                      PATH_SEGMENT@189..193
+                        NAME_REF@189..193
+                          IDENT@189..193 "root"
+                    COLON2@193..195 "::"
+                    PATH_SEGMENT@195..201
+                      NAME_REF@195..201
+                        IDENT@195..201 "export"
+                R_CURLY@201..202 "}"
+            R_CURLY@202..203 "}"
+        R_CURLY@203..204 "}"
+    SEMICOLON@204..205 ";"
+  WHITESPACE@205..206 " "
+  COMMENT@206..248 "// Nonsensical but pe ..."
+  WHITESPACE@248..249 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0002_use_tree_list.rs b/crates/syntax/test_data/parser/inline/ok/0002_use_tree_list.rs
new file mode 100644
index 00000000000..381cba1e29e
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0002_use_tree_list.rs
@@ -0,0 +1,4 @@
+use {crate::path::from::root, or::path::from::crate_name}; // Rust 2018 (with a crate named `or`)
+use {path::from::root}; // Rust 2015
+use ::{some::arbritrary::path}; // Rust 2015
+use ::{{{root::export}}}; // Nonsensical but perfectly legal nesting
diff --git a/crates/syntax/test_data/parser/inline/ok/0003_where_pred_for.rast b/crates/syntax/test_data/parser/inline/ok/0003_where_pred_for.rast
new file mode 100644
index 00000000000..62da7b88734
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0003_where_pred_for.rast
@@ -0,0 +1,60 @@
+SOURCE_FILE@0..54
+  FN@0..53
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..12
+      IDENT@3..12 "for_trait"
+    GENERIC_PARAM_LIST@12..15
+      L_ANGLE@12..13 "<"
+      TYPE_PARAM@13..14
+        NAME@13..14
+          IDENT@13..14 "F"
+      R_ANGLE@14..15 ">"
+    PARAM_LIST@15..17
+      L_PAREN@15..16 "("
+      R_PAREN@16..17 ")"
+    WHITESPACE@17..18 "\n"
+    WHERE_CLAUSE@18..49
+      WHERE_KW@18..23 "where"
+      WHITESPACE@23..27 "\n   "
+      WHERE_PRED@27..49
+        FOR_KW@27..30 "for"
+        GENERIC_PARAM_LIST@30..34
+          L_ANGLE@30..31 "<"
+          LIFETIME_PARAM@31..33
+            LIFETIME@31..33 "\'a"
+          R_ANGLE@33..34 ">"
+        WHITESPACE@34..35 " "
+        PATH_TYPE@35..36
+          PATH@35..36
+            PATH_SEGMENT@35..36
+              NAME_REF@35..36
+                IDENT@35..36 "F"
+        COLON@36..37 ":"
+        WHITESPACE@37..38 " "
+        TYPE_BOUND_LIST@38..49
+          TYPE_BOUND@38..49
+            PATH_TYPE@38..49
+              PATH@38..49
+                PATH_SEGMENT@38..49
+                  NAME_REF@38..40
+                    IDENT@38..40 "Fn"
+                  PARAM_LIST@40..49
+                    L_PAREN@40..41 "("
+                    PARAM@41..48
+                      REF_TYPE@41..48
+                        AMP@41..42 "&"
+                        LIFETIME@42..44 "\'a"
+                        WHITESPACE@44..45 " "
+                        PATH_TYPE@45..48
+                          PATH@45..48
+                            PATH_SEGMENT@45..48
+                              NAME_REF@45..48
+                                IDENT@45..48 "str"
+                    R_PAREN@48..49 ")"
+    WHITESPACE@49..50 "\n"
+    BLOCK_EXPR@50..53
+      L_CURLY@50..51 "{"
+      WHITESPACE@51..52 " "
+      R_CURLY@52..53 "}"
+  WHITESPACE@53..54 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0003_where_pred_for.rs b/crates/syntax/test_data/parser/inline/ok/0003_where_pred_for.rs
new file mode 100644
index 00000000000..423bc105bd7
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0003_where_pred_for.rs
@@ -0,0 +1,4 @@
+fn for_trait<F>()
+where
+   for<'a> F: Fn(&'a str)
+{ }
diff --git a/crates/syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rast b/crates/syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rast
new file mode 100644
index 00000000000..b650735ba1d
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rast
@@ -0,0 +1,60 @@
+SOURCE_FILE@0..39
+  TYPE_ALIAS@0..38
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "F"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    PATH_TYPE@9..37
+      PATH@9..37
+        PATH_SEGMENT@9..37
+          NAME_REF@9..12
+            IDENT@9..12 "Box"
+          GENERIC_ARG_LIST@12..37
+            L_ANGLE@12..13 "<"
+            TYPE_ARG@13..36
+              PATH_TYPE@13..36
+                PATH@13..36
+                  PATH_SEGMENT@13..36
+                    NAME_REF@13..15
+                      IDENT@13..15 "Fn"
+                    PARAM_LIST@15..36
+                      L_PAREN@15..16 "("
+                      PARAM@16..19
+                        PATH_TYPE@16..19
+                          PATH@16..19
+                            PATH_SEGMENT@16..19
+                              NAME_REF@16..19
+                                IDENT@16..19 "i32"
+                      COMMA@19..20 ","
+                      WHITESPACE@20..21 " "
+                      PARAM@21..25
+                        REF_TYPE@21..25
+                          AMP@21..22 "&"
+                          PATH_TYPE@22..25
+                            PATH@22..25
+                              PATH_SEGMENT@22..25
+                                NAME_REF@22..25
+                                  IDENT@22..25 "i32"
+                      COMMA@25..26 ","
+                      WHITESPACE@26..27 " "
+                      PARAM@27..31
+                        REF_TYPE@27..31
+                          AMP@27..28 "&"
+                          PATH_TYPE@28..31
+                            PATH@28..31
+                              PATH_SEGMENT@28..31
+                                NAME_REF@28..31
+                                  IDENT@28..31 "i32"
+                      COMMA@31..32 ","
+                      WHITESPACE@32..33 " "
+                      PARAM@33..35
+                        TUPLE_TYPE@33..35
+                          L_PAREN@33..34 "("
+                          R_PAREN@34..35 ")"
+                      R_PAREN@35..36 ")"
+            R_ANGLE@36..37 ">"
+    SEMICOLON@37..38 ";"
+  WHITESPACE@38..39 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rs b/crates/syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rs
new file mode 100644
index 00000000000..93636e926e1
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rs
@@ -0,0 +1 @@
+type F = Box<Fn(i32, &i32, &i32, ())>;
diff --git a/crates/syntax/test_data/parser/inline/ok/0005_function_type_params.rast b/crates/syntax/test_data/parser/inline/ok/0005_function_type_params.rast
new file mode 100644
index 00000000000..8e0252ce743
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0005_function_type_params.rast
@@ -0,0 +1,37 @@
+SOURCE_FILE@0..28
+  FN@0..27
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    GENERIC_PARAM_LIST@6..23
+      L_ANGLE@6..7 "<"
+      TYPE_PARAM@7..22
+        NAME@7..8
+          IDENT@7..8 "T"
+        COLON@8..9 ":"
+        WHITESPACE@9..10 " "
+        TYPE_BOUND_LIST@10..22
+          TYPE_BOUND@10..15
+            PATH_TYPE@10..15
+              PATH@10..15
+                PATH_SEGMENT@10..15
+                  NAME_REF@10..15
+                    IDENT@10..15 "Clone"
+          WHITESPACE@15..16 " "
+          PLUS@16..17 "+"
+          WHITESPACE@17..18 " "
+          TYPE_BOUND@18..22
+            PATH_TYPE@18..22
+              PATH@18..22
+                PATH_SEGMENT@18..22
+                  NAME_REF@18..22
+                    IDENT@18..22 "Copy"
+      R_ANGLE@22..23 ">"
+    PARAM_LIST@23..25
+      L_PAREN@23..24 "("
+      R_PAREN@24..25 ")"
+    BLOCK_EXPR@25..27
+      L_CURLY@25..26 "{"
+      R_CURLY@26..27 "}"
+  WHITESPACE@27..28 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0005_function_type_params.rs b/crates/syntax/test_data/parser/inline/ok/0005_function_type_params.rs
new file mode 100644
index 00000000000..9df40ed396c
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0005_function_type_params.rs
@@ -0,0 +1 @@
+fn foo<T: Clone + Copy>(){}
diff --git a/crates/syntax/test_data/parser/inline/ok/0006_self_param.rast b/crates/syntax/test_data/parser/inline/ok/0006_self_param.rast
new file mode 100644
index 00000000000..d24ad74232e
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0006_self_param.rast
@@ -0,0 +1,116 @@
+SOURCE_FILE@0..128
+  IMPL@0..127
+    IMPL_KW@0..4 "impl"
+    WHITESPACE@4..5 " "
+    PATH_TYPE@5..6
+      PATH@5..6
+        PATH_SEGMENT@5..6
+          NAME_REF@5..6
+            IDENT@5..6 "S"
+    WHITESPACE@6..7 " "
+    ASSOC_ITEM_LIST@7..127
+      L_CURLY@7..8 "{"
+      WHITESPACE@8..13 "\n    "
+      FN@13..26
+        FN_KW@13..15 "fn"
+        WHITESPACE@15..16 " "
+        NAME@16..17
+          IDENT@16..17 "a"
+        PARAM_LIST@17..23
+          L_PAREN@17..18 "("
+          SELF_PARAM@18..22
+            SELF_KW@18..22 "self"
+          R_PAREN@22..23 ")"
+        WHITESPACE@23..24 " "
+        BLOCK_EXPR@24..26
+          L_CURLY@24..25 "{"
+          R_CURLY@25..26 "}"
+      WHITESPACE@26..31 "\n    "
+      FN@31..46
+        FN_KW@31..33 "fn"
+        WHITESPACE@33..34 " "
+        NAME@34..35
+          IDENT@34..35 "b"
+        PARAM_LIST@35..43
+          L_PAREN@35..36 "("
+          SELF_PARAM@36..41
+            AMP@36..37 "&"
+            SELF_KW@37..41 "self"
+          COMMA@41..42 ","
+          R_PAREN@42..43 ")"
+        WHITESPACE@43..44 " "
+        BLOCK_EXPR@44..46
+          L_CURLY@44..45 "{"
+          R_CURLY@45..46 "}"
+      WHITESPACE@46..51 "\n    "
+      FN@51..69
+        FN_KW@51..53 "fn"
+        WHITESPACE@53..54 " "
+        NAME@54..55
+          IDENT@54..55 "c"
+        PARAM_LIST@55..66
+          L_PAREN@55..56 "("
+          SELF_PARAM@56..64
+            AMP@56..57 "&"
+            LIFETIME@57..59 "\'a"
+            WHITESPACE@59..60 " "
+            SELF_KW@60..64 "self"
+          COMMA@64..65 ","
+          R_PAREN@65..66 ")"
+        WHITESPACE@66..67 " "
+        BLOCK_EXPR@67..69
+          L_CURLY@67..68 "{"
+          R_CURLY@68..69 "}"
+      WHITESPACE@69..74 "\n    "
+      FN@74..103
+        FN_KW@74..76 "fn"
+        WHITESPACE@76..77 " "
+        NAME@77..78
+          IDENT@77..78 "d"
+        PARAM_LIST@78..100
+          L_PAREN@78..79 "("
+          SELF_PARAM@79..91
+            AMP@79..80 "&"
+            LIFETIME@80..82 "\'a"
+            WHITESPACE@82..83 " "
+            MUT_KW@83..86 "mut"
+            WHITESPACE@86..87 " "
+            SELF_KW@87..91 "self"
+          COMMA@91..92 ","
+          WHITESPACE@92..93 " "
+          PARAM@93..99
+            IDENT_PAT@93..94
+              NAME@93..94
+                IDENT@93..94 "x"
+            COLON@94..95 ":"
+            WHITESPACE@95..96 " "
+            PATH_TYPE@96..99
+              PATH@96..99
+                PATH_SEGMENT@96..99
+                  NAME_REF@96..99
+                    IDENT@96..99 "i32"
+          R_PAREN@99..100 ")"
+        WHITESPACE@100..101 " "
+        BLOCK_EXPR@101..103
+          L_CURLY@101..102 "{"
+          R_CURLY@102..103 "}"
+      WHITESPACE@103..108 "\n    "
+      FN@108..125
+        FN_KW@108..110 "fn"
+        WHITESPACE@110..111 " "
+        NAME@111..112
+          IDENT@111..112 "e"
+        PARAM_LIST@112..122
+          L_PAREN@112..113 "("
+          SELF_PARAM@113..121
+            MUT_KW@113..116 "mut"
+            WHITESPACE@116..117 " "
+            SELF_KW@117..121 "self"
+          R_PAREN@121..122 ")"
+        WHITESPACE@122..123 " "
+        BLOCK_EXPR@123..125
+          L_CURLY@123..124 "{"
+          R_CURLY@124..125 "}"
+      WHITESPACE@125..126 "\n"
+      R_CURLY@126..127 "}"
+  WHITESPACE@127..128 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0006_self_param.rs b/crates/syntax/test_data/parser/inline/ok/0006_self_param.rs
new file mode 100644
index 00000000000..80c0a43f5de
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0006_self_param.rs
@@ -0,0 +1,7 @@
+impl S {
+    fn a(self) {}
+    fn b(&self,) {}
+    fn c(&'a self,) {}
+    fn d(&'a mut self, x: i32) {}
+    fn e(mut self) {}
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0007_type_param_bounds.rast b/crates/syntax/test_data/parser/inline/ok/0007_type_param_bounds.rast
new file mode 100644
index 00000000000..e95688f56a5
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0007_type_param_bounds.rast
@@ -0,0 +1,40 @@
+SOURCE_FILE@0..35
+  STRUCT@0..34
+    STRUCT_KW@0..6 "struct"
+    WHITESPACE@6..7 " "
+    NAME@7..8
+      IDENT@7..8 "S"
+    GENERIC_PARAM_LIST@8..33
+      L_ANGLE@8..9 "<"
+      TYPE_PARAM@9..32
+        NAME@9..10
+          IDENT@9..10 "T"
+        COLON@10..11 ":"
+        WHITESPACE@11..12 " "
+        TYPE_BOUND_LIST@12..32
+          TYPE_BOUND@12..14
+            LIFETIME@12..14 "\'a"
+          WHITESPACE@14..15 " "
+          PLUS@15..16 "+"
+          WHITESPACE@16..17 " "
+          TYPE_BOUND@17..23
+            QUESTION@17..18 "?"
+            PATH_TYPE@18..23
+              PATH@18..23
+                PATH_SEGMENT@18..23
+                  NAME_REF@18..23
+                    IDENT@18..23 "Sized"
+          WHITESPACE@23..24 " "
+          PLUS@24..25 "+"
+          WHITESPACE@25..26 " "
+          TYPE_BOUND@26..32
+            L_PAREN@26..27 "("
+            PATH_TYPE@27..31
+              PATH@27..31
+                PATH_SEGMENT@27..31
+                  NAME_REF@27..31
+                    IDENT@27..31 "Copy"
+            R_PAREN@31..32 ")"
+      R_ANGLE@32..33 ">"
+    SEMICOLON@33..34 ";"
+  WHITESPACE@34..35 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0007_type_param_bounds.rs b/crates/syntax/test_data/parser/inline/ok/0007_type_param_bounds.rs
new file mode 100644
index 00000000000..919bde0ee92
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0007_type_param_bounds.rs
@@ -0,0 +1 @@
+struct S<T: 'a + ?Sized + (Copy)>;
diff --git a/crates/syntax/test_data/parser/inline/ok/0008_path_part.rast b/crates/syntax/test_data/parser/inline/ok/0008_path_part.rast
new file mode 100644
index 00000000000..7d2f7eab05b
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0008_path_part.rast
@@ -0,0 +1,96 @@
+SOURCE_FILE@0..103
+  FN@0..102
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..102
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      LET_STMT@15..33
+        LET_KW@15..18 "let"
+        WHITESPACE@18..19 " "
+        PATH_PAT@19..27
+          PATH@19..27
+            PATH@19..22
+              PATH_SEGMENT@19..22
+                NAME_REF@19..22
+                  IDENT@19..22 "foo"
+            COLON2@22..24 "::"
+            PATH_SEGMENT@24..27
+              NAME_REF@24..27
+                IDENT@24..27 "Bar"
+        WHITESPACE@27..28 " "
+        EQ@28..29 "="
+        WHITESPACE@29..30 " "
+        TUPLE_EXPR@30..32
+          L_PAREN@30..31 "("
+          R_PAREN@31..32 ")"
+        SEMICOLON@32..33 ";"
+      WHITESPACE@33..38 "\n    "
+      LET_STMT@38..53
+        LET_KW@38..41 "let"
+        WHITESPACE@41..42 " "
+        PATH_PAT@42..47
+          PATH@42..47
+            PATH_SEGMENT@42..47
+              COLON2@42..44 "::"
+              NAME_REF@44..47
+                IDENT@44..47 "Bar"
+        WHITESPACE@47..48 " "
+        EQ@48..49 "="
+        WHITESPACE@49..50 " "
+        TUPLE_EXPR@50..52
+          L_PAREN@50..51 "("
+          R_PAREN@51..52 ")"
+        SEMICOLON@52..53 ";"
+      WHITESPACE@53..58 "\n    "
+      LET_STMT@58..78
+        LET_KW@58..61 "let"
+        WHITESPACE@61..62 " "
+        RECORD_PAT@62..72
+          PATH@62..65
+            PATH_SEGMENT@62..65
+              NAME_REF@62..65
+                IDENT@62..65 "Bar"
+          WHITESPACE@65..66 " "
+          RECORD_PAT_FIELD_LIST@66..72
+            L_CURLY@66..67 "{"
+            WHITESPACE@67..68 " "
+            DOT2@68..70 ".."
+            WHITESPACE@70..71 " "
+            R_CURLY@71..72 "}"
+        WHITESPACE@72..73 " "
+        EQ@73..74 "="
+        WHITESPACE@74..75 " "
+        TUPLE_EXPR@75..77
+          L_PAREN@75..76 "("
+          R_PAREN@76..77 ")"
+        SEMICOLON@77..78 ";"
+      WHITESPACE@78..83 "\n    "
+      LET_STMT@83..100
+        LET_KW@83..86 "let"
+        WHITESPACE@86..87 " "
+        TUPLE_STRUCT_PAT@87..94
+          PATH@87..90
+            PATH_SEGMENT@87..90
+              NAME_REF@87..90
+                IDENT@87..90 "Bar"
+          L_PAREN@90..91 "("
+          REST_PAT@91..93
+            DOT2@91..93 ".."
+          R_PAREN@93..94 ")"
+        WHITESPACE@94..95 " "
+        EQ@95..96 "="
+        WHITESPACE@96..97 " "
+        TUPLE_EXPR@97..99
+          L_PAREN@97..98 "("
+          R_PAREN@98..99 ")"
+        SEMICOLON@99..100 ";"
+      WHITESPACE@100..101 "\n"
+      R_CURLY@101..102 "}"
+  WHITESPACE@102..103 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0008_path_part.rs b/crates/syntax/test_data/parser/inline/ok/0008_path_part.rs
new file mode 100644
index 00000000000..f6e32c7c149
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0008_path_part.rs
@@ -0,0 +1,6 @@
+fn foo() {
+    let foo::Bar = ();
+    let ::Bar = ();
+    let Bar { .. } = ();
+    let Bar(..) = ();
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0009_loop_expr.rast b/crates/syntax/test_data/parser/inline/ok/0009_loop_expr.rast
new file mode 100644
index 00000000000..f62826fd55d
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0009_loop_expr.rast
@@ -0,0 +1,24 @@
+SOURCE_FILE@0..26
+  FN@0..25
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..25
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..23
+        LOOP_EXPR@15..22
+          LOOP_KW@15..19 "loop"
+          WHITESPACE@19..20 " "
+          BLOCK_EXPR@20..22
+            L_CURLY@20..21 "{"
+            R_CURLY@21..22 "}"
+        SEMICOLON@22..23 ";"
+      WHITESPACE@23..24 "\n"
+      R_CURLY@24..25 "}"
+  WHITESPACE@25..26 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0009_loop_expr.rs b/crates/syntax/test_data/parser/inline/ok/0009_loop_expr.rs
new file mode 100644
index 00000000000..9f078fa4816
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0009_loop_expr.rs
@@ -0,0 +1,3 @@
+fn foo() {
+    loop {};
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0010_extern_block.rast b/crates/syntax/test_data/parser/inline/ok/0010_extern_block.rast
new file mode 100644
index 00000000000..869875875e1
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0010_extern_block.rast
@@ -0,0 +1,9 @@
+SOURCE_FILE@0..10
+  EXTERN_BLOCK@0..9
+    ABI@0..6
+      EXTERN_KW@0..6 "extern"
+    WHITESPACE@6..7 " "
+    EXTERN_ITEM_LIST@7..9
+      L_CURLY@7..8 "{"
+      R_CURLY@8..9 "}"
+  WHITESPACE@9..10 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0010_extern_block.rs b/crates/syntax/test_data/parser/inline/ok/0010_extern_block.rs
new file mode 100644
index 00000000000..26a9ccd1e67
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0010_extern_block.rs
@@ -0,0 +1 @@
+extern {}
diff --git a/crates/syntax/test_data/parser/inline/ok/0011_field_expr.rast b/crates/syntax/test_data/parser/inline/ok/0011_field_expr.rast
new file mode 100644
index 00000000000..66a609346ae
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0011_field_expr.rast
@@ -0,0 +1,59 @@
+SOURCE_FILE@0..48
+  FN@0..47
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..47
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..21
+        FIELD_EXPR@15..20
+          PATH_EXPR@15..16
+            PATH@15..16
+              PATH_SEGMENT@15..16
+                NAME_REF@15..16
+                  IDENT@15..16 "x"
+          DOT@16..17 "."
+          NAME_REF@17..20
+            IDENT@17..20 "foo"
+        SEMICOLON@20..21 ";"
+      WHITESPACE@21..26 "\n    "
+      EXPR_STMT@26..34
+        FIELD_EXPR@26..33
+          FIELD_EXPR@26..29
+            PATH_EXPR@26..27
+              PATH@26..27
+                PATH_SEGMENT@26..27
+                  NAME_REF@26..27
+                    IDENT@26..27 "x"
+            DOT@27..28 "."
+            NAME_REF@28..29
+              INT_NUMBER@28..29 "0"
+          DOT@29..30 "."
+          NAME_REF@30..33
+            IDENT@30..33 "bar"
+        SEMICOLON@33..34 ";"
+      WHITESPACE@34..39 "\n    "
+      EXPR_STMT@39..45
+        CALL_EXPR@39..44
+          FIELD_EXPR@39..42
+            PATH_EXPR@39..40
+              PATH@39..40
+                PATH_SEGMENT@39..40
+                  NAME_REF@39..40
+                    IDENT@39..40 "x"
+            DOT@40..41 "."
+            NAME_REF@41..42
+              INT_NUMBER@41..42 "0"
+          ARG_LIST@42..44
+            L_PAREN@42..43 "("
+            R_PAREN@43..44 ")"
+        SEMICOLON@44..45 ";"
+      WHITESPACE@45..46 "\n"
+      R_CURLY@46..47 "}"
+  WHITESPACE@47..48 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0011_field_expr.rs b/crates/syntax/test_data/parser/inline/ok/0011_field_expr.rs
new file mode 100644
index 00000000000..b8da2ddc309
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0011_field_expr.rs
@@ -0,0 +1,5 @@
+fn foo() {
+    x.foo;
+    x.0.bar;
+    x.0();
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0012_type_item_where_clause.rast b/crates/syntax/test_data/parser/inline/ok/0012_type_item_where_clause.rast
new file mode 100644
index 00000000000..28c94bfd64f
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0012_type_item_where_clause.rast
@@ -0,0 +1,33 @@
+SOURCE_FILE@0..31
+  TYPE_ALIAS@0..30
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..8
+      IDENT@5..8 "Foo"
+    WHITESPACE@8..9 " "
+    WHERE_CLAUSE@9..24
+      WHERE_KW@9..14 "where"
+      WHITESPACE@14..15 " "
+      WHERE_PRED@15..24
+        PATH_TYPE@15..18
+          PATH@15..18
+            PATH_SEGMENT@15..18
+              NAME_REF@15..18
+                IDENT@15..18 "Foo"
+        COLON@18..19 ":"
+        WHITESPACE@19..20 " "
+        TYPE_BOUND_LIST@20..24
+          TYPE_BOUND@20..24
+            PATH_TYPE@20..24
+              PATH@20..24
+                PATH_SEGMENT@20..24
+                  NAME_REF@20..24
+                    IDENT@20..24 "Copy"
+    WHITESPACE@24..25 " "
+    EQ@25..26 "="
+    WHITESPACE@26..27 " "
+    TUPLE_TYPE@27..29
+      L_PAREN@27..28 "("
+      R_PAREN@28..29 ")"
+    SEMICOLON@29..30 ";"
+  WHITESPACE@30..31 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0012_type_item_where_clause.rs b/crates/syntax/test_data/parser/inline/ok/0012_type_item_where_clause.rs
new file mode 100644
index 00000000000..a602d07f03b
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0012_type_item_where_clause.rs
@@ -0,0 +1 @@
+type Foo where Foo: Copy = ();
diff --git a/crates/syntax/test_data/parser/inline/ok/0013_pointer_type_mut.rast b/crates/syntax/test_data/parser/inline/ok/0013_pointer_type_mut.rast
new file mode 100644
index 00000000000..d33215b507c
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0013_pointer_type_mut.rast
@@ -0,0 +1,35 @@
+SOURCE_FILE@0..36
+  TYPE_ALIAS@0..17
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "M"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    PTR_TYPE@9..16
+      STAR@9..10 "*"
+      MUT_KW@10..13 "mut"
+      WHITESPACE@13..14 " "
+      TUPLE_TYPE@14..16
+        L_PAREN@14..15 "("
+        R_PAREN@15..16 ")"
+    SEMICOLON@16..17 ";"
+  WHITESPACE@17..18 "\n"
+  TYPE_ALIAS@18..35
+    TYPE_KW@18..22 "type"
+    WHITESPACE@22..23 " "
+    NAME@23..24
+      IDENT@23..24 "C"
+    WHITESPACE@24..25 " "
+    EQ@25..26 "="
+    WHITESPACE@26..27 " "
+    PTR_TYPE@27..34
+      STAR@27..28 "*"
+      MUT_KW@28..31 "mut"
+      WHITESPACE@31..32 " "
+      TUPLE_TYPE@32..34
+        L_PAREN@32..33 "("
+        R_PAREN@33..34 ")"
+    SEMICOLON@34..35 ";"
+  WHITESPACE@35..36 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0013_pointer_type_mut.rs b/crates/syntax/test_data/parser/inline/ok/0013_pointer_type_mut.rs
new file mode 100644
index 00000000000..04b2bb9ba5c
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0013_pointer_type_mut.rs
@@ -0,0 +1,2 @@
+type M = *mut ();
+type C = *mut ();
diff --git a/crates/syntax/test_data/parser/inline/ok/0014_never_type.rast b/crates/syntax/test_data/parser/inline/ok/0014_never_type.rast
new file mode 100644
index 00000000000..b1d5106ce9a
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0014_never_type.rast
@@ -0,0 +1,13 @@
+SOURCE_FILE@0..16
+  TYPE_ALIAS@0..15
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..10
+      IDENT@5..10 "Never"
+    WHITESPACE@10..11 " "
+    EQ@11..12 "="
+    WHITESPACE@12..13 " "
+    NEVER_TYPE@13..14
+      BANG@13..14 "!"
+    SEMICOLON@14..15 ";"
+  WHITESPACE@15..16 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0014_never_type.rs b/crates/syntax/test_data/parser/inline/ok/0014_never_type.rs
new file mode 100644
index 00000000000..de399fcf4a2
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0014_never_type.rs
@@ -0,0 +1 @@
+type Never = !;
diff --git a/crates/syntax/test_data/parser/inline/ok/0015_continue_expr.rast b/crates/syntax/test_data/parser/inline/ok/0015_continue_expr.rast
new file mode 100644
index 00000000000..104e153ce69
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0015_continue_expr.rast
@@ -0,0 +1,35 @@
+SOURCE_FILE@0..69
+  FN@0..68
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..68
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      LOOP_EXPR@15..66
+        LOOP_KW@15..19 "loop"
+        WHITESPACE@19..20 " "
+        BLOCK_EXPR@20..66
+          L_CURLY@20..21 "{"
+          WHITESPACE@21..30 "\n        "
+          EXPR_STMT@30..39
+            CONTINUE_EXPR@30..38
+              CONTINUE_KW@30..38 "continue"
+            SEMICOLON@38..39 ";"
+          WHITESPACE@39..48 "\n        "
+          EXPR_STMT@48..60
+            CONTINUE_EXPR@48..59
+              CONTINUE_KW@48..56 "continue"
+              WHITESPACE@56..57 " "
+              LIFETIME@57..59 "\'l"
+            SEMICOLON@59..60 ";"
+          WHITESPACE@60..65 "\n    "
+          R_CURLY@65..66 "}"
+      WHITESPACE@66..67 "\n"
+      R_CURLY@67..68 "}"
+  WHITESPACE@68..69 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0015_continue_expr.rs b/crates/syntax/test_data/parser/inline/ok/0015_continue_expr.rs
new file mode 100644
index 00000000000..474cc3f0e0c
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0015_continue_expr.rs
@@ -0,0 +1,6 @@
+fn foo() {
+    loop {
+        continue;
+        continue 'l;
+    }
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0017_array_type.rast b/crates/syntax/test_data/parser/inline/ok/0017_array_type.rast
new file mode 100644
index 00000000000..c131df1c951
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0017_array_type.rast
@@ -0,0 +1,21 @@
+SOURCE_FILE@0..19
+  TYPE_ALIAS@0..18
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "T"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    ARRAY_TYPE@9..17
+      L_BRACK@9..10 "["
+      TUPLE_TYPE@10..12
+        L_PAREN@10..11 "("
+        R_PAREN@11..12 ")"
+      SEMICOLON@12..13 ";"
+      WHITESPACE@13..14 " "
+      LITERAL@14..16
+        INT_NUMBER@14..16 "92"
+      R_BRACK@16..17 "]"
+    SEMICOLON@17..18 ";"
+  WHITESPACE@18..19 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0017_array_type.rs b/crates/syntax/test_data/parser/inline/ok/0017_array_type.rs
new file mode 100644
index 00000000000..27eb22f2238
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0017_array_type.rs
@@ -0,0 +1 @@
+type T = [(); 92];
diff --git a/crates/syntax/test_data/parser/inline/ok/0018_arb_self_types.rast b/crates/syntax/test_data/parser/inline/ok/0018_arb_self_types.rast
new file mode 100644
index 00000000000..ddbd665888f
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0018_arb_self_types.rast
@@ -0,0 +1,72 @@
+SOURCE_FILE@0..69
+  IMPL@0..68
+    IMPL_KW@0..4 "impl"
+    WHITESPACE@4..5 " "
+    PATH_TYPE@5..6
+      PATH@5..6
+        PATH_SEGMENT@5..6
+          NAME_REF@5..6
+            IDENT@5..6 "S"
+    WHITESPACE@6..7 " "
+    ASSOC_ITEM_LIST@7..68
+      L_CURLY@7..8 "{"
+      WHITESPACE@8..13 "\n    "
+      FN@13..33
+        FN_KW@13..15 "fn"
+        WHITESPACE@15..16 " "
+        NAME@16..17
+          IDENT@16..17 "a"
+        PARAM_LIST@17..30
+          L_PAREN@17..18 "("
+          SELF_PARAM@18..29
+            SELF_KW@18..22 "self"
+            COLON@22..23 ":"
+            WHITESPACE@23..24 " "
+            REF_TYPE@24..29
+              AMP@24..25 "&"
+              PATH_TYPE@25..29
+                PATH@25..29
+                  PATH_SEGMENT@25..29
+                    NAME_REF@25..29
+                      IDENT@25..29 "Self"
+          R_PAREN@29..30 ")"
+        WHITESPACE@30..31 " "
+        BLOCK_EXPR@31..33
+          L_CURLY@31..32 "{"
+          R_CURLY@32..33 "}"
+      WHITESPACE@33..38 "\n    "
+      FN@38..66
+        FN_KW@38..40 "fn"
+        WHITESPACE@40..41 " "
+        NAME@41..42
+          IDENT@41..42 "b"
+        PARAM_LIST@42..63
+          L_PAREN@42..43 "("
+          SELF_PARAM@43..62
+            MUT_KW@43..46 "mut"
+            WHITESPACE@46..47 " "
+            SELF_KW@47..51 "self"
+            COLON@51..52 ":"
+            WHITESPACE@52..53 " "
+            PATH_TYPE@53..62
+              PATH@53..62
+                PATH_SEGMENT@53..62
+                  NAME_REF@53..56
+                    IDENT@53..56 "Box"
+                  GENERIC_ARG_LIST@56..62
+                    L_ANGLE@56..57 "<"
+                    TYPE_ARG@57..61
+                      PATH_TYPE@57..61
+                        PATH@57..61
+                          PATH_SEGMENT@57..61
+                            NAME_REF@57..61
+                              IDENT@57..61 "Self"
+                    R_ANGLE@61..62 ">"
+          R_PAREN@62..63 ")"
+        WHITESPACE@63..64 " "
+        BLOCK_EXPR@64..66
+          L_CURLY@64..65 "{"
+          R_CURLY@65..66 "}"
+      WHITESPACE@66..67 "\n"
+      R_CURLY@67..68 "}"
+  WHITESPACE@68..69 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0018_arb_self_types.rs b/crates/syntax/test_data/parser/inline/ok/0018_arb_self_types.rs
new file mode 100644
index 00000000000..6a170d5ac1d
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0018_arb_self_types.rs
@@ -0,0 +1,4 @@
+impl S {
+    fn a(self: &Self) {}
+    fn b(mut self: Box<Self>) {}
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0019_unary_expr.rast b/crates/syntax/test_data/parser/inline/ok/0019_unary_expr.rast
new file mode 100644
index 00000000000..7db38ea4da5
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0019_unary_expr.rast
@@ -0,0 +1,44 @@
+SOURCE_FILE@0..44
+  FN@0..43
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..43
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..20
+        PREFIX_EXPR@15..19
+          STAR@15..16 "*"
+          PREFIX_EXPR@16..19
+            STAR@16..17 "*"
+            REF_EXPR@17..19
+              AMP@17..18 "&"
+              LITERAL@18..19
+                INT_NUMBER@18..19 "1"
+        SEMICOLON@19..20 ";"
+      WHITESPACE@20..25 "\n    "
+      EXPR_STMT@25..32
+        PREFIX_EXPR@25..31
+          BANG@25..26 "!"
+          PREFIX_EXPR@26..31
+            BANG@26..27 "!"
+            LITERAL@27..31
+              TRUE_KW@27..31 "true"
+        SEMICOLON@31..32 ";"
+      WHITESPACE@32..37 "\n    "
+      EXPR_STMT@37..41
+        PREFIX_EXPR@37..40
+          MINUS@37..38 "-"
+          PREFIX_EXPR@38..40
+            MINUS@38..39 "-"
+            LITERAL@39..40
+              INT_NUMBER@39..40 "1"
+        SEMICOLON@40..41 ";"
+      WHITESPACE@41..42 "\n"
+      R_CURLY@42..43 "}"
+  WHITESPACE@43..44 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0019_unary_expr.rs b/crates/syntax/test_data/parser/inline/ok/0019_unary_expr.rs
new file mode 100644
index 00000000000..f1c3f7118b2
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0019_unary_expr.rs
@@ -0,0 +1,5 @@
+fn foo() {
+    **&1;
+    !!true;
+    --1;
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0020_use_star.rast b/crates/syntax/test_data/parser/inline/ok/0020_use_star.rast
new file mode 100644
index 00000000000..b3623c4455d
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0020_use_star.rast
@@ -0,0 +1,59 @@
+SOURCE_FILE@0..60
+  USE@0..6
+    USE_KW@0..3 "use"
+    WHITESPACE@3..4 " "
+    USE_TREE@4..5
+      STAR@4..5 "*"
+    SEMICOLON@5..6 ";"
+  WHITESPACE@6..7 "\n"
+  USE@7..15
+    USE_KW@7..10 "use"
+    WHITESPACE@10..11 " "
+    USE_TREE@11..14
+      COLON2@11..13 "::"
+      STAR@13..14 "*"
+    SEMICOLON@14..15 ";"
+  WHITESPACE@15..16 "\n"
+  USE@16..36
+    USE_KW@16..19 "use"
+    WHITESPACE@19..20 " "
+    USE_TREE@20..35
+      PATH@20..30
+        PATH@20..24
+          PATH_SEGMENT@20..24
+            NAME_REF@20..24
+              IDENT@20..24 "some"
+        COLON2@24..26 "::"
+        PATH_SEGMENT@26..30
+          NAME_REF@26..30
+            IDENT@26..30 "path"
+      COLON2@30..32 "::"
+      USE_TREE_LIST@32..35
+        L_CURLY@32..33 "{"
+        USE_TREE@33..34
+          STAR@33..34 "*"
+        R_CURLY@34..35 "}"
+    SEMICOLON@35..36 ";"
+  WHITESPACE@36..37 "\n"
+  USE@37..59
+    USE_KW@37..40 "use"
+    WHITESPACE@40..41 " "
+    USE_TREE@41..58
+      PATH@41..51
+        PATH@41..45
+          PATH_SEGMENT@41..45
+            NAME_REF@41..45
+              IDENT@41..45 "some"
+        COLON2@45..47 "::"
+        PATH_SEGMENT@47..51
+          NAME_REF@47..51
+            IDENT@47..51 "path"
+      COLON2@51..53 "::"
+      USE_TREE_LIST@53..58
+        L_CURLY@53..54 "{"
+        USE_TREE@54..57
+          COLON2@54..56 "::"
+          STAR@56..57 "*"
+        R_CURLY@57..58 "}"
+    SEMICOLON@58..59 ";"
+  WHITESPACE@59..60 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0020_use_star.rs b/crates/syntax/test_data/parser/inline/ok/0020_use_star.rs
new file mode 100644
index 00000000000..6f15769a8c7
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0020_use_star.rs
@@ -0,0 +1,4 @@
+use *;
+use ::*;
+use some::path::{*};
+use some::path::{::*};
diff --git a/crates/syntax/test_data/parser/inline/ok/0021_impl_item_list.rast b/crates/syntax/test_data/parser/inline/ok/0021_impl_item_list.rast
new file mode 100644
index 00000000000..ca0702aba59
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0021_impl_item_list.rast
@@ -0,0 +1,78 @@
+SOURCE_FILE@0..89
+  IMPL@0..88
+    IMPL_KW@0..4 "impl"
+    WHITESPACE@4..5 " "
+    PATH_TYPE@5..6
+      PATH@5..6
+        PATH_SEGMENT@5..6
+          NAME_REF@5..6
+            IDENT@5..6 "F"
+    WHITESPACE@6..7 " "
+    ASSOC_ITEM_LIST@7..88
+      L_CURLY@7..8 "{"
+      WHITESPACE@8..13 "\n    "
+      TYPE_ALIAS@13..26
+        TYPE_KW@13..17 "type"
+        WHITESPACE@17..18 " "
+        NAME@18..19
+          IDENT@18..19 "A"
+        WHITESPACE@19..20 " "
+        EQ@20..21 "="
+        WHITESPACE@21..22 " "
+        PATH_TYPE@22..25
+          PATH@22..25
+            PATH_SEGMENT@22..25
+              NAME_REF@22..25
+                IDENT@22..25 "i32"
+        SEMICOLON@25..26 ";"
+      WHITESPACE@26..31 "\n    "
+      CONST@31..49
+        CONST_KW@31..36 "const"
+        WHITESPACE@36..37 " "
+        NAME@37..38
+          IDENT@37..38 "B"
+        COLON@38..39 ":"
+        WHITESPACE@39..40 " "
+        PATH_TYPE@40..43
+          PATH@40..43
+            PATH_SEGMENT@40..43
+              NAME_REF@40..43
+                IDENT@40..43 "i32"
+        WHITESPACE@43..44 " "
+        EQ@44..45 "="
+        WHITESPACE@45..46 " "
+        LITERAL@46..48
+          INT_NUMBER@46..48 "92"
+        SEMICOLON@48..49 ";"
+      WHITESPACE@49..54 "\n    "
+      FN@54..65
+        FN_KW@54..56 "fn"
+        WHITESPACE@56..57 " "
+        NAME@57..60
+          IDENT@57..60 "foo"
+        PARAM_LIST@60..62
+          L_PAREN@60..61 "("
+          R_PAREN@61..62 ")"
+        WHITESPACE@62..63 " "
+        BLOCK_EXPR@63..65
+          L_CURLY@63..64 "{"
+          R_CURLY@64..65 "}"
+      WHITESPACE@65..70 "\n    "
+      FN@70..86
+        FN_KW@70..72 "fn"
+        WHITESPACE@72..73 " "
+        NAME@73..76
+          IDENT@73..76 "bar"
+        PARAM_LIST@76..83
+          L_PAREN@76..77 "("
+          SELF_PARAM@77..82
+            AMP@77..78 "&"
+            SELF_KW@78..82 "self"
+          R_PAREN@82..83 ")"
+        WHITESPACE@83..84 " "
+        BLOCK_EXPR@84..86
+          L_CURLY@84..85 "{"
+          R_CURLY@85..86 "}"
+      WHITESPACE@86..87 "\n"
+      R_CURLY@87..88 "}"
+  WHITESPACE@88..89 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0021_impl_item_list.rs b/crates/syntax/test_data/parser/inline/ok/0021_impl_item_list.rs
new file mode 100644
index 00000000000..f108514879d
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0021_impl_item_list.rs
@@ -0,0 +1,6 @@
+impl F {
+    type A = i32;
+    const B: i32 = 92;
+    fn foo() {}
+    fn bar(&self) {}
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0022_crate_visibility.rast b/crates/syntax/test_data/parser/inline/ok/0022_crate_visibility.rast
new file mode 100644
index 00000000000..50742cbcf1f
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0022_crate_visibility.rast
@@ -0,0 +1,53 @@
+SOURCE_FILE@0..81
+  STRUCT@0..20
+    VISIBILITY@0..10
+      PUB_KW@0..3 "pub"
+      L_PAREN@3..4 "("
+      CRATE_KW@4..9 "crate"
+      R_PAREN@9..10 ")"
+    WHITESPACE@10..11 " "
+    STRUCT_KW@11..17 "struct"
+    WHITESPACE@17..18 " "
+    NAME@18..19
+      IDENT@18..19 "S"
+    SEMICOLON@19..20 ";"
+  WHITESPACE@20..21 "\n"
+  STRUCT@21..40
+    VISIBILITY@21..30
+      PUB_KW@21..24 "pub"
+      L_PAREN@24..25 "("
+      SELF_KW@25..29 "self"
+      R_PAREN@29..30 ")"
+    WHITESPACE@30..31 " "
+    STRUCT_KW@31..37 "struct"
+    WHITESPACE@37..38 " "
+    NAME@38..39
+      IDENT@38..39 "S"
+    SEMICOLON@39..40 ";"
+  WHITESPACE@40..41 "\n"
+  STRUCT@41..60
+    VISIBILITY@41..50
+      PUB_KW@41..44 "pub"
+      L_PAREN@44..45 "("
+      SELF_KW@45..49 "self"
+      R_PAREN@49..50 ")"
+    WHITESPACE@50..51 " "
+    STRUCT_KW@51..57 "struct"
+    WHITESPACE@57..58 " "
+    NAME@58..59
+      IDENT@58..59 "S"
+    SEMICOLON@59..60 ";"
+  WHITESPACE@60..61 "\n"
+  STRUCT@61..80
+    VISIBILITY@61..70
+      PUB_KW@61..64 "pub"
+      L_PAREN@64..65 "("
+      SELF_KW@65..69 "self"
+      R_PAREN@69..70 ")"
+    WHITESPACE@70..71 " "
+    STRUCT_KW@71..77 "struct"
+    WHITESPACE@77..78 " "
+    NAME@78..79
+      IDENT@78..79 "S"
+    SEMICOLON@79..80 ";"
+  WHITESPACE@80..81 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0022_crate_visibility.rs b/crates/syntax/test_data/parser/inline/ok/0022_crate_visibility.rs
new file mode 100644
index 00000000000..faeefde94e2
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0022_crate_visibility.rs
@@ -0,0 +1,4 @@
+pub(crate) struct S;
+pub(self) struct S;
+pub(self) struct S;
+pub(self) struct S;
diff --git a/crates/syntax/test_data/parser/inline/ok/0023_placeholder_type.rast b/crates/syntax/test_data/parser/inline/ok/0023_placeholder_type.rast
new file mode 100644
index 00000000000..e4fe2b948b0
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0023_placeholder_type.rast
@@ -0,0 +1,13 @@
+SOURCE_FILE@0..22
+  TYPE_ALIAS@0..21
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..16
+      IDENT@5..16 "Placeholder"
+    WHITESPACE@16..17 " "
+    EQ@17..18 "="
+    WHITESPACE@18..19 " "
+    INFER_TYPE@19..20
+      UNDERSCORE@19..20 "_"
+    SEMICOLON@20..21 ";"
+  WHITESPACE@21..22 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0023_placeholder_type.rs b/crates/syntax/test_data/parser/inline/ok/0023_placeholder_type.rs
new file mode 100644
index 00000000000..7952dbd57d6
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0023_placeholder_type.rs
@@ -0,0 +1 @@
+type Placeholder = _;
diff --git a/crates/syntax/test_data/parser/inline/ok/0024_slice_pat.rast b/crates/syntax/test_data/parser/inline/ok/0024_slice_pat.rast
new file mode 100644
index 00000000000..2dbce34b61e
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0024_slice_pat.rast
@@ -0,0 +1,41 @@
+SOURCE_FILE@0..39
+  FN@0..38
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..38
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      LET_STMT@16..36
+        LET_KW@16..19 "let"
+        WHITESPACE@19..20 " "
+        SLICE_PAT@20..30
+          L_BRACK@20..21 "["
+          IDENT_PAT@21..22
+            NAME@21..22
+              IDENT@21..22 "a"
+          COMMA@22..23 ","
+          WHITESPACE@23..24 " "
+          IDENT_PAT@24..25
+            NAME@24..25
+              IDENT@24..25 "b"
+          COMMA@25..26 ","
+          WHITESPACE@26..27 " "
+          REST_PAT@27..29
+            DOT2@27..29 ".."
+          R_BRACK@29..30 "]"
+        WHITESPACE@30..31 " "
+        EQ@31..32 "="
+        WHITESPACE@32..33 " "
+        ARRAY_EXPR@33..35
+          L_BRACK@33..34 "["
+          R_BRACK@34..35 "]"
+        SEMICOLON@35..36 ";"
+      WHITESPACE@36..37 "\n"
+      R_CURLY@37..38 "}"
+  WHITESPACE@38..39 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0024_slice_pat.rs b/crates/syntax/test_data/parser/inline/ok/0024_slice_pat.rs
new file mode 100644
index 00000000000..7955973b952
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0024_slice_pat.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let [a, b, ..] = [];
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0025_slice_type.rast b/crates/syntax/test_data/parser/inline/ok/0025_slice_type.rast
new file mode 100644
index 00000000000..fd819ea370e
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0025_slice_type.rast
@@ -0,0 +1,17 @@
+SOURCE_FILE@0..15
+  TYPE_ALIAS@0..14
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "T"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    SLICE_TYPE@9..13
+      L_BRACK@9..10 "["
+      TUPLE_TYPE@10..12
+        L_PAREN@10..11 "("
+        R_PAREN@11..12 ")"
+      R_BRACK@12..13 "]"
+    SEMICOLON@13..14 ";"
+  WHITESPACE@14..15 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0025_slice_type.rs b/crates/syntax/test_data/parser/inline/ok/0025_slice_type.rs
new file mode 100644
index 00000000000..4da1af82705
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0025_slice_type.rs
@@ -0,0 +1 @@
+type T = [()];
diff --git a/crates/syntax/test_data/parser/inline/ok/0026_tuple_pat_fields.rast b/crates/syntax/test_data/parser/inline/ok/0026_tuple_pat_fields.rast
new file mode 100644
index 00000000000..467a3013469
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0026_tuple_pat_fields.rast
@@ -0,0 +1,104 @@
+SOURCE_FILE@0..97
+  FN@0..96
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..96
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      LET_STMT@15..28
+        LET_KW@15..18 "let"
+        WHITESPACE@18..19 " "
+        TUPLE_STRUCT_PAT@19..22
+          PATH@19..20
+            PATH_SEGMENT@19..20
+              NAME_REF@19..20
+                IDENT@19..20 "S"
+          L_PAREN@20..21 "("
+          R_PAREN@21..22 ")"
+        WHITESPACE@22..23 " "
+        EQ@23..24 "="
+        WHITESPACE@24..25 " "
+        TUPLE_EXPR@25..27
+          L_PAREN@25..26 "("
+          R_PAREN@26..27 ")"
+        SEMICOLON@27..28 ";"
+      WHITESPACE@28..33 "\n    "
+      LET_STMT@33..47
+        LET_KW@33..36 "let"
+        WHITESPACE@36..37 " "
+        TUPLE_STRUCT_PAT@37..41
+          PATH@37..38
+            PATH_SEGMENT@37..38
+              NAME_REF@37..38
+                IDENT@37..38 "S"
+          L_PAREN@38..39 "("
+          WILDCARD_PAT@39..40
+            UNDERSCORE@39..40 "_"
+          R_PAREN@40..41 ")"
+        WHITESPACE@41..42 " "
+        EQ@42..43 "="
+        WHITESPACE@43..44 " "
+        TUPLE_EXPR@44..46
+          L_PAREN@44..45 "("
+          R_PAREN@45..46 ")"
+        SEMICOLON@46..47 ";"
+      WHITESPACE@47..52 "\n    "
+      LET_STMT@52..67
+        LET_KW@52..55 "let"
+        WHITESPACE@55..56 " "
+        TUPLE_STRUCT_PAT@56..61
+          PATH@56..57
+            PATH_SEGMENT@56..57
+              NAME_REF@56..57
+                IDENT@56..57 "S"
+          L_PAREN@57..58 "("
+          WILDCARD_PAT@58..59
+            UNDERSCORE@58..59 "_"
+          COMMA@59..60 ","
+          R_PAREN@60..61 ")"
+        WHITESPACE@61..62 " "
+        EQ@62..63 "="
+        WHITESPACE@63..64 " "
+        TUPLE_EXPR@64..66
+          L_PAREN@64..65 "("
+          R_PAREN@65..66 ")"
+        SEMICOLON@66..67 ";"
+      WHITESPACE@67..72 "\n    "
+      LET_STMT@72..94
+        LET_KW@72..75 "let"
+        WHITESPACE@75..76 " "
+        TUPLE_STRUCT_PAT@76..88
+          PATH@76..77
+            PATH_SEGMENT@76..77
+              NAME_REF@76..77
+                IDENT@76..77 "S"
+          L_PAREN@77..78 "("
+          WILDCARD_PAT@78..79
+            UNDERSCORE@78..79 "_"
+          COMMA@79..80 ","
+          WHITESPACE@80..81 " "
+          REST_PAT@81..83
+            DOT2@81..83 ".."
+          WHITESPACE@83..84 " "
+          COMMA@84..85 ","
+          WHITESPACE@85..86 " "
+          IDENT_PAT@86..87
+            NAME@86..87
+              IDENT@86..87 "x"
+          R_PAREN@87..88 ")"
+        WHITESPACE@88..89 " "
+        EQ@89..90 "="
+        WHITESPACE@90..91 " "
+        TUPLE_EXPR@91..93
+          L_PAREN@91..92 "("
+          R_PAREN@92..93 ")"
+        SEMICOLON@93..94 ";"
+      WHITESPACE@94..95 "\n"
+      R_CURLY@95..96 "}"
+  WHITESPACE@96..97 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0026_tuple_pat_fields.rs b/crates/syntax/test_data/parser/inline/ok/0026_tuple_pat_fields.rs
new file mode 100644
index 00000000000..0dfe6362967
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0026_tuple_pat_fields.rs
@@ -0,0 +1,6 @@
+fn foo() {
+    let S() = ();
+    let S(_) = ();
+    let S(_,) = ();
+    let S(_, .. , x) = ();
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0027_ref_pat.rast b/crates/syntax/test_data/parser/inline/ok/0027_ref_pat.rast
new file mode 100644
index 00000000000..348b54dc9d8
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0027_ref_pat.rast
@@ -0,0 +1,49 @@
+SOURCE_FILE@0..52
+  FN@0..51
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..51
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      LET_STMT@16..28
+        LET_KW@16..19 "let"
+        WHITESPACE@19..20 " "
+        REF_PAT@20..22
+          AMP@20..21 "&"
+          IDENT_PAT@21..22
+            NAME@21..22
+              IDENT@21..22 "a"
+        WHITESPACE@22..23 " "
+        EQ@23..24 "="
+        WHITESPACE@24..25 " "
+        TUPLE_EXPR@25..27
+          L_PAREN@25..26 "("
+          R_PAREN@26..27 ")"
+        SEMICOLON@27..28 ";"
+      WHITESPACE@28..33 "\n    "
+      LET_STMT@33..49
+        LET_KW@33..36 "let"
+        WHITESPACE@36..37 " "
+        REF_PAT@37..43
+          AMP@37..38 "&"
+          MUT_KW@38..41 "mut"
+          WHITESPACE@41..42 " "
+          IDENT_PAT@42..43
+            NAME@42..43
+              IDENT@42..43 "b"
+        WHITESPACE@43..44 " "
+        EQ@44..45 "="
+        WHITESPACE@45..46 " "
+        TUPLE_EXPR@46..48
+          L_PAREN@46..47 "("
+          R_PAREN@47..48 ")"
+        SEMICOLON@48..49 ";"
+      WHITESPACE@49..50 "\n"
+      R_CURLY@50..51 "}"
+  WHITESPACE@51..52 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0027_ref_pat.rs b/crates/syntax/test_data/parser/inline/ok/0027_ref_pat.rs
new file mode 100644
index 00000000000..de41f5cae0f
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0027_ref_pat.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let &a = ();
+    let &mut b = ();
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0028_impl_trait_type.rast b/crates/syntax/test_data/parser/inline/ok/0028_impl_trait_type.rast
new file mode 100644
index 00000000000..32b2959bdfc
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0028_impl_trait_type.rast
@@ -0,0 +1,43 @@
+SOURCE_FILE@0..43
+  TYPE_ALIAS@0..42
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "A"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    IMPL_TRAIT_TYPE@9..41
+      IMPL_KW@9..13 "impl"
+      WHITESPACE@13..14 " "
+      TYPE_BOUND_LIST@14..41
+        TYPE_BOUND@14..36
+          PATH_TYPE@14..36
+            PATH@14..36
+              PATH_SEGMENT@14..36
+                NAME_REF@14..22
+                  IDENT@14..22 "Iterator"
+                GENERIC_ARG_LIST@22..36
+                  L_ANGLE@22..23 "<"
+                  ASSOC_TYPE_ARG@23..35
+                    NAME_REF@23..27
+                      IDENT@23..27 "Item"
+                    EQ@27..28 "="
+                    PATH_TYPE@28..35
+                      PATH@28..35
+                        PATH_SEGMENT@28..35
+                          NAME_REF@28..31
+                            IDENT@28..31 "Foo"
+                          GENERIC_ARG_LIST@31..35
+                            L_ANGLE@31..32 "<"
+                            LIFETIME_ARG@32..34
+                              LIFETIME@32..34 "\'a"
+                            R_ANGLE@34..35 ">"
+                  R_ANGLE@35..36 ">"
+        WHITESPACE@36..37 " "
+        PLUS@37..38 "+"
+        WHITESPACE@38..39 " "
+        TYPE_BOUND@39..41
+          LIFETIME@39..41 "\'a"
+    SEMICOLON@41..42 ";"
+  WHITESPACE@42..43 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0028_impl_trait_type.rs b/crates/syntax/test_data/parser/inline/ok/0028_impl_trait_type.rs
new file mode 100644
index 00000000000..54c5a7c4604
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0028_impl_trait_type.rs
@@ -0,0 +1 @@
+type A = impl Iterator<Item=Foo<'a>> + 'a;
diff --git a/crates/syntax/test_data/parser/inline/ok/0029_cast_expr.rast b/crates/syntax/test_data/parser/inline/ok/0029_cast_expr.rast
new file mode 100644
index 00000000000..e096b3a1f64
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0029_cast_expr.rast
@@ -0,0 +1,89 @@
+SOURCE_FILE@0..89
+  FN@0..88
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..88
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..25
+        CAST_EXPR@15..24
+          LITERAL@15..17
+            INT_NUMBER@15..17 "82"
+          WHITESPACE@17..18 " "
+          AS_KW@18..20 "as"
+          WHITESPACE@20..21 " "
+          PATH_TYPE@21..24
+            PATH@21..24
+              PATH_SEGMENT@21..24
+                NAME_REF@21..24
+                  IDENT@21..24 "i32"
+        SEMICOLON@24..25 ";"
+      WHITESPACE@25..30 "\n    "
+      EXPR_STMT@30..43
+        BIN_EXPR@30..42
+          CAST_EXPR@30..38
+            LITERAL@30..32
+              INT_NUMBER@30..32 "81"
+            WHITESPACE@32..33 " "
+            AS_KW@33..35 "as"
+            WHITESPACE@35..36 " "
+            PATH_TYPE@36..38
+              PATH@36..38
+                PATH_SEGMENT@36..38
+                  NAME_REF@36..38
+                    IDENT@36..38 "i8"
+          WHITESPACE@38..39 " "
+          PLUS@39..40 "+"
+          WHITESPACE@40..41 " "
+          LITERAL@41..42
+            INT_NUMBER@41..42 "1"
+        SEMICOLON@42..43 ";"
+      WHITESPACE@43..48 "\n    "
+      EXPR_STMT@48..62
+        BIN_EXPR@48..61
+          CAST_EXPR@48..57
+            LITERAL@48..50
+              INT_NUMBER@48..50 "79"
+            WHITESPACE@50..51 " "
+            AS_KW@51..53 "as"
+            WHITESPACE@53..54 " "
+            PATH_TYPE@54..57
+              PATH@54..57
+                PATH_SEGMENT@54..57
+                  NAME_REF@54..57
+                    IDENT@54..57 "i16"
+          WHITESPACE@57..58 " "
+          MINUS@58..59 "-"
+          WHITESPACE@59..60 " "
+          LITERAL@60..61
+            INT_NUMBER@60..61 "1"
+        SEMICOLON@61..62 ";"
+      WHITESPACE@62..67 "\n    "
+      EXPR_STMT@67..86
+        BIN_EXPR@67..85
+          CAST_EXPR@67..77
+            LITERAL@67..71
+              INT_NUMBER@67..71 "0x36"
+            WHITESPACE@71..72 " "
+            AS_KW@72..74 "as"
+            WHITESPACE@74..75 " "
+            PATH_TYPE@75..77
+              PATH@75..77
+                PATH_SEGMENT@75..77
+                  NAME_REF@75..77
+                    IDENT@75..77 "u8"
+          WHITESPACE@77..78 " "
+          LTEQ@78..80 "<="
+          WHITESPACE@80..81 " "
+          LITERAL@81..85
+            INT_NUMBER@81..85 "0x37"
+        SEMICOLON@85..86 ";"
+      WHITESPACE@86..87 "\n"
+      R_CURLY@87..88 "}"
+  WHITESPACE@88..89 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0029_cast_expr.rs b/crates/syntax/test_data/parser/inline/ok/0029_cast_expr.rs
new file mode 100644
index 00000000000..bfe8e4b362a
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0029_cast_expr.rs
@@ -0,0 +1,6 @@
+fn foo() {
+    82 as i32;
+    81 as i8 + 1;
+    79 as i16 - 1;
+    0x36 as u8 <= 0x37;
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0030_cond.rast b/crates/syntax/test_data/parser/inline/ok/0030_cond.rast
new file mode 100644
index 00000000000..58a97d3ad89
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0030_cond.rast
@@ -0,0 +1,202 @@
+SOURCE_FILE@0..197
+  FN@0..37
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..37
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..11 " "
+      IF_EXPR@11..35
+        IF_KW@11..13 "if"
+        WHITESPACE@13..14 " "
+        CONDITION@14..32
+          LET_KW@14..17 "let"
+          WHITESPACE@17..18 " "
+          TUPLE_STRUCT_PAT@18..25
+            PATH@18..22
+              PATH_SEGMENT@18..22
+                NAME_REF@18..22
+                  IDENT@18..22 "Some"
+            L_PAREN@22..23 "("
+            WILDCARD_PAT@23..24
+              UNDERSCORE@23..24 "_"
+            R_PAREN@24..25 ")"
+          WHITESPACE@25..26 " "
+          EQ@26..27 "="
+          WHITESPACE@27..28 " "
+          PATH_EXPR@28..32
+            PATH@28..32
+              PATH_SEGMENT@28..32
+                NAME_REF@28..32
+                  IDENT@28..32 "None"
+        WHITESPACE@32..33 " "
+        BLOCK_EXPR@33..35
+          L_CURLY@33..34 "{"
+          R_CURLY@34..35 "}"
+      WHITESPACE@35..36 " "
+      R_CURLY@36..37 "}"
+  WHITESPACE@37..38 "\n"
+  FN@38..196
+    FN_KW@38..40 "fn"
+    WHITESPACE@40..41 " "
+    NAME@41..44
+      IDENT@41..44 "bar"
+    PARAM_LIST@44..46
+      L_PAREN@44..45 "("
+      R_PAREN@45..46 ")"
+    WHITESPACE@46..47 " "
+    BLOCK_EXPR@47..196
+      L_CURLY@47..48 "{"
+      WHITESPACE@48..53 "\n    "
+      EXPR_STMT@53..87
+        IF_EXPR@53..87
+          IF_KW@53..55 "if"
+          WHITESPACE@55..56 " "
+          CONDITION@56..84
+            LET_KW@56..59 "let"
+            WHITESPACE@59..60 " "
+            OR_PAT@60..77
+              TUPLE_STRUCT_PAT@60..67
+                PATH@60..64
+                  PATH_SEGMENT@60..64
+                    NAME_REF@60..64
+                      IDENT@60..64 "Some"
+                L_PAREN@64..65 "("
+                WILDCARD_PAT@65..66
+                  UNDERSCORE@65..66 "_"
+                R_PAREN@66..67 ")"
+              WHITESPACE@67..68 " "
+              PIPE@68..69 "|"
+              WHITESPACE@69..70 " "
+              TUPLE_STRUCT_PAT@70..77
+                PATH@70..74
+                  PATH_SEGMENT@70..74
+                    NAME_REF@70..74
+                      IDENT@70..74 "Some"
+                L_PAREN@74..75 "("
+                WILDCARD_PAT@75..76
+                  UNDERSCORE@75..76 "_"
+                R_PAREN@76..77 ")"
+            WHITESPACE@77..78 " "
+            EQ@78..79 "="
+            WHITESPACE@79..80 " "
+            PATH_EXPR@80..84
+              PATH@80..84
+                PATH_SEGMENT@80..84
+                  NAME_REF@80..84
+                    IDENT@80..84 "None"
+          WHITESPACE@84..85 " "
+          BLOCK_EXPR@85..87
+            L_CURLY@85..86 "{"
+            R_CURLY@86..87 "}"
+      WHITESPACE@87..92 "\n    "
+      EXPR_STMT@92..118
+        IF_EXPR@92..118
+          IF_KW@92..94 "if"
+          WHITESPACE@94..95 " "
+          CONDITION@95..115
+            LET_KW@95..98 "let"
+            WHITESPACE@98..99 " "
+            PIPE@99..100 "|"
+            WHITESPACE@100..101 " "
+            TUPLE_STRUCT_PAT@101..108
+              PATH@101..105
+                PATH_SEGMENT@101..105
+                  NAME_REF@101..105
+                    IDENT@101..105 "Some"
+              L_PAREN@105..106 "("
+              WILDCARD_PAT@106..107
+                UNDERSCORE@106..107 "_"
+              R_PAREN@107..108 ")"
+            WHITESPACE@108..109 " "
+            EQ@109..110 "="
+            WHITESPACE@110..111 " "
+            PATH_EXPR@111..115
+              PATH@111..115
+                PATH_SEGMENT@111..115
+                  NAME_REF@111..115
+                    IDENT@111..115 "None"
+          WHITESPACE@115..116 " "
+          BLOCK_EXPR@116..118
+            L_CURLY@116..117 "{"
+            R_CURLY@117..118 "}"
+      WHITESPACE@118..123 "\n    "
+      EXPR_STMT@123..160
+        WHILE_EXPR@123..160
+          WHILE_KW@123..128 "while"
+          WHITESPACE@128..129 " "
+          CONDITION@129..157
+            LET_KW@129..132 "let"
+            WHITESPACE@132..133 " "
+            OR_PAT@133..150
+              TUPLE_STRUCT_PAT@133..140
+                PATH@133..137
+                  PATH_SEGMENT@133..137
+                    NAME_REF@133..137
+                      IDENT@133..137 "Some"
+                L_PAREN@137..138 "("
+                WILDCARD_PAT@138..139
+                  UNDERSCORE@138..139 "_"
+                R_PAREN@139..140 ")"
+              WHITESPACE@140..141 " "
+              PIPE@141..142 "|"
+              WHITESPACE@142..143 " "
+              TUPLE_STRUCT_PAT@143..150
+                PATH@143..147
+                  PATH_SEGMENT@143..147
+                    NAME_REF@143..147
+                      IDENT@143..147 "Some"
+                L_PAREN@147..148 "("
+                WILDCARD_PAT@148..149
+                  UNDERSCORE@148..149 "_"
+                R_PAREN@149..150 ")"
+            WHITESPACE@150..151 " "
+            EQ@151..152 "="
+            WHITESPACE@152..153 " "
+            PATH_EXPR@153..157
+              PATH@153..157
+                PATH_SEGMENT@153..157
+                  NAME_REF@153..157
+                    IDENT@153..157 "None"
+          WHITESPACE@157..158 " "
+          BLOCK_EXPR@158..160
+            L_CURLY@158..159 "{"
+            R_CURLY@159..160 "}"
+      WHITESPACE@160..165 "\n    "
+      WHILE_EXPR@165..194
+        WHILE_KW@165..170 "while"
+        WHITESPACE@170..171 " "
+        CONDITION@171..191
+          LET_KW@171..174 "let"
+          WHITESPACE@174..175 " "
+          PIPE@175..176 "|"
+          WHITESPACE@176..177 " "
+          TUPLE_STRUCT_PAT@177..184
+            PATH@177..181
+              PATH_SEGMENT@177..181
+                NAME_REF@177..181
+                  IDENT@177..181 "Some"
+            L_PAREN@181..182 "("
+            WILDCARD_PAT@182..183
+              UNDERSCORE@182..183 "_"
+            R_PAREN@183..184 ")"
+          WHITESPACE@184..185 " "
+          EQ@185..186 "="
+          WHITESPACE@186..187 " "
+          PATH_EXPR@187..191
+            PATH@187..191
+              PATH_SEGMENT@187..191
+                NAME_REF@187..191
+                  IDENT@187..191 "None"
+        WHITESPACE@191..192 " "
+        BLOCK_EXPR@192..194
+          L_CURLY@192..193 "{"
+          R_CURLY@193..194 "}"
+      WHITESPACE@194..195 "\n"
+      R_CURLY@195..196 "}"
+  WHITESPACE@196..197 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0030_cond.rs b/crates/syntax/test_data/parser/inline/ok/0030_cond.rs
new file mode 100644
index 00000000000..2552a2621f9
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0030_cond.rs
@@ -0,0 +1,7 @@
+fn foo() { if let Some(_) = None {} }
+fn bar() {
+    if let Some(_) | Some(_) = None {}
+    if let | Some(_) = None {}
+    while let Some(_) | Some(_) = None {}
+    while let | Some(_) = None {}
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0031_while_expr.rast b/crates/syntax/test_data/parser/inline/ok/0031_while_expr.rast
new file mode 100644
index 00000000000..173cecf6d9d
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0031_while_expr.rast
@@ -0,0 +1,84 @@
+SOURCE_FILE@0..93
+  FN@0..92
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..92
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..29
+        WHILE_EXPR@15..28
+          WHILE_KW@15..20 "while"
+          WHITESPACE@20..21 " "
+          CONDITION@21..25
+            LITERAL@21..25
+              TRUE_KW@21..25 "true"
+          WHITESPACE@25..26 " "
+          BLOCK_EXPR@26..28
+            L_CURLY@26..27 "{"
+            R_CURLY@27..28 "}"
+        SEMICOLON@28..29 ";"
+      WHITESPACE@29..34 "\n    "
+      EXPR_STMT@34..67
+        WHILE_EXPR@34..66
+          WHILE_KW@34..39 "while"
+          WHITESPACE@39..40 " "
+          CONDITION@40..63
+            LET_KW@40..43 "let"
+            WHITESPACE@43..44 " "
+            TUPLE_STRUCT_PAT@44..51
+              PATH@44..48
+                PATH_SEGMENT@44..48
+                  NAME_REF@44..48
+                    IDENT@44..48 "Some"
+              L_PAREN@48..49 "("
+              IDENT_PAT@49..50
+                NAME@49..50
+                  IDENT@49..50 "x"
+              R_PAREN@50..51 ")"
+            WHITESPACE@51..52 " "
+            EQ@52..53 "="
+            WHITESPACE@53..54 " "
+            METHOD_CALL_EXPR@54..63
+              PATH_EXPR@54..56
+                PATH@54..56
+                  PATH_SEGMENT@54..56
+                    NAME_REF@54..56
+                      IDENT@54..56 "it"
+              DOT@56..57 "."
+              NAME_REF@57..61
+                IDENT@57..61 "next"
+              ARG_LIST@61..63
+                L_PAREN@61..62 "("
+                R_PAREN@62..63 ")"
+          WHITESPACE@63..64 " "
+          BLOCK_EXPR@64..66
+            L_CURLY@64..65 "{"
+            R_CURLY@65..66 "}"
+        SEMICOLON@66..67 ";"
+      WHITESPACE@67..72 "\n    "
+      EXPR_STMT@72..90
+        WHILE_EXPR@72..89
+          WHILE_KW@72..77 "while"
+          WHITESPACE@77..78 " "
+          CONDITION@78..86
+            BLOCK_EXPR@78..86
+              L_CURLY@78..79 "{"
+              WHITESPACE@79..80 " "
+              LITERAL@80..84
+                TRUE_KW@80..84 "true"
+              WHITESPACE@84..85 " "
+              R_CURLY@85..86 "}"
+          WHITESPACE@86..87 " "
+          BLOCK_EXPR@87..89
+            L_CURLY@87..88 "{"
+            R_CURLY@88..89 "}"
+        SEMICOLON@89..90 ";"
+      WHITESPACE@90..91 "\n"
+      R_CURLY@91..92 "}"
+  WHITESPACE@92..93 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0031_while_expr.rs b/crates/syntax/test_data/parser/inline/ok/0031_while_expr.rs
new file mode 100644
index 00000000000..2f818816025
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0031_while_expr.rs
@@ -0,0 +1,5 @@
+fn foo() {
+    while true {};
+    while let Some(x) = it.next() {};
+    while { true } {};
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0032_fn_pointer_type.rast b/crates/syntax/test_data/parser/inline/ok/0032_fn_pointer_type.rast
new file mode 100644
index 00000000000..dda6577eda8
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0032_fn_pointer_type.rast
@@ -0,0 +1,98 @@
+SOURCE_FILE@0..113
+  TYPE_ALIAS@0..14
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "A"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    FN_PTR_TYPE@9..13
+      FN_KW@9..11 "fn"
+      PARAM_LIST@11..13
+        L_PAREN@11..12 "("
+        R_PAREN@12..13 ")"
+    SEMICOLON@13..14 ";"
+  WHITESPACE@14..15 "\n"
+  TYPE_ALIAS@15..36
+    TYPE_KW@15..19 "type"
+    WHITESPACE@19..20 " "
+    NAME@20..21
+      IDENT@20..21 "B"
+    WHITESPACE@21..22 " "
+    EQ@22..23 "="
+    WHITESPACE@23..24 " "
+    FN_PTR_TYPE@24..35
+      UNSAFE_KW@24..30 "unsafe"
+      WHITESPACE@30..31 " "
+      FN_KW@31..33 "fn"
+      PARAM_LIST@33..35
+        L_PAREN@33..34 "("
+        R_PAREN@34..35 ")"
+    SEMICOLON@35..36 ";"
+  WHITESPACE@36..37 "\n"
+  TYPE_ALIAS@37..69
+    TYPE_KW@37..41 "type"
+    WHITESPACE@41..42 " "
+    NAME@42..43
+      IDENT@42..43 "C"
+    WHITESPACE@43..44 " "
+    EQ@44..45 "="
+    WHITESPACE@45..46 " "
+    FN_PTR_TYPE@46..68
+      UNSAFE_KW@46..52 "unsafe"
+      WHITESPACE@52..53 " "
+      ABI@53..63
+        EXTERN_KW@53..59 "extern"
+        WHITESPACE@59..60 " "
+        STRING@60..63 "\"C\""
+      WHITESPACE@63..64 " "
+      FN_KW@64..66 "fn"
+      PARAM_LIST@66..68
+        L_PAREN@66..67 "("
+        R_PAREN@67..68 ")"
+    SEMICOLON@68..69 ";"
+  WHITESPACE@69..70 "\n"
+  TYPE_ALIAS@70..112
+    TYPE_KW@70..74 "type"
+    WHITESPACE@74..75 " "
+    NAME@75..76
+      IDENT@75..76 "D"
+    WHITESPACE@76..77 " "
+    EQ@77..78 "="
+    WHITESPACE@78..79 " "
+    FN_PTR_TYPE@79..111
+      ABI@79..89
+        EXTERN_KW@79..85 "extern"
+        WHITESPACE@85..86 " "
+        STRING@86..89 "\"C\""
+      WHITESPACE@89..90 " "
+      FN_KW@90..92 "fn"
+      WHITESPACE@92..93 " "
+      PARAM_LIST@93..105
+        L_PAREN@93..94 "("
+        WHITESPACE@94..95 " "
+        PARAM@95..97
+          PATH_TYPE@95..97
+            PATH@95..97
+              PATH_SEGMENT@95..97
+                NAME_REF@95..97
+                  IDENT@95..97 "u8"
+        WHITESPACE@97..98 " "
+        COMMA@98..99 ","
+        WHITESPACE@99..100 " "
+        PARAM@100..103
+          DOT3@100..103 "..."
+        WHITESPACE@103..104 " "
+        R_PAREN@104..105 ")"
+      WHITESPACE@105..106 " "
+      RET_TYPE@106..111
+        THIN_ARROW@106..108 "->"
+        WHITESPACE@108..109 " "
+        PATH_TYPE@109..111
+          PATH@109..111
+            PATH_SEGMENT@109..111
+              NAME_REF@109..111
+                IDENT@109..111 "u8"
+    SEMICOLON@111..112 ";"
+  WHITESPACE@112..113 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0032_fn_pointer_type.rs b/crates/syntax/test_data/parser/inline/ok/0032_fn_pointer_type.rs
new file mode 100644
index 00000000000..9493da83d56
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0032_fn_pointer_type.rs
@@ -0,0 +1,4 @@
+type A = fn();
+type B = unsafe fn();
+type C = unsafe extern "C" fn();
+type D = extern "C" fn ( u8 , ... ) -> u8;
diff --git a/crates/syntax/test_data/parser/inline/ok/0033_reference_type;.rast b/crates/syntax/test_data/parser/inline/ok/0033_reference_type;.rast
new file mode 100644
index 00000000000..974df9f9aa1
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0033_reference_type;.rast
@@ -0,0 +1,50 @@
+SOURCE_FILE@0..54
+  TYPE_ALIAS@0..13
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "A"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    REF_TYPE@9..12
+      AMP@9..10 "&"
+      TUPLE_TYPE@10..12
+        L_PAREN@10..11 "("
+        R_PAREN@11..12 ")"
+    SEMICOLON@12..13 ";"
+  WHITESPACE@13..14 "\n"
+  TYPE_ALIAS@14..35
+    TYPE_KW@14..18 "type"
+    WHITESPACE@18..19 " "
+    NAME@19..20
+      IDENT@19..20 "B"
+    WHITESPACE@20..21 " "
+    EQ@21..22 "="
+    WHITESPACE@22..23 " "
+    REF_TYPE@23..34
+      AMP@23..24 "&"
+      LIFETIME@24..31 "\'static"
+      WHITESPACE@31..32 " "
+      TUPLE_TYPE@32..34
+        L_PAREN@32..33 "("
+        R_PAREN@33..34 ")"
+    SEMICOLON@34..35 ";"
+  WHITESPACE@35..36 "\n"
+  TYPE_ALIAS@36..53
+    TYPE_KW@36..40 "type"
+    WHITESPACE@40..41 " "
+    NAME@41..42
+      IDENT@41..42 "C"
+    WHITESPACE@42..43 " "
+    EQ@43..44 "="
+    WHITESPACE@44..45 " "
+    REF_TYPE@45..52
+      AMP@45..46 "&"
+      MUT_KW@46..49 "mut"
+      WHITESPACE@49..50 " "
+      TUPLE_TYPE@50..52
+        L_PAREN@50..51 "("
+        R_PAREN@51..52 ")"
+    SEMICOLON@52..53 ";"
+  WHITESPACE@53..54 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0033_reference_type;.rs b/crates/syntax/test_data/parser/inline/ok/0033_reference_type;.rs
new file mode 100644
index 00000000000..3ac0badabc5
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0033_reference_type;.rs
@@ -0,0 +1,3 @@
+type A = &();
+type B = &'static ();
+type C = &mut ();
diff --git a/crates/syntax/test_data/parser/inline/ok/0034_break_expr.rast b/crates/syntax/test_data/parser/inline/ok/0034_break_expr.rast
new file mode 100644
index 00000000000..f905def6ff0
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0034_break_expr.rast
@@ -0,0 +1,53 @@
+SOURCE_FILE@0..102
+  FN@0..101
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..101
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      LOOP_EXPR@15..99
+        LOOP_KW@15..19 "loop"
+        WHITESPACE@19..20 " "
+        BLOCK_EXPR@20..99
+          L_CURLY@20..21 "{"
+          WHITESPACE@21..30 "\n        "
+          EXPR_STMT@30..36
+            BREAK_EXPR@30..35
+              BREAK_KW@30..35 "break"
+            SEMICOLON@35..36 ";"
+          WHITESPACE@36..45 "\n        "
+          EXPR_STMT@45..54
+            BREAK_EXPR@45..53
+              BREAK_KW@45..50 "break"
+              WHITESPACE@50..51 " "
+              LIFETIME@51..53 "\'l"
+            SEMICOLON@53..54 ";"
+          WHITESPACE@54..63 "\n        "
+          EXPR_STMT@63..72
+            BREAK_EXPR@63..71
+              BREAK_KW@63..68 "break"
+              WHITESPACE@68..69 " "
+              LITERAL@69..71
+                INT_NUMBER@69..71 "92"
+            SEMICOLON@71..72 ";"
+          WHITESPACE@72..81 "\n        "
+          EXPR_STMT@81..93
+            BREAK_EXPR@81..92
+              BREAK_KW@81..86 "break"
+              WHITESPACE@86..87 " "
+              LIFETIME@87..89 "\'l"
+              WHITESPACE@89..90 " "
+              LITERAL@90..92
+                INT_NUMBER@90..92 "92"
+            SEMICOLON@92..93 ";"
+          WHITESPACE@93..98 "\n    "
+          R_CURLY@98..99 "}"
+      WHITESPACE@99..100 "\n"
+      R_CURLY@100..101 "}"
+  WHITESPACE@101..102 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0034_break_expr.rs b/crates/syntax/test_data/parser/inline/ok/0034_break_expr.rs
new file mode 100644
index 00000000000..1b40946365f
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0034_break_expr.rs
@@ -0,0 +1,8 @@
+fn foo() {
+    loop {
+        break;
+        break 'l;
+        break 92;
+        break 'l 92;
+    }
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0037_qual_paths.rast b/crates/syntax/test_data/parser/inline/ok/0037_qual_paths.rast
new file mode 100644
index 00000000000..b6379e62f8c
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0037_qual_paths.rast
@@ -0,0 +1,78 @@
+SOURCE_FILE@0..71
+  TYPE_ALIAS@0..26
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "X"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    PATH_TYPE@9..25
+      PATH@9..25
+        PATH@9..17
+          PATH_SEGMENT@9..17
+            L_ANGLE@9..10 "<"
+            PATH_TYPE@10..11
+              PATH@10..11
+                PATH_SEGMENT@10..11
+                  NAME_REF@10..11
+                    IDENT@10..11 "A"
+            WHITESPACE@11..12 " "
+            AS_KW@12..14 "as"
+            WHITESPACE@14..15 " "
+            PATH_TYPE@15..16
+              PATH@15..16
+                PATH_SEGMENT@15..16
+                  NAME_REF@15..16
+                    IDENT@15..16 "B"
+            R_ANGLE@16..17 ">"
+        COLON2@17..19 "::"
+        PATH_SEGMENT@19..25
+          NAME_REF@19..25
+            IDENT@19..25 "Output"
+    SEMICOLON@25..26 ";"
+  WHITESPACE@26..27 "\n"
+  FN@27..70
+    FN_KW@27..29 "fn"
+    WHITESPACE@29..30 " "
+    NAME@30..33
+      IDENT@30..33 "foo"
+    PARAM_LIST@33..35
+      L_PAREN@33..34 "("
+      R_PAREN@34..35 ")"
+    WHITESPACE@35..36 " "
+    BLOCK_EXPR@36..70
+      L_CURLY@36..37 "{"
+      WHITESPACE@37..38 " "
+      EXPR_STMT@38..68
+        CALL_EXPR@38..67
+          PATH_EXPR@38..65
+            PATH@38..65
+              PATH@38..56
+                PATH_SEGMENT@38..56
+                  L_ANGLE@38..39 "<"
+                  PATH_TYPE@39..44
+                    PATH@39..44
+                      PATH_SEGMENT@39..44
+                        NAME_REF@39..44
+                          IDENT@39..44 "usize"
+                  WHITESPACE@44..45 " "
+                  AS_KW@45..47 "as"
+                  WHITESPACE@47..48 " "
+                  PATH_TYPE@48..55
+                    PATH@48..55
+                      PATH_SEGMENT@48..55
+                        NAME_REF@48..55
+                          IDENT@48..55 "Default"
+                  R_ANGLE@55..56 ">"
+              COLON2@56..58 "::"
+              PATH_SEGMENT@58..65
+                NAME_REF@58..65
+                  IDENT@58..65 "default"
+          ARG_LIST@65..67
+            L_PAREN@65..66 "("
+            R_PAREN@66..67 ")"
+        SEMICOLON@67..68 ";"
+      WHITESPACE@68..69 " "
+      R_CURLY@69..70 "}"
+  WHITESPACE@70..71 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0037_qual_paths.rs b/crates/syntax/test_data/parser/inline/ok/0037_qual_paths.rs
new file mode 100644
index 00000000000..d140692e210
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0037_qual_paths.rs
@@ -0,0 +1,2 @@
+type X = <A as B>::Output;
+fn foo() { <usize as Default>::default(); }
diff --git a/crates/syntax/test_data/parser/inline/ok/0038_full_range_expr.rast b/crates/syntax/test_data/parser/inline/ok/0038_full_range_expr.rast
new file mode 100644
index 00000000000..64e705fb3d2
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0038_full_range_expr.rast
@@ -0,0 +1,28 @@
+SOURCE_FILE@0..21
+  FN@0..20
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..20
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..11 " "
+      EXPR_STMT@11..18
+        INDEX_EXPR@11..17
+          PATH_EXPR@11..13
+            PATH@11..13
+              PATH_SEGMENT@11..13
+                NAME_REF@11..13
+                  IDENT@11..13 "xs"
+          L_BRACK@13..14 "["
+          RANGE_EXPR@14..16
+            DOT2@14..16 ".."
+          R_BRACK@16..17 "]"
+        SEMICOLON@17..18 ";"
+      WHITESPACE@18..19 " "
+      R_CURLY@19..20 "}"
+  WHITESPACE@20..21 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0038_full_range_expr.rs b/crates/syntax/test_data/parser/inline/ok/0038_full_range_expr.rs
new file mode 100644
index 00000000000..ae21ad94cb3
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0038_full_range_expr.rs
@@ -0,0 +1 @@
+fn foo() { xs[..]; }
diff --git a/crates/syntax/test_data/parser/inline/ok/0039_type_arg.rast b/crates/syntax/test_data/parser/inline/ok/0039_type_arg.rast
new file mode 100644
index 00000000000..69e98b9d6c0
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0039_type_arg.rast
@@ -0,0 +1,55 @@
+SOURCE_FILE@0..46
+  TYPE_ALIAS@0..45
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "A"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    PATH_TYPE@9..44
+      PATH@9..44
+        PATH_SEGMENT@9..44
+          NAME_REF@9..10
+            IDENT@9..10 "B"
+          GENERIC_ARG_LIST@10..44
+            L_ANGLE@10..11 "<"
+            LIFETIME_ARG@11..18
+              LIFETIME@11..18 "\'static"
+            COMMA@18..19 ","
+            WHITESPACE@19..20 " "
+            TYPE_ARG@20..23
+              PATH_TYPE@20..23
+                PATH@20..23
+                  PATH_SEGMENT@20..23
+                    NAME_REF@20..23
+                      IDENT@20..23 "i32"
+            COMMA@23..24 ","
+            WHITESPACE@24..25 " "
+            CONST_ARG@25..26
+              LITERAL@25..26
+                INT_NUMBER@25..26 "1"
+            COMMA@26..27 ","
+            WHITESPACE@27..28 " "
+            CONST_ARG@28..33
+              BLOCK_EXPR@28..33
+                L_CURLY@28..29 "{"
+                WHITESPACE@29..30 " "
+                LITERAL@30..31
+                  INT_NUMBER@30..31 "2"
+                WHITESPACE@31..32 " "
+                R_CURLY@32..33 "}"
+            COMMA@33..34 ","
+            WHITESPACE@34..35 " "
+            ASSOC_TYPE_ARG@35..43
+              NAME_REF@35..39
+                IDENT@35..39 "Item"
+              EQ@39..40 "="
+              PATH_TYPE@40..43
+                PATH@40..43
+                  PATH_SEGMENT@40..43
+                    NAME_REF@40..43
+                      IDENT@40..43 "u64"
+            R_ANGLE@43..44 ">"
+    SEMICOLON@44..45 ";"
+  WHITESPACE@45..46 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0039_type_arg.rs b/crates/syntax/test_data/parser/inline/ok/0039_type_arg.rs
new file mode 100644
index 00000000000..0d07d76514e
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0039_type_arg.rs
@@ -0,0 +1 @@
+type A = B<'static, i32, 1, { 2 }, Item=u64>;
diff --git a/crates/syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.rast b/crates/syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.rast
new file mode 100644
index 00000000000..db5bd284969
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.rast
@@ -0,0 +1,62 @@
+SOURCE_FILE@0..71
+  FN@0..19
+    VISIBILITY@0..5
+      CRATE_KW@0..5 "crate"
+    WHITESPACE@5..6 " "
+    FN_KW@6..8 "fn"
+    WHITESPACE@8..9 " "
+    NAME@9..13
+      IDENT@9..13 "main"
+    PARAM_LIST@13..15
+      L_PAREN@13..14 "("
+      R_PAREN@14..15 ")"
+    WHITESPACE@15..16 " "
+    BLOCK_EXPR@16..19
+      L_CURLY@16..17 "{"
+      WHITESPACE@17..18 " "
+      R_CURLY@18..19 "}"
+  WHITESPACE@19..20 "\n"
+  STRUCT@20..49
+    STRUCT_KW@20..26 "struct"
+    WHITESPACE@26..27 " "
+    NAME@27..28
+      IDENT@27..28 "S"
+    WHITESPACE@28..29 " "
+    RECORD_FIELD_LIST@29..49
+      L_CURLY@29..30 "{"
+      WHITESPACE@30..31 " "
+      RECORD_FIELD@31..47
+        VISIBILITY@31..36
+          CRATE_KW@31..36 "crate"
+        WHITESPACE@36..37 " "
+        NAME@37..42
+          IDENT@37..42 "field"
+        COLON@42..43 ":"
+        WHITESPACE@43..44 " "
+        PATH_TYPE@44..47
+          PATH@44..47
+            PATH_SEGMENT@44..47
+              NAME_REF@44..47
+                IDENT@44..47 "u32"
+      WHITESPACE@47..48 " "
+      R_CURLY@48..49 "}"
+  WHITESPACE@49..50 "\n"
+  STRUCT@50..70
+    STRUCT_KW@50..56 "struct"
+    WHITESPACE@56..57 " "
+    NAME@57..58
+      IDENT@57..58 "T"
+    TUPLE_FIELD_LIST@58..69
+      L_PAREN@58..59 "("
+      TUPLE_FIELD@59..68
+        VISIBILITY@59..64
+          CRATE_KW@59..64 "crate"
+        WHITESPACE@64..65 " "
+        PATH_TYPE@65..68
+          PATH@65..68
+            PATH_SEGMENT@65..68
+              NAME_REF@65..68
+                IDENT@65..68 "u32"
+      R_PAREN@68..69 ")"
+    SEMICOLON@69..70 ";"
+  WHITESPACE@70..71 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.rs b/crates/syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.rs
new file mode 100644
index 00000000000..e2b5f2161df
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.rs
@@ -0,0 +1,3 @@
+crate fn main() { }
+struct S { crate field: u32 }
+struct T(crate u32);
diff --git a/crates/syntax/test_data/parser/inline/ok/0041_trait_item.rast b/crates/syntax/test_data/parser/inline/ok/0041_trait_item.rast
new file mode 100644
index 00000000000..3638462f8b2
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0041_trait_item.rast
@@ -0,0 +1,125 @@
+SOURCE_FILE@0..101
+  TRAIT@0..41
+    TRAIT_KW@0..5 "trait"
+    WHITESPACE@5..6 " "
+    NAME@6..7
+      IDENT@6..7 "T"
+    GENERIC_PARAM_LIST@7..10
+      L_ANGLE@7..8 "<"
+      TYPE_PARAM@8..9
+        NAME@8..9
+          IDENT@8..9 "U"
+      R_ANGLE@9..10 ">"
+    COLON@10..11 ":"
+    WHITESPACE@11..12 " "
+    TYPE_BOUND_LIST@12..24
+      TYPE_BOUND@12..16
+        PATH_TYPE@12..16
+          PATH@12..16
+            PATH_SEGMENT@12..16
+              NAME_REF@12..16
+                IDENT@12..16 "Hash"
+      WHITESPACE@16..17 " "
+      PLUS@17..18 "+"
+      WHITESPACE@18..19 " "
+      TYPE_BOUND@19..24
+        PATH_TYPE@19..24
+          PATH@19..24
+            PATH_SEGMENT@19..24
+              NAME_REF@19..24
+                IDENT@19..24 "Clone"
+    WHITESPACE@24..25 " "
+    WHERE_CLAUSE@25..38
+      WHERE_KW@25..30 "where"
+      WHITESPACE@30..31 " "
+      WHERE_PRED@31..38
+        PATH_TYPE@31..32
+          PATH@31..32
+            PATH_SEGMENT@31..32
+              NAME_REF@31..32
+                IDENT@31..32 "U"
+        COLON@32..33 ":"
+        WHITESPACE@33..34 " "
+        TYPE_BOUND_LIST@34..38
+          TYPE_BOUND@34..38
+            PATH_TYPE@34..38
+              PATH@34..38
+                PATH_SEGMENT@34..38
+                  NAME_REF@34..38
+                    IDENT@34..38 "Copy"
+    WHITESPACE@38..39 " "
+    ASSOC_ITEM_LIST@39..41
+      L_CURLY@39..40 "{"
+      R_CURLY@40..41 "}"
+  WHITESPACE@41..42 "\n"
+  TRAIT@42..100
+    TRAIT_KW@42..47 "trait"
+    WHITESPACE@47..48 " "
+    NAME@48..49
+      IDENT@48..49 "X"
+    GENERIC_PARAM_LIST@49..69
+      L_ANGLE@49..50 "<"
+      TYPE_PARAM@50..68
+        NAME@50..51
+          IDENT@50..51 "U"
+        COLON@51..52 ":"
+        WHITESPACE@52..53 " "
+        TYPE_BOUND_LIST@53..68
+          TYPE_BOUND@53..58
+            PATH_TYPE@53..58
+              PATH@53..58
+                PATH_SEGMENT@53..58
+                  NAME_REF@53..58
+                    IDENT@53..58 "Debug"
+          WHITESPACE@58..59 " "
+          PLUS@59..60 "+"
+          WHITESPACE@60..61 " "
+          TYPE_BOUND@61..68
+            PATH_TYPE@61..68
+              PATH@61..68
+                PATH_SEGMENT@61..68
+                  NAME_REF@61..68
+                    IDENT@61..68 "Display"
+      R_ANGLE@68..69 ">"
+    COLON@69..70 ":"
+    WHITESPACE@70..71 " "
+    TYPE_BOUND_LIST@71..83
+      TYPE_BOUND@71..75
+        PATH_TYPE@71..75
+          PATH@71..75
+            PATH_SEGMENT@71..75
+              NAME_REF@71..75
+                IDENT@71..75 "Hash"
+      WHITESPACE@75..76 " "
+      PLUS@76..77 "+"
+      WHITESPACE@77..78 " "
+      TYPE_BOUND@78..83
+        PATH_TYPE@78..83
+          PATH@78..83
+            PATH_SEGMENT@78..83
+              NAME_REF@78..83
+                IDENT@78..83 "Clone"
+    WHITESPACE@83..84 " "
+    WHERE_CLAUSE@84..97
+      WHERE_KW@84..89 "where"
+      WHITESPACE@89..90 " "
+      WHERE_PRED@90..97
+        PATH_TYPE@90..91
+          PATH@90..91
+            PATH_SEGMENT@90..91
+              NAME_REF@90..91
+                IDENT@90..91 "U"
+        COLON@91..92 ":"
+        WHITESPACE@92..93 " "
+        TYPE_BOUND_LIST@93..97
+          TYPE_BOUND@93..97
+            PATH_TYPE@93..97
+              PATH@93..97
+                PATH_SEGMENT@93..97
+                  NAME_REF@93..97
+                    IDENT@93..97 "Copy"
+    WHITESPACE@97..98 " "
+    ASSOC_ITEM_LIST@98..100
+      L_CURLY@98..99 "{"
+      R_CURLY@99..100 "}"
+  WHITESPACE@100..101 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0041_trait_item.rs b/crates/syntax/test_data/parser/inline/ok/0041_trait_item.rs
new file mode 100644
index 00000000000..32761dd03d0
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0041_trait_item.rs
@@ -0,0 +1,2 @@
+trait T<U>: Hash + Clone where U: Copy {}
+trait X<U: Debug + Display>: Hash + Clone where U: Copy {}
diff --git a/crates/syntax/test_data/parser/inline/ok/0042_call_expr.rast b/crates/syntax/test_data/parser/inline/ok/0042_call_expr.rast
new file mode 100644
index 00000000000..fa38e946673
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0042_call_expr.rast
@@ -0,0 +1,147 @@
+SOURCE_FILE@0..118
+  FN@0..117
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..117
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      LET_STMT@15..27
+        LET_KW@15..18 "let"
+        WHITESPACE@18..19 " "
+        WILDCARD_PAT@19..20
+          UNDERSCORE@19..20 "_"
+        WHITESPACE@20..21 " "
+        EQ@21..22 "="
+        WHITESPACE@22..23 " "
+        CALL_EXPR@23..26
+          PATH_EXPR@23..24
+            PATH@23..24
+              PATH_SEGMENT@23..24
+                NAME_REF@23..24
+                  IDENT@23..24 "f"
+          ARG_LIST@24..26
+            L_PAREN@24..25 "("
+            R_PAREN@25..26 ")"
+        SEMICOLON@26..27 ";"
+      WHITESPACE@27..32 "\n    "
+      LET_STMT@32..54
+        LET_KW@32..35 "let"
+        WHITESPACE@35..36 " "
+        WILDCARD_PAT@36..37
+          UNDERSCORE@36..37 "_"
+        WHITESPACE@37..38 " "
+        EQ@38..39 "="
+        WHITESPACE@39..40 " "
+        CALL_EXPR@40..53
+          CALL_EXPR@40..46
+            CALL_EXPR@40..43
+              PATH_EXPR@40..41
+                PATH@40..41
+                  PATH_SEGMENT@40..41
+                    NAME_REF@40..41
+                      IDENT@40..41 "f"
+              ARG_LIST@41..43
+                L_PAREN@41..42 "("
+                R_PAREN@42..43 ")"
+            ARG_LIST@43..46
+              L_PAREN@43..44 "("
+              LITERAL@44..45
+                INT_NUMBER@44..45 "1"
+              R_PAREN@45..46 ")"
+          ARG_LIST@46..53
+            L_PAREN@46..47 "("
+            LITERAL@47..48
+              INT_NUMBER@47..48 "1"
+            COMMA@48..49 ","
+            WHITESPACE@49..50 " "
+            LITERAL@50..51
+              INT_NUMBER@50..51 "2"
+            COMMA@51..52 ","
+            R_PAREN@52..53 ")"
+        SEMICOLON@53..54 ";"
+      WHITESPACE@54..59 "\n    "
+      LET_STMT@59..84
+        LET_KW@59..62 "let"
+        WHITESPACE@62..63 " "
+        WILDCARD_PAT@63..64
+          UNDERSCORE@63..64 "_"
+        WHITESPACE@64..65 " "
+        EQ@65..66 "="
+        WHITESPACE@66..67 " "
+        CALL_EXPR@67..83
+          PATH_EXPR@67..68
+            PATH@67..68
+              PATH_SEGMENT@67..68
+                NAME_REF@67..68
+                  IDENT@67..68 "f"
+          ARG_LIST@68..83
+            L_PAREN@68..69 "("
+            CALL_EXPR@69..82
+              PATH_EXPR@69..80
+                PATH@69..80
+                  PATH@69..74
+                    PATH_SEGMENT@69..74
+                      L_ANGLE@69..70 "<"
+                      PATH_TYPE@70..73
+                        PATH@70..73
+                          PATH_SEGMENT@70..73
+                            NAME_REF@70..73
+                              IDENT@70..73 "Foo"
+                      R_ANGLE@73..74 ">"
+                  COLON2@74..76 "::"
+                  PATH_SEGMENT@76..80
+                    NAME_REF@76..80
+                      IDENT@76..80 "func"
+              ARG_LIST@80..82
+                L_PAREN@80..81 "("
+                R_PAREN@81..82 ")"
+            R_PAREN@82..83 ")"
+        SEMICOLON@83..84 ";"
+      WHITESPACE@84..89 "\n    "
+      EXPR_STMT@89..115
+        CALL_EXPR@89..114
+          PATH_EXPR@89..90
+            PATH@89..90
+              PATH_SEGMENT@89..90
+                NAME_REF@89..90
+                  IDENT@89..90 "f"
+          ARG_LIST@90..114
+            L_PAREN@90..91 "("
+            CALL_EXPR@91..113
+              PATH_EXPR@91..111
+                PATH@91..111
+                  PATH@91..105
+                    PATH_SEGMENT@91..105
+                      L_ANGLE@91..92 "<"
+                      PATH_TYPE@92..95
+                        PATH@92..95
+                          PATH_SEGMENT@92..95
+                            NAME_REF@92..95
+                              IDENT@92..95 "Foo"
+                      WHITESPACE@95..96 " "
+                      AS_KW@96..98 "as"
+                      WHITESPACE@98..99 " "
+                      PATH_TYPE@99..104
+                        PATH@99..104
+                          PATH_SEGMENT@99..104
+                            NAME_REF@99..104
+                              IDENT@99..104 "Trait"
+                      R_ANGLE@104..105 ">"
+                  COLON2@105..107 "::"
+                  PATH_SEGMENT@107..111
+                    NAME_REF@107..111
+                      IDENT@107..111 "func"
+              ARG_LIST@111..113
+                L_PAREN@111..112 "("
+                R_PAREN@112..113 ")"
+            R_PAREN@113..114 ")"
+        SEMICOLON@114..115 ";"
+      WHITESPACE@115..116 "\n"
+      R_CURLY@116..117 "}"
+  WHITESPACE@117..118 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0042_call_expr.rs b/crates/syntax/test_data/parser/inline/ok/0042_call_expr.rs
new file mode 100644
index 00000000000..ffbf46d6d1f
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0042_call_expr.rs
@@ -0,0 +1,6 @@
+fn foo() {
+    let _ = f();
+    let _ = f()(1)(1, 2,);
+    let _ = f(<Foo>::func());
+    f(<Foo as Trait>::func());
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0043_use_alias.rast b/crates/syntax/test_data/parser/inline/ok/0043_use_alias.rast
new file mode 100644
index 00000000000..60b517230e8
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0043_use_alias.rast
@@ -0,0 +1,138 @@
+SOURCE_FILE@0..198
+  USE@0..28
+    USE_KW@0..3 "use"
+    WHITESPACE@3..4 " "
+    USE_TREE@4..27
+      PATH@4..14
+        PATH@4..8
+          PATH_SEGMENT@4..8
+            NAME_REF@4..8
+              IDENT@4..8 "some"
+        COLON2@8..10 "::"
+        PATH_SEGMENT@10..14
+          NAME_REF@10..14
+            IDENT@10..14 "path"
+      WHITESPACE@14..15 " "
+      RENAME@15..27
+        AS_KW@15..17 "as"
+        WHITESPACE@17..18 " "
+        NAME@18..27
+          IDENT@18..27 "some_name"
+    SEMICOLON@27..28 ";"
+  WHITESPACE@28..29 "\n"
+  USE@29..181
+    USE_KW@29..32 "use"
+    WHITESPACE@32..33 " "
+    USE_TREE@33..180
+      PATH@33..37
+        PATH_SEGMENT@33..37
+          NAME_REF@33..37
+            IDENT@33..37 "some"
+      COLON2@37..39 "::"
+      USE_TREE_LIST@39..180
+        L_CURLY@39..40 "{"
+        WHITESPACE@40..42 "\n "
+        USE_TREE@42..72
+          PATH@42..53
+            PATH@42..47
+              PATH_SEGMENT@42..47
+                NAME_REF@42..47
+                  IDENT@42..47 "other"
+            COLON2@47..49 "::"
+            PATH_SEGMENT@49..53
+              NAME_REF@49..53
+                IDENT@49..53 "path"
+          WHITESPACE@53..54 " "
+          RENAME@54..72
+            AS_KW@54..56 "as"
+            WHITESPACE@56..57 " "
+            NAME@57..72
+              IDENT@57..72 "some_other_name"
+        COMMA@72..73 ","
+        WHITESPACE@73..75 "\n "
+        USE_TREE@75..108
+          PATH@75..90
+            PATH@75..84
+              PATH_SEGMENT@75..84
+                NAME_REF@75..84
+                  IDENT@75..84 "different"
+            COLON2@84..86 "::"
+            PATH_SEGMENT@86..90
+              NAME_REF@86..90
+                IDENT@86..90 "path"
+          WHITESPACE@90..91 " "
+          RENAME@91..108
+            AS_KW@91..93 "as"
+            WHITESPACE@93..94 " "
+            NAME@94..108
+              IDENT@94..108 "different_name"
+        COMMA@108..109 ","
+        WHITESPACE@109..111 "\n "
+        USE_TREE@111..129
+          PATH@111..129
+            PATH@111..123
+              PATH@111..114
+                PATH_SEGMENT@111..114
+                  NAME_REF@111..114
+                    IDENT@111..114 "yet"
+              COLON2@114..116 "::"
+              PATH_SEGMENT@116..123
+                NAME_REF@116..123
+                  IDENT@116..123 "another"
+            COLON2@123..125 "::"
+            PATH_SEGMENT@125..129
+              NAME_REF@125..129
+                IDENT@125..129 "path"
+        COMMA@129..130 ","
+        WHITESPACE@130..132 "\n "
+        USE_TREE@132..178
+          PATH@132..175
+            PATH@132..164
+              PATH@132..158
+                PATH@132..148
+                  PATH@132..144
+                    PATH@132..139
+                      PATH_SEGMENT@132..139
+                        NAME_REF@132..139
+                          IDENT@132..139 "running"
+                    COLON2@139..141 "::"
+                    PATH_SEGMENT@141..144
+                      NAME_REF@141..144
+                        IDENT@141..144 "out"
+                  COLON2@144..146 "::"
+                  PATH_SEGMENT@146..148
+                    NAME_REF@146..148
+                      IDENT@146..148 "of"
+                COLON2@148..150 "::"
+                PATH_SEGMENT@150..158
+                  NAME_REF@150..158
+                    IDENT@150..158 "synonyms"
+              COLON2@158..160 "::"
+              PATH_SEGMENT@160..164
+                NAME_REF@160..164
+                  IDENT@160..164 "for_"
+            COLON2@164..166 "::"
+            PATH_SEGMENT@166..175
+              NAME_REF@166..175
+                IDENT@166..175 "different"
+          COLON2@175..177 "::"
+          STAR@177..178 "*"
+        WHITESPACE@178..179 "\n"
+        R_CURLY@179..180 "}"
+    SEMICOLON@180..181 ";"
+  WHITESPACE@181..182 "\n"
+  USE@182..197
+    USE_KW@182..185 "use"
+    WHITESPACE@185..186 " "
+    USE_TREE@186..196
+      PATH@186..191
+        PATH_SEGMENT@186..191
+          NAME_REF@186..191
+            IDENT@186..191 "Trait"
+      WHITESPACE@191..192 " "
+      RENAME@192..196
+        AS_KW@192..194 "as"
+        WHITESPACE@194..195 " "
+        UNDERSCORE@195..196 "_"
+    SEMICOLON@196..197 ";"
+  WHITESPACE@197..198 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0043_use_alias.rs b/crates/syntax/test_data/parser/inline/ok/0043_use_alias.rs
new file mode 100644
index 00000000000..9be50f87708
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0043_use_alias.rs
@@ -0,0 +1,8 @@
+use some::path as some_name;
+use some::{
+ other::path as some_other_name,
+ different::path as different_name,
+ yet::another::path,
+ running::out::of::synonyms::for_::different::*
+};
+use Trait as _;
diff --git a/crates/syntax/test_data/parser/inline/ok/0044_block_items.rast b/crates/syntax/test_data/parser/inline/ok/0044_block_items.rast
new file mode 100644
index 00000000000..1fd3cd0e783
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0044_block_items.rast
@@ -0,0 +1,28 @@
+SOURCE_FILE@0..21
+  FN@0..20
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..4
+      IDENT@3..4 "a"
+    PARAM_LIST@4..6
+      L_PAREN@4..5 "("
+      R_PAREN@5..6 ")"
+    WHITESPACE@6..7 " "
+    BLOCK_EXPR@7..20
+      L_CURLY@7..8 "{"
+      WHITESPACE@8..9 " "
+      FN@9..18
+        FN_KW@9..11 "fn"
+        WHITESPACE@11..12 " "
+        NAME@12..13
+          IDENT@12..13 "b"
+        PARAM_LIST@13..15
+          L_PAREN@13..14 "("
+          R_PAREN@14..15 ")"
+        WHITESPACE@15..16 " "
+        BLOCK_EXPR@16..18
+          L_CURLY@16..17 "{"
+          R_CURLY@17..18 "}"
+      WHITESPACE@18..19 " "
+      R_CURLY@19..20 "}"
+  WHITESPACE@20..21 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0044_block_items.rs b/crates/syntax/test_data/parser/inline/ok/0044_block_items.rs
new file mode 100644
index 00000000000..d9868718c79
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0044_block_items.rs
@@ -0,0 +1 @@
+fn a() { fn b() {} }
diff --git a/crates/syntax/test_data/parser/inline/ok/0045_param_list_opt_patterns.rast b/crates/syntax/test_data/parser/inline/ok/0045_param_list_opt_patterns.rast
new file mode 100644
index 00000000000..6baea6e3ca2
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0045_param_list_opt_patterns.rast
@@ -0,0 +1,46 @@
+SOURCE_FILE@0..35
+  FN@0..34
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    GENERIC_PARAM_LIST@6..30
+      L_ANGLE@6..7 "<"
+      TYPE_PARAM@7..29
+        NAME@7..8
+          IDENT@7..8 "F"
+        COLON@8..9 ":"
+        WHITESPACE@9..10 " "
+        TYPE_BOUND_LIST@10..29
+          TYPE_BOUND@10..29
+            PATH_TYPE@10..29
+              PATH@10..29
+                PATH_SEGMENT@10..29
+                  NAME_REF@10..15
+                    IDENT@10..15 "FnMut"
+                  PARAM_LIST@15..29
+                    L_PAREN@15..16 "("
+                    PARAM@16..28
+                      REF_TYPE@16..28
+                        AMP@16..17 "&"
+                        MUT_KW@17..20 "mut"
+                        WHITESPACE@20..21 " "
+                        PATH_TYPE@21..28
+                          PATH@21..28
+                            PATH_SEGMENT@21..28
+                              NAME_REF@21..24
+                                IDENT@21..24 "Foo"
+                              GENERIC_ARG_LIST@24..28
+                                L_ANGLE@24..25 "<"
+                                LIFETIME_ARG@25..27
+                                  LIFETIME@25..27 "\'a"
+                                R_ANGLE@27..28 ">"
+                    R_PAREN@28..29 ")"
+      R_ANGLE@29..30 ">"
+    PARAM_LIST@30..32
+      L_PAREN@30..31 "("
+      R_PAREN@31..32 ")"
+    BLOCK_EXPR@32..34
+      L_CURLY@32..33 "{"
+      R_CURLY@33..34 "}"
+  WHITESPACE@34..35 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0045_param_list_opt_patterns.rs b/crates/syntax/test_data/parser/inline/ok/0045_param_list_opt_patterns.rs
new file mode 100644
index 00000000000..9b93442c0f2
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0045_param_list_opt_patterns.rs
@@ -0,0 +1 @@
+fn foo<F: FnMut(&mut Foo<'a>)>(){}
diff --git a/crates/syntax/test_data/parser/inline/ok/0046_singleton_tuple_type.rast b/crates/syntax/test_data/parser/inline/ok/0046_singleton_tuple_type.rast
new file mode 100644
index 00000000000..e89284c1405
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0046_singleton_tuple_type.rast
@@ -0,0 +1,20 @@
+SOURCE_FILE@0..17
+  TYPE_ALIAS@0..16
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "T"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    TUPLE_TYPE@9..15
+      L_PAREN@9..10 "("
+      PATH_TYPE@10..13
+        PATH@10..13
+          PATH_SEGMENT@10..13
+            NAME_REF@10..13
+              IDENT@10..13 "i32"
+      COMMA@13..14 ","
+      R_PAREN@14..15 ")"
+    SEMICOLON@15..16 ";"
+  WHITESPACE@16..17 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0046_singleton_tuple_type.rs b/crates/syntax/test_data/parser/inline/ok/0046_singleton_tuple_type.rs
new file mode 100644
index 00000000000..cb66bad2470
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0046_singleton_tuple_type.rs
@@ -0,0 +1 @@
+type T = (i32,);
diff --git a/crates/syntax/test_data/parser/inline/ok/0048_path_type_with_bounds.rast b/crates/syntax/test_data/parser/inline/ok/0048_path_type_with_bounds.rast
new file mode 100644
index 00000000000..4d8404e7c09
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0048_path_type_with_bounds.rast
@@ -0,0 +1,81 @@
+SOURCE_FILE@0..58
+  FN@0..26
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    RET_TYPE@9..23
+      THIN_ARROW@9..11 "->"
+      WHITESPACE@11..12 " "
+      PATH_TYPE@12..23
+        PATH@12..23
+          PATH_SEGMENT@12..23
+            NAME_REF@12..15
+              IDENT@12..15 "Box"
+            GENERIC_ARG_LIST@15..23
+              L_ANGLE@15..16 "<"
+              TYPE_ARG@16..22
+                DYN_TRAIT_TYPE@16..22
+                  TYPE_BOUND_LIST@16..22
+                    TYPE_BOUND@16..17
+                      PATH_TYPE@16..17
+                        PATH@16..17
+                          PATH_SEGMENT@16..17
+                            NAME_REF@16..17
+                              IDENT@16..17 "T"
+                    WHITESPACE@17..18 " "
+                    PLUS@18..19 "+"
+                    WHITESPACE@19..20 " "
+                    TYPE_BOUND@20..22
+                      LIFETIME@20..22 "\'f"
+              R_ANGLE@22..23 ">"
+    WHITESPACE@23..24 " "
+    BLOCK_EXPR@24..26
+      L_CURLY@24..25 "{"
+      R_CURLY@25..26 "}"
+  WHITESPACE@26..27 "\n"
+  FN@27..57
+    FN_KW@27..29 "fn"
+    WHITESPACE@29..30 " "
+    NAME@30..33
+      IDENT@30..33 "foo"
+    PARAM_LIST@33..35
+      L_PAREN@33..34 "("
+      R_PAREN@34..35 ")"
+    WHITESPACE@35..36 " "
+    RET_TYPE@36..54
+      THIN_ARROW@36..38 "->"
+      WHITESPACE@38..39 " "
+      PATH_TYPE@39..54
+        PATH@39..54
+          PATH_SEGMENT@39..54
+            NAME_REF@39..42
+              IDENT@39..42 "Box"
+            GENERIC_ARG_LIST@42..54
+              L_ANGLE@42..43 "<"
+              TYPE_ARG@43..53
+                DYN_TRAIT_TYPE@43..53
+                  DYN_KW@43..46 "dyn"
+                  WHITESPACE@46..47 " "
+                  TYPE_BOUND_LIST@47..53
+                    TYPE_BOUND@47..48
+                      PATH_TYPE@47..48
+                        PATH@47..48
+                          PATH_SEGMENT@47..48
+                            NAME_REF@47..48
+                              IDENT@47..48 "T"
+                    WHITESPACE@48..49 " "
+                    PLUS@49..50 "+"
+                    WHITESPACE@50..51 " "
+                    TYPE_BOUND@51..53
+                      LIFETIME@51..53 "\'f"
+              R_ANGLE@53..54 ">"
+    WHITESPACE@54..55 " "
+    BLOCK_EXPR@55..57
+      L_CURLY@55..56 "{"
+      R_CURLY@56..57 "}"
+  WHITESPACE@57..58 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0048_path_type_with_bounds.rs b/crates/syntax/test_data/parser/inline/ok/0048_path_type_with_bounds.rs
new file mode 100644
index 00000000000..4bb0f63b739
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0048_path_type_with_bounds.rs
@@ -0,0 +1,2 @@
+fn foo() -> Box<T + 'f> {}
+fn foo() -> Box<dyn T + 'f> {}
diff --git a/crates/syntax/test_data/parser/inline/ok/0050_fn_decl.rast b/crates/syntax/test_data/parser/inline/ok/0050_fn_decl.rast
new file mode 100644
index 00000000000..a5bf55131dd
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0050_fn_decl.rast
@@ -0,0 +1,22 @@
+SOURCE_FILE@0..22
+  TRAIT@0..21
+    TRAIT_KW@0..5 "trait"
+    WHITESPACE@5..6 " "
+    NAME@6..7
+      IDENT@6..7 "T"
+    WHITESPACE@7..8 " "
+    ASSOC_ITEM_LIST@8..21
+      L_CURLY@8..9 "{"
+      WHITESPACE@9..10 " "
+      FN@10..19
+        FN_KW@10..12 "fn"
+        WHITESPACE@12..13 " "
+        NAME@13..16
+          IDENT@13..16 "foo"
+        PARAM_LIST@16..18
+          L_PAREN@16..17 "("
+          R_PAREN@17..18 ")"
+        SEMICOLON@18..19 ";"
+      WHITESPACE@19..20 " "
+      R_CURLY@20..21 "}"
+  WHITESPACE@21..22 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0050_fn_decl.rs b/crates/syntax/test_data/parser/inline/ok/0050_fn_decl.rs
new file mode 100644
index 00000000000..c9f74f7f5c8
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0050_fn_decl.rs
@@ -0,0 +1 @@
+trait T { fn foo(); }
diff --git a/crates/syntax/test_data/parser/inline/ok/0051_unit_type.rast b/crates/syntax/test_data/parser/inline/ok/0051_unit_type.rast
new file mode 100644
index 00000000000..6330dbf9e60
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0051_unit_type.rast
@@ -0,0 +1,14 @@
+SOURCE_FILE@0..13
+  TYPE_ALIAS@0..12
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "T"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    TUPLE_TYPE@9..11
+      L_PAREN@9..10 "("
+      R_PAREN@10..11 ")"
+    SEMICOLON@11..12 ";"
+  WHITESPACE@12..13 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0051_unit_type.rs b/crates/syntax/test_data/parser/inline/ok/0051_unit_type.rs
new file mode 100644
index 00000000000..c039cf7d324
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0051_unit_type.rs
@@ -0,0 +1 @@
+type T = ();
diff --git a/crates/syntax/test_data/parser/inline/ok/0052_path_type.rast b/crates/syntax/test_data/parser/inline/ok/0052_path_type.rast
new file mode 100644
index 00000000000..9bc36bea70a
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0052_path_type.rast
@@ -0,0 +1,70 @@
+SOURCE_FILE@0..71
+  TYPE_ALIAS@0..13
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "A"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    PATH_TYPE@9..12
+      PATH@9..12
+        PATH_SEGMENT@9..12
+          NAME_REF@9..12
+            IDENT@9..12 "Foo"
+    SEMICOLON@12..13 ";"
+  WHITESPACE@13..14 "\n"
+  TYPE_ALIAS@14..29
+    TYPE_KW@14..18 "type"
+    WHITESPACE@18..19 " "
+    NAME@19..20
+      IDENT@19..20 "B"
+    WHITESPACE@20..21 " "
+    EQ@21..22 "="
+    WHITESPACE@22..23 " "
+    PATH_TYPE@23..28
+      PATH@23..28
+        PATH_SEGMENT@23..28
+          COLON2@23..25 "::"
+          NAME_REF@25..28
+            IDENT@25..28 "Foo"
+    SEMICOLON@28..29 ";"
+  WHITESPACE@29..30 "\n"
+  TYPE_ALIAS@30..49
+    TYPE_KW@30..34 "type"
+    WHITESPACE@34..35 " "
+    NAME@35..36
+      IDENT@35..36 "C"
+    WHITESPACE@36..37 " "
+    EQ@37..38 "="
+    WHITESPACE@38..39 " "
+    PATH_TYPE@39..48
+      PATH@39..48
+        PATH@39..43
+          PATH_SEGMENT@39..43
+            SELF_KW@39..43 "self"
+        COLON2@43..45 "::"
+        PATH_SEGMENT@45..48
+          NAME_REF@45..48
+            IDENT@45..48 "Foo"
+    SEMICOLON@48..49 ";"
+  WHITESPACE@49..50 "\n"
+  TYPE_ALIAS@50..70
+    TYPE_KW@50..54 "type"
+    WHITESPACE@54..55 " "
+    NAME@55..56
+      IDENT@55..56 "D"
+    WHITESPACE@56..57 " "
+    EQ@57..58 "="
+    WHITESPACE@58..59 " "
+    PATH_TYPE@59..69
+      PATH@59..69
+        PATH@59..64
+          PATH_SEGMENT@59..64
+            SUPER_KW@59..64 "super"
+        COLON2@64..66 "::"
+        PATH_SEGMENT@66..69
+          NAME_REF@66..69
+            IDENT@66..69 "Foo"
+    SEMICOLON@69..70 ";"
+  WHITESPACE@70..71 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0052_path_type.rs b/crates/syntax/test_data/parser/inline/ok/0052_path_type.rs
new file mode 100644
index 00000000000..bf94f32e196
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0052_path_type.rs
@@ -0,0 +1,4 @@
+type A = Foo;
+type B = ::Foo;
+type C = self::Foo;
+type D = super::Foo;
diff --git a/crates/syntax/test_data/parser/inline/ok/0053_path_expr.rast b/crates/syntax/test_data/parser/inline/ok/0053_path_expr.rast
new file mode 100644
index 00000000000..c34cfeb3155
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0053_path_expr.rast
@@ -0,0 +1,95 @@
+SOURCE_FILE@0..91
+  FN@0..90
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..90
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      LET_STMT@15..25
+        LET_KW@15..18 "let"
+        WHITESPACE@18..19 " "
+        WILDCARD_PAT@19..20
+          UNDERSCORE@19..20 "_"
+        WHITESPACE@20..21 " "
+        EQ@21..22 "="
+        WHITESPACE@22..23 " "
+        PATH_EXPR@23..24
+          PATH@23..24
+            PATH_SEGMENT@23..24
+              NAME_REF@23..24
+                IDENT@23..24 "a"
+        SEMICOLON@24..25 ";"
+      WHITESPACE@25..30 "\n    "
+      LET_STMT@30..43
+        LET_KW@30..33 "let"
+        WHITESPACE@33..34 " "
+        WILDCARD_PAT@34..35
+          UNDERSCORE@34..35 "_"
+        WHITESPACE@35..36 " "
+        EQ@36..37 "="
+        WHITESPACE@37..38 " "
+        PATH_EXPR@38..42
+          PATH@38..42
+            PATH@38..39
+              PATH_SEGMENT@38..39
+                NAME_REF@38..39
+                  IDENT@38..39 "a"
+            COLON2@39..41 "::"
+            PATH_SEGMENT@41..42
+              NAME_REF@41..42
+                IDENT@41..42 "b"
+        SEMICOLON@42..43 ";"
+      WHITESPACE@43..48 "\n    "
+      LET_STMT@48..65
+        LET_KW@48..51 "let"
+        WHITESPACE@51..52 " "
+        WILDCARD_PAT@52..53
+          UNDERSCORE@52..53 "_"
+        WHITESPACE@53..54 " "
+        EQ@54..55 "="
+        WHITESPACE@55..56 " "
+        PATH_EXPR@56..64
+          PATH@56..64
+            PATH_SEGMENT@56..64
+              COLON2@56..58 "::"
+              NAME_REF@58..59
+                IDENT@58..59 "a"
+              GENERIC_ARG_LIST@59..64
+                COLON2@59..61 "::"
+                L_ANGLE@61..62 "<"
+                TYPE_ARG@62..63
+                  PATH_TYPE@62..63
+                    PATH@62..63
+                      PATH_SEGMENT@62..63
+                        NAME_REF@62..63
+                          IDENT@62..63 "b"
+                R_ANGLE@63..64 ">"
+        SEMICOLON@64..65 ";"
+      WHITESPACE@65..70 "\n    "
+      LET_STMT@70..88
+        LET_KW@70..73 "let"
+        WHITESPACE@73..74 " "
+        WILDCARD_PAT@74..75
+          UNDERSCORE@74..75 "_"
+        WHITESPACE@75..76 " "
+        EQ@76..77 "="
+        WHITESPACE@77..78 " "
+        MACRO_CALL@78..87
+          PATH@78..84
+            PATH_SEGMENT@78..84
+              NAME_REF@78..84
+                IDENT@78..84 "format"
+          BANG@84..85 "!"
+          TOKEN_TREE@85..87
+            L_PAREN@85..86 "("
+            R_PAREN@86..87 ")"
+        SEMICOLON@87..88 ";"
+      WHITESPACE@88..89 "\n"
+      R_CURLY@89..90 "}"
+  WHITESPACE@90..91 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0053_path_expr.rs b/crates/syntax/test_data/parser/inline/ok/0053_path_expr.rs
new file mode 100644
index 00000000000..333ebabef48
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0053_path_expr.rs
@@ -0,0 +1,6 @@
+fn foo() {
+    let _ = a;
+    let _ = a::b;
+    let _ = ::a::<b>;
+    let _ = format!();
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0054_record_field_attrs.rast b/crates/syntax/test_data/parser/inline/ok/0054_record_field_attrs.rast
new file mode 100644
index 00000000000..9ae271817e9
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0054_record_field_attrs.rast
@@ -0,0 +1,44 @@
+SOURCE_FILE@0..64
+  STRUCT@0..63
+    STRUCT_KW@0..6 "struct"
+    WHITESPACE@6..7 " "
+    NAME@7..8
+      IDENT@7..8 "S"
+    WHITESPACE@8..9 " "
+    RECORD_FIELD_LIST@9..63
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      RECORD_FIELD@15..60
+        ATTR@15..43
+          POUND@15..16 "#"
+          L_BRACK@16..17 "["
+          PATH@17..22
+            PATH_SEGMENT@17..22
+              NAME_REF@17..22
+                IDENT@17..22 "serde"
+          TOKEN_TREE@22..42
+            L_PAREN@22..23 "("
+            IDENT@23..27 "with"
+            WHITESPACE@27..28 " "
+            EQ@28..29 "="
+            WHITESPACE@29..30 " "
+            STRING@30..41 "\"url_serde\""
+            R_PAREN@41..42 ")"
+          R_BRACK@42..43 "]"
+        WHITESPACE@43..48 "\n    "
+        VISIBILITY@48..51
+          PUB_KW@48..51 "pub"
+        WHITESPACE@51..52 " "
+        NAME@52..55
+          IDENT@52..55 "uri"
+        COLON@55..56 ":"
+        WHITESPACE@56..57 " "
+        PATH_TYPE@57..60
+          PATH@57..60
+            PATH_SEGMENT@57..60
+              NAME_REF@57..60
+                IDENT@57..60 "Uri"
+      COMMA@60..61 ","
+      WHITESPACE@61..62 "\n"
+      R_CURLY@62..63 "}"
+  WHITESPACE@63..64 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0054_record_field_attrs.rs b/crates/syntax/test_data/parser/inline/ok/0054_record_field_attrs.rs
new file mode 100644
index 00000000000..4744d8ac065
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0054_record_field_attrs.rs
@@ -0,0 +1,4 @@
+struct S {
+    #[serde(with = "url_serde")]
+    pub uri: Uri,
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0055_literal_pattern.rast b/crates/syntax/test_data/parser/inline/ok/0055_literal_pattern.rast
new file mode 100644
index 00000000000..68bb4385256
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0055_literal_pattern.rast
@@ -0,0 +1,76 @@
+SOURCE_FILE@0..113
+  FN@0..112
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..112
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      MATCH_EXPR@16..110
+        MATCH_KW@16..21 "match"
+        WHITESPACE@21..22 " "
+        TUPLE_EXPR@22..24
+          L_PAREN@22..23 "("
+          R_PAREN@23..24 ")"
+        WHITESPACE@24..25 " "
+        MATCH_ARM_LIST@25..110
+          L_CURLY@25..26 "{"
+          WHITESPACE@26..35 "\n        "
+          MATCH_ARM@35..43
+            LITERAL_PAT@35..37
+              MINUS@35..36 "-"
+              LITERAL@36..37
+                INT_NUMBER@36..37 "1"
+            WHITESPACE@37..38 " "
+            FAT_ARROW@38..40 "=>"
+            WHITESPACE@40..41 " "
+            TUPLE_EXPR@41..43
+              L_PAREN@41..42 "("
+              R_PAREN@42..43 ")"
+          COMMA@43..44 ","
+          WHITESPACE@44..53 "\n        "
+          MATCH_ARM@53..61
+            LITERAL_PAT@53..55
+              LITERAL@53..55
+                INT_NUMBER@53..55 "92"
+            WHITESPACE@55..56 " "
+            FAT_ARROW@56..58 "=>"
+            WHITESPACE@58..59 " "
+            TUPLE_EXPR@59..61
+              L_PAREN@59..60 "("
+              R_PAREN@60..61 ")"
+          COMMA@61..62 ","
+          WHITESPACE@62..71 "\n        "
+          MATCH_ARM@71..80
+            LITERAL_PAT@71..74
+              LITERAL@71..74
+                CHAR@71..74 "\'c\'"
+            WHITESPACE@74..75 " "
+            FAT_ARROW@75..77 "=>"
+            WHITESPACE@77..78 " "
+            TUPLE_EXPR@78..80
+              L_PAREN@78..79 "("
+              R_PAREN@79..80 ")"
+          COMMA@80..81 ","
+          WHITESPACE@81..90 "\n        "
+          MATCH_ARM@90..103
+            LITERAL_PAT@90..97
+              LITERAL@90..97
+                STRING@90..97 "\"hello\""
+            WHITESPACE@97..98 " "
+            FAT_ARROW@98..100 "=>"
+            WHITESPACE@100..101 " "
+            TUPLE_EXPR@101..103
+              L_PAREN@101..102 "("
+              R_PAREN@102..103 ")"
+          COMMA@103..104 ","
+          WHITESPACE@104..109 "\n    "
+          R_CURLY@109..110 "}"
+      WHITESPACE@110..111 "\n"
+      R_CURLY@111..112 "}"
+  WHITESPACE@112..113 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0055_literal_pattern.rs b/crates/syntax/test_data/parser/inline/ok/0055_literal_pattern.rs
new file mode 100644
index 00000000000..6dfd67b4ce9
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0055_literal_pattern.rs
@@ -0,0 +1,8 @@
+fn main() {
+    match () {
+        -1 => (),
+        92 => (),
+        'c' => (),
+        "hello" => (),
+    }
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0056_where_clause.rast b/crates/syntax/test_data/parser/inline/ok/0056_where_clause.rast
new file mode 100644
index 00000000000..28129c50c61
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0056_where_clause.rast
@@ -0,0 +1,110 @@
+SOURCE_FILE@0..116
+  FN@0..115
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 "\n"
+    WHERE_CLAUSE@9..112
+      WHERE_KW@9..14 "where"
+      WHITESPACE@14..18 "\n   "
+      WHERE_PRED@18..29
+        LIFETIME@18..20 "\'a"
+        COLON@20..21 ":"
+        WHITESPACE@21..22 " "
+        TYPE_BOUND_LIST@22..29
+          TYPE_BOUND@22..24
+            LIFETIME@22..24 "\'b"
+          WHITESPACE@24..25 " "
+          PLUS@25..26 "+"
+          WHITESPACE@26..27 " "
+          TYPE_BOUND@27..29
+            LIFETIME@27..29 "\'c"
+      COMMA@29..30 ","
+      WHITESPACE@30..34 "\n   "
+      WHERE_PRED@34..59
+        PATH_TYPE@34..35
+          PATH@34..35
+            PATH_SEGMENT@34..35
+              NAME_REF@34..35
+                IDENT@34..35 "T"
+        COLON@35..36 ":"
+        WHITESPACE@36..37 " "
+        TYPE_BOUND_LIST@37..59
+          TYPE_BOUND@37..42
+            PATH_TYPE@37..42
+              PATH@37..42
+                PATH_SEGMENT@37..42
+                  NAME_REF@37..42
+                    IDENT@37..42 "Clone"
+          WHITESPACE@42..43 " "
+          PLUS@43..44 "+"
+          WHITESPACE@44..45 " "
+          TYPE_BOUND@45..49
+            PATH_TYPE@45..49
+              PATH@45..49
+                PATH_SEGMENT@45..49
+                  NAME_REF@45..49
+                    IDENT@45..49 "Copy"
+          WHITESPACE@49..50 " "
+          PLUS@50..51 "+"
+          WHITESPACE@51..52 " "
+          TYPE_BOUND@52..59
+            LIFETIME@52..59 "\'static"
+      COMMA@59..60 ","
+      WHITESPACE@60..64 "\n   "
+      WHERE_PRED@64..82
+        PATH_TYPE@64..78
+          PATH@64..78
+            PATH@64..72
+              PATH_SEGMENT@64..72
+                NAME_REF@64..72
+                  IDENT@64..72 "Iterator"
+            COLON2@72..74 "::"
+            PATH_SEGMENT@74..78
+              NAME_REF@74..78
+                IDENT@74..78 "Item"
+        COLON@78..79 ":"
+        WHITESPACE@79..80 " "
+        TYPE_BOUND_LIST@80..82
+          TYPE_BOUND@80..82
+            LIFETIME@80..82 "\'a"
+      COMMA@82..83 ","
+      WHITESPACE@83..87 "\n   "
+      WHERE_PRED@87..112
+        PATH_TYPE@87..108
+          PATH@87..108
+            PATH@87..102
+              PATH_SEGMENT@87..102
+                L_ANGLE@87..88 "<"
+                PATH_TYPE@88..89
+                  PATH@88..89
+                    PATH_SEGMENT@88..89
+                      NAME_REF@88..89
+                        IDENT@88..89 "T"
+                WHITESPACE@89..90 " "
+                AS_KW@90..92 "as"
+                WHITESPACE@92..93 " "
+                PATH_TYPE@93..101
+                  PATH@93..101
+                    PATH_SEGMENT@93..101
+                      NAME_REF@93..101
+                        IDENT@93..101 "Iterator"
+                R_ANGLE@101..102 ">"
+            COLON2@102..104 "::"
+            PATH_SEGMENT@104..108
+              NAME_REF@104..108
+                IDENT@104..108 "Item"
+        COLON@108..109 ":"
+        WHITESPACE@109..110 " "
+        TYPE_BOUND_LIST@110..112
+          TYPE_BOUND@110..112
+            LIFETIME@110..112 "\'a"
+    WHITESPACE@112..113 "\n"
+    BLOCK_EXPR@113..115
+      L_CURLY@113..114 "{"
+      R_CURLY@114..115 "}"
+  WHITESPACE@115..116 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0056_where_clause.rs b/crates/syntax/test_data/parser/inline/ok/0056_where_clause.rs
new file mode 100644
index 00000000000..19d7e571b0c
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0056_where_clause.rs
@@ -0,0 +1,7 @@
+fn foo()
+where
+   'a: 'b + 'c,
+   T: Clone + Copy + 'static,
+   Iterator::Item: 'a,
+   <T as Iterator>::Item: 'a
+{}
diff --git a/crates/syntax/test_data/parser/inline/ok/0058_range_pat.rast b/crates/syntax/test_data/parser/inline/ok/0058_range_pat.rast
new file mode 100644
index 00000000000..3e72f9671c3
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0058_range_pat.rast
@@ -0,0 +1,82 @@
+SOURCE_FILE@0..112
+  FN@0..111
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..111
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      MATCH_EXPR@16..109
+        MATCH_KW@16..21 "match"
+        WHITESPACE@21..22 " "
+        LITERAL@22..24
+          INT_NUMBER@22..24 "92"
+        WHITESPACE@24..25 " "
+        MATCH_ARM_LIST@25..109
+          L_CURLY@25..26 "{"
+          WHITESPACE@26..35 "\n        "
+          MATCH_ARM@35..50
+            RANGE_PAT@35..44
+              LITERAL_PAT@35..36
+                LITERAL@35..36
+                  INT_NUMBER@35..36 "0"
+              WHITESPACE@36..37 " "
+              DOT3@37..40 "..."
+              WHITESPACE@40..41 " "
+              LITERAL_PAT@41..44
+                LITERAL@41..44
+                  INT_NUMBER@41..44 "100"
+            WHITESPACE@44..45 " "
+            FAT_ARROW@45..47 "=>"
+            WHITESPACE@47..48 " "
+            TUPLE_EXPR@48..50
+              L_PAREN@48..49 "("
+              R_PAREN@49..50 ")"
+          COMMA@50..51 ","
+          WHITESPACE@51..60 "\n        "
+          MATCH_ARM@60..77
+            RANGE_PAT@60..71
+              LITERAL_PAT@60..63
+                LITERAL@60..63
+                  INT_NUMBER@60..63 "101"
+              WHITESPACE@63..64 " "
+              DOT2EQ@64..67 "..="
+              WHITESPACE@67..68 " "
+              LITERAL_PAT@68..71
+                LITERAL@68..71
+                  INT_NUMBER@68..71 "200"
+            WHITESPACE@71..72 " "
+            FAT_ARROW@72..74 "=>"
+            WHITESPACE@74..75 " "
+            TUPLE_EXPR@75..77
+              L_PAREN@75..76 "("
+              R_PAREN@76..77 ")"
+          COMMA@77..78 ","
+          WHITESPACE@78..87 "\n        "
+          MATCH_ARM@87..102
+            RANGE_PAT@87..97
+              LITERAL_PAT@87..90
+                LITERAL@87..90
+                  INT_NUMBER@87..90 "200"
+              WHITESPACE@90..91 " "
+              DOT2@91..93 ".."
+              WHITESPACE@93..94 " "
+              LITERAL_PAT@94..97
+                LITERAL@94..97
+                  INT_NUMBER@94..97 "301"
+            FAT_ARROW@97..99 "=>"
+            WHITESPACE@99..100 " "
+            TUPLE_EXPR@100..102
+              L_PAREN@100..101 "("
+              R_PAREN@101..102 ")"
+          COMMA@102..103 ","
+          WHITESPACE@103..108 "\n    "
+          R_CURLY@108..109 "}"
+      WHITESPACE@109..110 "\n"
+      R_CURLY@110..111 "}"
+  WHITESPACE@111..112 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0058_range_pat.rs b/crates/syntax/test_data/parser/inline/ok/0058_range_pat.rs
new file mode 100644
index 00000000000..c12ab6fcea2
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0058_range_pat.rs
@@ -0,0 +1,7 @@
+fn main() {
+    match 92 {
+        0 ... 100 => (),
+        101 ..= 200 => (),
+        200 .. 301=> (),
+    }
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0059_match_arms_commas.rast b/crates/syntax/test_data/parser/inline/ok/0059_match_arms_commas.rast
new file mode 100644
index 00000000000..984829317e2
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0059_match_arms_commas.rast
@@ -0,0 +1,58 @@
+SOURCE_FILE@0..83
+  FN@0..82
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..82
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      MATCH_EXPR@15..80
+        MATCH_KW@15..20 "match"
+        WHITESPACE@20..21 " "
+        TUPLE_EXPR@21..23
+          L_PAREN@21..22 "("
+          R_PAREN@22..23 ")"
+        WHITESPACE@23..24 " "
+        MATCH_ARM_LIST@24..80
+          L_CURLY@24..25 "{"
+          WHITESPACE@25..34 "\n        "
+          MATCH_ARM@34..41
+            WILDCARD_PAT@34..35
+              UNDERSCORE@34..35 "_"
+            WHITESPACE@35..36 " "
+            FAT_ARROW@36..38 "=>"
+            WHITESPACE@38..39 " "
+            TUPLE_EXPR@39..41
+              L_PAREN@39..40 "("
+              R_PAREN@40..41 ")"
+          COMMA@41..42 ","
+          WHITESPACE@42..51 "\n        "
+          MATCH_ARM@51..58
+            WILDCARD_PAT@51..52
+              UNDERSCORE@51..52 "_"
+            WHITESPACE@52..53 " "
+            FAT_ARROW@53..55 "=>"
+            WHITESPACE@55..56 " "
+            BLOCK_EXPR@56..58
+              L_CURLY@56..57 "{"
+              R_CURLY@57..58 "}"
+          WHITESPACE@58..67 "\n        "
+          MATCH_ARM@67..74
+            WILDCARD_PAT@67..68
+              UNDERSCORE@67..68 "_"
+            WHITESPACE@68..69 " "
+            FAT_ARROW@69..71 "=>"
+            WHITESPACE@71..72 " "
+            TUPLE_EXPR@72..74
+              L_PAREN@72..73 "("
+              R_PAREN@73..74 ")"
+          WHITESPACE@74..79 "\n    "
+          R_CURLY@79..80 "}"
+      WHITESPACE@80..81 "\n"
+      R_CURLY@81..82 "}"
+  WHITESPACE@82..83 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0059_match_arms_commas.rs b/crates/syntax/test_data/parser/inline/ok/0059_match_arms_commas.rs
new file mode 100644
index 00000000000..1f25d577a95
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0059_match_arms_commas.rs
@@ -0,0 +1,7 @@
+fn foo() {
+    match () {
+        _ => (),
+        _ => {}
+        _ => ()
+    }
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0060_extern_crate.rast b/crates/syntax/test_data/parser/inline/ok/0060_extern_crate.rast
new file mode 100644
index 00000000000..25e1777d1ab
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0060_extern_crate.rast
@@ -0,0 +1,10 @@
+SOURCE_FILE@0..18
+  EXTERN_CRATE@0..17
+    EXTERN_KW@0..6 "extern"
+    WHITESPACE@6..7 " "
+    CRATE_KW@7..12 "crate"
+    WHITESPACE@12..13 " "
+    NAME_REF@13..16
+      IDENT@13..16 "foo"
+    SEMICOLON@16..17 ";"
+  WHITESPACE@17..18 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0060_extern_crate.rs b/crates/syntax/test_data/parser/inline/ok/0060_extern_crate.rs
new file mode 100644
index 00000000000..49af74e1b74
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0060_extern_crate.rs
@@ -0,0 +1 @@
+extern crate foo;
diff --git a/crates/syntax/test_data/parser/inline/ok/0061_record_lit.rast b/crates/syntax/test_data/parser/inline/ok/0061_record_lit.rast
new file mode 100644
index 00000000000..a9ae1aa5953
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0061_record_lit.rast
@@ -0,0 +1,124 @@
+SOURCE_FILE@0..112
+  FN@0..111
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..111
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..20
+        RECORD_EXPR@15..19
+          PATH@15..16
+            PATH_SEGMENT@15..16
+              NAME_REF@15..16
+                IDENT@15..16 "S"
+          WHITESPACE@16..17 " "
+          RECORD_EXPR_FIELD_LIST@17..19
+            L_CURLY@17..18 "{"
+            R_CURLY@18..19 "}"
+        SEMICOLON@19..20 ";"
+      WHITESPACE@20..25 "\n    "
+      EXPR_STMT@25..41
+        RECORD_EXPR@25..40
+          PATH@25..26
+            PATH_SEGMENT@25..26
+              NAME_REF@25..26
+                IDENT@25..26 "S"
+          WHITESPACE@26..27 " "
+          RECORD_EXPR_FIELD_LIST@27..40
+            L_CURLY@27..28 "{"
+            WHITESPACE@28..29 " "
+            RECORD_EXPR_FIELD@29..30
+              PATH_EXPR@29..30
+                PATH@29..30
+                  PATH_SEGMENT@29..30
+                    NAME_REF@29..30
+                      IDENT@29..30 "x"
+            COMMA@30..31 ","
+            WHITESPACE@31..32 " "
+            RECORD_EXPR_FIELD@32..37
+              NAME_REF@32..33
+                IDENT@32..33 "y"
+              COLON@33..34 ":"
+              WHITESPACE@34..35 " "
+              LITERAL@35..37
+                INT_NUMBER@35..37 "32"
+            COMMA@37..38 ","
+            WHITESPACE@38..39 " "
+            R_CURLY@39..40 "}"
+        SEMICOLON@40..41 ";"
+      WHITESPACE@41..46 "\n    "
+      EXPR_STMT@46..83
+        RECORD_EXPR@46..82
+          PATH@46..47
+            PATH_SEGMENT@46..47
+              NAME_REF@46..47
+                IDENT@46..47 "S"
+          WHITESPACE@47..48 " "
+          RECORD_EXPR_FIELD_LIST@48..82
+            L_CURLY@48..49 "{"
+            WHITESPACE@49..50 " "
+            RECORD_EXPR_FIELD@50..51
+              PATH_EXPR@50..51
+                PATH@50..51
+                  PATH_SEGMENT@50..51
+                    NAME_REF@50..51
+                      IDENT@50..51 "x"
+            COMMA@51..52 ","
+            WHITESPACE@52..53 " "
+            RECORD_EXPR_FIELD@53..58
+              NAME_REF@53..54
+                IDENT@53..54 "y"
+              COLON@54..55 ":"
+              WHITESPACE@55..56 " "
+              LITERAL@56..58
+                INT_NUMBER@56..58 "32"
+            COMMA@58..59 ","
+            WHITESPACE@59..60 " "
+            DOT2@60..62 ".."
+            CALL_EXPR@62..80
+              PATH_EXPR@62..78
+                PATH@62..78
+                  PATH@62..69
+                    PATH_SEGMENT@62..69
+                      NAME_REF@62..69
+                        IDENT@62..69 "Default"
+                  COLON2@69..71 "::"
+                  PATH_SEGMENT@71..78
+                    NAME_REF@71..78
+                      IDENT@71..78 "default"
+              ARG_LIST@78..80
+                L_PAREN@78..79 "("
+                R_PAREN@79..80 ")"
+            WHITESPACE@80..81 " "
+            R_CURLY@81..82 "}"
+        SEMICOLON@82..83 ";"
+      WHITESPACE@83..88 "\n    "
+      EXPR_STMT@88..109
+        RECORD_EXPR@88..108
+          PATH@88..99
+            PATH_SEGMENT@88..99
+              NAME_REF@88..99
+                IDENT@88..99 "TupleStruct"
+          WHITESPACE@99..100 " "
+          RECORD_EXPR_FIELD_LIST@100..108
+            L_CURLY@100..101 "{"
+            WHITESPACE@101..102 " "
+            RECORD_EXPR_FIELD@102..106
+              NAME_REF@102..103
+                INT_NUMBER@102..103 "0"
+              COLON@103..104 ":"
+              WHITESPACE@104..105 " "
+              LITERAL@105..106
+                INT_NUMBER@105..106 "1"
+            WHITESPACE@106..107 " "
+            R_CURLY@107..108 "}"
+        SEMICOLON@108..109 ";"
+      WHITESPACE@109..110 "\n"
+      R_CURLY@110..111 "}"
+  WHITESPACE@111..112 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0061_record_lit.rs b/crates/syntax/test_data/parser/inline/ok/0061_record_lit.rs
new file mode 100644
index 00000000000..6285e554977
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0061_record_lit.rs
@@ -0,0 +1,6 @@
+fn foo() {
+    S {};
+    S { x, y: 32, };
+    S { x, y: 32, ..Default::default() };
+    TupleStruct { 0: 1 };
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0062_mod_contents.rast b/crates/syntax/test_data/parser/inline/ok/0062_mod_contents.rast
new file mode 100644
index 00000000000..de8217064f1
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0062_mod_contents.rast
@@ -0,0 +1,66 @@
+SOURCE_FILE@0..70
+  FN@0..11
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..11
+      L_CURLY@9..10 "{"
+      R_CURLY@10..11 "}"
+  WHITESPACE@11..12 "\n"
+  MACRO_CALL@12..31
+    PATH@12..23
+      PATH_SEGMENT@12..23
+        NAME_REF@12..23
+          IDENT@12..23 "macro_rules"
+    BANG@23..24 "!"
+    WHITESPACE@24..25 " "
+    NAME@25..28
+      IDENT@25..28 "foo"
+    WHITESPACE@28..29 " "
+    TOKEN_TREE@29..31
+      L_CURLY@29..30 "{"
+      R_CURLY@30..31 "}"
+  WHITESPACE@31..32 "\n"
+  MACRO_CALL@32..44
+    PATH@32..40
+      PATH@32..35
+        PATH_SEGMENT@32..35
+          NAME_REF@32..35
+            IDENT@32..35 "foo"
+      COLON2@35..37 "::"
+      PATH_SEGMENT@37..40
+        NAME_REF@37..40
+          IDENT@37..40 "bar"
+    BANG@40..41 "!"
+    TOKEN_TREE@41..43
+      L_PAREN@41..42 "("
+      R_PAREN@42..43 ")"
+    SEMICOLON@43..44 ";"
+  WHITESPACE@44..45 "\n"
+  MACRO_CALL@45..59
+    PATH@45..55
+      PATH@45..50
+        PATH_SEGMENT@45..50
+          SUPER_KW@45..50 "super"
+      COLON2@50..52 "::"
+      PATH_SEGMENT@52..55
+        NAME_REF@52..55
+          IDENT@52..55 "baz"
+    BANG@55..56 "!"
+    WHITESPACE@56..57 " "
+    TOKEN_TREE@57..59
+      L_CURLY@57..58 "{"
+      R_CURLY@58..59 "}"
+  WHITESPACE@59..60 "\n"
+  STRUCT@60..69
+    STRUCT_KW@60..66 "struct"
+    WHITESPACE@66..67 " "
+    NAME@67..68
+      IDENT@67..68 "S"
+    SEMICOLON@68..69 ";"
+  WHITESPACE@69..70 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0062_mod_contents.rs b/crates/syntax/test_data/parser/inline/ok/0062_mod_contents.rs
new file mode 100644
index 00000000000..24a15c5c5c9
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0062_mod_contents.rs
@@ -0,0 +1,5 @@
+fn foo() {}
+macro_rules! foo {}
+foo::bar!();
+super::baz! {}
+struct S;
diff --git a/crates/syntax/test_data/parser/inline/ok/0063_impl_def_neg.rast b/crates/syntax/test_data/parser/inline/ok/0063_impl_def_neg.rast
new file mode 100644
index 00000000000..4368930cc91
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0063_impl_def_neg.rast
@@ -0,0 +1,23 @@
+SOURCE_FILE@0..20
+  IMPL@0..19
+    IMPL_KW@0..4 "impl"
+    WHITESPACE@4..5 " "
+    BANG@5..6 "!"
+    PATH_TYPE@6..10
+      PATH@6..10
+        PATH_SEGMENT@6..10
+          NAME_REF@6..10
+            IDENT@6..10 "Send"
+    WHITESPACE@10..11 " "
+    FOR_KW@11..14 "for"
+    WHITESPACE@14..15 " "
+    PATH_TYPE@15..16
+      PATH@15..16
+        PATH_SEGMENT@15..16
+          NAME_REF@15..16
+            IDENT@15..16 "X"
+    WHITESPACE@16..17 " "
+    ASSOC_ITEM_LIST@17..19
+      L_CURLY@17..18 "{"
+      R_CURLY@18..19 "}"
+  WHITESPACE@19..20 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0063_impl_def_neg.rs b/crates/syntax/test_data/parser/inline/ok/0063_impl_def_neg.rs
new file mode 100644
index 00000000000..b7527c8705a
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0063_impl_def_neg.rs
@@ -0,0 +1 @@
+impl !Send for X {}
diff --git a/crates/syntax/test_data/parser/inline/ok/0064_if_expr.rast b/crates/syntax/test_data/parser/inline/ok/0064_if_expr.rast
new file mode 100644
index 00000000000..58716000344
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0064_if_expr.rast
@@ -0,0 +1,121 @@
+SOURCE_FILE@0..137
+  FN@0..136
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..136
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..26
+        IF_EXPR@15..25
+          IF_KW@15..17 "if"
+          WHITESPACE@17..18 " "
+          CONDITION@18..22
+            LITERAL@18..22
+              TRUE_KW@18..22 "true"
+          WHITESPACE@22..23 " "
+          BLOCK_EXPR@23..25
+            L_CURLY@23..24 "{"
+            R_CURLY@24..25 "}"
+        SEMICOLON@25..26 ";"
+      WHITESPACE@26..31 "\n    "
+      EXPR_STMT@31..50
+        IF_EXPR@31..49
+          IF_KW@31..33 "if"
+          WHITESPACE@33..34 " "
+          CONDITION@34..38
+            LITERAL@34..38
+              TRUE_KW@34..38 "true"
+          WHITESPACE@38..39 " "
+          BLOCK_EXPR@39..41
+            L_CURLY@39..40 "{"
+            R_CURLY@40..41 "}"
+          WHITESPACE@41..42 " "
+          ELSE_KW@42..46 "else"
+          WHITESPACE@46..47 " "
+          BLOCK_EXPR@47..49
+            L_CURLY@47..48 "{"
+            R_CURLY@48..49 "}"
+        SEMICOLON@49..50 ";"
+      WHITESPACE@50..55 "\n    "
+      EXPR_STMT@55..91
+        IF_EXPR@55..90
+          IF_KW@55..57 "if"
+          WHITESPACE@57..58 " "
+          CONDITION@58..62
+            LITERAL@58..62
+              TRUE_KW@58..62 "true"
+          WHITESPACE@62..63 " "
+          BLOCK_EXPR@63..65
+            L_CURLY@63..64 "{"
+            R_CURLY@64..65 "}"
+          WHITESPACE@65..66 " "
+          ELSE_KW@66..70 "else"
+          WHITESPACE@70..71 " "
+          IF_EXPR@71..90
+            IF_KW@71..73 "if"
+            WHITESPACE@73..74 " "
+            CONDITION@74..79
+              LITERAL@74..79
+                FALSE_KW@74..79 "false"
+            WHITESPACE@79..80 " "
+            BLOCK_EXPR@80..82
+              L_CURLY@80..81 "{"
+              R_CURLY@81..82 "}"
+            WHITESPACE@82..83 " "
+            ELSE_KW@83..87 "else"
+            WHITESPACE@87..88 " "
+            BLOCK_EXPR@88..90
+              L_CURLY@88..89 "{"
+              R_CURLY@89..90 "}"
+        SEMICOLON@90..91 ";"
+      WHITESPACE@91..96 "\n    "
+      EXPR_STMT@96..104
+        IF_EXPR@96..103
+          IF_KW@96..98 "if"
+          WHITESPACE@98..99 " "
+          CONDITION@99..100
+            PATH_EXPR@99..100
+              PATH@99..100
+                PATH_SEGMENT@99..100
+                  NAME_REF@99..100
+                    IDENT@99..100 "S"
+          WHITESPACE@100..101 " "
+          BLOCK_EXPR@101..103
+            L_CURLY@101..102 "{"
+            R_CURLY@102..103 "}"
+        SEMICOLON@103..104 ";"
+      WHITESPACE@104..109 "\n    "
+      EXPR_STMT@109..134
+        IF_EXPR@109..133
+          IF_KW@109..111 "if"
+          WHITESPACE@111..112 " "
+          CONDITION@112..120
+            BLOCK_EXPR@112..120
+              L_CURLY@112..113 "{"
+              WHITESPACE@113..114 " "
+              LITERAL@114..118
+                TRUE_KW@114..118 "true"
+              WHITESPACE@118..119 " "
+              R_CURLY@119..120 "}"
+          WHITESPACE@120..121 " "
+          BLOCK_EXPR@121..124
+            L_CURLY@121..122 "{"
+            WHITESPACE@122..123 " "
+            R_CURLY@123..124 "}"
+          WHITESPACE@124..125 " "
+          ELSE_KW@125..129 "else"
+          WHITESPACE@129..130 " "
+          BLOCK_EXPR@130..133
+            L_CURLY@130..131 "{"
+            WHITESPACE@131..132 " "
+            R_CURLY@132..133 "}"
+        SEMICOLON@133..134 ";"
+      WHITESPACE@134..135 "\n"
+      R_CURLY@135..136 "}"
+  WHITESPACE@136..137 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0064_if_expr.rs b/crates/syntax/test_data/parser/inline/ok/0064_if_expr.rs
new file mode 100644
index 00000000000..40f227ba3a4
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0064_if_expr.rs
@@ -0,0 +1,7 @@
+fn foo() {
+    if true {};
+    if true {} else {};
+    if true {} else if false {} else {};
+    if S {};
+    if { true } { } else { };
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0065_dyn_trait_type.rast b/crates/syntax/test_data/parser/inline/ok/0065_dyn_trait_type.rast
new file mode 100644
index 00000000000..3a7fcfe2487
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0065_dyn_trait_type.rast
@@ -0,0 +1,43 @@
+SOURCE_FILE@0..42
+  TYPE_ALIAS@0..41
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "A"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    DYN_TRAIT_TYPE@9..40
+      DYN_KW@9..12 "dyn"
+      WHITESPACE@12..13 " "
+      TYPE_BOUND_LIST@13..40
+        TYPE_BOUND@13..35
+          PATH_TYPE@13..35
+            PATH@13..35
+              PATH_SEGMENT@13..35
+                NAME_REF@13..21
+                  IDENT@13..21 "Iterator"
+                GENERIC_ARG_LIST@21..35
+                  L_ANGLE@21..22 "<"
+                  ASSOC_TYPE_ARG@22..34
+                    NAME_REF@22..26
+                      IDENT@22..26 "Item"
+                    EQ@26..27 "="
+                    PATH_TYPE@27..34
+                      PATH@27..34
+                        PATH_SEGMENT@27..34
+                          NAME_REF@27..30
+                            IDENT@27..30 "Foo"
+                          GENERIC_ARG_LIST@30..34
+                            L_ANGLE@30..31 "<"
+                            LIFETIME_ARG@31..33
+                              LIFETIME@31..33 "\'a"
+                            R_ANGLE@33..34 ">"
+                  R_ANGLE@34..35 ">"
+        WHITESPACE@35..36 " "
+        PLUS@36..37 "+"
+        WHITESPACE@37..38 " "
+        TYPE_BOUND@38..40
+          LIFETIME@38..40 "\'a"
+    SEMICOLON@40..41 ";"
+  WHITESPACE@41..42 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0065_dyn_trait_type.rs b/crates/syntax/test_data/parser/inline/ok/0065_dyn_trait_type.rs
new file mode 100644
index 00000000000..c3ecabb992b
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0065_dyn_trait_type.rs
@@ -0,0 +1 @@
+type A = dyn Iterator<Item=Foo<'a>> + 'a;
diff --git a/crates/syntax/test_data/parser/inline/ok/0066_match_arm.rast b/crates/syntax/test_data/parser/inline/ok/0066_match_arm.rast
new file mode 100644
index 00000000000..57d0661a54d
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0066_match_arm.rast
@@ -0,0 +1,151 @@
+SOURCE_FILE@0..167
+  FN@0..166
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..166
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..164
+        MATCH_EXPR@15..163
+          MATCH_KW@15..20 "match"
+          WHITESPACE@20..21 " "
+          TUPLE_EXPR@21..23
+            L_PAREN@21..22 "("
+            R_PAREN@22..23 ")"
+          WHITESPACE@23..24 " "
+          MATCH_ARM_LIST@24..163
+            L_CURLY@24..25 "{"
+            WHITESPACE@25..34 "\n        "
+            MATCH_ARM@34..41
+              WILDCARD_PAT@34..35
+                UNDERSCORE@34..35 "_"
+              WHITESPACE@35..36 " "
+              FAT_ARROW@36..38 "=>"
+              WHITESPACE@38..39 " "
+              TUPLE_EXPR@39..41
+                L_PAREN@39..40 "("
+                R_PAREN@40..41 ")"
+            COMMA@41..42 ","
+            WHITESPACE@42..51 "\n        "
+            MATCH_ARM@51..83
+              WILDCARD_PAT@51..52
+                UNDERSCORE@51..52 "_"
+              WHITESPACE@52..53 " "
+              MATCH_GUARD@53..77
+                IF_KW@53..55 "if"
+                WHITESPACE@55..56 " "
+                BIN_EXPR@56..77
+                  PATH_EXPR@56..60
+                    PATH@56..60
+                      PATH_SEGMENT@56..60
+                        NAME_REF@56..60
+                          IDENT@56..60 "Test"
+                  WHITESPACE@60..61 " "
+                  R_ANGLE@61..62 ">"
+                  WHITESPACE@62..63 " "
+                  RECORD_EXPR@63..77
+                    PATH@63..67
+                      PATH_SEGMENT@63..67
+                        NAME_REF@63..67
+                          IDENT@63..67 "Test"
+                    RECORD_EXPR_FIELD_LIST@67..77
+                      L_CURLY@67..68 "{"
+                      RECORD_EXPR_FIELD@68..76
+                        NAME_REF@68..73
+                          IDENT@68..73 "field"
+                        COLON@73..74 ":"
+                        WHITESPACE@74..75 " "
+                        LITERAL@75..76
+                          INT_NUMBER@75..76 "0"
+                      R_CURLY@76..77 "}"
+              WHITESPACE@77..78 " "
+              FAT_ARROW@78..80 "=>"
+              WHITESPACE@80..81 " "
+              TUPLE_EXPR@81..83
+                L_PAREN@81..82 "("
+                R_PAREN@82..83 ")"
+            COMMA@83..84 ","
+            WHITESPACE@84..93 "\n        "
+            MATCH_ARM@93..109
+              OR_PAT@93..98
+                IDENT_PAT@93..94
+                  NAME@93..94
+                    IDENT@93..94 "X"
+                WHITESPACE@94..95 " "
+                PIPE@95..96 "|"
+                WHITESPACE@96..97 " "
+                IDENT_PAT@97..98
+                  NAME@97..98
+                    IDENT@97..98 "Y"
+              WHITESPACE@98..99 " "
+              MATCH_GUARD@99..103
+                IF_KW@99..101 "if"
+                WHITESPACE@101..102 " "
+                PATH_EXPR@102..103
+                  PATH@102..103
+                    PATH_SEGMENT@102..103
+                      NAME_REF@102..103
+                        IDENT@102..103 "Z"
+              WHITESPACE@103..104 " "
+              FAT_ARROW@104..106 "=>"
+              WHITESPACE@106..107 " "
+              TUPLE_EXPR@107..109
+                L_PAREN@107..108 "("
+                R_PAREN@108..109 ")"
+            COMMA@109..110 ","
+            WHITESPACE@110..119 "\n        "
+            MATCH_ARM@119..137
+              PIPE@119..120 "|"
+              WHITESPACE@120..121 " "
+              OR_PAT@121..126
+                IDENT_PAT@121..122
+                  NAME@121..122
+                    IDENT@121..122 "X"
+                WHITESPACE@122..123 " "
+                PIPE@123..124 "|"
+                WHITESPACE@124..125 " "
+                IDENT_PAT@125..126
+                  NAME@125..126
+                    IDENT@125..126 "Y"
+              WHITESPACE@126..127 " "
+              MATCH_GUARD@127..131
+                IF_KW@127..129 "if"
+                WHITESPACE@129..130 " "
+                PATH_EXPR@130..131
+                  PATH@130..131
+                    PATH_SEGMENT@130..131
+                      NAME_REF@130..131
+                        IDENT@130..131 "Z"
+              WHITESPACE@131..132 " "
+              FAT_ARROW@132..134 "=>"
+              WHITESPACE@134..135 " "
+              TUPLE_EXPR@135..137
+                L_PAREN@135..136 "("
+                R_PAREN@136..137 ")"
+            COMMA@137..138 ","
+            WHITESPACE@138..147 "\n        "
+            MATCH_ARM@147..156
+              PIPE@147..148 "|"
+              WHITESPACE@148..149 " "
+              IDENT_PAT@149..150
+                NAME@149..150
+                  IDENT@149..150 "X"
+              WHITESPACE@150..151 " "
+              FAT_ARROW@151..153 "=>"
+              WHITESPACE@153..154 " "
+              TUPLE_EXPR@154..156
+                L_PAREN@154..155 "("
+                R_PAREN@155..156 ")"
+            COMMA@156..157 ","
+            WHITESPACE@157..162 "\n    "
+            R_CURLY@162..163 "}"
+        SEMICOLON@163..164 ";"
+      WHITESPACE@164..165 "\n"
+      R_CURLY@165..166 "}"
+  WHITESPACE@166..167 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0066_match_arm.rs b/crates/syntax/test_data/parser/inline/ok/0066_match_arm.rs
new file mode 100644
index 00000000000..9e009e24f4e
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0066_match_arm.rs
@@ -0,0 +1,9 @@
+fn foo() {
+    match () {
+        _ => (),
+        _ if Test > Test{field: 0} => (),
+        X | Y if Z => (),
+        | X | Y if Z => (),
+        | X => (),
+    };
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0067_crate_path.rast b/crates/syntax/test_data/parser/inline/ok/0067_crate_path.rast
new file mode 100644
index 00000000000..702f2e0b0aa
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0067_crate_path.rast
@@ -0,0 +1,15 @@
+SOURCE_FILE@0..16
+  USE@0..15
+    USE_KW@0..3 "use"
+    WHITESPACE@3..4 " "
+    USE_TREE@4..14
+      PATH@4..14
+        PATH@4..9
+          PATH_SEGMENT@4..9
+            CRATE_KW@4..9 "crate"
+        COLON2@9..11 "::"
+        PATH_SEGMENT@11..14
+          NAME_REF@11..14
+            IDENT@11..14 "foo"
+    SEMICOLON@14..15 ";"
+  WHITESPACE@15..16 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0067_crate_path.rs b/crates/syntax/test_data/parser/inline/ok/0067_crate_path.rs
new file mode 100644
index 00000000000..1bbb5930bf6
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0067_crate_path.rs
@@ -0,0 +1 @@
+use crate::foo;
diff --git a/crates/syntax/test_data/parser/inline/ok/0068_union_items.rast b/crates/syntax/test_data/parser/inline/ok/0068_union_items.rast
new file mode 100644
index 00000000000..6589e479519
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0068_union_items.rast
@@ -0,0 +1,46 @@
+SOURCE_FILE@0..51
+  UNION@0..12
+    UNION_KW@0..5 "union"
+    WHITESPACE@5..6 " "
+    NAME@6..9
+      IDENT@6..9 "Foo"
+    WHITESPACE@9..10 " "
+    RECORD_FIELD_LIST@10..12
+      L_CURLY@10..11 "{"
+      R_CURLY@11..12 "}"
+  WHITESPACE@12..13 "\n"
+  UNION@13..50
+    UNION_KW@13..18 "union"
+    WHITESPACE@18..19 " "
+    NAME@19..22
+      IDENT@19..22 "Foo"
+    WHITESPACE@22..23 " "
+    RECORD_FIELD_LIST@23..50
+      L_CURLY@23..24 "{"
+      WHITESPACE@24..29 "\n    "
+      RECORD_FIELD@29..35
+        NAME@29..30
+          IDENT@29..30 "a"
+        COLON@30..31 ":"
+        WHITESPACE@31..32 " "
+        PATH_TYPE@32..35
+          PATH@32..35
+            PATH_SEGMENT@32..35
+              NAME_REF@32..35
+                IDENT@32..35 "i32"
+      COMMA@35..36 ","
+      WHITESPACE@36..41 "\n    "
+      RECORD_FIELD@41..47
+        NAME@41..42
+          IDENT@41..42 "b"
+        COLON@42..43 ":"
+        WHITESPACE@43..44 " "
+        PATH_TYPE@44..47
+          PATH@44..47
+            PATH_SEGMENT@44..47
+              NAME_REF@44..47
+                IDENT@44..47 "f32"
+      COMMA@47..48 ","
+      WHITESPACE@48..49 "\n"
+      R_CURLY@49..50 "}"
+  WHITESPACE@50..51 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0068_union_items.rs b/crates/syntax/test_data/parser/inline/ok/0068_union_items.rs
new file mode 100644
index 00000000000..b7dd610d80a
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0068_union_items.rs
@@ -0,0 +1,5 @@
+union Foo {}
+union Foo {
+    a: i32,
+    b: f32,
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0069_use_tree_list_after_path.rast b/crates/syntax/test_data/parser/inline/ok/0069_use_tree_list_after_path.rast
new file mode 100644
index 00000000000..c4c5bc51e3e
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0069_use_tree_list_after_path.rast
@@ -0,0 +1,37 @@
+SOURCE_FILE@0..37
+  USE@0..18
+    USE_KW@0..3 "use"
+    WHITESPACE@3..4 " "
+    USE_TREE@4..17
+      PATH@4..9
+        PATH_SEGMENT@4..9
+          CRATE_KW@4..9 "crate"
+      COLON2@9..11 "::"
+      USE_TREE_LIST@11..17
+        L_CURLY@11..12 "{"
+        USE_TREE@12..16
+          PATH@12..16
+            PATH_SEGMENT@12..16
+              NAME_REF@12..16
+                IDENT@12..16 "Item"
+        R_CURLY@16..17 "}"
+    SEMICOLON@17..18 ";"
+  WHITESPACE@18..19 "\n"
+  USE@19..36
+    USE_KW@19..22 "use"
+    WHITESPACE@22..23 " "
+    USE_TREE@23..35
+      PATH@23..27
+        PATH_SEGMENT@23..27
+          SELF_KW@23..27 "self"
+      COLON2@27..29 "::"
+      USE_TREE_LIST@29..35
+        L_CURLY@29..30 "{"
+        USE_TREE@30..34
+          PATH@30..34
+            PATH_SEGMENT@30..34
+              NAME_REF@30..34
+                IDENT@30..34 "Item"
+        R_CURLY@34..35 "}"
+    SEMICOLON@35..36 ";"
+  WHITESPACE@36..37 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0069_use_tree_list_after_path.rs b/crates/syntax/test_data/parser/inline/ok/0069_use_tree_list_after_path.rs
new file mode 100644
index 00000000000..c0a3d634e57
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0069_use_tree_list_after_path.rs
@@ -0,0 +1,2 @@
+use crate::{Item};
+use self::{Item};
diff --git a/crates/syntax/test_data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rast b/crates/syntax/test_data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rast
new file mode 100644
index 00000000000..36c9cd5bb2b
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rast
@@ -0,0 +1,50 @@
+SOURCE_FILE@0..46
+  FN@0..45
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..45
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      LET_STMT@15..31
+        LET_KW@15..18 "let"
+        WHITESPACE@18..19 " "
+        WILDCARD_PAT@19..20
+          UNDERSCORE@19..20 "_"
+        WHITESPACE@20..21 " "
+        EQ@21..22 "="
+        WHITESPACE@22..23 " "
+        BIN_EXPR@23..30
+          BLOCK_EXPR@23..26
+            L_CURLY@23..24 "{"
+            LITERAL@24..25
+              INT_NUMBER@24..25 "1"
+            R_CURLY@25..26 "}"
+          WHITESPACE@26..27 " "
+          AMP@27..28 "&"
+          WHITESPACE@28..29 " "
+          LITERAL@29..30
+            INT_NUMBER@29..30 "2"
+        SEMICOLON@30..31 ";"
+      WHITESPACE@31..36 "\n    "
+      EXPR_STMT@36..39
+        BLOCK_EXPR@36..39
+          L_CURLY@36..37 "{"
+          LITERAL@37..38
+            INT_NUMBER@37..38 "1"
+          R_CURLY@38..39 "}"
+      WHITESPACE@39..40 " "
+      EXPR_STMT@40..43
+        REF_EXPR@40..42
+          AMP@40..41 "&"
+          LITERAL@41..42
+            INT_NUMBER@41..42 "2"
+        SEMICOLON@42..43 ";"
+      WHITESPACE@43..44 "\n"
+      R_CURLY@44..45 "}"
+  WHITESPACE@45..46 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rs b/crates/syntax/test_data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rs
new file mode 100644
index 00000000000..37b8437426d
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rs
@@ -0,0 +1,4 @@
+fn foo() {
+    let _ = {1} & 2;
+    {1} &2;
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0071_match_expr.rast b/crates/syntax/test_data/parser/inline/ok/0071_match_expr.rast
new file mode 100644
index 00000000000..d34d98ced0c
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0071_match_expr.rast
@@ -0,0 +1,93 @@
+SOURCE_FILE@0..97
+  FN@0..96
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..96
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..28
+        MATCH_EXPR@15..27
+          MATCH_KW@15..20 "match"
+          WHITESPACE@20..21 " "
+          TUPLE_EXPR@21..23
+            L_PAREN@21..22 "("
+            R_PAREN@22..23 ")"
+          WHITESPACE@23..24 " "
+          MATCH_ARM_LIST@24..27
+            L_CURLY@24..25 "{"
+            WHITESPACE@25..26 " "
+            R_CURLY@26..27 "}"
+        SEMICOLON@27..28 ";"
+      WHITESPACE@28..33 "\n    "
+      EXPR_STMT@33..44
+        MATCH_EXPR@33..43
+          MATCH_KW@33..38 "match"
+          WHITESPACE@38..39 " "
+          PATH_EXPR@39..40
+            PATH@39..40
+              PATH_SEGMENT@39..40
+                NAME_REF@39..40
+                  IDENT@39..40 "S"
+          WHITESPACE@40..41 " "
+          MATCH_ARM_LIST@41..43
+            L_CURLY@41..42 "{"
+            R_CURLY@42..43 "}"
+        SEMICOLON@43..44 ";"
+      WHITESPACE@44..49 "\n    "
+      EXPR_STMT@49..71
+        MATCH_EXPR@49..70
+          MATCH_KW@49..54 "match"
+          WHITESPACE@54..55 " "
+          BLOCK_EXPR@55..58
+            L_CURLY@55..56 "{"
+            WHITESPACE@56..57 " "
+            R_CURLY@57..58 "}"
+          WHITESPACE@58..59 " "
+          MATCH_ARM_LIST@59..70
+            L_CURLY@59..60 "{"
+            WHITESPACE@60..61 " "
+            MATCH_ARM@61..68
+              WILDCARD_PAT@61..62
+                UNDERSCORE@61..62 "_"
+              WHITESPACE@62..63 " "
+              FAT_ARROW@63..65 "=>"
+              WHITESPACE@65..66 " "
+              TUPLE_EXPR@66..68
+                L_PAREN@66..67 "("
+                R_PAREN@67..68 ")"
+            WHITESPACE@68..69 " "
+            R_CURLY@69..70 "}"
+        SEMICOLON@70..71 ";"
+      WHITESPACE@71..76 "\n    "
+      EXPR_STMT@76..94
+        MATCH_EXPR@76..93
+          MATCH_KW@76..81 "match"
+          WHITESPACE@81..82 " "
+          BLOCK_EXPR@82..90
+            L_CURLY@82..83 "{"
+            WHITESPACE@83..84 " "
+            RECORD_EXPR@84..88
+              PATH@84..85
+                PATH_SEGMENT@84..85
+                  NAME_REF@84..85
+                    IDENT@84..85 "S"
+              WHITESPACE@85..86 " "
+              RECORD_EXPR_FIELD_LIST@86..88
+                L_CURLY@86..87 "{"
+                R_CURLY@87..88 "}"
+            WHITESPACE@88..89 " "
+            R_CURLY@89..90 "}"
+          WHITESPACE@90..91 " "
+          MATCH_ARM_LIST@91..93
+            L_CURLY@91..92 "{"
+            R_CURLY@92..93 "}"
+        SEMICOLON@93..94 ";"
+      WHITESPACE@94..95 "\n"
+      R_CURLY@95..96 "}"
+  WHITESPACE@96..97 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0071_match_expr.rs b/crates/syntax/test_data/parser/inline/ok/0071_match_expr.rs
new file mode 100644
index 00000000000..c4021dc1048
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0071_match_expr.rs
@@ -0,0 +1,6 @@
+fn foo() {
+    match () { };
+    match S {};
+    match { } { _ => () };
+    match { S {} } {};
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0072_return_expr.rast b/crates/syntax/test_data/parser/inline/ok/0072_return_expr.rast
new file mode 100644
index 00000000000..437d7ac0424
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0072_return_expr.rast
@@ -0,0 +1,28 @@
+SOURCE_FILE@0..40
+  FN@0..39
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..39
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..22
+        RETURN_EXPR@15..21
+          RETURN_KW@15..21 "return"
+        SEMICOLON@21..22 ";"
+      WHITESPACE@22..27 "\n    "
+      EXPR_STMT@27..37
+        RETURN_EXPR@27..36
+          RETURN_KW@27..33 "return"
+          WHITESPACE@33..34 " "
+          LITERAL@34..36
+            INT_NUMBER@34..36 "92"
+        SEMICOLON@36..37 ";"
+      WHITESPACE@37..38 "\n"
+      R_CURLY@38..39 "}"
+  WHITESPACE@39..40 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0072_return_expr.rs b/crates/syntax/test_data/parser/inline/ok/0072_return_expr.rs
new file mode 100644
index 00000000000..5733666b605
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0072_return_expr.rs
@@ -0,0 +1,4 @@
+fn foo() {
+    return;
+    return 92;
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0073_type_item_type_params.rast b/crates/syntax/test_data/parser/inline/ok/0073_type_item_type_params.rast
new file mode 100644
index 00000000000..00cce69e6c7
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0073_type_item_type_params.rast
@@ -0,0 +1,20 @@
+SOURCE_FILE@0..21
+  TYPE_ALIAS@0..20
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..11
+      IDENT@5..11 "Result"
+    GENERIC_PARAM_LIST@11..14
+      L_ANGLE@11..12 "<"
+      TYPE_PARAM@12..13
+        NAME@12..13
+          IDENT@12..13 "T"
+      R_ANGLE@13..14 ">"
+    WHITESPACE@14..15 " "
+    EQ@15..16 "="
+    WHITESPACE@16..17 " "
+    TUPLE_TYPE@17..19
+      L_PAREN@17..18 "("
+      R_PAREN@18..19 ")"
+    SEMICOLON@19..20 ";"
+  WHITESPACE@20..21 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0073_type_item_type_params.rs b/crates/syntax/test_data/parser/inline/ok/0073_type_item_type_params.rs
new file mode 100644
index 00000000000..defd110c492
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0073_type_item_type_params.rs
@@ -0,0 +1 @@
+type Result<T> = ();
diff --git a/crates/syntax/test_data/parser/inline/ok/0074_stmt_postfix_expr_ambiguity.rast b/crates/syntax/test_data/parser/inline/ok/0074_stmt_postfix_expr_ambiguity.rast
new file mode 100644
index 00000000000..3a789b9f510
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0074_stmt_postfix_expr_ambiguity.rast
@@ -0,0 +1,59 @@
+SOURCE_FILE@0..84
+  FN@0..83
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..83
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      MATCH_EXPR@15..81
+        MATCH_KW@15..20 "match"
+        WHITESPACE@20..21 " "
+        TUPLE_EXPR@21..23
+          L_PAREN@21..22 "("
+          R_PAREN@22..23 ")"
+        WHITESPACE@23..24 " "
+        MATCH_ARM_LIST@24..81
+          L_CURLY@24..25 "{"
+          WHITESPACE@25..34 "\n        "
+          MATCH_ARM@34..41
+            WILDCARD_PAT@34..35
+              UNDERSCORE@34..35 "_"
+            WHITESPACE@35..36 " "
+            FAT_ARROW@36..38 "=>"
+            WHITESPACE@38..39 " "
+            BLOCK_EXPR@39..41
+              L_CURLY@39..40 "{"
+              R_CURLY@40..41 "}"
+          WHITESPACE@41..50 "\n        "
+          MATCH_ARM@50..58
+            TUPLE_PAT@50..52
+              L_PAREN@50..51 "("
+              R_PAREN@51..52 ")"
+            WHITESPACE@52..53 " "
+            FAT_ARROW@53..55 "=>"
+            WHITESPACE@55..56 " "
+            BLOCK_EXPR@56..58
+              L_CURLY@56..57 "{"
+              R_CURLY@57..58 "}"
+          WHITESPACE@58..67 "\n        "
+          MATCH_ARM@67..75
+            SLICE_PAT@67..69
+              L_BRACK@67..68 "["
+              R_BRACK@68..69 "]"
+            WHITESPACE@69..70 " "
+            FAT_ARROW@70..72 "=>"
+            WHITESPACE@72..73 " "
+            BLOCK_EXPR@73..75
+              L_CURLY@73..74 "{"
+              R_CURLY@74..75 "}"
+          WHITESPACE@75..80 "\n    "
+          R_CURLY@80..81 "}"
+      WHITESPACE@81..82 "\n"
+      R_CURLY@82..83 "}"
+  WHITESPACE@83..84 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0074_stmt_postfix_expr_ambiguity.rs b/crates/syntax/test_data/parser/inline/ok/0074_stmt_postfix_expr_ambiguity.rs
new file mode 100644
index 00000000000..2edd578f9d7
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0074_stmt_postfix_expr_ambiguity.rs
@@ -0,0 +1,7 @@
+fn foo() {
+    match () {
+        _ => {}
+        () => {}
+        [] => {}
+    }
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0075_block.rast b/crates/syntax/test_data/parser/inline/ok/0075_block.rast
new file mode 100644
index 00000000000..e847ce9b268
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0075_block.rast
@@ -0,0 +1,86 @@
+SOURCE_FILE@0..65
+  FN@0..9
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..4
+      IDENT@3..4 "a"
+    PARAM_LIST@4..6
+      L_PAREN@4..5 "("
+      R_PAREN@5..6 ")"
+    WHITESPACE@6..7 " "
+    BLOCK_EXPR@7..9
+      L_CURLY@7..8 "{"
+      R_CURLY@8..9 "}"
+  WHITESPACE@9..10 "\n"
+  FN@10..31
+    FN_KW@10..12 "fn"
+    WHITESPACE@12..13 " "
+    NAME@13..14
+      IDENT@13..14 "b"
+    PARAM_LIST@14..16
+      L_PAREN@14..15 "("
+      R_PAREN@15..16 ")"
+    WHITESPACE@16..17 " "
+    BLOCK_EXPR@17..31
+      L_CURLY@17..18 "{"
+      WHITESPACE@18..19 " "
+      LET_STMT@19..29
+        LET_KW@19..22 "let"
+        WHITESPACE@22..23 " "
+        WILDCARD_PAT@23..24
+          UNDERSCORE@23..24 "_"
+        WHITESPACE@24..25 " "
+        EQ@25..26 "="
+        WHITESPACE@26..27 " "
+        LITERAL@27..28
+          INT_NUMBER@27..28 "1"
+        SEMICOLON@28..29 ";"
+      WHITESPACE@29..30 " "
+      R_CURLY@30..31 "}"
+  WHITESPACE@31..32 "\n"
+  FN@32..48
+    FN_KW@32..34 "fn"
+    WHITESPACE@34..35 " "
+    NAME@35..36
+      IDENT@35..36 "c"
+    PARAM_LIST@36..38
+      L_PAREN@36..37 "("
+      R_PAREN@37..38 ")"
+    WHITESPACE@38..39 " "
+    BLOCK_EXPR@39..48
+      L_CURLY@39..40 "{"
+      WHITESPACE@40..41 " "
+      EXPR_STMT@41..43
+        LITERAL@41..42
+          INT_NUMBER@41..42 "1"
+        SEMICOLON@42..43 ";"
+      WHITESPACE@43..44 " "
+      EXPR_STMT@44..46
+        LITERAL@44..45
+          INT_NUMBER@44..45 "2"
+        SEMICOLON@45..46 ";"
+      WHITESPACE@46..47 " "
+      R_CURLY@47..48 "}"
+  WHITESPACE@48..49 "\n"
+  FN@49..64
+    FN_KW@49..51 "fn"
+    WHITESPACE@51..52 " "
+    NAME@52..53
+      IDENT@52..53 "d"
+    PARAM_LIST@53..55
+      L_PAREN@53..54 "("
+      R_PAREN@54..55 ")"
+    WHITESPACE@55..56 " "
+    BLOCK_EXPR@56..64
+      L_CURLY@56..57 "{"
+      WHITESPACE@57..58 " "
+      EXPR_STMT@58..60
+        LITERAL@58..59
+          INT_NUMBER@58..59 "1"
+        SEMICOLON@59..60 ";"
+      WHITESPACE@60..61 " "
+      LITERAL@61..62
+        INT_NUMBER@61..62 "2"
+      WHITESPACE@62..63 " "
+      R_CURLY@63..64 "}"
+  WHITESPACE@64..65 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0075_block.rs b/crates/syntax/test_data/parser/inline/ok/0075_block.rs
new file mode 100644
index 00000000000..81f44c53307
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0075_block.rs
@@ -0,0 +1,4 @@
+fn a() {}
+fn b() { let _ = 1; }
+fn c() { 1; 2; }
+fn d() { 1; 2 }
diff --git a/crates/syntax/test_data/parser/inline/ok/0076_function_where_clause.rast b/crates/syntax/test_data/parser/inline/ok/0076_function_where_clause.rast
new file mode 100644
index 00000000000..96217a7fdb4
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0076_function_where_clause.rast
@@ -0,0 +1,39 @@
+SOURCE_FILE@0..29
+  FN@0..28
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    GENERIC_PARAM_LIST@6..9
+      L_ANGLE@6..7 "<"
+      TYPE_PARAM@7..8
+        NAME@7..8
+          IDENT@7..8 "T"
+      R_ANGLE@8..9 ">"
+    PARAM_LIST@9..11
+      L_PAREN@9..10 "("
+      R_PAREN@10..11 ")"
+    WHITESPACE@11..12 " "
+    WHERE_CLAUSE@12..25
+      WHERE_KW@12..17 "where"
+      WHITESPACE@17..18 " "
+      WHERE_PRED@18..25
+        PATH_TYPE@18..19
+          PATH@18..19
+            PATH_SEGMENT@18..19
+              NAME_REF@18..19
+                IDENT@18..19 "T"
+        COLON@19..20 ":"
+        WHITESPACE@20..21 " "
+        TYPE_BOUND_LIST@21..25
+          TYPE_BOUND@21..25
+            PATH_TYPE@21..25
+              PATH@21..25
+                PATH_SEGMENT@21..25
+                  NAME_REF@21..25
+                    IDENT@21..25 "Copy"
+    WHITESPACE@25..26 " "
+    BLOCK_EXPR@26..28
+      L_CURLY@26..27 "{"
+      R_CURLY@27..28 "}"
+  WHITESPACE@28..29 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0076_function_where_clause.rs b/crates/syntax/test_data/parser/inline/ok/0076_function_where_clause.rs
new file mode 100644
index 00000000000..f0920b2a8ad
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0076_function_where_clause.rs
@@ -0,0 +1 @@
+fn foo<T>() where T: Copy {}
diff --git a/crates/syntax/test_data/parser/inline/ok/0077_try_expr.rast b/crates/syntax/test_data/parser/inline/ok/0077_try_expr.rast
new file mode 100644
index 00000000000..33e6fb93f7a
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0077_try_expr.rast
@@ -0,0 +1,25 @@
+SOURCE_FILE@0..21
+  FN@0..20
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..20
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..18
+        TRY_EXPR@15..17
+          PATH_EXPR@15..16
+            PATH@15..16
+              PATH_SEGMENT@15..16
+                NAME_REF@15..16
+                  IDENT@15..16 "x"
+          QUESTION@16..17 "?"
+        SEMICOLON@17..18 ";"
+      WHITESPACE@18..19 "\n"
+      R_CURLY@19..20 "}"
+  WHITESPACE@20..21 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0077_try_expr.rs b/crates/syntax/test_data/parser/inline/ok/0077_try_expr.rs
new file mode 100644
index 00000000000..8b74f7bc814
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0077_try_expr.rs
@@ -0,0 +1,3 @@
+fn foo() {
+    x?;
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0078_type_item.rast b/crates/syntax/test_data/parser/inline/ok/0078_type_item.rast
new file mode 100644
index 00000000000..2befc8388ec
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0078_type_item.rast
@@ -0,0 +1,16 @@
+SOURCE_FILE@0..16
+  TYPE_ALIAS@0..15
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..8
+      IDENT@5..8 "Foo"
+    WHITESPACE@8..9 " "
+    EQ@9..10 "="
+    WHITESPACE@10..11 " "
+    PATH_TYPE@11..14
+      PATH@11..14
+        PATH_SEGMENT@11..14
+          NAME_REF@11..14
+            IDENT@11..14 "Bar"
+    SEMICOLON@14..15 ";"
+  WHITESPACE@15..16 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0078_type_item.rs b/crates/syntax/test_data/parser/inline/ok/0078_type_item.rs
new file mode 100644
index 00000000000..04c0344fa36
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0078_type_item.rs
@@ -0,0 +1 @@
+type Foo = Bar;
diff --git a/crates/syntax/test_data/parser/inline/ok/0079_impl_def.rast b/crates/syntax/test_data/parser/inline/ok/0079_impl_def.rast
new file mode 100644
index 00000000000..209711fc496
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0079_impl_def.rast
@@ -0,0 +1,14 @@
+SOURCE_FILE@0..12
+  IMPL@0..11
+    IMPL_KW@0..4 "impl"
+    WHITESPACE@4..5 " "
+    PATH_TYPE@5..8
+      PATH@5..8
+        PATH_SEGMENT@5..8
+          NAME_REF@5..8
+            IDENT@5..8 "Foo"
+    WHITESPACE@8..9 " "
+    ASSOC_ITEM_LIST@9..11
+      L_CURLY@9..10 "{"
+      R_CURLY@10..11 "}"
+  WHITESPACE@11..12 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0079_impl_def.rs b/crates/syntax/test_data/parser/inline/ok/0079_impl_def.rs
new file mode 100644
index 00000000000..d6337f6b3a7
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0079_impl_def.rs
@@ -0,0 +1 @@
+impl Foo {}
diff --git a/crates/syntax/test_data/parser/inline/ok/0080_postfix_range.rast b/crates/syntax/test_data/parser/inline/ok/0080_postfix_range.rast
new file mode 100644
index 00000000000..b3003577cc0
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0080_postfix_range.rast
@@ -0,0 +1,95 @@
+SOURCE_FILE@0..89
+  FN@0..88
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..88
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      LET_STMT@15..27
+        LET_KW@15..18 "let"
+        WHITESPACE@18..19 " "
+        IDENT_PAT@19..20
+          NAME@19..20
+            IDENT@19..20 "x"
+        WHITESPACE@20..21 " "
+        EQ@21..22 "="
+        WHITESPACE@22..23 " "
+        RANGE_EXPR@23..26
+          LITERAL@23..24
+            INT_NUMBER@23..24 "1"
+          DOT2@24..26 ".."
+        SEMICOLON@26..27 ";"
+      WHITESPACE@27..32 "\n    "
+      EXPR_STMT@32..54
+        MATCH_EXPR@32..53
+          MATCH_KW@32..37 "match"
+          WHITESPACE@37..38 " "
+          RANGE_EXPR@38..41
+            LITERAL@38..39
+              INT_NUMBER@38..39 "1"
+            DOT2@39..41 ".."
+          WHITESPACE@41..42 " "
+          MATCH_ARM_LIST@42..53
+            L_CURLY@42..43 "{"
+            WHITESPACE@43..44 " "
+            MATCH_ARM@44..51
+              WILDCARD_PAT@44..45
+                UNDERSCORE@44..45 "_"
+              WHITESPACE@45..46 " "
+              FAT_ARROW@46..48 "=>"
+              WHITESPACE@48..49 " "
+              TUPLE_EXPR@49..51
+                L_PAREN@49..50 "("
+                R_PAREN@50..51 ")"
+            WHITESPACE@51..52 " "
+            R_CURLY@52..53 "}"
+        SEMICOLON@53..54 ";"
+      WHITESPACE@54..59 "\n    "
+      EXPR_STMT@59..86
+        MATCH_EXPR@59..85
+          MATCH_KW@59..64 "match"
+          WHITESPACE@64..65 " "
+          RANGE_EXPR@65..73
+            METHOD_CALL_EXPR@65..70
+              PATH_EXPR@65..66
+                PATH@65..66
+                  PATH_SEGMENT@65..66
+                    NAME_REF@65..66
+                      IDENT@65..66 "a"
+              DOT@66..67 "."
+              NAME_REF@67..68
+                IDENT@67..68 "b"
+              ARG_LIST@68..70
+                L_PAREN@68..69 "("
+                R_PAREN@69..70 ")"
+            DOT2@70..72 ".."
+            PATH_EXPR@72..73
+              PATH@72..73
+                PATH_SEGMENT@72..73
+                  NAME_REF@72..73
+                    IDENT@72..73 "S"
+          WHITESPACE@73..74 " "
+          MATCH_ARM_LIST@74..85
+            L_CURLY@74..75 "{"
+            WHITESPACE@75..76 " "
+            MATCH_ARM@76..83
+              WILDCARD_PAT@76..77
+                UNDERSCORE@76..77 "_"
+              WHITESPACE@77..78 " "
+              FAT_ARROW@78..80 "=>"
+              WHITESPACE@80..81 " "
+              TUPLE_EXPR@81..83
+                L_PAREN@81..82 "("
+                R_PAREN@82..83 ")"
+            WHITESPACE@83..84 " "
+            R_CURLY@84..85 "}"
+        SEMICOLON@85..86 ";"
+      WHITESPACE@86..87 "\n"
+      R_CURLY@87..88 "}"
+  WHITESPACE@88..89 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0080_postfix_range.rs b/crates/syntax/test_data/parser/inline/ok/0080_postfix_range.rs
new file mode 100644
index 00000000000..e7b7cfc6b1a
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0080_postfix_range.rs
@@ -0,0 +1,5 @@
+fn foo() {
+    let x = 1..;
+    match 1.. { _ => () };
+    match a.b()..S { _ => () };
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0081_for_type.rast b/crates/syntax/test_data/parser/inline/ok/0081_for_type.rast
new file mode 100644
index 00000000000..f319d5141d5
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0081_for_type.rast
@@ -0,0 +1,112 @@
+SOURCE_FILE@0..121
+  TYPE_ALIAS@0..28
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "A"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    FOR_TYPE@9..27
+      FOR_KW@9..12 "for"
+      GENERIC_PARAM_LIST@12..16
+        L_ANGLE@12..13 "<"
+        LIFETIME_PARAM@13..15
+          LIFETIME@13..15 "\'a"
+        R_ANGLE@15..16 ">"
+      WHITESPACE@16..17 " "
+      FN_PTR_TYPE@17..27
+        FN_KW@17..19 "fn"
+        PARAM_LIST@19..21
+          L_PAREN@19..20 "("
+          R_PAREN@20..21 ")"
+        WHITESPACE@21..22 " "
+        RET_TYPE@22..27
+          THIN_ARROW@22..24 "->"
+          WHITESPACE@24..25 " "
+          TUPLE_TYPE@25..27
+            L_PAREN@25..26 "("
+            R_PAREN@26..27 ")"
+    SEMICOLON@27..28 ";"
+  WHITESPACE@28..29 "\n"
+  TYPE_ALIAS@29..81
+    TYPE_KW@29..33 "type"
+    WHITESPACE@33..34 " "
+    NAME@34..35
+      IDENT@34..35 "B"
+    WHITESPACE@35..36 " "
+    EQ@36..37 "="
+    WHITESPACE@37..38 " "
+    FOR_TYPE@38..80
+      FOR_KW@38..41 "for"
+      GENERIC_PARAM_LIST@41..45
+        L_ANGLE@41..42 "<"
+        LIFETIME_PARAM@42..44
+          LIFETIME@42..44 "\'a"
+        R_ANGLE@44..45 ">"
+      WHITESPACE@45..46 " "
+      FN_PTR_TYPE@46..80
+        UNSAFE_KW@46..52 "unsafe"
+        WHITESPACE@52..53 " "
+        ABI@53..63
+          EXTERN_KW@53..59 "extern"
+          WHITESPACE@59..60 " "
+          STRING@60..63 "\"C\""
+        WHITESPACE@63..64 " "
+        FN_KW@64..66 "fn"
+        PARAM_LIST@66..74
+          L_PAREN@66..67 "("
+          PARAM@67..73
+            REF_TYPE@67..73
+              AMP@67..68 "&"
+              LIFETIME@68..70 "\'a"
+              WHITESPACE@70..71 " "
+              TUPLE_TYPE@71..73
+                L_PAREN@71..72 "("
+                R_PAREN@72..73 ")"
+          R_PAREN@73..74 ")"
+        WHITESPACE@74..75 " "
+        RET_TYPE@75..80
+          THIN_ARROW@75..77 "->"
+          WHITESPACE@77..78 " "
+          TUPLE_TYPE@78..80
+            L_PAREN@78..79 "("
+            R_PAREN@79..80 ")"
+    SEMICOLON@80..81 ";"
+  WHITESPACE@81..82 "\n"
+  TYPE_ALIAS@82..120
+    TYPE_KW@82..86 "type"
+    WHITESPACE@86..87 " "
+    NAME@87..90
+      IDENT@87..90 "Obj"
+    WHITESPACE@90..91 " "
+    EQ@91..92 "="
+    WHITESPACE@92..93 " "
+    FOR_TYPE@93..119
+      FOR_KW@93..96 "for"
+      GENERIC_PARAM_LIST@96..100
+        L_ANGLE@96..97 "<"
+        LIFETIME_PARAM@97..99
+          LIFETIME@97..99 "\'a"
+        R_ANGLE@99..100 ">"
+      WHITESPACE@100..101 " "
+      PATH_TYPE@101..119
+        PATH@101..119
+          PATH_SEGMENT@101..119
+            NAME_REF@101..110
+              IDENT@101..110 "PartialEq"
+            GENERIC_ARG_LIST@110..119
+              L_ANGLE@110..111 "<"
+              TYPE_ARG@111..118
+                REF_TYPE@111..118
+                  AMP@111..112 "&"
+                  LIFETIME@112..114 "\'a"
+                  WHITESPACE@114..115 " "
+                  PATH_TYPE@115..118
+                    PATH@115..118
+                      PATH_SEGMENT@115..118
+                        NAME_REF@115..118
+                          IDENT@115..118 "i32"
+              R_ANGLE@118..119 ">"
+    SEMICOLON@119..120 ";"
+  WHITESPACE@120..121 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0081_for_type.rs b/crates/syntax/test_data/parser/inline/ok/0081_for_type.rs
new file mode 100644
index 00000000000..8ac7b9e1038
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0081_for_type.rs
@@ -0,0 +1,3 @@
+type A = for<'a> fn() -> ();
+type B = for<'a> unsafe extern "C" fn(&'a ()) -> ();
+type Obj = for<'a> PartialEq<&'a i32>;
diff --git a/crates/syntax/test_data/parser/inline/ok/0082_ref_expr.rast b/crates/syntax/test_data/parser/inline/ok/0082_ref_expr.rast
new file mode 100644
index 00000000000..70b975c0b14
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0082_ref_expr.rast
@@ -0,0 +1,138 @@
+SOURCE_FILE@0..200
+  FN@0..199
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..199
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      COMMENT@15..36 "// reference operator"
+      WHITESPACE@36..41 "\n    "
+      LET_STMT@41..52
+        LET_KW@41..44 "let"
+        WHITESPACE@44..45 " "
+        WILDCARD_PAT@45..46
+          UNDERSCORE@45..46 "_"
+        WHITESPACE@46..47 " "
+        EQ@47..48 "="
+        WHITESPACE@48..49 " "
+        REF_EXPR@49..51
+          AMP@49..50 "&"
+          LITERAL@50..51
+            INT_NUMBER@50..51 "1"
+        SEMICOLON@51..52 ";"
+      WHITESPACE@52..57 "\n    "
+      LET_STMT@57..75
+        LET_KW@57..60 "let"
+        WHITESPACE@60..61 " "
+        WILDCARD_PAT@61..62
+          UNDERSCORE@61..62 "_"
+        WHITESPACE@62..63 " "
+        EQ@63..64 "="
+        WHITESPACE@64..65 " "
+        REF_EXPR@65..74
+          AMP@65..66 "&"
+          MUT_KW@66..69 "mut"
+          WHITESPACE@69..70 " "
+          REF_EXPR@70..74
+            AMP@70..71 "&"
+            CALL_EXPR@71..74
+              PATH_EXPR@71..72
+                PATH@71..72
+                  PATH_SEGMENT@71..72
+                    NAME_REF@71..72
+                      IDENT@71..72 "f"
+              ARG_LIST@72..74
+                L_PAREN@72..73 "("
+                R_PAREN@73..74 ")"
+        SEMICOLON@74..75 ";"
+      WHITESPACE@75..80 "\n    "
+      LET_STMT@80..93
+        LET_KW@80..83 "let"
+        WHITESPACE@83..84 " "
+        WILDCARD_PAT@84..85
+          UNDERSCORE@84..85 "_"
+        WHITESPACE@85..86 " "
+        EQ@86..87 "="
+        WHITESPACE@87..88 " "
+        REF_EXPR@88..92
+          AMP@88..89 "&"
+          PATH_EXPR@89..92
+            PATH@89..92
+              PATH_SEGMENT@89..92
+                NAME_REF@89..92
+                  IDENT@89..92 "raw"
+        SEMICOLON@92..93 ";"
+      WHITESPACE@93..98 "\n    "
+      LET_STMT@98..113
+        LET_KW@98..101 "let"
+        WHITESPACE@101..102 " "
+        WILDCARD_PAT@102..103
+          UNDERSCORE@102..103 "_"
+        WHITESPACE@103..104 " "
+        EQ@104..105 "="
+        WHITESPACE@105..106 " "
+        REF_EXPR@106..112
+          AMP@106..107 "&"
+          FIELD_EXPR@107..112
+            PATH_EXPR@107..110
+              PATH@107..110
+                PATH_SEGMENT@107..110
+                  NAME_REF@107..110
+                    IDENT@107..110 "raw"
+            DOT@110..111 "."
+            NAME_REF@111..112
+              INT_NUMBER@111..112 "0"
+        SEMICOLON@112..113 ";"
+      WHITESPACE@113..118 "\n    "
+      COMMENT@118..143 "// raw reference oper ..."
+      WHITESPACE@143..148 "\n    "
+      LET_STMT@148..169
+        LET_KW@148..151 "let"
+        WHITESPACE@151..152 " "
+        WILDCARD_PAT@152..153
+          UNDERSCORE@152..153 "_"
+        WHITESPACE@153..154 " "
+        EQ@154..155 "="
+        WHITESPACE@155..156 " "
+        REF_EXPR@156..168
+          AMP@156..157 "&"
+          RAW_KW@157..160 "raw"
+          WHITESPACE@160..161 " "
+          MUT_KW@161..164 "mut"
+          WHITESPACE@164..165 " "
+          PATH_EXPR@165..168
+            PATH@165..168
+              PATH_SEGMENT@165..168
+                NAME_REF@165..168
+                  IDENT@165..168 "foo"
+        SEMICOLON@168..169 ";"
+      WHITESPACE@169..174 "\n    "
+      LET_STMT@174..197
+        LET_KW@174..177 "let"
+        WHITESPACE@177..178 " "
+        WILDCARD_PAT@178..179
+          UNDERSCORE@178..179 "_"
+        WHITESPACE@179..180 " "
+        EQ@180..181 "="
+        WHITESPACE@181..182 " "
+        REF_EXPR@182..196
+          AMP@182..183 "&"
+          RAW_KW@183..186 "raw"
+          WHITESPACE@186..187 " "
+          CONST_KW@187..192 "const"
+          WHITESPACE@192..193 " "
+          PATH_EXPR@193..196
+            PATH@193..196
+              PATH_SEGMENT@193..196
+                NAME_REF@193..196
+                  IDENT@193..196 "foo"
+        SEMICOLON@196..197 ";"
+      WHITESPACE@197..198 "\n"
+      R_CURLY@198..199 "}"
+  WHITESPACE@199..200 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0082_ref_expr.rs b/crates/syntax/test_data/parser/inline/ok/0082_ref_expr.rs
new file mode 100644
index 00000000000..c5262f4469b
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0082_ref_expr.rs
@@ -0,0 +1,10 @@
+fn foo() {
+    // reference operator
+    let _ = &1;
+    let _ = &mut &f();
+    let _ = &raw;
+    let _ = &raw.0;
+    // raw reference operator
+    let _ = &raw mut foo;
+    let _ = &raw const foo;
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0083_struct_items.rast b/crates/syntax/test_data/parser/inline/ok/0083_struct_items.rast
new file mode 100644
index 00000000000..cdbc40fe0b2
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0083_struct_items.rast
@@ -0,0 +1,87 @@
+SOURCE_FILE@0..106
+  STRUCT@0..11
+    STRUCT_KW@0..6 "struct"
+    WHITESPACE@6..7 " "
+    NAME@7..10
+      IDENT@7..10 "Foo"
+    SEMICOLON@10..11 ";"
+  WHITESPACE@11..12 "\n"
+  STRUCT@12..25
+    STRUCT_KW@12..18 "struct"
+    WHITESPACE@18..19 " "
+    NAME@19..22
+      IDENT@19..22 "Foo"
+    WHITESPACE@22..23 " "
+    RECORD_FIELD_LIST@23..25
+      L_CURLY@23..24 "{"
+      R_CURLY@24..25 "}"
+  WHITESPACE@25..26 "\n"
+  STRUCT@26..39
+    STRUCT_KW@26..32 "struct"
+    WHITESPACE@32..33 " "
+    NAME@33..36
+      IDENT@33..36 "Foo"
+    TUPLE_FIELD_LIST@36..38
+      L_PAREN@36..37 "("
+      R_PAREN@37..38 ")"
+    SEMICOLON@38..39 ";"
+  WHITESPACE@39..40 "\n"
+  STRUCT@40..66
+    STRUCT_KW@40..46 "struct"
+    WHITESPACE@46..47 " "
+    NAME@47..50
+      IDENT@47..50 "Foo"
+    TUPLE_FIELD_LIST@50..65
+      L_PAREN@50..51 "("
+      TUPLE_FIELD@51..57
+        PATH_TYPE@51..57
+          PATH@51..57
+            PATH_SEGMENT@51..57
+              NAME_REF@51..57
+                IDENT@51..57 "String"
+      COMMA@57..58 ","
+      WHITESPACE@58..59 " "
+      TUPLE_FIELD@59..64
+        PATH_TYPE@59..64
+          PATH@59..64
+            PATH_SEGMENT@59..64
+              NAME_REF@59..64
+                IDENT@59..64 "usize"
+      R_PAREN@64..65 ")"
+    SEMICOLON@65..66 ";"
+  WHITESPACE@66..67 "\n"
+  STRUCT@67..105
+    STRUCT_KW@67..73 "struct"
+    WHITESPACE@73..74 " "
+    NAME@74..77
+      IDENT@74..77 "Foo"
+    WHITESPACE@77..78 " "
+    RECORD_FIELD_LIST@78..105
+      L_CURLY@78..79 "{"
+      WHITESPACE@79..84 "\n    "
+      RECORD_FIELD@84..90
+        NAME@84..85
+          IDENT@84..85 "a"
+        COLON@85..86 ":"
+        WHITESPACE@86..87 " "
+        PATH_TYPE@87..90
+          PATH@87..90
+            PATH_SEGMENT@87..90
+              NAME_REF@87..90
+                IDENT@87..90 "i32"
+      COMMA@90..91 ","
+      WHITESPACE@91..96 "\n    "
+      RECORD_FIELD@96..102
+        NAME@96..97
+          IDENT@96..97 "b"
+        COLON@97..98 ":"
+        WHITESPACE@98..99 " "
+        PATH_TYPE@99..102
+          PATH@99..102
+            PATH_SEGMENT@99..102
+              NAME_REF@99..102
+                IDENT@99..102 "f32"
+      COMMA@102..103 ","
+      WHITESPACE@103..104 "\n"
+      R_CURLY@104..105 "}"
+  WHITESPACE@105..106 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0083_struct_items.rs b/crates/syntax/test_data/parser/inline/ok/0083_struct_items.rs
new file mode 100644
index 00000000000..693e3f3ee12
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0083_struct_items.rs
@@ -0,0 +1,8 @@
+struct Foo;
+struct Foo {}
+struct Foo();
+struct Foo(String, usize);
+struct Foo {
+    a: i32,
+    b: f32,
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0084_paren_type.rast b/crates/syntax/test_data/parser/inline/ok/0084_paren_type.rast
new file mode 100644
index 00000000000..ee889496686
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0084_paren_type.rast
@@ -0,0 +1,19 @@
+SOURCE_FILE@0..16
+  TYPE_ALIAS@0..15
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "T"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    PAREN_TYPE@9..14
+      L_PAREN@9..10 "("
+      PATH_TYPE@10..13
+        PATH@10..13
+          PATH_SEGMENT@10..13
+            NAME_REF@10..13
+              IDENT@10..13 "i32"
+      R_PAREN@13..14 ")"
+    SEMICOLON@14..15 ";"
+  WHITESPACE@15..16 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0084_paren_type.rs b/crates/syntax/test_data/parser/inline/ok/0084_paren_type.rs
new file mode 100644
index 00000000000..6e1b2510124
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0084_paren_type.rs
@@ -0,0 +1 @@
+type T = (i32);
diff --git a/crates/syntax/test_data/parser/inline/ok/0085_expr_literals.rast b/crates/syntax/test_data/parser/inline/ok/0085_expr_literals.rast
new file mode 100644
index 00000000000..9a87b5b936d
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0085_expr_literals.rast
@@ -0,0 +1,135 @@
+SOURCE_FILE@0..189
+  FN@0..188
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..188
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      LET_STMT@15..28
+        LET_KW@15..18 "let"
+        WHITESPACE@18..19 " "
+        WILDCARD_PAT@19..20
+          UNDERSCORE@19..20 "_"
+        WHITESPACE@20..21 " "
+        EQ@21..22 "="
+        WHITESPACE@22..23 " "
+        LITERAL@23..27
+          TRUE_KW@23..27 "true"
+        SEMICOLON@27..28 ";"
+      WHITESPACE@28..33 "\n    "
+      LET_STMT@33..47
+        LET_KW@33..36 "let"
+        WHITESPACE@36..37 " "
+        WILDCARD_PAT@37..38
+          UNDERSCORE@37..38 "_"
+        WHITESPACE@38..39 " "
+        EQ@39..40 "="
+        WHITESPACE@40..41 " "
+        LITERAL@41..46
+          FALSE_KW@41..46 "false"
+        SEMICOLON@46..47 ";"
+      WHITESPACE@47..52 "\n    "
+      LET_STMT@52..62
+        LET_KW@52..55 "let"
+        WHITESPACE@55..56 " "
+        WILDCARD_PAT@56..57
+          UNDERSCORE@56..57 "_"
+        WHITESPACE@57..58 " "
+        EQ@58..59 "="
+        WHITESPACE@59..60 " "
+        LITERAL@60..61
+          INT_NUMBER@60..61 "1"
+        SEMICOLON@61..62 ";"
+      WHITESPACE@62..67 "\n    "
+      LET_STMT@67..79
+        LET_KW@67..70 "let"
+        WHITESPACE@70..71 " "
+        WILDCARD_PAT@71..72
+          UNDERSCORE@71..72 "_"
+        WHITESPACE@72..73 " "
+        EQ@73..74 "="
+        WHITESPACE@74..75 " "
+        LITERAL@75..78
+          FLOAT_NUMBER@75..78 "2.0"
+        SEMICOLON@78..79 ";"
+      WHITESPACE@79..84 "\n    "
+      LET_STMT@84..97
+        LET_KW@84..87 "let"
+        WHITESPACE@87..88 " "
+        WILDCARD_PAT@88..89
+          UNDERSCORE@88..89 "_"
+        WHITESPACE@89..90 " "
+        EQ@90..91 "="
+        WHITESPACE@91..92 " "
+        LITERAL@92..96
+          BYTE@92..96 "b\'a\'"
+        SEMICOLON@96..97 ";"
+      WHITESPACE@97..102 "\n    "
+      LET_STMT@102..114
+        LET_KW@102..105 "let"
+        WHITESPACE@105..106 " "
+        WILDCARD_PAT@106..107
+          UNDERSCORE@106..107 "_"
+        WHITESPACE@107..108 " "
+        EQ@108..109 "="
+        WHITESPACE@109..110 " "
+        LITERAL@110..113
+          CHAR@110..113 "\'b\'"
+        SEMICOLON@113..114 ";"
+      WHITESPACE@114..119 "\n    "
+      LET_STMT@119..131
+        LET_KW@119..122 "let"
+        WHITESPACE@122..123 " "
+        WILDCARD_PAT@123..124
+          UNDERSCORE@123..124 "_"
+        WHITESPACE@124..125 " "
+        EQ@125..126 "="
+        WHITESPACE@126..127 " "
+        LITERAL@127..130
+          STRING@127..130 "\"c\""
+        SEMICOLON@130..131 ";"
+      WHITESPACE@131..136 "\n    "
+      LET_STMT@136..149
+        LET_KW@136..139 "let"
+        WHITESPACE@139..140 " "
+        WILDCARD_PAT@140..141
+          UNDERSCORE@140..141 "_"
+        WHITESPACE@141..142 " "
+        EQ@142..143 "="
+        WHITESPACE@143..144 " "
+        LITERAL@144..148
+          RAW_STRING@144..148 "r\"d\""
+        SEMICOLON@148..149 ";"
+      WHITESPACE@149..154 "\n    "
+      LET_STMT@154..167
+        LET_KW@154..157 "let"
+        WHITESPACE@157..158 " "
+        WILDCARD_PAT@158..159
+          UNDERSCORE@158..159 "_"
+        WHITESPACE@159..160 " "
+        EQ@160..161 "="
+        WHITESPACE@161..162 " "
+        LITERAL@162..166
+          BYTE_STRING@162..166 "b\"e\""
+        SEMICOLON@166..167 ";"
+      WHITESPACE@167..172 "\n    "
+      LET_STMT@172..186
+        LET_KW@172..175 "let"
+        WHITESPACE@175..176 " "
+        WILDCARD_PAT@176..177
+          UNDERSCORE@176..177 "_"
+        WHITESPACE@177..178 " "
+        EQ@178..179 "="
+        WHITESPACE@179..180 " "
+        LITERAL@180..185
+          RAW_BYTE_STRING@180..185 "br\"f\""
+        SEMICOLON@185..186 ";"
+      WHITESPACE@186..187 "\n"
+      R_CURLY@187..188 "}"
+  WHITESPACE@188..189 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0085_expr_literals.rs b/crates/syntax/test_data/parser/inline/ok/0085_expr_literals.rs
new file mode 100644
index 00000000000..2e11a5a6e68
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0085_expr_literals.rs
@@ -0,0 +1,12 @@
+fn foo() {
+    let _ = true;
+    let _ = false;
+    let _ = 1;
+    let _ = 2.0;
+    let _ = b'a';
+    let _ = 'b';
+    let _ = "c";
+    let _ = r"d";
+    let _ = b"e";
+    let _ = br"f";
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0086_function_ret_type.rast b/crates/syntax/test_data/parser/inline/ok/0086_function_ret_type.rast
new file mode 100644
index 00000000000..70e05a859b1
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0086_function_ret_type.rast
@@ -0,0 +1,34 @@
+SOURCE_FILE@0..30
+  FN@0..11
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..11
+      L_CURLY@9..10 "{"
+      R_CURLY@10..11 "}"
+  WHITESPACE@11..12 "\n"
+  FN@12..29
+    FN_KW@12..14 "fn"
+    WHITESPACE@14..15 " "
+    NAME@15..18
+      IDENT@15..18 "bar"
+    PARAM_LIST@18..20
+      L_PAREN@18..19 "("
+      R_PAREN@19..20 ")"
+    WHITESPACE@20..21 " "
+    RET_TYPE@21..26
+      THIN_ARROW@21..23 "->"
+      WHITESPACE@23..24 " "
+      TUPLE_TYPE@24..26
+        L_PAREN@24..25 "("
+        R_PAREN@25..26 ")"
+    WHITESPACE@26..27 " "
+    BLOCK_EXPR@27..29
+      L_CURLY@27..28 "{"
+      R_CURLY@28..29 "}"
+  WHITESPACE@29..30 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0086_function_ret_type.rs b/crates/syntax/test_data/parser/inline/ok/0086_function_ret_type.rs
new file mode 100644
index 00000000000..d22d8cada69
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0086_function_ret_type.rs
@@ -0,0 +1,2 @@
+fn foo() {}
+fn bar() -> () {}
diff --git a/crates/syntax/test_data/parser/inline/ok/0088_break_ambiguity.rast b/crates/syntax/test_data/parser/inline/ok/0088_break_ambiguity.rast
new file mode 100644
index 00000000000..f7b839303c3
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0088_break_ambiguity.rast
@@ -0,0 +1,65 @@
+SOURCE_FILE@0..88
+  FN@0..87
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    BLOCK_EXPR@8..87
+      L_CURLY@8..9 "{"
+      WHITESPACE@9..14 "\n    "
+      EXPR_STMT@14..25
+        IF_EXPR@14..25
+          IF_KW@14..16 "if"
+          WHITESPACE@16..17 " "
+          CONDITION@17..22
+            BREAK_EXPR@17..22
+              BREAK_KW@17..22 "break"
+          WHITESPACE@22..23 " "
+          BLOCK_EXPR@23..25
+            L_CURLY@23..24 "{"
+            R_CURLY@24..25 "}"
+      WHITESPACE@25..30 "\n    "
+      EXPR_STMT@30..44
+        WHILE_EXPR@30..44
+          WHILE_KW@30..35 "while"
+          WHITESPACE@35..36 " "
+          CONDITION@36..41
+            BREAK_EXPR@36..41
+              BREAK_KW@36..41 "break"
+          WHITESPACE@41..42 " "
+          BLOCK_EXPR@42..44
+            L_CURLY@42..43 "{"
+            R_CURLY@43..44 "}"
+      WHITESPACE@44..49 "\n    "
+      EXPR_STMT@49..66
+        FOR_EXPR@49..66
+          FOR_KW@49..52 "for"
+          WHITESPACE@52..53 " "
+          IDENT_PAT@53..54
+            NAME@53..54
+              IDENT@53..54 "i"
+          WHITESPACE@54..55 " "
+          IN_KW@55..57 "in"
+          WHITESPACE@57..58 " "
+          BREAK_EXPR@58..63
+            BREAK_KW@58..63 "break"
+          WHITESPACE@63..64 " "
+          BLOCK_EXPR@64..66
+            L_CURLY@64..65 "{"
+            R_CURLY@65..66 "}"
+      WHITESPACE@66..71 "\n    "
+      MATCH_EXPR@71..85
+        MATCH_KW@71..76 "match"
+        WHITESPACE@76..77 " "
+        BREAK_EXPR@77..82
+          BREAK_KW@77..82 "break"
+        WHITESPACE@82..83 " "
+        MATCH_ARM_LIST@83..85
+          L_CURLY@83..84 "{"
+          R_CURLY@84..85 "}"
+      WHITESPACE@85..86 "\n"
+      R_CURLY@86..87 "}"
+  WHITESPACE@87..88 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0088_break_ambiguity.rs b/crates/syntax/test_data/parser/inline/ok/0088_break_ambiguity.rs
new file mode 100644
index 00000000000..560eb05b949
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0088_break_ambiguity.rs
@@ -0,0 +1,6 @@
+fn foo(){
+    if break {}
+    while break {}
+    for i in break {}
+    match break {}
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0090_type_param_default.rast b/crates/syntax/test_data/parser/inline/ok/0090_type_param_default.rast
new file mode 100644
index 00000000000..2ef026e3709
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0090_type_param_default.rast
@@ -0,0 +1,22 @@
+SOURCE_FILE@0..19
+  STRUCT@0..18
+    STRUCT_KW@0..6 "struct"
+    WHITESPACE@6..7 " "
+    NAME@7..8
+      IDENT@7..8 "S"
+    GENERIC_PARAM_LIST@8..17
+      L_ANGLE@8..9 "<"
+      TYPE_PARAM@9..16
+        NAME@9..10
+          IDENT@9..10 "T"
+        WHITESPACE@10..11 " "
+        EQ@11..12 "="
+        WHITESPACE@12..13 " "
+        PATH_TYPE@13..16
+          PATH@13..16
+            PATH_SEGMENT@13..16
+              NAME_REF@13..16
+                IDENT@13..16 "i32"
+      R_ANGLE@16..17 ">"
+    SEMICOLON@17..18 ";"
+  WHITESPACE@18..19 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0090_type_param_default.rs b/crates/syntax/test_data/parser/inline/ok/0090_type_param_default.rs
new file mode 100644
index 00000000000..540eacb0277
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0090_type_param_default.rs
@@ -0,0 +1 @@
+struct S<T = i32>;
diff --git a/crates/syntax/test_data/parser/inline/ok/0092_fn_pointer_type_with_ret.rast b/crates/syntax/test_data/parser/inline/ok/0092_fn_pointer_type_with_ret.rast
new file mode 100644
index 00000000000..f80326465fd
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0092_fn_pointer_type_with_ret.rast
@@ -0,0 +1,23 @@
+SOURCE_FILE@0..21
+  TYPE_ALIAS@0..20
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "F"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    FN_PTR_TYPE@9..19
+      FN_KW@9..11 "fn"
+      PARAM_LIST@11..13
+        L_PAREN@11..12 "("
+        R_PAREN@12..13 ")"
+      WHITESPACE@13..14 " "
+      RET_TYPE@14..19
+        THIN_ARROW@14..16 "->"
+        WHITESPACE@16..17 " "
+        TUPLE_TYPE@17..19
+          L_PAREN@17..18 "("
+          R_PAREN@18..19 ")"
+    SEMICOLON@19..20 ";"
+  WHITESPACE@20..21 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0092_fn_pointer_type_with_ret.rs b/crates/syntax/test_data/parser/inline/ok/0092_fn_pointer_type_with_ret.rs
new file mode 100644
index 00000000000..e3ba5e87f5d
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0092_fn_pointer_type_with_ret.rs
@@ -0,0 +1 @@
+type F = fn() -> ();
diff --git a/crates/syntax/test_data/parser/inline/ok/0093_index_expr.rast b/crates/syntax/test_data/parser/inline/ok/0093_index_expr.rast
new file mode 100644
index 00000000000..82f03f9c18b
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0093_index_expr.rast
@@ -0,0 +1,33 @@
+SOURCE_FILE@0..26
+  FN@0..25
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..25
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..23
+        INDEX_EXPR@15..22
+          INDEX_EXPR@15..19
+            PATH_EXPR@15..16
+              PATH@15..16
+                PATH_SEGMENT@15..16
+                  NAME_REF@15..16
+                    IDENT@15..16 "x"
+            L_BRACK@16..17 "["
+            LITERAL@17..18
+              INT_NUMBER@17..18 "1"
+            R_BRACK@18..19 "]"
+          L_BRACK@19..20 "["
+          LITERAL@20..21
+            INT_NUMBER@20..21 "2"
+          R_BRACK@21..22 "]"
+        SEMICOLON@22..23 ";"
+      WHITESPACE@23..24 "\n"
+      R_CURLY@24..25 "}"
+  WHITESPACE@25..26 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0093_index_expr.rs b/crates/syntax/test_data/parser/inline/ok/0093_index_expr.rs
new file mode 100644
index 00000000000..b9ba78a6cbd
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0093_index_expr.rs
@@ -0,0 +1,3 @@
+fn foo() {
+    x[1][2];
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0095_placeholder_pat.rast b/crates/syntax/test_data/parser/inline/ok/0095_placeholder_pat.rast
new file mode 100644
index 00000000000..c1fdc6e259c
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0095_placeholder_pat.rast
@@ -0,0 +1,28 @@
+SOURCE_FILE@0..26
+  FN@0..25
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..25
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..12 " "
+      LET_STMT@12..23
+        LET_KW@12..15 "let"
+        WHITESPACE@15..16 " "
+        WILDCARD_PAT@16..17
+          UNDERSCORE@16..17 "_"
+        WHITESPACE@17..18 " "
+        EQ@18..19 "="
+        WHITESPACE@19..20 " "
+        TUPLE_EXPR@20..22
+          L_PAREN@20..21 "("
+          R_PAREN@21..22 ")"
+        SEMICOLON@22..23 ";"
+      WHITESPACE@23..24 " "
+      R_CURLY@24..25 "}"
+  WHITESPACE@25..26 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0095_placeholder_pat.rs b/crates/syntax/test_data/parser/inline/ok/0095_placeholder_pat.rs
new file mode 100644
index 00000000000..4d719c4335b
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0095_placeholder_pat.rs
@@ -0,0 +1 @@
+fn main() { let _ = (); }
diff --git a/crates/syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast b/crates/syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast
new file mode 100644
index 00000000000..e757249f06d
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast
@@ -0,0 +1,123 @@
+SOURCE_FILE@0..167
+  FN@0..166
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..166
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..25
+        IF_EXPR@15..25
+          IF_KW@15..17 "if"
+          WHITESPACE@17..18 " "
+          CONDITION@18..22
+            LITERAL@18..22
+              TRUE_KW@18..22 "true"
+          WHITESPACE@22..23 " "
+          BLOCK_EXPR@23..25
+            L_CURLY@23..24 "{"
+            R_CURLY@24..25 "}"
+      WHITESPACE@25..30 "\n    "
+      EXPR_STMT@30..37
+        LOOP_EXPR@30..37
+          LOOP_KW@30..34 "loop"
+          WHITESPACE@34..35 " "
+          BLOCK_EXPR@35..37
+            L_CURLY@35..36 "{"
+            R_CURLY@36..37 "}"
+      WHITESPACE@37..42 "\n    "
+      EXPR_STMT@42..53
+        MATCH_EXPR@42..53
+          MATCH_KW@42..47 "match"
+          WHITESPACE@47..48 " "
+          TUPLE_EXPR@48..50
+            L_PAREN@48..49 "("
+            R_PAREN@49..50 ")"
+          WHITESPACE@50..51 " "
+          MATCH_ARM_LIST@51..53
+            L_CURLY@51..52 "{"
+            R_CURLY@52..53 "}"
+      WHITESPACE@53..58 "\n    "
+      EXPR_STMT@58..71
+        WHILE_EXPR@58..71
+          WHILE_KW@58..63 "while"
+          WHITESPACE@63..64 " "
+          CONDITION@64..68
+            LITERAL@64..68
+              TRUE_KW@64..68 "true"
+          WHITESPACE@68..69 " "
+          BLOCK_EXPR@69..71
+            L_CURLY@69..70 "{"
+            R_CURLY@70..71 "}"
+      WHITESPACE@71..76 "\n    "
+      EXPR_STMT@76..90
+        FOR_EXPR@76..90
+          FOR_KW@76..79 "for"
+          WHITESPACE@79..80 " "
+          WILDCARD_PAT@80..81
+            UNDERSCORE@80..81 "_"
+          WHITESPACE@81..82 " "
+          IN_KW@82..84 "in"
+          WHITESPACE@84..85 " "
+          TUPLE_EXPR@85..87
+            L_PAREN@85..86 "("
+            R_PAREN@86..87 ")"
+          WHITESPACE@87..88 " "
+          BLOCK_EXPR@88..90
+            L_CURLY@88..89 "{"
+            R_CURLY@89..90 "}"
+      WHITESPACE@90..95 "\n    "
+      EXPR_STMT@95..97
+        BLOCK_EXPR@95..97
+          L_CURLY@95..96 "{"
+          R_CURLY@96..97 "}"
+      WHITESPACE@97..102 "\n    "
+      EXPR_STMT@102..104
+        BLOCK_EXPR@102..104
+          L_CURLY@102..103 "{"
+          R_CURLY@103..104 "}"
+      WHITESPACE@104..109 "\n    "
+      EXPR_STMT@109..152
+        MACRO_CALL@109..152
+          PATH@109..120
+            PATH_SEGMENT@109..120
+              NAME_REF@109..120
+                IDENT@109..120 "macro_rules"
+          BANG@120..121 "!"
+          WHITESPACE@121..122 " "
+          NAME@122..126
+            IDENT@122..126 "test"
+          WHITESPACE@126..127 " "
+          TOKEN_TREE@127..152
+            L_CURLY@127..128 "{"
+            WHITESPACE@128..138 "\n         "
+            TOKEN_TREE@138..140
+              L_PAREN@138..139 "("
+              R_PAREN@139..140 ")"
+            WHITESPACE@140..141 " "
+            EQ@141..142 "="
+            R_ANGLE@142..143 ">"
+            WHITESPACE@143..144 " "
+            TOKEN_TREE@144..146
+              L_CURLY@144..145 "{"
+              R_CURLY@145..146 "}"
+            WHITESPACE@146..151 "\n    "
+            R_CURLY@151..152 "}"
+      WHITESPACE@152..157 "\n    "
+      MACRO_CALL@157..164
+        PATH@157..161
+          PATH_SEGMENT@157..161
+            NAME_REF@157..161
+              IDENT@157..161 "test"
+        BANG@161..162 "!"
+        TOKEN_TREE@162..164
+          L_CURLY@162..163 "{"
+          R_CURLY@163..164 "}"
+      WHITESPACE@164..165 "\n"
+      R_CURLY@165..166 "}"
+  WHITESPACE@166..167 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rs b/crates/syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rs
new file mode 100644
index 00000000000..4919665cb57
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rs
@@ -0,0 +1,13 @@
+fn foo() {
+    if true {}
+    loop {}
+    match () {}
+    while true {}
+    for _ in () {}
+    {}
+    {}
+    macro_rules! test {
+         () => {}
+    }
+    test!{}
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0099_param_list.rast b/crates/syntax/test_data/parser/inline/ok/0099_param_list.rast
new file mode 100644
index 00000000000..f19e9fd5229
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0099_param_list.rast
@@ -0,0 +1,99 @@
+SOURCE_FILE@0..67
+  FN@0..9
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..4
+      IDENT@3..4 "a"
+    PARAM_LIST@4..6
+      L_PAREN@4..5 "("
+      R_PAREN@5..6 ")"
+    WHITESPACE@6..7 " "
+    BLOCK_EXPR@7..9
+      L_CURLY@7..8 "{"
+      R_CURLY@8..9 "}"
+  WHITESPACE@9..10 "\n"
+  FN@10..25
+    FN_KW@10..12 "fn"
+    WHITESPACE@12..13 " "
+    NAME@13..14
+      IDENT@13..14 "b"
+    PARAM_LIST@14..22
+      L_PAREN@14..15 "("
+      PARAM@15..21
+        IDENT_PAT@15..16
+          NAME@15..16
+            IDENT@15..16 "x"
+        COLON@16..17 ":"
+        WHITESPACE@17..18 " "
+        PATH_TYPE@18..21
+          PATH@18..21
+            PATH_SEGMENT@18..21
+              NAME_REF@18..21
+                IDENT@18..21 "i32"
+      R_PAREN@21..22 ")"
+    WHITESPACE@22..23 " "
+    BLOCK_EXPR@23..25
+      L_CURLY@23..24 "{"
+      R_CURLY@24..25 "}"
+  WHITESPACE@25..26 "\n"
+  FN@26..43
+    FN_KW@26..28 "fn"
+    WHITESPACE@28..29 " "
+    NAME@29..30
+      IDENT@29..30 "c"
+    PARAM_LIST@30..40
+      L_PAREN@30..31 "("
+      PARAM@31..37
+        IDENT_PAT@31..32
+          NAME@31..32
+            IDENT@31..32 "x"
+        COLON@32..33 ":"
+        WHITESPACE@33..34 " "
+        PATH_TYPE@34..37
+          PATH@34..37
+            PATH_SEGMENT@34..37
+              NAME_REF@34..37
+                IDENT@34..37 "i32"
+      COMMA@37..38 ","
+      WHITESPACE@38..39 " "
+      R_PAREN@39..40 ")"
+    WHITESPACE@40..41 " "
+    BLOCK_EXPR@41..43
+      L_CURLY@41..42 "{"
+      R_CURLY@42..43 "}"
+  WHITESPACE@43..44 "\n"
+  FN@44..66
+    FN_KW@44..46 "fn"
+    WHITESPACE@46..47 " "
+    NAME@47..48
+      IDENT@47..48 "d"
+    PARAM_LIST@48..63
+      L_PAREN@48..49 "("
+      PARAM@49..55
+        IDENT_PAT@49..50
+          NAME@49..50
+            IDENT@49..50 "x"
+        COLON@50..51 ":"
+        WHITESPACE@51..52 " "
+        PATH_TYPE@52..55
+          PATH@52..55
+            PATH_SEGMENT@52..55
+              NAME_REF@52..55
+                IDENT@52..55 "i32"
+      COMMA@55..56 ","
+      WHITESPACE@56..57 " "
+      PARAM@57..62
+        IDENT_PAT@57..58
+          NAME@57..58
+            IDENT@57..58 "y"
+        COLON@58..59 ":"
+        WHITESPACE@59..60 " "
+        TUPLE_TYPE@60..62
+          L_PAREN@60..61 "("
+          R_PAREN@61..62 ")"
+      R_PAREN@62..63 ")"
+    WHITESPACE@63..64 " "
+    BLOCK_EXPR@64..66
+      L_CURLY@64..65 "{"
+      R_CURLY@65..66 "}"
+  WHITESPACE@66..67 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0099_param_list.rs b/crates/syntax/test_data/parser/inline/ok/0099_param_list.rs
new file mode 100644
index 00000000000..9d55bedbba7
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0099_param_list.rs
@@ -0,0 +1,4 @@
+fn a() {}
+fn b(x: i32) {}
+fn c(x: i32, ) {}
+fn d(x: i32, y: ()) {}
diff --git a/crates/syntax/test_data/parser/inline/ok/0100_for_expr.rast b/crates/syntax/test_data/parser/inline/ok/0100_for_expr.rast
new file mode 100644
index 00000000000..5c4055e44b0
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0100_for_expr.rast
@@ -0,0 +1,34 @@
+SOURCE_FILE@0..33
+  FN@0..32
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..32
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..30
+        FOR_EXPR@15..29
+          FOR_KW@15..18 "for"
+          WHITESPACE@18..19 " "
+          IDENT_PAT@19..20
+            NAME@19..20
+              IDENT@19..20 "x"
+          WHITESPACE@20..21 " "
+          IN_KW@21..23 "in"
+          WHITESPACE@23..24 " "
+          ARRAY_EXPR@24..26
+            L_BRACK@24..25 "["
+            R_BRACK@25..26 "]"
+          WHITESPACE@26..27 " "
+          BLOCK_EXPR@27..29
+            L_CURLY@27..28 "{"
+            R_CURLY@28..29 "}"
+        SEMICOLON@29..30 ";"
+      WHITESPACE@30..31 "\n"
+      R_CURLY@31..32 "}"
+  WHITESPACE@32..33 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0100_for_expr.rs b/crates/syntax/test_data/parser/inline/ok/0100_for_expr.rs
new file mode 100644
index 00000000000..972197d2a17
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0100_for_expr.rs
@@ -0,0 +1,3 @@
+fn foo() {
+    for x in [] {};
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rast b/crates/syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rast
new file mode 100644
index 00000000000..866e60ed8a1
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rast
@@ -0,0 +1,132 @@
+SOURCE_FILE@0..119
+  FN@0..118
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..118
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      LET_STMT@15..29
+        LET_KW@15..18 "let"
+        WHITESPACE@18..19 " "
+        RECORD_PAT@19..23
+          PATH@19..20
+            PATH_SEGMENT@19..20
+              NAME_REF@19..20
+                IDENT@19..20 "S"
+          WHITESPACE@20..21 " "
+          RECORD_PAT_FIELD_LIST@21..23
+            L_CURLY@21..22 "{"
+            R_CURLY@22..23 "}"
+        WHITESPACE@23..24 " "
+        EQ@24..25 "="
+        WHITESPACE@25..26 " "
+        TUPLE_EXPR@26..28
+          L_PAREN@26..27 "("
+          R_PAREN@27..28 ")"
+        SEMICOLON@28..29 ";"
+      WHITESPACE@29..34 "\n    "
+      LET_STMT@34..62
+        LET_KW@34..37 "let"
+        WHITESPACE@37..38 " "
+        RECORD_PAT@38..56
+          PATH@38..39
+            PATH_SEGMENT@38..39
+              NAME_REF@38..39
+                IDENT@38..39 "S"
+          WHITESPACE@39..40 " "
+          RECORD_PAT_FIELD_LIST@40..56
+            L_CURLY@40..41 "{"
+            WHITESPACE@41..42 " "
+            RECORD_PAT_FIELD@42..43
+              IDENT_PAT@42..43
+                NAME@42..43
+                  IDENT@42..43 "f"
+            COMMA@43..44 ","
+            WHITESPACE@44..45 " "
+            RECORD_PAT_FIELD@45..54
+              IDENT_PAT@45..54
+                REF_KW@45..48 "ref"
+                WHITESPACE@48..49 " "
+                MUT_KW@49..52 "mut"
+                WHITESPACE@52..53 " "
+                NAME@53..54
+                  IDENT@53..54 "g"
+            WHITESPACE@54..55 " "
+            R_CURLY@55..56 "}"
+        WHITESPACE@56..57 " "
+        EQ@57..58 "="
+        WHITESPACE@58..59 " "
+        TUPLE_EXPR@59..61
+          L_PAREN@59..60 "("
+          R_PAREN@60..61 ")"
+        SEMICOLON@61..62 ";"
+      WHITESPACE@62..67 "\n    "
+      LET_STMT@67..90
+        LET_KW@67..70 "let"
+        WHITESPACE@70..71 " "
+        RECORD_PAT@71..84
+          PATH@71..72
+            PATH_SEGMENT@71..72
+              NAME_REF@71..72
+                IDENT@71..72 "S"
+          WHITESPACE@72..73 " "
+          RECORD_PAT_FIELD_LIST@73..84
+            L_CURLY@73..74 "{"
+            WHITESPACE@74..75 " "
+            RECORD_PAT_FIELD@75..79
+              NAME_REF@75..76
+                IDENT@75..76 "h"
+              COLON@76..77 ":"
+              WHITESPACE@77..78 " "
+              WILDCARD_PAT@78..79
+                UNDERSCORE@78..79 "_"
+            COMMA@79..80 ","
+            WHITESPACE@80..81 " "
+            DOT2@81..83 ".."
+            R_CURLY@83..84 "}"
+        WHITESPACE@84..85 " "
+        EQ@85..86 "="
+        WHITESPACE@86..87 " "
+        TUPLE_EXPR@87..89
+          L_PAREN@87..88 "("
+          R_PAREN@88..89 ")"
+        SEMICOLON@89..90 ";"
+      WHITESPACE@90..95 "\n    "
+      LET_STMT@95..116
+        LET_KW@95..98 "let"
+        WHITESPACE@98..99 " "
+        RECORD_PAT@99..110
+          PATH@99..100
+            PATH_SEGMENT@99..100
+              NAME_REF@99..100
+                IDENT@99..100 "S"
+          WHITESPACE@100..101 " "
+          RECORD_PAT_FIELD_LIST@101..110
+            L_CURLY@101..102 "{"
+            WHITESPACE@102..103 " "
+            RECORD_PAT_FIELD@103..107
+              NAME_REF@103..104
+                IDENT@103..104 "h"
+              COLON@104..105 ":"
+              WHITESPACE@105..106 " "
+              WILDCARD_PAT@106..107
+                UNDERSCORE@106..107 "_"
+            COMMA@107..108 ","
+            WHITESPACE@108..109 " "
+            R_CURLY@109..110 "}"
+        WHITESPACE@110..111 " "
+        EQ@111..112 "="
+        WHITESPACE@112..113 " "
+        TUPLE_EXPR@113..115
+          L_PAREN@113..114 "("
+          R_PAREN@114..115 ")"
+        SEMICOLON@115..116 ";"
+      WHITESPACE@116..117 "\n"
+      R_CURLY@117..118 "}"
+  WHITESPACE@118..119 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rs b/crates/syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rs
new file mode 100644
index 00000000000..da3412fa8a9
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rs
@@ -0,0 +1,6 @@
+fn foo() {
+    let S {} = ();
+    let S { f, ref mut g } = ();
+    let S { h: _, ..} = ();
+    let S { h: _, } = ();
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0103_array_expr.rast b/crates/syntax/test_data/parser/inline/ok/0103_array_expr.rast
new file mode 100644
index 00000000000..c4c0a0568a4
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0103_array_expr.rast
@@ -0,0 +1,54 @@
+SOURCE_FILE@0..55
+  FN@0..54
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..54
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..18
+        ARRAY_EXPR@15..17
+          L_BRACK@15..16 "["
+          R_BRACK@16..17 "]"
+        SEMICOLON@17..18 ";"
+      WHITESPACE@18..23 "\n    "
+      EXPR_STMT@23..27
+        ARRAY_EXPR@23..26
+          L_BRACK@23..24 "["
+          LITERAL@24..25
+            INT_NUMBER@24..25 "1"
+          R_BRACK@25..26 "]"
+        SEMICOLON@26..27 ";"
+      WHITESPACE@27..32 "\n    "
+      EXPR_STMT@32..40
+        ARRAY_EXPR@32..39
+          L_BRACK@32..33 "["
+          LITERAL@33..34
+            INT_NUMBER@33..34 "1"
+          COMMA@34..35 ","
+          WHITESPACE@35..36 " "
+          LITERAL@36..37
+            INT_NUMBER@36..37 "2"
+          COMMA@37..38 ","
+          R_BRACK@38..39 "]"
+        SEMICOLON@39..40 ";"
+      WHITESPACE@40..45 "\n    "
+      EXPR_STMT@45..52
+        ARRAY_EXPR@45..51
+          L_BRACK@45..46 "["
+          LITERAL@46..47
+            INT_NUMBER@46..47 "1"
+          SEMICOLON@47..48 ";"
+          WHITESPACE@48..49 " "
+          LITERAL@49..50
+            INT_NUMBER@49..50 "2"
+          R_BRACK@50..51 "]"
+        SEMICOLON@51..52 ";"
+      WHITESPACE@52..53 "\n"
+      R_CURLY@53..54 "}"
+  WHITESPACE@54..55 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0103_array_expr.rs b/crates/syntax/test_data/parser/inline/ok/0103_array_expr.rs
new file mode 100644
index 00000000000..4dc1999d140
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0103_array_expr.rs
@@ -0,0 +1,6 @@
+fn foo() {
+    [];
+    [1];
+    [1, 2,];
+    [1; 2];
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.rast b/crates/syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.rast
new file mode 100644
index 00000000000..1244a503134
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.rast
@@ -0,0 +1,41 @@
+SOURCE_FILE@0..29
+  TYPE_ALIAS@0..28
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "F"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    PATH_TYPE@9..27
+      PATH@9..27
+        PATH_SEGMENT@9..27
+          NAME_REF@9..12
+            IDENT@9..12 "Box"
+          GENERIC_ARG_LIST@12..27
+            L_ANGLE@12..13 "<"
+            TYPE_ARG@13..26
+              PATH_TYPE@13..26
+                PATH@13..26
+                  PATH_SEGMENT@13..26
+                    NAME_REF@13..15
+                      IDENT@13..15 "Fn"
+                    PARAM_LIST@15..20
+                      L_PAREN@15..16 "("
+                      PARAM@16..19
+                        PATH_TYPE@16..19
+                          PATH@16..19
+                            PATH_SEGMENT@16..19
+                              NAME_REF@16..19
+                                IDENT@16..19 "i32"
+                      R_PAREN@19..20 ")"
+                    WHITESPACE@20..21 " "
+                    RET_TYPE@21..26
+                      THIN_ARROW@21..23 "->"
+                      WHITESPACE@23..24 " "
+                      TUPLE_TYPE@24..26
+                        L_PAREN@24..25 "("
+                        R_PAREN@25..26 ")"
+            R_ANGLE@26..27 ">"
+    SEMICOLON@27..28 ";"
+  WHITESPACE@28..29 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.rs b/crates/syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.rs
new file mode 100644
index 00000000000..17ed20e5b13
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.rs
@@ -0,0 +1 @@
+type F = Box<Fn(i32) -> ()>;
diff --git a/crates/syntax/test_data/parser/inline/ok/0106_lambda_expr.rast b/crates/syntax/test_data/parser/inline/ok/0106_lambda_expr.rast
new file mode 100644
index 00000000000..9b8381619a2
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0106_lambda_expr.rast
@@ -0,0 +1,135 @@
+SOURCE_FILE@0..134
+  FN@0..133
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..133
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..21
+        CLOSURE_EXPR@15..20
+          PARAM_LIST@15..17
+            PIPE@15..16 "|"
+            PIPE@16..17 "|"
+          WHITESPACE@17..18 " "
+          TUPLE_EXPR@18..20
+            L_PAREN@18..19 "("
+            R_PAREN@19..20 ")"
+        SEMICOLON@20..21 ";"
+      WHITESPACE@21..26 "\n    "
+      EXPR_STMT@26..43
+        CLOSURE_EXPR@26..42
+          PARAM_LIST@26..28
+            PIPE@26..27 "|"
+            PIPE@27..28 "|"
+          WHITESPACE@28..29 " "
+          RET_TYPE@29..35
+            THIN_ARROW@29..31 "->"
+            WHITESPACE@31..32 " "
+            PATH_TYPE@32..35
+              PATH@32..35
+                PATH_SEGMENT@32..35
+                  NAME_REF@32..35
+                    IDENT@32..35 "i32"
+          WHITESPACE@35..36 " "
+          BLOCK_EXPR@36..42
+            L_CURLY@36..37 "{"
+            WHITESPACE@37..38 " "
+            LITERAL@38..40
+              INT_NUMBER@38..40 "92"
+            WHITESPACE@40..41 " "
+            R_CURLY@41..42 "}"
+        SEMICOLON@42..43 ";"
+      WHITESPACE@43..48 "\n    "
+      EXPR_STMT@48..54
+        CLOSURE_EXPR@48..53
+          PARAM_LIST@48..51
+            PIPE@48..49 "|"
+            PARAM@49..50
+              IDENT_PAT@49..50
+                NAME@49..50
+                  IDENT@49..50 "x"
+            PIPE@50..51 "|"
+          WHITESPACE@51..52 " "
+          PATH_EXPR@52..53
+            PATH@52..53
+              PATH_SEGMENT@52..53
+                NAME_REF@52..53
+                  IDENT@52..53 "x"
+        SEMICOLON@53..54 ";"
+      WHITESPACE@54..59 "\n    "
+      EXPR_STMT@59..76
+        CLOSURE_EXPR@59..75
+          MOVE_KW@59..63 "move"
+          WHITESPACE@63..64 " "
+          PARAM_LIST@64..73
+            PIPE@64..65 "|"
+            PARAM@65..71
+              IDENT_PAT@65..66
+                NAME@65..66
+                  IDENT@65..66 "x"
+              COLON@66..67 ":"
+              WHITESPACE@67..68 " "
+              PATH_TYPE@68..71
+                PATH@68..71
+                  PATH_SEGMENT@68..71
+                    NAME_REF@68..71
+                      IDENT@68..71 "i32"
+            COMMA@71..72 ","
+            PIPE@72..73 "|"
+          WHITESPACE@73..74 " "
+          PATH_EXPR@74..75
+            PATH@74..75
+              PATH_SEGMENT@74..75
+                NAME_REF@74..75
+                  IDENT@74..75 "x"
+        SEMICOLON@75..76 ";"
+      WHITESPACE@76..81 "\n    "
+      EXPR_STMT@81..93
+        CLOSURE_EXPR@81..92
+          ASYNC_KW@81..86 "async"
+          WHITESPACE@86..87 " "
+          PARAM_LIST@87..89
+            PIPE@87..88 "|"
+            PIPE@88..89 "|"
+          WHITESPACE@89..90 " "
+          BLOCK_EXPR@90..92
+            L_CURLY@90..91 "{"
+            R_CURLY@91..92 "}"
+        SEMICOLON@92..93 ";"
+      WHITESPACE@93..98 "\n    "
+      EXPR_STMT@98..109
+        CLOSURE_EXPR@98..108
+          MOVE_KW@98..102 "move"
+          WHITESPACE@102..103 " "
+          PARAM_LIST@103..105
+            PIPE@103..104 "|"
+            PIPE@104..105 "|"
+          WHITESPACE@105..106 " "
+          BLOCK_EXPR@106..108
+            L_CURLY@106..107 "{"
+            R_CURLY@107..108 "}"
+        SEMICOLON@108..109 ";"
+      WHITESPACE@109..114 "\n    "
+      EXPR_STMT@114..131
+        CLOSURE_EXPR@114..130
+          ASYNC_KW@114..119 "async"
+          WHITESPACE@119..120 " "
+          MOVE_KW@120..124 "move"
+          WHITESPACE@124..125 " "
+          PARAM_LIST@125..127
+            PIPE@125..126 "|"
+            PIPE@126..127 "|"
+          WHITESPACE@127..128 " "
+          BLOCK_EXPR@128..130
+            L_CURLY@128..129 "{"
+            R_CURLY@129..130 "}"
+        SEMICOLON@130..131 ";"
+      WHITESPACE@131..132 "\n"
+      R_CURLY@132..133 "}"
+  WHITESPACE@133..134 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0106_lambda_expr.rs b/crates/syntax/test_data/parser/inline/ok/0106_lambda_expr.rs
new file mode 100644
index 00000000000..0757178239d
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0106_lambda_expr.rs
@@ -0,0 +1,9 @@
+fn foo() {
+    || ();
+    || -> i32 { 92 };
+    |x| x;
+    move |x: i32,| x;
+    async || {};
+    move || {};
+    async move || {};
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0107_method_call_expr.rast b/crates/syntax/test_data/parser/inline/ok/0107_method_call_expr.rast
new file mode 100644
index 00000000000..be8365e0571
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0107_method_call_expr.rast
@@ -0,0 +1,62 @@
+SOURCE_FILE@0..49
+  FN@0..48
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..48
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..23
+        METHOD_CALL_EXPR@15..22
+          PATH_EXPR@15..16
+            PATH@15..16
+              PATH_SEGMENT@15..16
+                NAME_REF@15..16
+                  IDENT@15..16 "x"
+          DOT@16..17 "."
+          NAME_REF@17..20
+            IDENT@17..20 "foo"
+          ARG_LIST@20..22
+            L_PAREN@20..21 "("
+            R_PAREN@21..22 ")"
+        SEMICOLON@22..23 ";"
+      WHITESPACE@23..28 "\n    "
+      EXPR_STMT@28..46
+        METHOD_CALL_EXPR@28..45
+          PATH_EXPR@28..29
+            PATH@28..29
+              PATH_SEGMENT@28..29
+                NAME_REF@28..29
+                  IDENT@28..29 "y"
+          DOT@29..30 "."
+          NAME_REF@30..33
+            IDENT@30..33 "bar"
+          GENERIC_ARG_LIST@33..38
+            COLON2@33..35 "::"
+            L_ANGLE@35..36 "<"
+            TYPE_ARG@36..37
+              PATH_TYPE@36..37
+                PATH@36..37
+                  PATH_SEGMENT@36..37
+                    NAME_REF@36..37
+                      IDENT@36..37 "T"
+            R_ANGLE@37..38 ">"
+          ARG_LIST@38..45
+            L_PAREN@38..39 "("
+            LITERAL@39..40
+              INT_NUMBER@39..40 "1"
+            COMMA@40..41 ","
+            WHITESPACE@41..42 " "
+            LITERAL@42..43
+              INT_NUMBER@42..43 "2"
+            COMMA@43..44 ","
+            R_PAREN@44..45 ")"
+        SEMICOLON@45..46 ";"
+      WHITESPACE@46..47 "\n"
+      R_CURLY@47..48 "}"
+  WHITESPACE@48..49 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0107_method_call_expr.rs b/crates/syntax/test_data/parser/inline/ok/0107_method_call_expr.rs
new file mode 100644
index 00000000000..1a3aa35ae8e
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0107_method_call_expr.rs
@@ -0,0 +1,4 @@
+fn foo() {
+    x.foo();
+    y.bar::<T>(1, 2,);
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0108_tuple_expr.rast b/crates/syntax/test_data/parser/inline/ok/0108_tuple_expr.rast
new file mode 100644
index 00000000000..ca7e4a5c361
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0108_tuple_expr.rast
@@ -0,0 +1,38 @@
+SOURCE_FILE@0..40
+  FN@0..39
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..39
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..18
+        TUPLE_EXPR@15..17
+          L_PAREN@15..16 "("
+          R_PAREN@16..17 ")"
+        SEMICOLON@17..18 ";"
+      WHITESPACE@18..23 "\n    "
+      EXPR_STMT@23..27
+        PAREN_EXPR@23..26
+          L_PAREN@23..24 "("
+          LITERAL@24..25
+            INT_NUMBER@24..25 "1"
+          R_PAREN@25..26 ")"
+        SEMICOLON@26..27 ";"
+      WHITESPACE@27..32 "\n    "
+      EXPR_STMT@32..37
+        TUPLE_EXPR@32..36
+          L_PAREN@32..33 "("
+          LITERAL@33..34
+            INT_NUMBER@33..34 "1"
+          COMMA@34..35 ","
+          R_PAREN@35..36 ")"
+        SEMICOLON@36..37 ";"
+      WHITESPACE@37..38 "\n"
+      R_CURLY@38..39 "}"
+  WHITESPACE@39..40 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0108_tuple_expr.rs b/crates/syntax/test_data/parser/inline/ok/0108_tuple_expr.rs
new file mode 100644
index 00000000000..e4f774280ca
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0108_tuple_expr.rs
@@ -0,0 +1,5 @@
+fn foo() {
+    ();
+    (1);
+    (1,);
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0109_label.rast b/crates/syntax/test_data/parser/inline/ok/0109_label.rast
new file mode 100644
index 00000000000..c9588025ce5
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0109_label.rast
@@ -0,0 +1,64 @@
+SOURCE_FILE@0..74
+  FN@0..73
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..73
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..26
+        LOOP_EXPR@15..26
+          LABEL@15..18
+            LIFETIME@15..17 "\'a"
+            COLON@17..18 ":"
+          WHITESPACE@18..19 " "
+          LOOP_KW@19..23 "loop"
+          WHITESPACE@23..24 " "
+          BLOCK_EXPR@24..26
+            L_CURLY@24..25 "{"
+            R_CURLY@25..26 "}"
+      WHITESPACE@26..31 "\n    "
+      EXPR_STMT@31..48
+        WHILE_EXPR@31..48
+          LABEL@31..34
+            LIFETIME@31..33 "\'b"
+            COLON@33..34 ":"
+          WHITESPACE@34..35 " "
+          WHILE_KW@35..40 "while"
+          WHITESPACE@40..41 " "
+          CONDITION@41..45
+            LITERAL@41..45
+              TRUE_KW@41..45 "true"
+          WHITESPACE@45..46 " "
+          BLOCK_EXPR@46..48
+            L_CURLY@46..47 "{"
+            R_CURLY@47..48 "}"
+      WHITESPACE@48..53 "\n    "
+      FOR_EXPR@53..71
+        LABEL@53..56
+          LIFETIME@53..55 "\'c"
+          COLON@55..56 ":"
+        WHITESPACE@56..57 " "
+        FOR_KW@57..60 "for"
+        WHITESPACE@60..61 " "
+        IDENT_PAT@61..62
+          NAME@61..62
+            IDENT@61..62 "x"
+        WHITESPACE@62..63 " "
+        IN_KW@63..65 "in"
+        WHITESPACE@65..66 " "
+        TUPLE_EXPR@66..68
+          L_PAREN@66..67 "("
+          R_PAREN@67..68 ")"
+        WHITESPACE@68..69 " "
+        BLOCK_EXPR@69..71
+          L_CURLY@69..70 "{"
+          R_CURLY@70..71 "}"
+      WHITESPACE@71..72 "\n"
+      R_CURLY@72..73 "}"
+  WHITESPACE@73..74 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0109_label.rs b/crates/syntax/test_data/parser/inline/ok/0109_label.rs
new file mode 100644
index 00000000000..48e83f263b9
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0109_label.rs
@@ -0,0 +1,5 @@
+fn foo() {
+    'a: loop {}
+    'b: while true {}
+    'c: for x in () {}
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0110_use_path.rast b/crates/syntax/test_data/parser/inline/ok/0110_use_path.rast
new file mode 100644
index 00000000000..82028096f83
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0110_use_path.rast
@@ -0,0 +1,38 @@
+SOURCE_FILE@0..154
+  USE@0..17
+    USE_KW@0..3 "use"
+    WHITESPACE@3..4 " "
+    USE_TREE@4..16
+      PATH@4..16
+        PATH_SEGMENT@4..16
+          COLON2@4..6 "::"
+          NAME_REF@6..16
+            IDENT@6..16 "crate_name"
+    SEMICOLON@16..17 ";"
+  WHITESPACE@17..18 " "
+  COMMENT@18..45 "// Rust 2018 - All fl ..."
+  WHITESPACE@45..46 "\n"
+  USE@46..61
+    USE_KW@46..49 "use"
+    WHITESPACE@49..50 " "
+    USE_TREE@50..60
+      PATH@50..60
+        PATH_SEGMENT@50..60
+          NAME_REF@50..60
+            IDENT@50..60 "crate_name"
+    SEMICOLON@60..61 ";"
+  WHITESPACE@61..62 " "
+  COMMENT@62..91 "// Rust 2018 - Anchor ..."
+  WHITESPACE@91..92 "\n"
+  USE@92..124
+    USE_KW@92..95 "use"
+    WHITESPACE@95..96 " "
+    USE_TREE@96..123
+      PATH@96..123
+        PATH_SEGMENT@96..123
+          NAME_REF@96..123
+            IDENT@96..123 "item_in_scope_or_crat ..."
+    SEMICOLON@123..124 ";"
+  WHITESPACE@124..125 " "
+  COMMENT@125..153 "// Rust 2018 - Unifor ..."
+  WHITESPACE@153..154 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0110_use_path.rs b/crates/syntax/test_data/parser/inline/ok/0110_use_path.rs
new file mode 100644
index 00000000000..328e9473602
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0110_use_path.rs
@@ -0,0 +1,3 @@
+use ::crate_name; // Rust 2018 - All flavours
+use crate_name; // Rust 2018 - Anchored paths
+use item_in_scope_or_crate_name; // Rust 2018 - Uniform Paths
diff --git a/crates/syntax/test_data/parser/inline/ok/0111_tuple_pat.rast b/crates/syntax/test_data/parser/inline/ok/0111_tuple_pat.rast
new file mode 100644
index 00000000000..b82ed0230b1
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0111_tuple_pat.rast
@@ -0,0 +1,89 @@
+SOURCE_FILE@0..94
+  FN@0..93
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..93
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      LET_STMT@16..36
+        LET_KW@16..19 "let"
+        WHITESPACE@19..20 " "
+        TUPLE_PAT@20..30
+          L_PAREN@20..21 "("
+          IDENT_PAT@21..22
+            NAME@21..22
+              IDENT@21..22 "a"
+          COMMA@22..23 ","
+          WHITESPACE@23..24 " "
+          IDENT_PAT@24..25
+            NAME@24..25
+              IDENT@24..25 "b"
+          COMMA@25..26 ","
+          WHITESPACE@26..27 " "
+          REST_PAT@27..29
+            DOT2@27..29 ".."
+          R_PAREN@29..30 ")"
+        WHITESPACE@30..31 " "
+        EQ@31..32 "="
+        WHITESPACE@32..33 " "
+        TUPLE_EXPR@33..35
+          L_PAREN@33..34 "("
+          R_PAREN@34..35 ")"
+        SEMICOLON@35..36 ";"
+      WHITESPACE@36..41 "\n    "
+      LET_STMT@41..55
+        LET_KW@41..44 "let"
+        WHITESPACE@44..45 " "
+        TUPLE_PAT@45..49
+          L_PAREN@45..46 "("
+          IDENT_PAT@46..47
+            NAME@46..47
+              IDENT@46..47 "a"
+          COMMA@47..48 ","
+          R_PAREN@48..49 ")"
+        WHITESPACE@49..50 " "
+        EQ@50..51 "="
+        WHITESPACE@51..52 " "
+        TUPLE_EXPR@52..54
+          L_PAREN@52..53 "("
+          R_PAREN@53..54 ")"
+        SEMICOLON@54..55 ";"
+      WHITESPACE@55..60 "\n    "
+      LET_STMT@60..74
+        LET_KW@60..63 "let"
+        WHITESPACE@63..64 " "
+        TUPLE_PAT@64..68
+          L_PAREN@64..65 "("
+          REST_PAT@65..67
+            DOT2@65..67 ".."
+          R_PAREN@67..68 ")"
+        WHITESPACE@68..69 " "
+        EQ@69..70 "="
+        WHITESPACE@70..71 " "
+        TUPLE_EXPR@71..73
+          L_PAREN@71..72 "("
+          R_PAREN@72..73 ")"
+        SEMICOLON@73..74 ";"
+      WHITESPACE@74..79 "\n    "
+      LET_STMT@79..91
+        LET_KW@79..82 "let"
+        WHITESPACE@82..83 " "
+        TUPLE_PAT@83..85
+          L_PAREN@83..84 "("
+          R_PAREN@84..85 ")"
+        WHITESPACE@85..86 " "
+        EQ@86..87 "="
+        WHITESPACE@87..88 " "
+        TUPLE_EXPR@88..90
+          L_PAREN@88..89 "("
+          R_PAREN@89..90 ")"
+        SEMICOLON@90..91 ";"
+      WHITESPACE@91..92 "\n"
+      R_CURLY@92..93 "}"
+  WHITESPACE@93..94 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0111_tuple_pat.rs b/crates/syntax/test_data/parser/inline/ok/0111_tuple_pat.rs
new file mode 100644
index 00000000000..ba719879d4c
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0111_tuple_pat.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let (a, b, ..) = ();
+    let (a,) = ();
+    let (..) = ();
+    let () = ();
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0112_bind_pat.rast b/crates/syntax/test_data/parser/inline/ok/0112_bind_pat.rast
new file mode 100644
index 00000000000..7b9a498c8ee
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0112_bind_pat.rast
@@ -0,0 +1,127 @@
+SOURCE_FILE@0..146
+  FN@0..145
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..145
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      LET_STMT@16..27
+        LET_KW@16..19 "let"
+        WHITESPACE@19..20 " "
+        IDENT_PAT@20..21
+          NAME@20..21
+            IDENT@20..21 "a"
+        WHITESPACE@21..22 " "
+        EQ@22..23 "="
+        WHITESPACE@23..24 " "
+        TUPLE_EXPR@24..26
+          L_PAREN@24..25 "("
+          R_PAREN@25..26 ")"
+        SEMICOLON@26..27 ";"
+      WHITESPACE@27..32 "\n    "
+      LET_STMT@32..47
+        LET_KW@32..35 "let"
+        WHITESPACE@35..36 " "
+        IDENT_PAT@36..41
+          MUT_KW@36..39 "mut"
+          WHITESPACE@39..40 " "
+          NAME@40..41
+            IDENT@40..41 "b"
+        WHITESPACE@41..42 " "
+        EQ@42..43 "="
+        WHITESPACE@43..44 " "
+        TUPLE_EXPR@44..46
+          L_PAREN@44..45 "("
+          R_PAREN@45..46 ")"
+        SEMICOLON@46..47 ";"
+      WHITESPACE@47..52 "\n    "
+      LET_STMT@52..67
+        LET_KW@52..55 "let"
+        WHITESPACE@55..56 " "
+        IDENT_PAT@56..61
+          REF_KW@56..59 "ref"
+          WHITESPACE@59..60 " "
+          NAME@60..61
+            IDENT@60..61 "c"
+        WHITESPACE@61..62 " "
+        EQ@62..63 "="
+        WHITESPACE@63..64 " "
+        TUPLE_EXPR@64..66
+          L_PAREN@64..65 "("
+          R_PAREN@65..66 ")"
+        SEMICOLON@66..67 ";"
+      WHITESPACE@67..72 "\n    "
+      LET_STMT@72..91
+        LET_KW@72..75 "let"
+        WHITESPACE@75..76 " "
+        IDENT_PAT@76..85
+          REF_KW@76..79 "ref"
+          WHITESPACE@79..80 " "
+          MUT_KW@80..83 "mut"
+          WHITESPACE@83..84 " "
+          NAME@84..85
+            IDENT@84..85 "d"
+        WHITESPACE@85..86 " "
+        EQ@86..87 "="
+        WHITESPACE@87..88 " "
+        TUPLE_EXPR@88..90
+          L_PAREN@88..89 "("
+          R_PAREN@89..90 ")"
+        SEMICOLON@90..91 ";"
+      WHITESPACE@91..96 "\n    "
+      LET_STMT@96..111
+        LET_KW@96..99 "let"
+        WHITESPACE@99..100 " "
+        IDENT_PAT@100..105
+          NAME@100..101
+            IDENT@100..101 "e"
+          WHITESPACE@101..102 " "
+          AT@102..103 "@"
+          WHITESPACE@103..104 " "
+          WILDCARD_PAT@104..105
+            UNDERSCORE@104..105 "_"
+        WHITESPACE@105..106 " "
+        EQ@106..107 "="
+        WHITESPACE@107..108 " "
+        TUPLE_EXPR@108..110
+          L_PAREN@108..109 "("
+          R_PAREN@109..110 ")"
+        SEMICOLON@110..111 ";"
+      WHITESPACE@111..116 "\n    "
+      LET_STMT@116..143
+        LET_KW@116..119 "let"
+        WHITESPACE@119..120 " "
+        IDENT_PAT@120..137
+          REF_KW@120..123 "ref"
+          WHITESPACE@123..124 " "
+          MUT_KW@124..127 "mut"
+          WHITESPACE@127..128 " "
+          NAME@128..129
+            IDENT@128..129 "f"
+          WHITESPACE@129..130 " "
+          AT@130..131 "@"
+          WHITESPACE@131..132 " "
+          IDENT_PAT@132..137
+            NAME@132..133
+              IDENT@132..133 "g"
+            WHITESPACE@133..134 " "
+            AT@134..135 "@"
+            WHITESPACE@135..136 " "
+            WILDCARD_PAT@136..137
+              UNDERSCORE@136..137 "_"
+        WHITESPACE@137..138 " "
+        EQ@138..139 "="
+        WHITESPACE@139..140 " "
+        TUPLE_EXPR@140..142
+          L_PAREN@140..141 "("
+          R_PAREN@141..142 ")"
+        SEMICOLON@142..143 ";"
+      WHITESPACE@143..144 "\n"
+      R_CURLY@144..145 "}"
+  WHITESPACE@145..146 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0112_bind_pat.rs b/crates/syntax/test_data/parser/inline/ok/0112_bind_pat.rs
new file mode 100644
index 00000000000..820a9e72ce5
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0112_bind_pat.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let a = ();
+    let mut b = ();
+    let ref c = ();
+    let ref mut d = ();
+    let e @ _ = ();
+    let ref mut f @ g @ _ = ();
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0113_nocontentexpr.rast b/crates/syntax/test_data/parser/inline/ok/0113_nocontentexpr.rast
new file mode 100644
index 00000000000..d761c1c68e1
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0113_nocontentexpr.rast
@@ -0,0 +1,55 @@
+SOURCE_FILE@0..50
+  FN@0..49
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    BLOCK_EXPR@8..49
+      L_CURLY@8..9 "{"
+      WHITESPACE@9..14 "\n    "
+      SEMICOLON@14..15 ";"
+      SEMICOLON@15..16 ";"
+      SEMICOLON@16..17 ";"
+      EXPR_STMT@17..29
+        CALL_EXPR@17..28
+          PATH_EXPR@17..26
+            PATH@17..26
+              PATH_SEGMENT@17..26
+                NAME_REF@17..26
+                  IDENT@17..26 "some_expr"
+          ARG_LIST@26..28
+            L_PAREN@26..27 "("
+            R_PAREN@27..28 ")"
+        SEMICOLON@28..29 ";"
+      SEMICOLON@29..30 ";"
+      SEMICOLON@30..31 ";"
+      SEMICOLON@31..32 ";"
+      EXPR_STMT@32..38
+        BLOCK_EXPR@32..37
+          L_CURLY@32..33 "{"
+          SEMICOLON@33..34 ";"
+          SEMICOLON@34..35 ";"
+          SEMICOLON@35..36 ";"
+          R_CURLY@36..37 "}"
+        SEMICOLON@37..38 ";"
+      SEMICOLON@38..39 ";"
+      SEMICOLON@39..40 ";"
+      SEMICOLON@40..41 ";"
+      CALL_EXPR@41..47
+        PATH_EXPR@41..43
+          PATH@41..43
+            PATH_SEGMENT@41..43
+              NAME_REF@41..43
+                IDENT@41..43 "Ok"
+        ARG_LIST@43..47
+          L_PAREN@43..44 "("
+          TUPLE_EXPR@44..46
+            L_PAREN@44..45 "("
+            R_PAREN@45..46 ")"
+          R_PAREN@46..47 ")"
+      WHITESPACE@47..48 "\n"
+      R_CURLY@48..49 "}"
+  WHITESPACE@49..50 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0113_nocontentexpr.rs b/crates/syntax/test_data/parser/inline/ok/0113_nocontentexpr.rs
new file mode 100644
index 00000000000..bbf09e367cf
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0113_nocontentexpr.rs
@@ -0,0 +1,3 @@
+fn foo(){
+    ;;;some_expr();;;;{;;;};;;;Ok(())
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0114_tuple_struct_where.rast b/crates/syntax/test_data/parser/inline/ok/0114_tuple_struct_where.rast
new file mode 100644
index 00000000000..0e1594dc485
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0114_tuple_struct_where.rast
@@ -0,0 +1,64 @@
+SOURCE_FILE@0..53
+  STRUCT@0..33
+    STRUCT_KW@0..6 "struct"
+    WHITESPACE@6..7 " "
+    NAME@7..11
+      IDENT@7..11 "Test"
+    GENERIC_PARAM_LIST@11..14
+      L_ANGLE@11..12 "<"
+      TYPE_PARAM@12..13
+        NAME@12..13
+          IDENT@12..13 "T"
+      R_ANGLE@13..14 ">"
+    TUPLE_FIELD_LIST@14..17
+      L_PAREN@14..15 "("
+      TUPLE_FIELD@15..16
+        PATH_TYPE@15..16
+          PATH@15..16
+            PATH_SEGMENT@15..16
+              NAME_REF@15..16
+                IDENT@15..16 "T"
+      R_PAREN@16..17 ")"
+    WHITESPACE@17..18 " "
+    WHERE_CLAUSE@18..32
+      WHERE_KW@18..23 "where"
+      WHITESPACE@23..24 " "
+      WHERE_PRED@24..32
+        PATH_TYPE@24..25
+          PATH@24..25
+            PATH_SEGMENT@24..25
+              NAME_REF@24..25
+                IDENT@24..25 "T"
+        COLON@25..26 ":"
+        WHITESPACE@26..27 " "
+        TYPE_BOUND_LIST@27..32
+          TYPE_BOUND@27..32
+            PATH_TYPE@27..32
+              PATH@27..32
+                PATH_SEGMENT@27..32
+                  NAME_REF@27..32
+                    IDENT@27..32 "Clone"
+    SEMICOLON@32..33 ";"
+  WHITESPACE@33..34 "\n"
+  STRUCT@34..52
+    STRUCT_KW@34..40 "struct"
+    WHITESPACE@40..41 " "
+    NAME@41..45
+      IDENT@41..45 "Test"
+    GENERIC_PARAM_LIST@45..48
+      L_ANGLE@45..46 "<"
+      TYPE_PARAM@46..47
+        NAME@46..47
+          IDENT@46..47 "T"
+      R_ANGLE@47..48 ">"
+    TUPLE_FIELD_LIST@48..51
+      L_PAREN@48..49 "("
+      TUPLE_FIELD@49..50
+        PATH_TYPE@49..50
+          PATH@49..50
+            PATH_SEGMENT@49..50
+              NAME_REF@49..50
+                IDENT@49..50 "T"
+      R_PAREN@50..51 ")"
+    SEMICOLON@51..52 ";"
+  WHITESPACE@52..53 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0114_tuple_struct_where.rs b/crates/syntax/test_data/parser/inline/ok/0114_tuple_struct_where.rs
new file mode 100644
index 00000000000..ddd59016dc6
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0114_tuple_struct_where.rs
@@ -0,0 +1,2 @@
+struct Test<T>(T) where T: Clone;
+struct Test<T>(T);
diff --git a/crates/syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.rast b/crates/syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.rast
new file mode 100644
index 00000000000..4d09c9f50f3
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.rast
@@ -0,0 +1,41 @@
+SOURCE_FILE@0..60
+  STRUCT@0..59
+    STRUCT_KW@0..6 "struct"
+    WHITESPACE@6..7 " "
+    NAME@7..8
+      IDENT@7..8 "S"
+    WHITESPACE@8..9 " "
+    TUPLE_FIELD_LIST@9..58
+      L_PAREN@9..10 "("
+      WHITESPACE@10..15 "\n    "
+      TUPLE_FIELD@15..55
+        ATTR@15..43
+          POUND@15..16 "#"
+          L_BRACK@16..17 "["
+          PATH@17..22
+            PATH_SEGMENT@17..22
+              NAME_REF@17..22
+                IDENT@17..22 "serde"
+          TOKEN_TREE@22..42
+            L_PAREN@22..23 "("
+            IDENT@23..27 "with"
+            WHITESPACE@27..28 " "
+            EQ@28..29 "="
+            WHITESPACE@29..30 " "
+            STRING@30..41 "\"url_serde\""
+            R_PAREN@41..42 ")"
+          R_BRACK@42..43 "]"
+        WHITESPACE@43..48 "\n    "
+        VISIBILITY@48..51
+          PUB_KW@48..51 "pub"
+        WHITESPACE@51..52 " "
+        PATH_TYPE@52..55
+          PATH@52..55
+            PATH_SEGMENT@52..55
+              NAME_REF@52..55
+                IDENT@52..55 "Uri"
+      COMMA@55..56 ","
+      WHITESPACE@56..57 "\n"
+      R_PAREN@57..58 ")"
+    SEMICOLON@58..59 ";"
+  WHITESPACE@59..60 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.rs b/crates/syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.rs
new file mode 100644
index 00000000000..635b9ac21af
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.rs
@@ -0,0 +1,4 @@
+struct S (
+    #[serde(with = "url_serde")]
+    pub Uri,
+);
diff --git a/crates/syntax/test_data/parser/inline/ok/0117_macro_call_type.rast b/crates/syntax/test_data/parser/inline/ok/0117_macro_call_type.rast
new file mode 100644
index 00000000000..f3d4ad72c32
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0117_macro_call_type.rast
@@ -0,0 +1,43 @@
+SOURCE_FILE@0..41
+  TYPE_ALIAS@0..16
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "A"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    MACRO_CALL@9..15
+      PATH@9..12
+        PATH_SEGMENT@9..12
+          NAME_REF@9..12
+            IDENT@9..12 "foo"
+      BANG@12..13 "!"
+      TOKEN_TREE@13..15
+        L_PAREN@13..14 "("
+        R_PAREN@14..15 ")"
+    SEMICOLON@15..16 ";"
+  WHITESPACE@16..17 "\n"
+  TYPE_ALIAS@17..40
+    TYPE_KW@17..21 "type"
+    WHITESPACE@21..22 " "
+    NAME@22..23
+      IDENT@22..23 "B"
+    WHITESPACE@23..24 " "
+    EQ@24..25 "="
+    WHITESPACE@25..26 " "
+    MACRO_CALL@26..39
+      PATH@26..36
+        PATH@26..31
+          PATH_SEGMENT@26..31
+            CRATE_KW@26..31 "crate"
+        COLON2@31..33 "::"
+        PATH_SEGMENT@33..36
+          NAME_REF@33..36
+            IDENT@33..36 "foo"
+      BANG@36..37 "!"
+      TOKEN_TREE@37..39
+        L_PAREN@37..38 "("
+        R_PAREN@38..39 ")"
+    SEMICOLON@39..40 ";"
+  WHITESPACE@40..41 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0117_macro_call_type.rs b/crates/syntax/test_data/parser/inline/ok/0117_macro_call_type.rs
new file mode 100644
index 00000000000..edb470c8999
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0117_macro_call_type.rs
@@ -0,0 +1,2 @@
+type A = foo!();
+type B = crate::foo!();
diff --git a/crates/syntax/test_data/parser/inline/ok/0118_impl_inner_attributes.rast b/crates/syntax/test_data/parser/inline/ok/0118_impl_inner_attributes.rast
new file mode 100644
index 00000000000..141a7b2035f
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0118_impl_inner_attributes.rast
@@ -0,0 +1,40 @@
+SOURCE_FILE@0..94
+  ENUM@0..8
+    ENUM_KW@0..4 "enum"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "F"
+    VARIANT_LIST@6..8
+      L_CURLY@6..7 "{"
+      R_CURLY@7..8 "}"
+  WHITESPACE@8..9 "\n"
+  IMPL@9..93
+    IMPL_KW@9..13 "impl"
+    WHITESPACE@13..14 " "
+    PATH_TYPE@14..15
+      PATH@14..15
+        PATH_SEGMENT@14..15
+          NAME_REF@14..15
+            IDENT@14..15 "F"
+    WHITESPACE@15..16 " "
+    ASSOC_ITEM_LIST@16..93
+      L_CURLY@16..17 "{"
+      WHITESPACE@17..23 "\n     "
+      COMMENT@23..48 "//! This is a doc com ..."
+      WHITESPACE@48..54 "\n     "
+      ATTR@54..91
+        POUND@54..55 "#"
+        BANG@55..56 "!"
+        L_BRACK@56..57 "["
+        PATH@57..60
+          PATH_SEGMENT@57..60
+            NAME_REF@57..60
+              IDENT@57..60 "doc"
+        TOKEN_TREE@60..90
+          L_PAREN@60..61 "("
+          STRING@61..89 "\"This is also a doc c ..."
+          R_PAREN@89..90 ")"
+        R_BRACK@90..91 "]"
+      WHITESPACE@91..92 "\n"
+      R_CURLY@92..93 "}"
+  WHITESPACE@93..94 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0118_impl_inner_attributes.rs b/crates/syntax/test_data/parser/inline/ok/0118_impl_inner_attributes.rs
new file mode 100644
index 00000000000..4d68cceb710
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0118_impl_inner_attributes.rs
@@ -0,0 +1,5 @@
+enum F{}
+impl F {
+     //! This is a doc comment
+     #![doc("This is also a doc comment")]
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0118_match_guard.rast b/crates/syntax/test_data/parser/inline/ok/0118_match_guard.rast
new file mode 100644
index 00000000000..0cf4eb0a5aa
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0118_match_guard.rast
@@ -0,0 +1,47 @@
+SOURCE_FILE@0..58
+  FN@0..57
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..57
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      MATCH_EXPR@15..55
+        MATCH_KW@15..20 "match"
+        WHITESPACE@20..21 " "
+        TUPLE_EXPR@21..23
+          L_PAREN@21..22 "("
+          R_PAREN@22..23 ")"
+        WHITESPACE@23..24 " "
+        MATCH_ARM_LIST@24..55
+          L_CURLY@24..25 "{"
+          WHITESPACE@25..34 "\n        "
+          MATCH_ARM@34..48
+            WILDCARD_PAT@34..35
+              UNDERSCORE@34..35 "_"
+            WHITESPACE@35..36 " "
+            MATCH_GUARD@36..42
+              IF_KW@36..38 "if"
+              WHITESPACE@38..39 " "
+              PATH_EXPR@39..42
+                PATH@39..42
+                  PATH_SEGMENT@39..42
+                    NAME_REF@39..42
+                      IDENT@39..42 "foo"
+            WHITESPACE@42..43 " "
+            FAT_ARROW@43..45 "=>"
+            WHITESPACE@45..46 " "
+            TUPLE_EXPR@46..48
+              L_PAREN@46..47 "("
+              R_PAREN@47..48 ")"
+          COMMA@48..49 ","
+          WHITESPACE@49..54 "\n    "
+          R_CURLY@54..55 "}"
+      WHITESPACE@55..56 "\n"
+      R_CURLY@56..57 "}"
+  WHITESPACE@57..58 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0118_match_guard.rs b/crates/syntax/test_data/parser/inline/ok/0118_match_guard.rs
new file mode 100644
index 00000000000..f1bd72fc4cb
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0118_match_guard.rs
@@ -0,0 +1,5 @@
+fn foo() {
+    match () {
+        _ if foo => (),
+    }
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.rast b/crates/syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.rast
new file mode 100644
index 00000000000..ec7a00f1db8
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.rast
@@ -0,0 +1,80 @@
+SOURCE_FILE@0..139
+  FN@0..138
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..138
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      MATCH_EXPR@15..136
+        MATCH_KW@15..20 "match"
+        WHITESPACE@20..21 " "
+        TUPLE_EXPR@21..23
+          L_PAREN@21..22 "("
+          R_PAREN@22..23 ")"
+        WHITESPACE@23..24 " "
+        MATCH_ARM_LIST@24..136
+          L_CURLY@24..25 "{"
+          WHITESPACE@25..34 "\n        "
+          ATTR@34..60
+            POUND@34..35 "#"
+            BANG@35..36 "!"
+            L_BRACK@36..37 "["
+            PATH@37..40
+              PATH_SEGMENT@37..40
+                NAME_REF@37..40
+                  IDENT@37..40 "doc"
+            TOKEN_TREE@40..59
+              L_PAREN@40..41 "("
+              STRING@41..58 "\"Inner attribute\""
+              R_PAREN@58..59 ")"
+            R_BRACK@59..60 "]"
+          WHITESPACE@60..69 "\n        "
+          ATTR@69..86
+            POUND@69..70 "#"
+            BANG@70..71 "!"
+            L_BRACK@71..72 "["
+            PATH@72..75
+              PATH_SEGMENT@72..75
+                NAME_REF@72..75
+                  IDENT@72..75 "doc"
+            TOKEN_TREE@75..85
+              L_PAREN@75..76 "("
+              STRING@76..84 "\"Can be\""
+              R_PAREN@84..85 ")"
+            R_BRACK@85..86 "]"
+          WHITESPACE@86..95 "\n        "
+          ATTR@95..113
+            POUND@95..96 "#"
+            BANG@96..97 "!"
+            L_BRACK@97..98 "["
+            PATH@98..101
+              PATH_SEGMENT@98..101
+                NAME_REF@98..101
+                  IDENT@98..101 "doc"
+            TOKEN_TREE@101..112
+              L_PAREN@101..102 "("
+              STRING@102..111 "\"Stacked\""
+              R_PAREN@111..112 ")"
+            R_BRACK@112..113 "]"
+          WHITESPACE@113..122 "\n        "
+          MATCH_ARM@122..129
+            WILDCARD_PAT@122..123
+              UNDERSCORE@122..123 "_"
+            WHITESPACE@123..124 " "
+            FAT_ARROW@124..126 "=>"
+            WHITESPACE@126..127 " "
+            TUPLE_EXPR@127..129
+              L_PAREN@127..128 "("
+              R_PAREN@128..129 ")"
+          COMMA@129..130 ","
+          WHITESPACE@130..135 "\n    "
+          R_CURLY@135..136 "}"
+      WHITESPACE@136..137 "\n"
+      R_CURLY@137..138 "}"
+  WHITESPACE@138..139 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.rs b/crates/syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.rs
new file mode 100644
index 00000000000..54a67c9d7b7
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.rs
@@ -0,0 +1,8 @@
+fn foo() {
+    match () {
+        #![doc("Inner attribute")]
+        #![doc("Can be")]
+        #![doc("Stacked")]
+        _ => (),
+    }
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0121_match_arms_outer_attributes.rast b/crates/syntax/test_data/parser/inline/ok/0121_match_arms_outer_attributes.rast
new file mode 100644
index 00000000000..97924da0526
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0121_match_arms_outer_attributes.rast
@@ -0,0 +1,145 @@
+SOURCE_FILE@0..259
+  FN@0..258
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..258
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      MATCH_EXPR@15..256
+        MATCH_KW@15..20 "match"
+        WHITESPACE@20..21 " "
+        TUPLE_EXPR@21..23
+          L_PAREN@21..22 "("
+          R_PAREN@22..23 ")"
+        WHITESPACE@23..24 " "
+        MATCH_ARM_LIST@24..256
+          L_CURLY@24..25 "{"
+          WHITESPACE@25..34 "\n        "
+          MATCH_ARM@34..74
+            ATTR@34..58
+              POUND@34..35 "#"
+              L_BRACK@35..36 "["
+              PATH@36..39
+                PATH_SEGMENT@36..39
+                  NAME_REF@36..39
+                    IDENT@36..39 "cfg"
+              TOKEN_TREE@39..57
+                L_PAREN@39..40 "("
+                IDENT@40..47 "feature"
+                WHITESPACE@47..48 " "
+                EQ@48..49 "="
+                WHITESPACE@49..50 " "
+                STRING@50..56 "\"some\""
+                R_PAREN@56..57 ")"
+              R_BRACK@57..58 "]"
+            WHITESPACE@58..67 "\n        "
+            WILDCARD_PAT@67..68
+              UNDERSCORE@67..68 "_"
+            WHITESPACE@68..69 " "
+            FAT_ARROW@69..71 "=>"
+            WHITESPACE@71..72 " "
+            TUPLE_EXPR@72..74
+              L_PAREN@72..73 "("
+              R_PAREN@73..74 ")"
+          COMMA@74..75 ","
+          WHITESPACE@75..84 "\n        "
+          MATCH_ARM@84..125
+            ATTR@84..109
+              POUND@84..85 "#"
+              L_BRACK@85..86 "["
+              PATH@86..89
+                PATH_SEGMENT@86..89
+                  NAME_REF@86..89
+                    IDENT@86..89 "cfg"
+              TOKEN_TREE@89..108
+                L_PAREN@89..90 "("
+                IDENT@90..97 "feature"
+                WHITESPACE@97..98 " "
+                EQ@98..99 "="
+                WHITESPACE@99..100 " "
+                STRING@100..107 "\"other\""
+                R_PAREN@107..108 ")"
+              R_BRACK@108..109 "]"
+            WHITESPACE@109..118 "\n        "
+            WILDCARD_PAT@118..119
+              UNDERSCORE@118..119 "_"
+            WHITESPACE@119..120 " "
+            FAT_ARROW@120..122 "=>"
+            WHITESPACE@122..123 " "
+            TUPLE_EXPR@123..125
+              L_PAREN@123..124 "("
+              R_PAREN@124..125 ")"
+          COMMA@125..126 ","
+          WHITESPACE@126..135 "\n        "
+          MATCH_ARM@135..249
+            ATTR@135..159
+              POUND@135..136 "#"
+              L_BRACK@136..137 "["
+              PATH@137..140
+                PATH_SEGMENT@137..140
+                  NAME_REF@137..140
+                    IDENT@137..140 "cfg"
+              TOKEN_TREE@140..158
+                L_PAREN@140..141 "("
+                IDENT@141..148 "feature"
+                WHITESPACE@148..149 " "
+                EQ@149..150 "="
+                WHITESPACE@150..151 " "
+                STRING@151..157 "\"many\""
+                R_PAREN@157..158 ")"
+              R_BRACK@158..159 "]"
+            WHITESPACE@159..168 "\n        "
+            ATTR@168..198
+              POUND@168..169 "#"
+              L_BRACK@169..170 "["
+              PATH@170..173
+                PATH_SEGMENT@170..173
+                  NAME_REF@170..173
+                    IDENT@170..173 "cfg"
+              TOKEN_TREE@173..197
+                L_PAREN@173..174 "("
+                IDENT@174..181 "feature"
+                WHITESPACE@181..182 " "
+                EQ@182..183 "="
+                WHITESPACE@183..184 " "
+                STRING@184..196 "\"attributes\""
+                R_PAREN@196..197 ")"
+              R_BRACK@197..198 "]"
+            WHITESPACE@198..207 "\n        "
+            ATTR@207..233
+              POUND@207..208 "#"
+              L_BRACK@208..209 "["
+              PATH@209..212
+                PATH_SEGMENT@209..212
+                  NAME_REF@209..212
+                    IDENT@209..212 "cfg"
+              TOKEN_TREE@212..232
+                L_PAREN@212..213 "("
+                IDENT@213..220 "feature"
+                WHITESPACE@220..221 " "
+                EQ@221..222 "="
+                WHITESPACE@222..223 " "
+                STRING@223..231 "\"before\""
+                R_PAREN@231..232 ")"
+              R_BRACK@232..233 "]"
+            WHITESPACE@233..242 "\n        "
+            WILDCARD_PAT@242..243
+              UNDERSCORE@242..243 "_"
+            WHITESPACE@243..244 " "
+            FAT_ARROW@244..246 "=>"
+            WHITESPACE@246..247 " "
+            TUPLE_EXPR@247..249
+              L_PAREN@247..248 "("
+              R_PAREN@248..249 ")"
+          COMMA@249..250 ","
+          WHITESPACE@250..255 "\n    "
+          R_CURLY@255..256 "}"
+      WHITESPACE@256..257 "\n"
+      R_CURLY@257..258 "}"
+  WHITESPACE@258..259 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0121_match_arms_outer_attributes.rs b/crates/syntax/test_data/parser/inline/ok/0121_match_arms_outer_attributes.rs
new file mode 100644
index 00000000000..676db42d1a7
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0121_match_arms_outer_attributes.rs
@@ -0,0 +1,12 @@
+fn foo() {
+    match () {
+        #[cfg(feature = "some")]
+        _ => (),
+        #[cfg(feature = "other")]
+        _ => (),
+        #[cfg(feature = "many")]
+        #[cfg(feature = "attributes")]
+        #[cfg(feature = "before")]
+        _ => (),
+    }
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.rast b/crates/syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.rast
new file mode 100644
index 00000000000..570b9520526
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.rast
@@ -0,0 +1,65 @@
+SOURCE_FILE@0..64
+  FN@0..63
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    GENERIC_PARAM_LIST@6..49
+      L_ANGLE@6..7 "<"
+      LIFETIME_PARAM@7..29
+        ATTR@7..26
+          POUND@7..8 "#"
+          L_BRACK@8..9 "["
+          PATH@9..15
+            PATH_SEGMENT@9..15
+              NAME_REF@9..15
+                IDENT@9..15 "derive"
+          TOKEN_TREE@15..25
+            L_PAREN@15..16 "("
+            IDENT@16..24 "Lifetime"
+            R_PAREN@24..25 ")"
+          R_BRACK@25..26 "]"
+        WHITESPACE@26..27 " "
+        LIFETIME@27..29 "\'a"
+      COMMA@29..30 ","
+      WHITESPACE@30..31 " "
+      TYPE_PARAM@31..48
+        ATTR@31..46
+          POUND@31..32 "#"
+          L_BRACK@32..33 "["
+          PATH@33..39
+            PATH_SEGMENT@33..39
+              NAME_REF@33..39
+                IDENT@33..39 "derive"
+          TOKEN_TREE@39..45
+            L_PAREN@39..40 "("
+            IDENT@40..44 "Type"
+            R_PAREN@44..45 ")"
+          R_BRACK@45..46 "]"
+        WHITESPACE@46..47 " "
+        NAME@47..48
+          IDENT@47..48 "T"
+      R_ANGLE@48..49 ">"
+    PARAM_LIST@49..59
+      L_PAREN@49..50 "("
+      PARAM@50..58
+        WILDCARD_PAT@50..51
+          UNDERSCORE@50..51 "_"
+        COLON@51..52 ":"
+        WHITESPACE@52..53 " "
+        REF_TYPE@53..58
+          AMP@53..54 "&"
+          LIFETIME@54..56 "\'a"
+          WHITESPACE@56..57 " "
+          PATH_TYPE@57..58
+            PATH@57..58
+              PATH_SEGMENT@57..58
+                NAME_REF@57..58
+                  IDENT@57..58 "T"
+      R_PAREN@58..59 ")"
+    WHITESPACE@59..60 " "
+    BLOCK_EXPR@60..63
+      L_CURLY@60..61 "{"
+      WHITESPACE@61..62 "\n"
+      R_CURLY@62..63 "}"
+  WHITESPACE@63..64 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.rs b/crates/syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.rs
new file mode 100644
index 00000000000..e8fdf741fb9
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.rs
@@ -0,0 +1,2 @@
+fn foo<#[derive(Lifetime)] 'a, #[derive(Type)] T>(_: &'a T) {
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0123_param_list_vararg.rast b/crates/syntax/test_data/parser/inline/ok/0123_param_list_vararg.rast
new file mode 100644
index 00000000000..7cdec663473
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0123_param_list_vararg.rast
@@ -0,0 +1,50 @@
+SOURCE_FILE@0..57
+  EXTERN_BLOCK@0..56
+    ABI@0..10
+      EXTERN_KW@0..6 "extern"
+      WHITESPACE@6..7 " "
+      STRING@7..10 "\"C\""
+    WHITESPACE@10..11 " "
+    EXTERN_ITEM_LIST@11..56
+      L_CURLY@11..12 "{"
+      WHITESPACE@12..13 " "
+      FN@13..54
+        FN_KW@13..15 "fn"
+        WHITESPACE@15..16 " "
+        NAME@16..22
+          IDENT@16..22 "printf"
+        PARAM_LIST@22..46
+          L_PAREN@22..23 "("
+          PARAM@23..40
+            IDENT_PAT@23..29
+              NAME@23..29
+                IDENT@23..29 "format"
+            COLON@29..30 ":"
+            WHITESPACE@30..31 " "
+            PTR_TYPE@31..40
+              STAR@31..32 "*"
+              CONST_KW@32..37 "const"
+              WHITESPACE@37..38 " "
+              PATH_TYPE@38..40
+                PATH@38..40
+                  PATH_SEGMENT@38..40
+                    NAME_REF@38..40
+                      IDENT@38..40 "i8"
+          COMMA@40..41 ","
+          WHITESPACE@41..42 " "
+          PARAM@42..45
+            DOT3@42..45 "..."
+          R_PAREN@45..46 ")"
+        WHITESPACE@46..47 " "
+        RET_TYPE@47..53
+          THIN_ARROW@47..49 "->"
+          WHITESPACE@49..50 " "
+          PATH_TYPE@50..53
+            PATH@50..53
+              PATH_SEGMENT@50..53
+                NAME_REF@50..53
+                  IDENT@50..53 "i32"
+        SEMICOLON@53..54 ";"
+      WHITESPACE@54..55 " "
+      R_CURLY@55..56 "}"
+  WHITESPACE@56..57 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0123_param_list_vararg.rs b/crates/syntax/test_data/parser/inline/ok/0123_param_list_vararg.rs
new file mode 100644
index 00000000000..c59addaf420
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0123_param_list_vararg.rs
@@ -0,0 +1 @@
+extern "C" { fn printf(format: *const i8, ...) -> i32; }
diff --git a/crates/syntax/test_data/parser/inline/ok/0125_crate_keyword_path.rast b/crates/syntax/test_data/parser/inline/ok/0125_crate_keyword_path.rast
new file mode 100644
index 00000000000..aa4d7a784f4
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0125_crate_keyword_path.rast
@@ -0,0 +1,31 @@
+SOURCE_FILE@0..27
+  FN@0..26
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..26
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..11 " "
+      EXPR_STMT@11..24
+        CALL_EXPR@11..23
+          PATH_EXPR@11..21
+            PATH@11..21
+              PATH@11..16
+                PATH_SEGMENT@11..16
+                  CRATE_KW@11..16 "crate"
+              COLON2@16..18 "::"
+              PATH_SEGMENT@18..21
+                NAME_REF@18..21
+                  IDENT@18..21 "foo"
+          ARG_LIST@21..23
+            L_PAREN@21..22 "("
+            R_PAREN@22..23 ")"
+        SEMICOLON@23..24 ";"
+      WHITESPACE@24..25 " "
+      R_CURLY@25..26 "}"
+  WHITESPACE@26..27 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0125_crate_keyword_path.rs b/crates/syntax/test_data/parser/inline/ok/0125_crate_keyword_path.rs
new file mode 100644
index 00000000000..0f454d121d6
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0125_crate_keyword_path.rs
@@ -0,0 +1 @@
+fn foo() { crate::foo(); }
diff --git a/crates/syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rast b/crates/syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rast
new file mode 100644
index 00000000000..54ea2c7c669
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rast
@@ -0,0 +1,47 @@
+SOURCE_FILE@0..46
+  FN@0..45
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..45
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      RECORD_EXPR@16..43
+        PATH@16..17
+          PATH_SEGMENT@16..17
+            NAME_REF@16..17
+              IDENT@16..17 "S"
+        WHITESPACE@17..18 " "
+        RECORD_EXPR_FIELD_LIST@18..43
+          L_CURLY@18..19 "{"
+          WHITESPACE@19..20 " "
+          RECORD_EXPR_FIELD@20..41
+            ATTR@20..32
+              POUND@20..21 "#"
+              L_BRACK@21..22 "["
+              PATH@22..25
+                PATH_SEGMENT@22..25
+                  NAME_REF@22..25
+                    IDENT@22..25 "cfg"
+              TOKEN_TREE@25..31
+                L_PAREN@25..26 "("
+                IDENT@26..30 "test"
+                R_PAREN@30..31 ")"
+              R_BRACK@31..32 "]"
+            WHITESPACE@32..33 " "
+            NAME_REF@33..38
+              IDENT@33..38 "field"
+            COLON@38..39 ":"
+            WHITESPACE@39..40 " "
+            LITERAL@40..41
+              INT_NUMBER@40..41 "1"
+          WHITESPACE@41..42 " "
+          R_CURLY@42..43 "}"
+      WHITESPACE@43..44 "\n"
+      R_CURLY@44..45 "}"
+  WHITESPACE@45..46 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rs b/crates/syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rs
new file mode 100644
index 00000000000..a6c7760c767
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rs
@@ -0,0 +1,3 @@
+fn main() {
+    S { #[cfg(test)] field: 1 }
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.rast b/crates/syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.rast
new file mode 100644
index 00000000000..0342e64f396
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.rast
@@ -0,0 +1,97 @@
+SOURCE_FILE@0..82
+  FN@0..81
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..81
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..26
+        ATTR@15..19
+          POUND@15..16 "#"
+          L_BRACK@16..17 "["
+          PATH@17..18
+            PATH_SEGMENT@17..18
+              NAME_REF@17..18
+                IDENT@17..18 "A"
+          R_BRACK@18..19 "]"
+        WHITESPACE@19..20 " "
+        CALL_EXPR@20..25
+          PATH_EXPR@20..23
+            PATH@20..23
+              PATH_SEGMENT@20..23
+                NAME_REF@20..23
+                  IDENT@20..23 "foo"
+          ARG_LIST@23..25
+            L_PAREN@23..24 "("
+            R_PAREN@24..25 ")"
+        SEMICOLON@25..26 ";"
+      WHITESPACE@26..31 "\n    "
+      EXPR_STMT@31..42
+        ATTR@31..35
+          POUND@31..32 "#"
+          L_BRACK@32..33 "["
+          PATH@33..34
+            PATH_SEGMENT@33..34
+              NAME_REF@33..34
+                IDENT@33..34 "B"
+          R_BRACK@34..35 "]"
+        WHITESPACE@35..36 " "
+        MACRO_CALL@36..42
+          PATH@36..39
+            PATH_SEGMENT@36..39
+              NAME_REF@36..39
+                IDENT@36..39 "bar"
+          BANG@39..40 "!"
+          TOKEN_TREE@40..42
+            L_CURLY@40..41 "{"
+            R_CURLY@41..42 "}"
+      WHITESPACE@42..47 "\n    "
+      EXPR_STMT@47..59
+        ATTR@47..51
+          POUND@47..48 "#"
+          L_BRACK@48..49 "["
+          PATH@49..50
+            PATH_SEGMENT@49..50
+              NAME_REF@49..50
+                IDENT@49..50 "C"
+          R_BRACK@50..51 "]"
+        WHITESPACE@51..52 " "
+        ATTR@52..56
+          POUND@52..53 "#"
+          L_BRACK@53..54 "["
+          PATH@54..55
+            PATH_SEGMENT@54..55
+              NAME_REF@54..55
+                IDENT@54..55 "D"
+          R_BRACK@55..56 "]"
+        WHITESPACE@56..57 " "
+        BLOCK_EXPR@57..59
+          L_CURLY@57..58 "{"
+          R_CURLY@58..59 "}"
+      WHITESPACE@59..64 "\n    "
+      EXPR_STMT@64..79
+        ATTR@64..68
+          POUND@64..65 "#"
+          L_BRACK@65..66 "["
+          PATH@66..67
+            PATH_SEGMENT@66..67
+              NAME_REF@66..67
+                IDENT@66..67 "D"
+          R_BRACK@67..68 "]"
+        WHITESPACE@68..69 " "
+        RETURN_EXPR@69..78
+          RETURN_KW@69..75 "return"
+          WHITESPACE@75..76 " "
+          TUPLE_EXPR@76..78
+            L_PAREN@76..77 "("
+            R_PAREN@77..78 ")"
+        SEMICOLON@78..79 ";"
+      WHITESPACE@79..80 "\n"
+      R_CURLY@80..81 "}"
+  WHITESPACE@81..82 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.rs b/crates/syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.rs
new file mode 100644
index 00000000000..b28c078f935
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.rs
@@ -0,0 +1,6 @@
+fn foo() {
+    #[A] foo();
+    #[B] bar!{}
+    #[C] #[D] {}
+    #[D] return ();
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.rast b/crates/syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.rast
new file mode 100644
index 00000000000..3b46e5b479d
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.rast
@@ -0,0 +1,57 @@
+SOURCE_FILE@0..47
+  FN@0..46
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..46
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..31
+        BLOCK_EXPR@15..31
+          L_CURLY@15..16 "{"
+          WHITESPACE@16..17 " "
+          TRY_EXPR@17..29
+            ATTR@17..21
+              POUND@17..18 "#"
+              L_BRACK@18..19 "["
+              PATH@19..20
+                PATH_SEGMENT@19..20
+                  NAME_REF@19..20
+                    IDENT@19..20 "A"
+              R_BRACK@20..21 "]"
+            WHITESPACE@21..22 " "
+            MACRO_CALL@22..28
+              PATH@22..25
+                PATH_SEGMENT@22..25
+                  NAME_REF@22..25
+                    IDENT@22..25 "bar"
+              BANG@25..26 "!"
+              TOKEN_TREE@26..28
+                L_PAREN@26..27 "("
+                R_PAREN@27..28 ")"
+            QUESTION@28..29 "?"
+          WHITESPACE@29..30 " "
+          R_CURLY@30..31 "}"
+      WHITESPACE@31..36 "\n    "
+      REF_EXPR@36..44
+        ATTR@36..40
+          POUND@36..37 "#"
+          L_BRACK@37..38 "["
+          PATH@38..39
+            PATH_SEGMENT@38..39
+              NAME_REF@38..39
+                IDENT@38..39 "B"
+          R_BRACK@39..40 "]"
+        WHITESPACE@40..41 " "
+        AMP@41..42 "&"
+        TUPLE_EXPR@42..44
+          L_PAREN@42..43 "("
+          R_PAREN@43..44 ")"
+      WHITESPACE@44..45 "\n"
+      R_CURLY@45..46 "}"
+  WHITESPACE@46..47 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.rs b/crates/syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.rs
new file mode 100644
index 00000000000..9c5c8eb3615
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.rs
@@ -0,0 +1,4 @@
+fn foo() {
+    { #[A] bar!()? }
+    #[B] &()
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0129_marco_pat.rast b/crates/syntax/test_data/parser/inline/ok/0129_marco_pat.rast
new file mode 100644
index 00000000000..e283966ca23
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0129_marco_pat.rast
@@ -0,0 +1,36 @@
+SOURCE_FILE@0..33
+  FN@0..32
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..32
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      LET_STMT@16..30
+        LET_KW@16..19 "let"
+        WHITESPACE@19..20 " "
+        MACRO_PAT@20..25
+          MACRO_CALL@20..25
+            PATH@20..21
+              PATH_SEGMENT@20..21
+                NAME_REF@20..21
+                  IDENT@20..21 "m"
+            BANG@21..22 "!"
+            TOKEN_TREE@22..25
+              L_PAREN@22..23 "("
+              IDENT@23..24 "x"
+              R_PAREN@24..25 ")"
+        WHITESPACE@25..26 " "
+        EQ@26..27 "="
+        WHITESPACE@27..28 " "
+        LITERAL@28..29
+          INT_NUMBER@28..29 "0"
+        SEMICOLON@29..30 ";"
+      WHITESPACE@30..31 "\n"
+      R_CURLY@31..32 "}"
+  WHITESPACE@32..33 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0129_marco_pat.rs b/crates/syntax/test_data/parser/inline/ok/0129_marco_pat.rs
new file mode 100644
index 00000000000..811181d9ba8
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0129_marco_pat.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let m!(x) = 0;
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0130_let_stmt.rast b/crates/syntax/test_data/parser/inline/ok/0130_let_stmt.rast
new file mode 100644
index 00000000000..4c07cefa6d7
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0130_let_stmt.rast
@@ -0,0 +1,126 @@
+SOURCE_FILE@0..135
+  FN@0..134
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..134
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      LET_STMT@15..21
+        LET_KW@15..18 "let"
+        WHITESPACE@18..19 " "
+        IDENT_PAT@19..20
+          NAME@19..20
+            IDENT@19..20 "a"
+        SEMICOLON@20..21 ";"
+      WHITESPACE@21..26 "\n    "
+      LET_STMT@26..37
+        LET_KW@26..29 "let"
+        WHITESPACE@29..30 " "
+        IDENT_PAT@30..31
+          NAME@30..31
+            IDENT@30..31 "b"
+        COLON@31..32 ":"
+        WHITESPACE@32..33 " "
+        PATH_TYPE@33..36
+          PATH@33..36
+            PATH_SEGMENT@33..36
+              NAME_REF@33..36
+                IDENT@33..36 "i32"
+        SEMICOLON@36..37 ";"
+      WHITESPACE@37..42 "\n    "
+      LET_STMT@42..53
+        LET_KW@42..45 "let"
+        WHITESPACE@45..46 " "
+        IDENT_PAT@46..47
+          NAME@46..47
+            IDENT@46..47 "c"
+        WHITESPACE@47..48 " "
+        EQ@48..49 "="
+        WHITESPACE@49..50 " "
+        LITERAL@50..52
+          INT_NUMBER@50..52 "92"
+        SEMICOLON@52..53 ";"
+      WHITESPACE@53..58 "\n    "
+      LET_STMT@58..74
+        LET_KW@58..61 "let"
+        WHITESPACE@61..62 " "
+        IDENT_PAT@62..63
+          NAME@62..63
+            IDENT@62..63 "d"
+        COLON@63..64 ":"
+        WHITESPACE@64..65 " "
+        PATH_TYPE@65..68
+          PATH@65..68
+            PATH_SEGMENT@65..68
+              NAME_REF@65..68
+                IDENT@65..68 "i32"
+        WHITESPACE@68..69 " "
+        EQ@69..70 "="
+        WHITESPACE@70..71 " "
+        LITERAL@71..73
+          INT_NUMBER@71..73 "92"
+        SEMICOLON@73..74 ";"
+      WHITESPACE@74..79 "\n    "
+      LET_STMT@79..88
+        LET_KW@79..82 "let"
+        WHITESPACE@82..83 " "
+        IDENT_PAT@83..84
+          NAME@83..84
+            IDENT@83..84 "e"
+        COLON@84..85 ":"
+        WHITESPACE@85..86 " "
+        NEVER_TYPE@86..87
+          BANG@86..87 "!"
+        SEMICOLON@87..88 ";"
+      WHITESPACE@88..93 "\n    "
+      LET_STMT@93..107
+        LET_KW@93..96 "let"
+        WHITESPACE@96..97 " "
+        WILDCARD_PAT@97..98
+          UNDERSCORE@97..98 "_"
+        COLON@98..99 ":"
+        WHITESPACE@99..100 " "
+        NEVER_TYPE@100..101
+          BANG@100..101 "!"
+        WHITESPACE@101..102 " "
+        EQ@102..103 "="
+        WHITESPACE@103..104 " "
+        BLOCK_EXPR@104..106
+          L_CURLY@104..105 "{"
+          R_CURLY@105..106 "}"
+        SEMICOLON@106..107 ";"
+      WHITESPACE@107..112 "\n    "
+      LET_STMT@112..132
+        LET_KW@112..115 "let"
+        WHITESPACE@115..116 " "
+        IDENT_PAT@116..117
+          NAME@116..117
+            IDENT@116..117 "f"
+        WHITESPACE@117..118 " "
+        EQ@118..119 "="
+        WHITESPACE@119..120 " "
+        CLOSURE_EXPR@120..131
+          ATTR@120..127
+            POUND@120..121 "#"
+            L_BRACK@121..122 "["
+            PATH@122..126
+              PATH_SEGMENT@122..126
+                NAME_REF@122..126
+                  IDENT@122..126 "attr"
+            R_BRACK@126..127 "]"
+          PARAM_LIST@127..129
+            PIPE@127..128 "|"
+            PIPE@128..129 "|"
+          BLOCK_EXPR@129..131
+            L_CURLY@129..130 "{"
+            R_CURLY@130..131 "}"
+        SEMICOLON@131..132 ";"
+      WHITESPACE@132..133 "\n"
+      R_CURLY@133..134 "}"
+  WHITESPACE@134..135 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0130_let_stmt.rs b/crates/syntax/test_data/parser/inline/ok/0130_let_stmt.rs
new file mode 100644
index 00000000000..fa8ee49a231
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0130_let_stmt.rs
@@ -0,0 +1,9 @@
+fn foo() {
+    let a;
+    let b: i32;
+    let c = 92;
+    let d: i32 = 92;
+    let e: !;
+    let _: ! = {};
+    let f = #[attr]||{};
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0130_try_block_expr.rast b/crates/syntax/test_data/parser/inline/ok/0130_try_block_expr.rast
new file mode 100644
index 00000000000..ffdffe2f801
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0130_try_block_expr.rast
@@ -0,0 +1,31 @@
+SOURCE_FILE@0..33
+  FN@0..32
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..32
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      LET_STMT@15..30
+        LET_KW@15..18 "let"
+        WHITESPACE@18..19 " "
+        WILDCARD_PAT@19..20
+          UNDERSCORE@19..20 "_"
+        WHITESPACE@20..21 " "
+        EQ@21..22 "="
+        WHITESPACE@22..23 " "
+        EFFECT_EXPR@23..29
+          TRY_KW@23..26 "try"
+          WHITESPACE@26..27 " "
+          BLOCK_EXPR@27..29
+            L_CURLY@27..28 "{"
+            R_CURLY@28..29 "}"
+        SEMICOLON@29..30 ";"
+      WHITESPACE@30..31 "\n"
+      R_CURLY@31..32 "}"
+  WHITESPACE@32..33 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0130_try_block_expr.rs b/crates/syntax/test_data/parser/inline/ok/0130_try_block_expr.rs
new file mode 100644
index 00000000000..0f1b41eb64b
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0130_try_block_expr.rs
@@ -0,0 +1,3 @@
+fn foo() {
+    let _ = try {};
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0131_existential_type.rast b/crates/syntax/test_data/parser/inline/ok/0131_existential_type.rast
new file mode 100644
index 00000000000..d47071a911a
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0131_existential_type.rast
@@ -0,0 +1,31 @@
+SOURCE_FILE@0..37
+  TYPE_ALIAS@0..36
+    EXISTENTIAL_KW@0..11 "existential"
+    WHITESPACE@11..12 " "
+    TYPE_KW@12..16 "type"
+    WHITESPACE@16..17 " "
+    NAME@17..20
+      IDENT@17..20 "Foo"
+    COLON@20..21 ":"
+    WHITESPACE@21..22 " "
+    TYPE_BOUND_LIST@22..35
+      TYPE_BOUND@22..35
+        PATH_TYPE@22..35
+          PATH@22..35
+            PATH_SEGMENT@22..35
+              NAME_REF@22..24
+                IDENT@22..24 "Fn"
+              PARAM_LIST@24..26
+                L_PAREN@24..25 "("
+                R_PAREN@25..26 ")"
+              WHITESPACE@26..27 " "
+              RET_TYPE@27..35
+                THIN_ARROW@27..29 "->"
+                WHITESPACE@29..30 " "
+                PATH_TYPE@30..35
+                  PATH@30..35
+                    PATH_SEGMENT@30..35
+                      NAME_REF@30..35
+                        IDENT@30..35 "usize"
+    SEMICOLON@35..36 ";"
+  WHITESPACE@36..37 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0131_existential_type.rs b/crates/syntax/test_data/parser/inline/ok/0131_existential_type.rs
new file mode 100644
index 00000000000..23baf7145cc
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0131_existential_type.rs
@@ -0,0 +1 @@
+existential type Foo: Fn() -> usize;
diff --git a/crates/syntax/test_data/parser/inline/ok/0132_box_expr.rast b/crates/syntax/test_data/parser/inline/ok/0132_box_expr.rast
new file mode 100644
index 00000000000..c5503824729
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0132_box_expr.rast
@@ -0,0 +1,89 @@
+SOURCE_FILE@0..106
+  FN@0..105
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..105
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      LET_STMT@15..32
+        LET_KW@15..18 "let"
+        WHITESPACE@18..19 " "
+        IDENT_PAT@19..20
+          NAME@19..20
+            IDENT@19..20 "x"
+        WHITESPACE@20..21 " "
+        EQ@21..22 "="
+        WHITESPACE@22..23 " "
+        BOX_EXPR@23..31
+          BOX_KW@23..26 "box"
+          WHITESPACE@26..27 " "
+          LITERAL@27..31
+            INT_NUMBER@27..31 "1i32"
+        SEMICOLON@31..32 ";"
+      WHITESPACE@32..37 "\n    "
+      LET_STMT@37..66
+        LET_KW@37..40 "let"
+        WHITESPACE@40..41 " "
+        IDENT_PAT@41..42
+          NAME@41..42
+            IDENT@41..42 "y"
+        WHITESPACE@42..43 " "
+        EQ@43..44 "="
+        WHITESPACE@44..45 " "
+        TUPLE_EXPR@45..65
+          L_PAREN@45..46 "("
+          BOX_EXPR@46..54
+            BOX_KW@46..49 "box"
+            WHITESPACE@49..50 " "
+            LITERAL@50..54
+              INT_NUMBER@50..54 "1i32"
+          COMMA@54..55 ","
+          WHITESPACE@55..56 " "
+          BOX_EXPR@56..64
+            BOX_KW@56..59 "box"
+            WHITESPACE@59..60 " "
+            LITERAL@60..64
+              INT_NUMBER@60..64 "2i32"
+          R_PAREN@64..65 ")"
+        SEMICOLON@65..66 ";"
+      WHITESPACE@66..71 "\n    "
+      LET_STMT@71..103
+        LET_KW@71..74 "let"
+        WHITESPACE@74..75 " "
+        IDENT_PAT@75..76
+          NAME@75..76
+            IDENT@75..76 "z"
+        WHITESPACE@76..77 " "
+        EQ@77..78 "="
+        WHITESPACE@78..79 " "
+        CALL_EXPR@79..102
+          PATH_EXPR@79..82
+            PATH@79..82
+              PATH_SEGMENT@79..82
+                NAME_REF@79..82
+                  IDENT@79..82 "Foo"
+          ARG_LIST@82..102
+            L_PAREN@82..83 "("
+            BOX_EXPR@83..91
+              BOX_KW@83..86 "box"
+              WHITESPACE@86..87 " "
+              LITERAL@87..91
+                INT_NUMBER@87..91 "1i32"
+            COMMA@91..92 ","
+            WHITESPACE@92..93 " "
+            BOX_EXPR@93..101
+              BOX_KW@93..96 "box"
+              WHITESPACE@96..97 " "
+              LITERAL@97..101
+                INT_NUMBER@97..101 "2i32"
+            R_PAREN@101..102 ")"
+        SEMICOLON@102..103 ";"
+      WHITESPACE@103..104 "\n"
+      R_CURLY@104..105 "}"
+  WHITESPACE@105..106 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0132_box_expr.rs b/crates/syntax/test_data/parser/inline/ok/0132_box_expr.rs
new file mode 100644
index 00000000000..fc9923b7137
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0132_box_expr.rs
@@ -0,0 +1,5 @@
+fn foo() {
+    let x = box 1i32;
+    let y = (box 1i32, box 2i32);
+    let z = Foo(box 1i32, box 2i32);
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.rast b/crates/syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.rast
new file mode 100644
index 00000000000..429a0506e1a
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.rast
@@ -0,0 +1,62 @@
+SOURCE_FILE@0..111
+  FN@0..110
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..18
+      IDENT@3..18 "simple_function"
+    PARAM_LIST@18..20
+      L_PAREN@18..19 "("
+      R_PAREN@19..20 ")"
+    WHITESPACE@20..21 " "
+    BLOCK_EXPR@21..110
+      L_CURLY@21..22 "{"
+      WHITESPACE@22..27 "\n    "
+      ENUM@27..75
+        ENUM_KW@27..31 "enum"
+        WHITESPACE@31..32 " "
+        NAME@32..41
+          IDENT@32..41 "LocalEnum"
+        WHITESPACE@41..42 " "
+        VARIANT_LIST@42..75
+          L_CURLY@42..43 "{"
+          WHITESPACE@43..52 "\n        "
+          VARIANT@52..55
+            NAME@52..55
+              IDENT@52..55 "One"
+          COMMA@55..56 ","
+          WHITESPACE@56..65 "\n        "
+          VARIANT@65..68
+            NAME@65..68
+              IDENT@65..68 "Two"
+          COMMA@68..69 ","
+          WHITESPACE@69..74 "\n    "
+          R_CURLY@74..75 "}"
+      SEMICOLON@75..76 ";"
+      WHITESPACE@76..81 "\n    "
+      FN@81..90
+        FN_KW@81..83 "fn"
+        WHITESPACE@83..84 " "
+        NAME@84..85
+          IDENT@84..85 "f"
+        PARAM_LIST@85..87
+          L_PAREN@85..86 "("
+          R_PAREN@86..87 ")"
+        WHITESPACE@87..88 " "
+        BLOCK_EXPR@88..90
+          L_CURLY@88..89 "{"
+          R_CURLY@89..90 "}"
+      SEMICOLON@90..91 ";"
+      WHITESPACE@91..96 "\n    "
+      STRUCT@96..107
+        STRUCT_KW@96..102 "struct"
+        WHITESPACE@102..103 " "
+        NAME@103..104
+          IDENT@103..104 "S"
+        WHITESPACE@104..105 " "
+        RECORD_FIELD_LIST@105..107
+          L_CURLY@105..106 "{"
+          R_CURLY@106..107 "}"
+      SEMICOLON@107..108 ";"
+      WHITESPACE@108..109 "\n"
+      R_CURLY@109..110 "}"
+  WHITESPACE@110..111 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.rs b/crates/syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.rs
new file mode 100644
index 00000000000..eadc7fffb13
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.rs
@@ -0,0 +1,8 @@
+fn simple_function() {
+    enum LocalEnum {
+        One,
+        Two,
+    };
+    fn f() {};
+    struct S {};
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0137_await_expr.rast b/crates/syntax/test_data/parser/inline/ok/0137_await_expr.rast
new file mode 100644
index 00000000000..923effe3831
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0137_await_expr.rast
@@ -0,0 +1,69 @@
+SOURCE_FILE@0..67
+  FN@0..66
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..66
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..23
+        AWAIT_EXPR@15..22
+          PATH_EXPR@15..16
+            PATH@15..16
+              PATH_SEGMENT@15..16
+                NAME_REF@15..16
+                  IDENT@15..16 "x"
+          DOT@16..17 "."
+          AWAIT_KW@17..22 "await"
+        SEMICOLON@22..23 ";"
+      WHITESPACE@23..28 "\n    "
+      EXPR_STMT@28..38
+        AWAIT_EXPR@28..37
+          FIELD_EXPR@28..31
+            PATH_EXPR@28..29
+              PATH@28..29
+                PATH_SEGMENT@28..29
+                  NAME_REF@28..29
+                    IDENT@28..29 "x"
+            DOT@29..30 "."
+            NAME_REF@30..31
+              INT_NUMBER@30..31 "0"
+          DOT@31..32 "."
+          AWAIT_KW@32..37 "await"
+        SEMICOLON@37..38 ";"
+      WHITESPACE@38..43 "\n    "
+      EXPR_STMT@43..64
+        METHOD_CALL_EXPR@43..63
+          TRY_EXPR@43..55
+            AWAIT_EXPR@43..54
+              CALL_EXPR@43..48
+                FIELD_EXPR@43..46
+                  PATH_EXPR@43..44
+                    PATH@43..44
+                      PATH_SEGMENT@43..44
+                        NAME_REF@43..44
+                          IDENT@43..44 "x"
+                  DOT@44..45 "."
+                  NAME_REF@45..46
+                    INT_NUMBER@45..46 "0"
+                ARG_LIST@46..48
+                  L_PAREN@46..47 "("
+                  R_PAREN@47..48 ")"
+              DOT@48..49 "."
+              AWAIT_KW@49..54 "await"
+            QUESTION@54..55 "?"
+          DOT@55..56 "."
+          NAME_REF@56..61
+            IDENT@56..61 "hello"
+          ARG_LIST@61..63
+            L_PAREN@61..62 "("
+            R_PAREN@62..63 ")"
+        SEMICOLON@63..64 ";"
+      WHITESPACE@64..65 "\n"
+      R_CURLY@65..66 "}"
+  WHITESPACE@66..67 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0137_await_expr.rs b/crates/syntax/test_data/parser/inline/ok/0137_await_expr.rs
new file mode 100644
index 00000000000..d2ba89ca607
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0137_await_expr.rs
@@ -0,0 +1,5 @@
+fn foo() {
+    x.await;
+    x.0.await;
+    x.0().await?.hello();
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0138_associated_type_bounds.rast b/crates/syntax/test_data/parser/inline/ok/0138_associated_type_bounds.rast
new file mode 100644
index 00000000000..3870ec1353d
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0138_associated_type_bounds.rast
@@ -0,0 +1,55 @@
+SOURCE_FILE@0..59
+  FN@0..58
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..12
+      IDENT@3..12 "print_all"
+    GENERIC_PARAM_LIST@12..40
+      L_ANGLE@12..13 "<"
+      TYPE_PARAM@13..39
+        NAME@13..14
+          IDENT@13..14 "T"
+        COLON@14..15 ":"
+        WHITESPACE@15..16 " "
+        TYPE_BOUND_LIST@16..39
+          TYPE_BOUND@16..39
+            PATH_TYPE@16..39
+              PATH@16..39
+                PATH_SEGMENT@16..39
+                  NAME_REF@16..24
+                    IDENT@16..24 "Iterator"
+                  GENERIC_ARG_LIST@24..39
+                    L_ANGLE@24..25 "<"
+                    ASSOC_TYPE_ARG@25..38
+                      NAME_REF@25..29
+                        IDENT@25..29 "Item"
+                      COLON@29..30 ":"
+                      WHITESPACE@30..31 " "
+                      TYPE_BOUND_LIST@31..38
+                        TYPE_BOUND@31..38
+                          PATH_TYPE@31..38
+                            PATH@31..38
+                              PATH_SEGMENT@31..38
+                                NAME_REF@31..38
+                                  IDENT@31..38 "Display"
+                    R_ANGLE@38..39 ">"
+      R_ANGLE@39..40 ">"
+    PARAM_LIST@40..55
+      L_PAREN@40..41 "("
+      PARAM@41..54
+        IDENT_PAT@41..51
+          NAME@41..51
+            IDENT@41..51 "printables"
+        COLON@51..52 ":"
+        WHITESPACE@52..53 " "
+        PATH_TYPE@53..54
+          PATH@53..54
+            PATH_SEGMENT@53..54
+              NAME_REF@53..54
+                IDENT@53..54 "T"
+      R_PAREN@54..55 ")"
+    WHITESPACE@55..56 " "
+    BLOCK_EXPR@56..58
+      L_CURLY@56..57 "{"
+      R_CURLY@57..58 "}"
+  WHITESPACE@58..59 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0138_associated_type_bounds.rs b/crates/syntax/test_data/parser/inline/ok/0138_associated_type_bounds.rs
new file mode 100644
index 00000000000..eb21a657b90
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0138_associated_type_bounds.rs
@@ -0,0 +1 @@
+fn print_all<T: Iterator<Item: Display>>(printables: T) {}
diff --git a/crates/syntax/test_data/parser/inline/ok/0138_expression_after_block.rast b/crates/syntax/test_data/parser/inline/ok/0138_expression_after_block.rast
new file mode 100644
index 00000000000..f7c0e0ab0b7
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0138_expression_after_block.rast
@@ -0,0 +1,64 @@
+SOURCE_FILE@0..52
+  FN@0..51
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..51
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..14 "\n   "
+      LET_STMT@14..34
+        LET_KW@14..17 "let"
+        WHITESPACE@17..18 " "
+        IDENT_PAT@18..23
+          MUT_KW@18..21 "mut"
+          WHITESPACE@21..22 " "
+          NAME@22..23
+            IDENT@22..23 "p"
+        WHITESPACE@23..24 " "
+        EQ@24..25 "="
+        WHITESPACE@25..26 " "
+        RECORD_EXPR@26..33
+          PATH@26..27
+            PATH_SEGMENT@26..27
+              NAME_REF@26..27
+                IDENT@26..27 "F"
+          RECORD_EXPR_FIELD_LIST@27..33
+            L_CURLY@27..28 "{"
+            RECORD_EXPR_FIELD@28..32
+              NAME_REF@28..29
+                IDENT@28..29 "x"
+              COLON@29..30 ":"
+              WHITESPACE@30..31 " "
+              LITERAL@31..32
+                INT_NUMBER@31..32 "5"
+            R_CURLY@32..33 "}"
+        SEMICOLON@33..34 ";"
+      WHITESPACE@34..38 "\n   "
+      EXPR_STMT@38..49
+        BIN_EXPR@38..48
+          FIELD_EXPR@38..43
+            BLOCK_EXPR@38..41
+              L_CURLY@38..39 "{"
+              PATH_EXPR@39..40
+                PATH@39..40
+                  PATH_SEGMENT@39..40
+                    NAME_REF@39..40
+                      IDENT@39..40 "p"
+              R_CURLY@40..41 "}"
+            DOT@41..42 "."
+            NAME_REF@42..43
+              IDENT@42..43 "x"
+          WHITESPACE@43..44 " "
+          EQ@44..45 "="
+          WHITESPACE@45..46 " "
+          LITERAL@46..48
+            INT_NUMBER@46..48 "10"
+        SEMICOLON@48..49 ";"
+      WHITESPACE@49..50 "\n"
+      R_CURLY@50..51 "}"
+  WHITESPACE@51..52 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0138_expression_after_block.rs b/crates/syntax/test_data/parser/inline/ok/0138_expression_after_block.rs
new file mode 100644
index 00000000000..76007e3ee77
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0138_expression_after_block.rs
@@ -0,0 +1,4 @@
+fn foo() {
+   let mut p = F{x: 5};
+   {p}.x = 10;
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast b/crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast
new file mode 100644
index 00000000000..6403ff8d5c7
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast
@@ -0,0 +1,25 @@
+SOURCE_FILE@0..26
+  FN@0..25
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..4
+      IDENT@3..4 "f"
+    PARAM_LIST@4..22
+      L_PAREN@4..5 "("
+      ATTR@5..16
+        POUND@5..6 "#"
+        L_BRACK@6..7 "["
+        PATH@7..15
+          PATH_SEGMENT@7..15
+            NAME_REF@7..15
+              IDENT@7..15 "must_use"
+        R_BRACK@15..16 "]"
+      WHITESPACE@16..17 " "
+      SELF_PARAM@17..21
+        SELF_KW@17..21 "self"
+      R_PAREN@21..22 ")"
+    WHITESPACE@22..23 " "
+    BLOCK_EXPR@23..25
+      L_CURLY@23..24 "{"
+      R_CURLY@24..25 "}"
+  WHITESPACE@25..26 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rs b/crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rs
new file mode 100644
index 00000000000..35155057a68
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rs
@@ -0,0 +1 @@
+fn f(#[must_use] self) {}
diff --git a/crates/syntax/test_data/parser/inline/ok/0139_param_outer_arg.rast b/crates/syntax/test_data/parser/inline/ok/0139_param_outer_arg.rast
new file mode 100644
index 00000000000..495e4c51b58
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0139_param_outer_arg.rast
@@ -0,0 +1,34 @@
+SOURCE_FILE@0..28
+  FN@0..27
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..4
+      IDENT@3..4 "f"
+    PARAM_LIST@4..24
+      L_PAREN@4..5 "("
+      ATTR@5..13
+        POUND@5..6 "#"
+        L_BRACK@6..7 "["
+        PATH@7..12
+          PATH_SEGMENT@7..12
+            NAME_REF@7..12
+              IDENT@7..12 "attr1"
+        R_BRACK@12..13 "]"
+      WHITESPACE@13..14 " "
+      PARAM@14..23
+        IDENT_PAT@14..17
+          NAME@14..17
+            IDENT@14..17 "pat"
+        COLON@17..18 ":"
+        WHITESPACE@18..19 " "
+        PATH_TYPE@19..23
+          PATH@19..23
+            PATH_SEGMENT@19..23
+              NAME_REF@19..23
+                IDENT@19..23 "Type"
+      R_PAREN@23..24 ")"
+    WHITESPACE@24..25 " "
+    BLOCK_EXPR@25..27
+      L_CURLY@25..26 "{"
+      R_CURLY@26..27 "}"
+  WHITESPACE@27..28 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0139_param_outer_arg.rs b/crates/syntax/test_data/parser/inline/ok/0139_param_outer_arg.rs
new file mode 100644
index 00000000000..c238be791bd
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0139_param_outer_arg.rs
@@ -0,0 +1 @@
+fn f(#[attr1] pat: Type) {}
diff --git a/crates/syntax/test_data/parser/inline/ok/0142_for_range_from.rast b/crates/syntax/test_data/parser/inline/ok/0142_for_range_from.rast
new file mode 100644
index 00000000000..36e448c94ee
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0142_for_range_from.rast
@@ -0,0 +1,40 @@
+SOURCE_FILE@0..51
+  FN@0..50
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..50
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..14 "\n   "
+      FOR_EXPR@14..48
+        FOR_KW@14..17 "for"
+        WHITESPACE@17..18 " "
+        IDENT_PAT@18..19
+          NAME@18..19
+            IDENT@18..19 "x"
+        WHITESPACE@19..20 " "
+        IN_KW@20..22 "in"
+        WHITESPACE@22..23 " "
+        RANGE_EXPR@23..27
+          LITERAL@23..24
+            INT_NUMBER@23..24 "0"
+          WHITESPACE@24..25 " "
+          DOT2@25..27 ".."
+        WHITESPACE@27..28 " "
+        BLOCK_EXPR@28..48
+          L_CURLY@28..29 "{"
+          WHITESPACE@29..37 "\n       "
+          EXPR_STMT@37..43
+            BREAK_EXPR@37..42
+              BREAK_KW@37..42 "break"
+            SEMICOLON@42..43 ";"
+          WHITESPACE@43..47 "\n   "
+          R_CURLY@47..48 "}"
+      WHITESPACE@48..49 "\n"
+      R_CURLY@49..50 "}"
+  WHITESPACE@50..51 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0142_for_range_from.rs b/crates/syntax/test_data/parser/inline/ok/0142_for_range_from.rs
new file mode 100644
index 00000000000..af0d40a7aa2
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0142_for_range_from.rs
@@ -0,0 +1,5 @@
+fn foo() {
+   for x in 0 .. {
+       break;
+   }
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0143_box_pat.rast b/crates/syntax/test_data/parser/inline/ok/0143_box_pat.rast
new file mode 100644
index 00000000000..65887b96216
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0143_box_pat.rast
@@ -0,0 +1,110 @@
+SOURCE_FILE@0..118
+  FN@0..117
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..117
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      LET_STMT@16..31
+        LET_KW@16..19 "let"
+        WHITESPACE@19..20 " "
+        BOX_PAT@20..25
+          BOX_KW@20..23 "box"
+          WHITESPACE@23..24 " "
+          IDENT_PAT@24..25
+            NAME@24..25
+              IDENT@24..25 "i"
+        WHITESPACE@25..26 " "
+        EQ@26..27 "="
+        WHITESPACE@27..28 " "
+        TUPLE_EXPR@28..30
+          L_PAREN@28..29 "("
+          R_PAREN@29..30 ")"
+        SEMICOLON@30..31 ";"
+      WHITESPACE@31..36 "\n    "
+      LET_STMT@36..87
+        LET_KW@36..39 "let"
+        WHITESPACE@39..40 " "
+        BOX_PAT@40..81
+          BOX_KW@40..43 "box"
+          WHITESPACE@43..44 " "
+          RECORD_PAT@44..81
+            PATH@44..49
+              PATH_SEGMENT@44..49
+                NAME_REF@44..49
+                  IDENT@44..49 "Outer"
+            WHITESPACE@49..50 " "
+            RECORD_PAT_FIELD_LIST@50..81
+              L_CURLY@50..51 "{"
+              WHITESPACE@51..52 " "
+              RECORD_PAT_FIELD@52..57
+                BOX_PAT@52..57
+                  BOX_KW@52..55 "box"
+                  WHITESPACE@55..56 " "
+                  IDENT_PAT@56..57
+                    NAME@56..57
+                      IDENT@56..57 "i"
+              COMMA@57..58 ","
+              WHITESPACE@58..59 " "
+              RECORD_PAT_FIELD@59..79
+                NAME_REF@59..60
+                  IDENT@59..60 "j"
+                COLON@60..61 ":"
+                WHITESPACE@61..62 " "
+                BOX_PAT@62..79
+                  BOX_KW@62..65 "box"
+                  WHITESPACE@65..66 " "
+                  TUPLE_STRUCT_PAT@66..79
+                    PATH@66..71
+                      PATH_SEGMENT@66..71
+                        NAME_REF@66..71
+                          IDENT@66..71 "Inner"
+                    L_PAREN@71..72 "("
+                    BOX_PAT@72..78
+                      BOX_KW@72..75 "box"
+                      WHITESPACE@75..76 " "
+                      REF_PAT@76..78
+                        AMP@76..77 "&"
+                        IDENT_PAT@77..78
+                          NAME@77..78
+                            IDENT@77..78 "x"
+                    R_PAREN@78..79 ")"
+              WHITESPACE@79..80 " "
+              R_CURLY@80..81 "}"
+        WHITESPACE@81..82 " "
+        EQ@82..83 "="
+        WHITESPACE@83..84 " "
+        TUPLE_EXPR@84..86
+          L_PAREN@84..85 "("
+          R_PAREN@85..86 ")"
+        SEMICOLON@86..87 ";"
+      WHITESPACE@87..92 "\n    "
+      LET_STMT@92..115
+        LET_KW@92..95 "let"
+        WHITESPACE@95..96 " "
+        BOX_PAT@96..109
+          BOX_KW@96..99 "box"
+          WHITESPACE@99..100 " "
+          IDENT_PAT@100..109
+            REF_KW@100..103 "ref"
+            WHITESPACE@103..104 " "
+            MUT_KW@104..107 "mut"
+            WHITESPACE@107..108 " "
+            NAME@108..109
+              IDENT@108..109 "i"
+        WHITESPACE@109..110 " "
+        EQ@110..111 "="
+        WHITESPACE@111..112 " "
+        TUPLE_EXPR@112..114
+          L_PAREN@112..113 "("
+          R_PAREN@113..114 ")"
+        SEMICOLON@114..115 ";"
+      WHITESPACE@115..116 "\n"
+      R_CURLY@116..117 "}"
+  WHITESPACE@117..118 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0143_box_pat.rs b/crates/syntax/test_data/parser/inline/ok/0143_box_pat.rs
new file mode 100644
index 00000000000..9d458aa1e6b
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0143_box_pat.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let box i = ();
+    let box Outer { box i, j: box Inner(box &x) } = ();
+    let box ref mut i = ();
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0144_dot_dot_pat.rast b/crates/syntax/test_data/parser/inline/ok/0144_dot_dot_pat.rast
new file mode 100644
index 00000000000..8a5bde0b6af
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0144_dot_dot_pat.rast
@@ -0,0 +1,455 @@
+SOURCE_FILE@0..555
+  FN@0..554
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..554
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      LET_STMT@16..28
+        LET_KW@16..19 "let"
+        WHITESPACE@19..20 " "
+        REST_PAT@20..22
+          DOT2@20..22 ".."
+        WHITESPACE@22..23 " "
+        EQ@23..24 "="
+        WHITESPACE@24..25 " "
+        TUPLE_EXPR@25..27
+          L_PAREN@25..26 "("
+          R_PAREN@26..27 ")"
+        SEMICOLON@27..28 ";"
+      WHITESPACE@28..33 "\n    "
+      COMMENT@33..35 "//"
+      WHITESPACE@35..40 "\n    "
+      COMMENT@40..49 "// Tuples"
+      WHITESPACE@49..54 "\n    "
+      COMMENT@54..56 "//"
+      WHITESPACE@56..61 "\n    "
+      LET_STMT@61..78
+        LET_KW@61..64 "let"
+        WHITESPACE@64..65 " "
+        TUPLE_PAT@65..72
+          L_PAREN@65..66 "("
+          IDENT_PAT@66..67
+            NAME@66..67
+              IDENT@66..67 "a"
+          COMMA@67..68 ","
+          WHITESPACE@68..69 " "
+          REST_PAT@69..71
+            DOT2@69..71 ".."
+          R_PAREN@71..72 ")"
+        WHITESPACE@72..73 " "
+        EQ@73..74 "="
+        WHITESPACE@74..75 " "
+        TUPLE_EXPR@75..77
+          L_PAREN@75..76 "("
+          R_PAREN@76..77 ")"
+        SEMICOLON@77..78 ";"
+      WHITESPACE@78..83 "\n    "
+      LET_STMT@83..101
+        LET_KW@83..86 "let"
+        WHITESPACE@86..87 " "
+        TUPLE_PAT@87..95
+          L_PAREN@87..88 "("
+          IDENT_PAT@88..89
+            NAME@88..89
+              IDENT@88..89 "a"
+          COMMA@89..90 ","
+          WHITESPACE@90..91 " "
+          REST_PAT@91..93
+            DOT2@91..93 ".."
+          COMMA@93..94 ","
+          R_PAREN@94..95 ")"
+        WHITESPACE@95..96 " "
+        EQ@96..97 "="
+        WHITESPACE@97..98 " "
+        TUPLE_EXPR@98..100
+          L_PAREN@98..99 "("
+          R_PAREN@99..100 ")"
+        SEMICOLON@100..101 ";"
+      WHITESPACE@101..106 "\n    "
+      LET_STMT@106..128
+        LET_KW@106..109 "let"
+        WHITESPACE@109..110 " "
+        TUPLE_STRUCT_PAT@110..122
+          PATH@110..115
+            PATH_SEGMENT@110..115
+              NAME_REF@110..115
+                IDENT@110..115 "Tuple"
+          L_PAREN@115..116 "("
+          IDENT_PAT@116..117
+            NAME@116..117
+              IDENT@116..117 "a"
+          COMMA@117..118 ","
+          WHITESPACE@118..119 " "
+          REST_PAT@119..121
+            DOT2@119..121 ".."
+          R_PAREN@121..122 ")"
+        WHITESPACE@122..123 " "
+        EQ@123..124 "="
+        WHITESPACE@124..125 " "
+        TUPLE_EXPR@125..127
+          L_PAREN@125..126 "("
+          R_PAREN@126..127 ")"
+        SEMICOLON@127..128 ";"
+      WHITESPACE@128..133 "\n    "
+      LET_STMT@133..156
+        LET_KW@133..136 "let"
+        WHITESPACE@136..137 " "
+        TUPLE_STRUCT_PAT@137..150
+          PATH@137..142
+            PATH_SEGMENT@137..142
+              NAME_REF@137..142
+                IDENT@137..142 "Tuple"
+          L_PAREN@142..143 "("
+          IDENT_PAT@143..144
+            NAME@143..144
+              IDENT@143..144 "a"
+          COMMA@144..145 ","
+          WHITESPACE@145..146 " "
+          REST_PAT@146..148
+            DOT2@146..148 ".."
+          COMMA@148..149 ","
+          R_PAREN@149..150 ")"
+        WHITESPACE@150..151 " "
+        EQ@151..152 "="
+        WHITESPACE@152..153 " "
+        TUPLE_EXPR@153..155
+          L_PAREN@153..154 "("
+          R_PAREN@154..155 ")"
+        SEMICOLON@155..156 ";"
+      WHITESPACE@156..161 "\n    "
+      LET_STMT@161..179
+        LET_KW@161..164 "let"
+        WHITESPACE@164..165 " "
+        TUPLE_PAT@165..173
+          L_PAREN@165..166 "("
+          REST_PAT@166..168
+            DOT2@166..168 ".."
+          COMMA@168..169 ","
+          WHITESPACE@169..170 " "
+          REST_PAT@170..172
+            DOT2@170..172 ".."
+          R_PAREN@172..173 ")"
+        WHITESPACE@173..174 " "
+        EQ@174..175 "="
+        WHITESPACE@175..176 " "
+        TUPLE_EXPR@176..178
+          L_PAREN@176..177 "("
+          R_PAREN@177..178 ")"
+        SEMICOLON@178..179 ";"
+      WHITESPACE@179..184 "\n    "
+      LET_STMT@184..207
+        LET_KW@184..187 "let"
+        WHITESPACE@187..188 " "
+        TUPLE_STRUCT_PAT@188..201
+          PATH@188..193
+            PATH_SEGMENT@188..193
+              NAME_REF@188..193
+                IDENT@188..193 "Tuple"
+          L_PAREN@193..194 "("
+          REST_PAT@194..196
+            DOT2@194..196 ".."
+          COMMA@196..197 ","
+          WHITESPACE@197..198 " "
+          REST_PAT@198..200
+            DOT2@198..200 ".."
+          R_PAREN@200..201 ")"
+        WHITESPACE@201..202 " "
+        EQ@202..203 "="
+        WHITESPACE@203..204 " "
+        TUPLE_EXPR@204..206
+          L_PAREN@204..205 "("
+          R_PAREN@205..206 ")"
+        SEMICOLON@206..207 ";"
+      WHITESPACE@207..212 "\n    "
+      LET_STMT@212..233
+        LET_KW@212..215 "let"
+        WHITESPACE@215..216 " "
+        TUPLE_PAT@216..227
+          L_PAREN@216..217 "("
+          REST_PAT@217..219
+            DOT2@217..219 ".."
+          COMMA@219..220 ","
+          WHITESPACE@220..221 " "
+          IDENT_PAT@221..222
+            NAME@221..222
+              IDENT@221..222 "a"
+          COMMA@222..223 ","
+          WHITESPACE@223..224 " "
+          REST_PAT@224..226
+            DOT2@224..226 ".."
+          R_PAREN@226..227 ")"
+        WHITESPACE@227..228 " "
+        EQ@228..229 "="
+        WHITESPACE@229..230 " "
+        TUPLE_EXPR@230..232
+          L_PAREN@230..231 "("
+          R_PAREN@231..232 ")"
+        SEMICOLON@232..233 ";"
+      WHITESPACE@233..238 "\n    "
+      LET_STMT@238..264
+        LET_KW@238..241 "let"
+        WHITESPACE@241..242 " "
+        TUPLE_STRUCT_PAT@242..258
+          PATH@242..247
+            PATH_SEGMENT@242..247
+              NAME_REF@242..247
+                IDENT@242..247 "Tuple"
+          L_PAREN@247..248 "("
+          REST_PAT@248..250
+            DOT2@248..250 ".."
+          COMMA@250..251 ","
+          WHITESPACE@251..252 " "
+          IDENT_PAT@252..253
+            NAME@252..253
+              IDENT@252..253 "a"
+          COMMA@253..254 ","
+          WHITESPACE@254..255 " "
+          REST_PAT@255..257
+            DOT2@255..257 ".."
+          R_PAREN@257..258 ")"
+        WHITESPACE@258..259 " "
+        EQ@259..260 "="
+        WHITESPACE@260..261 " "
+        TUPLE_EXPR@261..263
+          L_PAREN@261..262 "("
+          R_PAREN@262..263 ")"
+        SEMICOLON@263..264 ";"
+      WHITESPACE@264..269 "\n    "
+      COMMENT@269..271 "//"
+      WHITESPACE@271..276 "\n    "
+      COMMENT@276..285 "// Slices"
+      WHITESPACE@285..290 "\n    "
+      COMMENT@290..292 "//"
+      WHITESPACE@292..297 "\n    "
+      LET_STMT@297..311
+        LET_KW@297..300 "let"
+        WHITESPACE@300..301 " "
+        SLICE_PAT@301..305
+          L_BRACK@301..302 "["
+          REST_PAT@302..304
+            DOT2@302..304 ".."
+          R_BRACK@304..305 "]"
+        WHITESPACE@305..306 " "
+        EQ@306..307 "="
+        WHITESPACE@307..308 " "
+        TUPLE_EXPR@308..310
+          L_PAREN@308..309 "("
+          R_PAREN@309..310 ")"
+        SEMICOLON@310..311 ";"
+      WHITESPACE@311..316 "\n    "
+      LET_STMT@316..336
+        LET_KW@316..319 "let"
+        WHITESPACE@319..320 " "
+        SLICE_PAT@320..330
+          L_BRACK@320..321 "["
+          IDENT_PAT@321..325
+            NAME@321..325
+              IDENT@321..325 "head"
+          COMMA@325..326 ","
+          WHITESPACE@326..327 " "
+          REST_PAT@327..329
+            DOT2@327..329 ".."
+          R_BRACK@329..330 "]"
+        WHITESPACE@330..331 " "
+        EQ@331..332 "="
+        WHITESPACE@332..333 " "
+        TUPLE_EXPR@333..335
+          L_PAREN@333..334 "("
+          R_PAREN@334..335 ")"
+        SEMICOLON@335..336 ";"
+      WHITESPACE@336..341 "\n    "
+      LET_STMT@341..368
+        LET_KW@341..344 "let"
+        WHITESPACE@344..345 " "
+        SLICE_PAT@345..362
+          L_BRACK@345..346 "["
+          IDENT_PAT@346..350
+            NAME@346..350
+              IDENT@346..350 "head"
+          COMMA@350..351 ","
+          WHITESPACE@351..352 " "
+          IDENT_PAT@352..361
+            NAME@352..356
+              IDENT@352..356 "tail"
+            WHITESPACE@356..357 " "
+            AT@357..358 "@"
+            WHITESPACE@358..359 " "
+            REST_PAT@359..361
+              DOT2@359..361 ".."
+          R_BRACK@361..362 "]"
+        WHITESPACE@362..363 " "
+        EQ@363..364 "="
+        WHITESPACE@364..365 " "
+        TUPLE_EXPR@365..367
+          L_PAREN@365..366 "("
+          R_PAREN@366..367 ")"
+        SEMICOLON@367..368 ";"
+      WHITESPACE@368..373 "\n    "
+      LET_STMT@373..399
+        LET_KW@373..376 "let"
+        WHITESPACE@376..377 " "
+        SLICE_PAT@377..393
+          L_BRACK@377..378 "["
+          IDENT_PAT@378..382
+            NAME@378..382
+              IDENT@378..382 "head"
+          COMMA@382..383 ","
+          WHITESPACE@383..384 " "
+          REST_PAT@384..386
+            DOT2@384..386 ".."
+          COMMA@386..387 ","
+          WHITESPACE@387..388 " "
+          IDENT_PAT@388..392
+            NAME@388..392
+              IDENT@388..392 "cons"
+          R_BRACK@392..393 "]"
+        WHITESPACE@393..394 " "
+        EQ@394..395 "="
+        WHITESPACE@395..396 " "
+        TUPLE_EXPR@396..398
+          L_PAREN@396..397 "("
+          R_PAREN@397..398 ")"
+        SEMICOLON@398..399 ";"
+      WHITESPACE@399..404 "\n    "
+      LET_STMT@404..436
+        LET_KW@404..407 "let"
+        WHITESPACE@407..408 " "
+        SLICE_PAT@408..430
+          L_BRACK@408..409 "["
+          IDENT_PAT@409..413
+            NAME@409..413
+              IDENT@409..413 "head"
+          COMMA@413..414 ","
+          WHITESPACE@414..415 " "
+          IDENT_PAT@415..423
+            NAME@415..418
+              IDENT@415..418 "mid"
+            WHITESPACE@418..419 " "
+            AT@419..420 "@"
+            WHITESPACE@420..421 " "
+            REST_PAT@421..423
+              DOT2@421..423 ".."
+          COMMA@423..424 ","
+          WHITESPACE@424..425 " "
+          IDENT_PAT@425..429
+            NAME@425..429
+              IDENT@425..429 "cons"
+          R_BRACK@429..430 "]"
+        WHITESPACE@430..431 " "
+        EQ@431..432 "="
+        WHITESPACE@432..433 " "
+        TUPLE_EXPR@433..435
+          L_PAREN@433..434 "("
+          R_PAREN@434..435 ")"
+        SEMICOLON@435..436 ";"
+      WHITESPACE@436..441 "\n    "
+      LET_STMT@441..471
+        LET_KW@441..444 "let"
+        WHITESPACE@444..445 " "
+        SLICE_PAT@445..465
+          L_BRACK@445..446 "["
+          IDENT_PAT@446..450
+            NAME@446..450
+              IDENT@446..450 "head"
+          COMMA@450..451 ","
+          WHITESPACE@451..452 " "
+          REST_PAT@452..454
+            DOT2@452..454 ".."
+          COMMA@454..455 ","
+          WHITESPACE@455..456 " "
+          REST_PAT@456..458
+            DOT2@456..458 ".."
+          COMMA@458..459 ","
+          WHITESPACE@459..460 " "
+          IDENT_PAT@460..464
+            NAME@460..464
+              IDENT@460..464 "cons"
+          R_BRACK@464..465 "]"
+        WHITESPACE@465..466 " "
+        EQ@466..467 "="
+        WHITESPACE@467..468 " "
+        TUPLE_EXPR@468..470
+          L_PAREN@468..469 "("
+          R_PAREN@469..470 ")"
+        SEMICOLON@470..471 ";"
+      WHITESPACE@471..476 "\n    "
+      LET_STMT@476..512
+        LET_KW@476..479 "let"
+        WHITESPACE@479..480 " "
+        SLICE_PAT@480..506
+          L_BRACK@480..481 "["
+          IDENT_PAT@481..485
+            NAME@481..485
+              IDENT@481..485 "head"
+          COMMA@485..486 ","
+          WHITESPACE@486..487 " "
+          REST_PAT@487..489
+            DOT2@487..489 ".."
+          COMMA@489..490 ","
+          WHITESPACE@490..491 " "
+          IDENT_PAT@491..494
+            NAME@491..494
+              IDENT@491..494 "mid"
+          COMMA@494..495 ","
+          WHITESPACE@495..496 " "
+          IDENT_PAT@496..505
+            NAME@496..500
+              IDENT@496..500 "tail"
+            WHITESPACE@500..501 " "
+            AT@501..502 "@"
+            WHITESPACE@502..503 " "
+            REST_PAT@503..505
+              DOT2@503..505 ".."
+          R_BRACK@505..506 "]"
+        WHITESPACE@506..507 " "
+        EQ@507..508 "="
+        WHITESPACE@508..509 " "
+        TUPLE_EXPR@509..511
+          L_PAREN@509..510 "("
+          R_PAREN@510..511 ")"
+        SEMICOLON@511..512 ";"
+      WHITESPACE@512..517 "\n    "
+      LET_STMT@517..552
+        LET_KW@517..520 "let"
+        WHITESPACE@520..521 " "
+        SLICE_PAT@521..546
+          L_BRACK@521..522 "["
+          IDENT_PAT@522..526
+            NAME@522..526
+              IDENT@522..526 "head"
+          COMMA@526..527 ","
+          WHITESPACE@527..528 " "
+          REST_PAT@528..530
+            DOT2@528..530 ".."
+          COMMA@530..531 ","
+          WHITESPACE@531..532 " "
+          IDENT_PAT@532..535
+            NAME@532..535
+              IDENT@532..535 "mid"
+          COMMA@535..536 ","
+          WHITESPACE@536..537 " "
+          REST_PAT@537..539
+            DOT2@537..539 ".."
+          COMMA@539..540 ","
+          WHITESPACE@540..541 " "
+          IDENT_PAT@541..545
+            NAME@541..545
+              IDENT@541..545 "cons"
+          R_BRACK@545..546 "]"
+        WHITESPACE@546..547 " "
+        EQ@547..548 "="
+        WHITESPACE@548..549 " "
+        TUPLE_EXPR@549..551
+          L_PAREN@549..550 "("
+          R_PAREN@550..551 ")"
+        SEMICOLON@551..552 ";"
+      WHITESPACE@552..553 "\n"
+      R_CURLY@553..554 "}"
+  WHITESPACE@554..555 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0144_dot_dot_pat.rs b/crates/syntax/test_data/parser/inline/ok/0144_dot_dot_pat.rs
new file mode 100644
index 00000000000..3262f27e140
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0144_dot_dot_pat.rs
@@ -0,0 +1,25 @@
+fn main() {
+    let .. = ();
+    //
+    // Tuples
+    //
+    let (a, ..) = ();
+    let (a, ..,) = ();
+    let Tuple(a, ..) = ();
+    let Tuple(a, ..,) = ();
+    let (.., ..) = ();
+    let Tuple(.., ..) = ();
+    let (.., a, ..) = ();
+    let Tuple(.., a, ..) = ();
+    //
+    // Slices
+    //
+    let [..] = ();
+    let [head, ..] = ();
+    let [head, tail @ ..] = ();
+    let [head, .., cons] = ();
+    let [head, mid @ .., cons] = ();
+    let [head, .., .., cons] = ();
+    let [head, .., mid, tail @ ..] = ();
+    let [head, .., mid, .., cons] = ();
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0145_record_field_pat.rast b/crates/syntax/test_data/parser/inline/ok/0145_record_field_pat.rast
new file mode 100644
index 00000000000..925409bdfe3
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0145_record_field_pat.rast
@@ -0,0 +1,75 @@
+SOURCE_FILE@0..63
+  FN@0..62
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..62
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      LET_STMT@15..35
+        LET_KW@15..18 "let"
+        WHITESPACE@18..19 " "
+        RECORD_PAT@19..29
+          PATH@19..20
+            PATH_SEGMENT@19..20
+              NAME_REF@19..20
+                IDENT@19..20 "S"
+          WHITESPACE@20..21 " "
+          RECORD_PAT_FIELD_LIST@21..29
+            L_CURLY@21..22 "{"
+            WHITESPACE@22..23 " "
+            RECORD_PAT_FIELD@23..27
+              NAME_REF@23..24
+                INT_NUMBER@23..24 "0"
+              COLON@24..25 ":"
+              WHITESPACE@25..26 " "
+              LITERAL_PAT@26..27
+                LITERAL@26..27
+                  INT_NUMBER@26..27 "1"
+            WHITESPACE@27..28 " "
+            R_CURLY@28..29 "}"
+        WHITESPACE@29..30 " "
+        EQ@30..31 "="
+        WHITESPACE@31..32 " "
+        TUPLE_EXPR@32..34
+          L_PAREN@32..33 "("
+          R_PAREN@33..34 ")"
+        SEMICOLON@34..35 ";"
+      WHITESPACE@35..40 "\n    "
+      LET_STMT@40..60
+        LET_KW@40..43 "let"
+        WHITESPACE@43..44 " "
+        RECORD_PAT@44..54
+          PATH@44..45
+            PATH_SEGMENT@44..45
+              NAME_REF@44..45
+                IDENT@44..45 "S"
+          WHITESPACE@45..46 " "
+          RECORD_PAT_FIELD_LIST@46..54
+            L_CURLY@46..47 "{"
+            WHITESPACE@47..48 " "
+            RECORD_PAT_FIELD@48..52
+              NAME_REF@48..49
+                IDENT@48..49 "x"
+              COLON@49..50 ":"
+              WHITESPACE@50..51 " "
+              LITERAL_PAT@51..52
+                LITERAL@51..52
+                  INT_NUMBER@51..52 "1"
+            WHITESPACE@52..53 " "
+            R_CURLY@53..54 "}"
+        WHITESPACE@54..55 " "
+        EQ@55..56 "="
+        WHITESPACE@56..57 " "
+        TUPLE_EXPR@57..59
+          L_PAREN@57..58 "("
+          R_PAREN@58..59 ")"
+        SEMICOLON@59..60 ";"
+      WHITESPACE@60..61 "\n"
+      R_CURLY@61..62 "}"
+  WHITESPACE@62..63 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0145_record_field_pat.rs b/crates/syntax/test_data/parser/inline/ok/0145_record_field_pat.rs
new file mode 100644
index 00000000000..26b1d5f8952
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0145_record_field_pat.rs
@@ -0,0 +1,4 @@
+fn foo() {
+    let S { 0: 1 } = ();
+    let S { x: 1 } = ();
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0146_as_precedence.rast b/crates/syntax/test_data/parser/inline/ok/0146_as_precedence.rast
new file mode 100644
index 00000000000..a36cc8dab36
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0146_as_precedence.rast
@@ -0,0 +1,42 @@
+SOURCE_FILE@0..43
+  FN@0..42
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..42
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      LET_STMT@15..40
+        LET_KW@15..18 "let"
+        WHITESPACE@18..19 " "
+        WILDCARD_PAT@19..20
+          UNDERSCORE@19..20 "_"
+        WHITESPACE@20..21 " "
+        EQ@21..22 "="
+        WHITESPACE@22..23 " "
+        CAST_EXPR@23..39
+          REF_EXPR@23..25
+            AMP@23..24 "&"
+            LITERAL@24..25
+              INT_NUMBER@24..25 "1"
+          WHITESPACE@25..26 " "
+          AS_KW@26..28 "as"
+          WHITESPACE@28..29 " "
+          PTR_TYPE@29..39
+            STAR@29..30 "*"
+            CONST_KW@30..35 "const"
+            WHITESPACE@35..36 " "
+            PATH_TYPE@36..39
+              PATH@36..39
+                PATH_SEGMENT@36..39
+                  NAME_REF@36..39
+                    IDENT@36..39 "i32"
+        SEMICOLON@39..40 ";"
+      WHITESPACE@40..41 "\n"
+      R_CURLY@41..42 "}"
+  WHITESPACE@42..43 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0146_as_precedence.rs b/crates/syntax/test_data/parser/inline/ok/0146_as_precedence.rs
new file mode 100644
index 00000000000..a06dec1faf3
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0146_as_precedence.rs
@@ -0,0 +1,3 @@
+fn foo() {
+    let _ = &1 as *const i32;
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0147_const_param.rast b/crates/syntax/test_data/parser/inline/ok/0147_const_param.rast
new file mode 100644
index 00000000000..9312eab65e4
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0147_const_param.rast
@@ -0,0 +1,23 @@
+SOURCE_FILE@0..24
+  STRUCT@0..23
+    STRUCT_KW@0..6 "struct"
+    WHITESPACE@6..7 " "
+    NAME@7..8
+      IDENT@7..8 "S"
+    GENERIC_PARAM_LIST@8..22
+      L_ANGLE@8..9 "<"
+      CONST_PARAM@9..21
+        CONST_KW@9..14 "const"
+        WHITESPACE@14..15 " "
+        NAME@15..16
+          IDENT@15..16 "N"
+        COLON@16..17 ":"
+        WHITESPACE@17..18 " "
+        PATH_TYPE@18..21
+          PATH@18..21
+            PATH_SEGMENT@18..21
+              NAME_REF@18..21
+                IDENT@18..21 "u32"
+      R_ANGLE@21..22 ">"
+    SEMICOLON@22..23 ";"
+  WHITESPACE@23..24 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0147_const_param.rs b/crates/syntax/test_data/parser/inline/ok/0147_const_param.rs
new file mode 100644
index 00000000000..8cdb3b70367
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0147_const_param.rs
@@ -0,0 +1 @@
+struct S<const N: u32>;
diff --git a/crates/syntax/test_data/parser/inline/ok/0147_macro_def.rast b/crates/syntax/test_data/parser/inline/ok/0147_macro_def.rast
new file mode 100644
index 00000000000..6655aeab139
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0147_macro_def.rast
@@ -0,0 +1,45 @@
+SOURCE_FILE@0..50
+  MACRO_DEF@0..28
+    MACRO_KW@0..5 "macro"
+    WHITESPACE@5..6 " "
+    NAME@6..7
+      IDENT@6..7 "m"
+    WHITESPACE@7..8 " "
+    TOKEN_TREE@8..28
+      L_CURLY@8..9 "{"
+      WHITESPACE@9..10 " "
+      TOKEN_TREE@10..20
+        L_PAREN@10..11 "("
+        DOLLAR@11..12 "$"
+        IDENT@12..13 "i"
+        COLON@13..14 ":"
+        IDENT@14..19 "ident"
+        R_PAREN@19..20 ")"
+      WHITESPACE@20..21 " "
+      EQ@21..22 "="
+      R_ANGLE@22..23 ">"
+      WHITESPACE@23..24 " "
+      TOKEN_TREE@24..26
+        L_CURLY@24..25 "{"
+        R_CURLY@25..26 "}"
+      WHITESPACE@26..27 " "
+      R_CURLY@27..28 "}"
+  WHITESPACE@28..29 "\n"
+  MACRO_DEF@29..49
+    MACRO_KW@29..34 "macro"
+    WHITESPACE@34..35 " "
+    NAME@35..36
+      IDENT@35..36 "m"
+    TOKEN_TREE@36..49
+      TOKEN_TREE@36..46
+        L_PAREN@36..37 "("
+        DOLLAR@37..38 "$"
+        IDENT@38..39 "i"
+        COLON@39..40 ":"
+        IDENT@40..45 "ident"
+        R_PAREN@45..46 ")"
+      WHITESPACE@46..47 " "
+      TOKEN_TREE@47..49
+        L_CURLY@47..48 "{"
+        R_CURLY@48..49 "}"
+  WHITESPACE@49..50 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0147_macro_def.rs b/crates/syntax/test_data/parser/inline/ok/0147_macro_def.rs
new file mode 100644
index 00000000000..319a4e2aad2
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0147_macro_def.rs
@@ -0,0 +1,2 @@
+macro m { ($i:ident) => {} }
+macro m($i:ident) {}
diff --git a/crates/syntax/test_data/parser/inline/ok/0148_pub_macro_def.rast b/crates/syntax/test_data/parser/inline/ok/0148_pub_macro_def.rast
new file mode 100644
index 00000000000..1c527f60b9c
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0148_pub_macro_def.rast
@@ -0,0 +1,21 @@
+SOURCE_FILE@0..24
+  MACRO_DEF@0..23
+    VISIBILITY@0..3
+      PUB_KW@0..3 "pub"
+    WHITESPACE@3..4 " "
+    MACRO_KW@4..9 "macro"
+    WHITESPACE@9..10 " "
+    NAME@10..11
+      IDENT@10..11 "m"
+    TOKEN_TREE@11..23
+      TOKEN_TREE@11..20
+        L_PAREN@11..12 "("
+        DOLLAR@12..13 "$"
+        COLON@13..14 ":"
+        IDENT@14..19 "ident"
+        R_PAREN@19..20 ")"
+      WHITESPACE@20..21 " "
+      TOKEN_TREE@21..23
+        L_CURLY@21..22 "{"
+        R_CURLY@22..23 "}"
+  WHITESPACE@23..24 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0148_pub_macro_def.rs b/crates/syntax/test_data/parser/inline/ok/0148_pub_macro_def.rs
new file mode 100644
index 00000000000..3b2be597fd8
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0148_pub_macro_def.rs
@@ -0,0 +1 @@
+pub macro m($:ident) {}
diff --git a/crates/syntax/test_data/parser/inline/ok/0150_array_attrs.rast b/crates/syntax/test_data/parser/inline/ok/0150_array_attrs.rast
new file mode 100644
index 00000000000..f284aafcdfd
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0150_array_attrs.rast
@@ -0,0 +1,47 @@
+SOURCE_FILE@0..40
+  CONST@0..39
+    CONST_KW@0..5 "const"
+    WHITESPACE@5..6 " "
+    NAME@6..7
+      IDENT@6..7 "A"
+    COLON@7..8 ":"
+    WHITESPACE@8..9 " "
+    REF_TYPE@9..15
+      AMP@9..10 "&"
+      SLICE_TYPE@10..15
+        L_BRACK@10..11 "["
+        PATH_TYPE@11..14
+          PATH@11..14
+            PATH_SEGMENT@11..14
+              NAME_REF@11..14
+                IDENT@11..14 "i64"
+        R_BRACK@14..15 "]"
+    WHITESPACE@15..16 " "
+    EQ@16..17 "="
+    WHITESPACE@17..18 " "
+    REF_EXPR@18..38
+      AMP@18..19 "&"
+      ARRAY_EXPR@19..38
+        L_BRACK@19..20 "["
+        LITERAL@20..21
+          INT_NUMBER@20..21 "1"
+        COMMA@21..22 ","
+        WHITESPACE@22..23 " "
+        LITERAL@23..37
+          ATTR@23..35
+            POUND@23..24 "#"
+            L_BRACK@24..25 "["
+            PATH@25..28
+              PATH_SEGMENT@25..28
+                NAME_REF@25..28
+                  IDENT@25..28 "cfg"
+            TOKEN_TREE@28..34
+              L_PAREN@28..29 "("
+              IDENT@29..33 "test"
+              R_PAREN@33..34 ")"
+            R_BRACK@34..35 "]"
+          WHITESPACE@35..36 " "
+          INT_NUMBER@36..37 "2"
+        R_BRACK@37..38 "]"
+    SEMICOLON@38..39 ";"
+  WHITESPACE@39..40 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0150_array_attrs.rs b/crates/syntax/test_data/parser/inline/ok/0150_array_attrs.rs
new file mode 100644
index 00000000000..2ac310924fd
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0150_array_attrs.rs
@@ -0,0 +1 @@
+const A: &[i64] = &[1, #[cfg(test)] 2];
diff --git a/crates/syntax/test_data/parser/inline/ok/0150_impl_type_params.rast b/crates/syntax/test_data/parser/inline/ok/0150_impl_type_params.rast
new file mode 100644
index 00000000000..12194abdafe
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0150_impl_type_params.rast
@@ -0,0 +1,38 @@
+SOURCE_FILE@0..29
+  IMPL@0..28
+    IMPL_KW@0..4 "impl"
+    GENERIC_PARAM_LIST@4..18
+      L_ANGLE@4..5 "<"
+      CONST_PARAM@5..17
+        CONST_KW@5..10 "const"
+        WHITESPACE@10..11 " "
+        NAME@11..12
+          IDENT@11..12 "N"
+        COLON@12..13 ":"
+        WHITESPACE@13..14 " "
+        PATH_TYPE@14..17
+          PATH@14..17
+            PATH_SEGMENT@14..17
+              NAME_REF@14..17
+                IDENT@14..17 "u32"
+      R_ANGLE@17..18 ">"
+    WHITESPACE@18..19 " "
+    PATH_TYPE@19..25
+      PATH@19..25
+        PATH_SEGMENT@19..25
+          NAME_REF@19..22
+            IDENT@19..22 "Bar"
+          GENERIC_ARG_LIST@22..25
+            L_ANGLE@22..23 "<"
+            TYPE_ARG@23..24
+              PATH_TYPE@23..24
+                PATH@23..24
+                  PATH_SEGMENT@23..24
+                    NAME_REF@23..24
+                      IDENT@23..24 "N"
+            R_ANGLE@24..25 ">"
+    WHITESPACE@25..26 " "
+    ASSOC_ITEM_LIST@26..28
+      L_CURLY@26..27 "{"
+      R_CURLY@27..28 "}"
+  WHITESPACE@28..29 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0150_impl_type_params.rs b/crates/syntax/test_data/parser/inline/ok/0150_impl_type_params.rs
new file mode 100644
index 00000000000..cb0a105c29f
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0150_impl_type_params.rs
@@ -0,0 +1 @@
+impl<const N: u32> Bar<N> {}
diff --git a/crates/syntax/test_data/parser/inline/ok/0151_fn.rast b/crates/syntax/test_data/parser/inline/ok/0151_fn.rast
new file mode 100644
index 00000000000..23c4269b306
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0151_fn.rast
@@ -0,0 +1,14 @@
+SOURCE_FILE@0..12
+  FN@0..11
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..11
+      L_CURLY@9..10 "{"
+      R_CURLY@10..11 "}"
+  WHITESPACE@11..12 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0151_fn.rs b/crates/syntax/test_data/parser/inline/ok/0151_fn.rs
new file mode 100644
index 00000000000..8f3b7ef112a
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0151_fn.rs
@@ -0,0 +1 @@
+fn foo() {}
diff --git a/crates/syntax/test_data/parser/inline/ok/0151_trait_alias.rast b/crates/syntax/test_data/parser/inline/ok/0151_trait_alias.rast
new file mode 100644
index 00000000000..dac50410e42
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0151_trait_alias.rast
@@ -0,0 +1,128 @@
+SOURCE_FILE@0..83
+  TRAIT@0..18
+    TRAIT_KW@0..5 "trait"
+    WHITESPACE@5..6 " "
+    NAME@6..7
+      IDENT@6..7 "Z"
+    GENERIC_PARAM_LIST@7..10
+      L_ANGLE@7..8 "<"
+      TYPE_PARAM@8..9
+        NAME@8..9
+          IDENT@8..9 "U"
+      R_ANGLE@9..10 ">"
+    WHITESPACE@10..11 " "
+    EQ@11..12 "="
+    WHITESPACE@12..13 " "
+    TYPE_BOUND_LIST@13..17
+      TYPE_BOUND@13..17
+        PATH_TYPE@13..17
+          PATH@13..17
+            PATH_SEGMENT@13..17
+              NAME_REF@13..14
+                IDENT@13..14 "T"
+              GENERIC_ARG_LIST@14..17
+                L_ANGLE@14..15 "<"
+                TYPE_ARG@15..16
+                  PATH_TYPE@15..16
+                    PATH@15..16
+                      PATH_SEGMENT@15..16
+                        NAME_REF@15..16
+                          IDENT@15..16 "U"
+                R_ANGLE@16..17 ">"
+    SEMICOLON@17..18 ";"
+  WHITESPACE@18..19 "\n"
+  TRAIT@19..51
+    TRAIT_KW@19..24 "trait"
+    WHITESPACE@24..25 " "
+    NAME@25..26
+      IDENT@25..26 "Z"
+    GENERIC_PARAM_LIST@26..29
+      L_ANGLE@26..27 "<"
+      TYPE_PARAM@27..28
+        NAME@27..28
+          IDENT@27..28 "U"
+      R_ANGLE@28..29 ">"
+    WHITESPACE@29..30 " "
+    EQ@30..31 "="
+    WHITESPACE@31..32 " "
+    TYPE_BOUND_LIST@32..36
+      TYPE_BOUND@32..36
+        PATH_TYPE@32..36
+          PATH@32..36
+            PATH_SEGMENT@32..36
+              NAME_REF@32..33
+                IDENT@32..33 "T"
+              GENERIC_ARG_LIST@33..36
+                L_ANGLE@33..34 "<"
+                TYPE_ARG@34..35
+                  PATH_TYPE@34..35
+                    PATH@34..35
+                      PATH_SEGMENT@34..35
+                        NAME_REF@34..35
+                          IDENT@34..35 "U"
+                R_ANGLE@35..36 ">"
+    WHITESPACE@36..37 " "
+    WHERE_CLAUSE@37..50
+      WHERE_KW@37..42 "where"
+      WHITESPACE@42..43 " "
+      WHERE_PRED@43..50
+        PATH_TYPE@43..44
+          PATH@43..44
+            PATH_SEGMENT@43..44
+              NAME_REF@43..44
+                IDENT@43..44 "U"
+        COLON@44..45 ":"
+        WHITESPACE@45..46 " "
+        TYPE_BOUND_LIST@46..50
+          TYPE_BOUND@46..50
+            PATH_TYPE@46..50
+              PATH@46..50
+                PATH_SEGMENT@46..50
+                  NAME_REF@46..50
+                    IDENT@46..50 "Copy"
+    SEMICOLON@50..51 ";"
+  WHITESPACE@51..52 "\n"
+  TRAIT@52..82
+    TRAIT_KW@52..57 "trait"
+    WHITESPACE@57..58 " "
+    NAME@58..59
+      IDENT@58..59 "Z"
+    GENERIC_PARAM_LIST@59..62
+      L_ANGLE@59..60 "<"
+      TYPE_PARAM@60..61
+        NAME@60..61
+          IDENT@60..61 "U"
+      R_ANGLE@61..62 ">"
+    WHITESPACE@62..63 " "
+    EQ@63..64 "="
+    WHITESPACE@64..65 " "
+    TYPE_BOUND_LIST@65..65
+    WHERE_CLAUSE@65..81
+      WHERE_KW@65..70 "where"
+      WHITESPACE@70..71 " "
+      WHERE_PRED@71..81
+        PATH_TYPE@71..75
+          PATH@71..75
+            PATH_SEGMENT@71..75
+              NAME_REF@71..75
+                IDENT@71..75 "Self"
+        COLON@75..76 ":"
+        WHITESPACE@76..77 " "
+        TYPE_BOUND_LIST@77..81
+          TYPE_BOUND@77..81
+            PATH_TYPE@77..81
+              PATH@77..81
+                PATH_SEGMENT@77..81
+                  NAME_REF@77..78
+                    IDENT@77..78 "T"
+                  GENERIC_ARG_LIST@78..81
+                    L_ANGLE@78..79 "<"
+                    TYPE_ARG@79..80
+                      PATH_TYPE@79..80
+                        PATH@79..80
+                          PATH_SEGMENT@79..80
+                            NAME_REF@79..80
+                              IDENT@79..80 "U"
+                    R_ANGLE@80..81 ">"
+    SEMICOLON@81..82 ";"
+  WHITESPACE@82..83 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0151_trait_alias.rs b/crates/syntax/test_data/parser/inline/ok/0151_trait_alias.rs
new file mode 100644
index 00000000000..4bd428ee469
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0151_trait_alias.rs
@@ -0,0 +1,3 @@
+trait Z<U> = T<U>;
+trait Z<U> = T<U> where U: Copy;
+trait Z<U> = where Self: T<U>;
diff --git a/crates/syntax/test_data/parser/inline/ok/0152_arg_with_attr.rast b/crates/syntax/test_data/parser/inline/ok/0152_arg_with_attr.rast
new file mode 100644
index 00000000000..2905c5f1a5d
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0152_arg_with_attr.rast
@@ -0,0 +1,36 @@
+SOURCE_FILE@0..34
+  FN@0..33
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..33
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      CALL_EXPR@16..31
+        PATH_EXPR@16..19
+          PATH@16..19
+            PATH_SEGMENT@16..19
+              NAME_REF@16..19
+                IDENT@16..19 "foo"
+        ARG_LIST@19..31
+          L_PAREN@19..20 "("
+          LITERAL@20..30
+            ATTR@20..27
+              POUND@20..21 "#"
+              L_BRACK@21..22 "["
+              PATH@22..26
+                PATH_SEGMENT@22..26
+                  NAME_REF@22..26
+                    IDENT@22..26 "attr"
+              R_BRACK@26..27 "]"
+            WHITESPACE@27..28 " "
+            INT_NUMBER@28..30 "92"
+          R_PAREN@30..31 ")"
+      WHITESPACE@31..32 "\n"
+      R_CURLY@32..33 "}"
+  WHITESPACE@33..34 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0152_arg_with_attr.rs b/crates/syntax/test_data/parser/inline/ok/0152_arg_with_attr.rs
new file mode 100644
index 00000000000..5daf1d7b0be
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0152_arg_with_attr.rs
@@ -0,0 +1,3 @@
+fn main() {
+    foo(#[attr] 92)
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0152_impl.rast b/crates/syntax/test_data/parser/inline/ok/0152_impl.rast
new file mode 100644
index 00000000000..7968cf9ffa0
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0152_impl.rast
@@ -0,0 +1,22 @@
+SOURCE_FILE@0..16
+  IMPL@0..15
+    IMPL_KW@0..4 "impl"
+    WHITESPACE@4..5 " "
+    PATH_TYPE@5..6
+      PATH@5..6
+        PATH_SEGMENT@5..6
+          NAME_REF@5..6
+            IDENT@5..6 "T"
+    WHITESPACE@6..7 " "
+    FOR_KW@7..10 "for"
+    WHITESPACE@10..11 " "
+    PATH_TYPE@11..12
+      PATH@11..12
+        PATH_SEGMENT@11..12
+          NAME_REF@11..12
+            IDENT@11..12 "S"
+    WHITESPACE@12..13 " "
+    ASSOC_ITEM_LIST@13..15
+      L_CURLY@13..14 "{"
+      R_CURLY@14..15 "}"
+  WHITESPACE@15..16 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0152_impl.rs b/crates/syntax/test_data/parser/inline/ok/0152_impl.rs
new file mode 100644
index 00000000000..a1a550d8a60
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0152_impl.rs
@@ -0,0 +1 @@
+impl T for S {}
diff --git a/crates/syntax/test_data/parser/inline/ok/0153_trait.rast b/crates/syntax/test_data/parser/inline/ok/0153_trait.rast
new file mode 100644
index 00000000000..9881e5048c8
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0153_trait.rast
@@ -0,0 +1,11 @@
+SOURCE_FILE@0..11
+  TRAIT@0..10
+    TRAIT_KW@0..5 "trait"
+    WHITESPACE@5..6 " "
+    NAME@6..7
+      IDENT@6..7 "T"
+    WHITESPACE@7..8 " "
+    ASSOC_ITEM_LIST@8..10
+      L_CURLY@8..9 "{"
+      R_CURLY@9..10 "}"
+  WHITESPACE@10..11 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0153_trait.rs b/crates/syntax/test_data/parser/inline/ok/0153_trait.rs
new file mode 100644
index 00000000000..8d183dbb5d3
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0153_trait.rs
@@ -0,0 +1 @@
+trait T {}
diff --git a/crates/syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rast b/crates/syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rast
new file mode 100644
index 00000000000..e6aff7b3735
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rast
@@ -0,0 +1,58 @@
+SOURCE_FILE@0..55
+  TYPE_ALIAS@0..24
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..8
+      IDENT@5..8 "Foo"
+    WHITESPACE@8..9 " "
+    EQ@9..10 "="
+    WHITESPACE@10..11 " "
+    FN_PTR_TYPE@11..23
+      FN_KW@11..13 "fn"
+      PARAM_LIST@13..23
+        L_PAREN@13..14 "("
+        PARAM@14..22
+          PATH_TYPE@14..22
+            PATH@14..22
+              PATH@14..17
+                PATH_SEGMENT@14..17
+                  NAME_REF@14..17
+                    IDENT@14..17 "Bar"
+              COLON2@17..19 "::"
+              PATH_SEGMENT@19..22
+                NAME_REF@19..22
+                  IDENT@19..22 "Baz"
+        R_PAREN@22..23 ")"
+    SEMICOLON@23..24 ";"
+  WHITESPACE@24..25 "\n"
+  TYPE_ALIAS@25..54
+    TYPE_KW@25..29 "type"
+    WHITESPACE@29..30 " "
+    NAME@30..33
+      IDENT@30..33 "Qux"
+    WHITESPACE@33..34 " "
+    EQ@34..35 "="
+    WHITESPACE@35..36 " "
+    FN_PTR_TYPE@36..53
+      FN_KW@36..38 "fn"
+      PARAM_LIST@38..53
+        L_PAREN@38..39 "("
+        PARAM@39..52
+          IDENT_PAT@39..42
+            NAME@39..42
+              IDENT@39..42 "baz"
+          COLON@42..43 ":"
+          WHITESPACE@43..44 " "
+          PATH_TYPE@44..52
+            PATH@44..52
+              PATH@44..47
+                PATH_SEGMENT@44..47
+                  NAME_REF@44..47
+                    IDENT@44..47 "Bar"
+              COLON2@47..49 "::"
+              PATH_SEGMENT@49..52
+                NAME_REF@49..52
+                  IDENT@49..52 "Baz"
+        R_PAREN@52..53 ")"
+    SEMICOLON@53..54 ";"
+  WHITESPACE@54..55 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rs b/crates/syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rs
new file mode 100644
index 00000000000..80a1701fd66
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rs
@@ -0,0 +1,2 @@
+type Foo = fn(Bar::Baz);
+type Qux = fn(baz: Bar::Baz);
diff --git a/crates/syntax/test_data/parser/inline/ok/0155_closure_params.rast b/crates/syntax/test_data/parser/inline/ok/0155_closure_params.rast
new file mode 100644
index 00000000000..31671b42018
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0155_closure_params.rast
@@ -0,0 +1,69 @@
+SOURCE_FILE@0..63
+  FN@0..62
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..62
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..15 "\n   "
+      LET_STMT@15..60
+        LET_KW@15..18 "let"
+        WHITESPACE@18..19 " "
+        IDENT_PAT@19..22
+          NAME@19..22
+            IDENT@19..22 "foo"
+        WHITESPACE@22..23 " "
+        EQ@23..24 "="
+        WHITESPACE@24..25 " "
+        CLOSURE_EXPR@25..59
+          PARAM_LIST@25..56
+            PIPE@25..26 "|"
+            PARAM@26..29
+              IDENT_PAT@26..29
+                NAME@26..29
+                  IDENT@26..29 "bar"
+            COMMA@29..30 ","
+            WHITESPACE@30..31 " "
+            PARAM@31..39
+              IDENT_PAT@31..34
+                NAME@31..34
+                  IDENT@31..34 "baz"
+              COLON@34..35 ":"
+              WHITESPACE@35..36 " "
+              PATH_TYPE@36..39
+                PATH@36..39
+                  PATH_SEGMENT@36..39
+                    NAME_REF@36..39
+                      IDENT@36..39 "Baz"
+            COMMA@39..40 ","
+            WHITESPACE@40..41 " "
+            PARAM@41..55
+              IDENT_PAT@41..44
+                NAME@41..44
+                  IDENT@41..44 "qux"
+              COLON@44..45 ":"
+              WHITESPACE@45..46 " "
+              PATH_TYPE@46..55
+                PATH@46..55
+                  PATH@46..49
+                    PATH_SEGMENT@46..49
+                      NAME_REF@46..49
+                        IDENT@46..49 "Qux"
+                  COLON2@49..51 "::"
+                  PATH_SEGMENT@51..55
+                    NAME_REF@51..55
+                      IDENT@51..55 "Quux"
+            PIPE@55..56 "|"
+          WHITESPACE@56..57 " "
+          TUPLE_EXPR@57..59
+            L_PAREN@57..58 "("
+            R_PAREN@58..59 ")"
+        SEMICOLON@59..60 ";"
+      WHITESPACE@60..61 "\n"
+      R_CURLY@61..62 "}"
+  WHITESPACE@62..63 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0155_closure_params.rs b/crates/syntax/test_data/parser/inline/ok/0155_closure_params.rs
new file mode 100644
index 00000000000..6ca8dd2d6a9
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0155_closure_params.rs
@@ -0,0 +1,3 @@
+fn main() {
+   let foo = |bar, baz: Baz, qux: Qux::Quux| ();
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0156_fn_def_param.rast b/crates/syntax/test_data/parser/inline/ok/0156_fn_def_param.rast
new file mode 100644
index 00000000000..508b4aca7d2
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0156_fn_def_param.rast
@@ -0,0 +1,43 @@
+SOURCE_FILE@0..30
+  FN@0..29
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..26
+      L_PAREN@6..7 "("
+      PARAM@7..25
+        TUPLE_PAT@7..13
+          L_PAREN@7..8 "("
+          IDENT_PAT@8..9
+            NAME@8..9
+              IDENT@8..9 "x"
+          COMMA@9..10 ","
+          WHITESPACE@10..11 " "
+          IDENT_PAT@11..12
+            NAME@11..12
+              IDENT@11..12 "y"
+          R_PAREN@12..13 ")"
+        COLON@13..14 ":"
+        WHITESPACE@14..15 " "
+        TUPLE_TYPE@15..25
+          L_PAREN@15..16 "("
+          PATH_TYPE@16..19
+            PATH@16..19
+              PATH_SEGMENT@16..19
+                NAME_REF@16..19
+                  IDENT@16..19 "i32"
+          COMMA@19..20 ","
+          WHITESPACE@20..21 " "
+          PATH_TYPE@21..24
+            PATH@21..24
+              PATH_SEGMENT@21..24
+                NAME_REF@21..24
+                  IDENT@21..24 "i32"
+          R_PAREN@24..25 ")"
+      R_PAREN@25..26 ")"
+    WHITESPACE@26..27 " "
+    BLOCK_EXPR@27..29
+      L_CURLY@27..28 "{"
+      R_CURLY@28..29 "}"
+  WHITESPACE@29..30 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0156_fn_def_param.rs b/crates/syntax/test_data/parser/inline/ok/0156_fn_def_param.rs
new file mode 100644
index 00000000000..7b277c16b15
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0156_fn_def_param.rs
@@ -0,0 +1 @@
+fn foo((x, y): (i32, i32)) {}
diff --git a/crates/syntax/test_data/parser/inline/ok/0156_or_pattern.rast b/crates/syntax/test_data/parser/inline/ok/0156_or_pattern.rast
new file mode 100644
index 00000000000..88a513cee26
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0156_or_pattern.rast
@@ -0,0 +1,111 @@
+SOURCE_FILE@0..130
+  FN@0..129
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..129
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      MATCH_EXPR@16..127
+        MATCH_KW@16..21 "match"
+        WHITESPACE@21..22 " "
+        TUPLE_EXPR@22..24
+          L_PAREN@22..23 "("
+          R_PAREN@23..24 ")"
+        WHITESPACE@24..25 " "
+        MATCH_ARM_LIST@25..127
+          L_CURLY@25..26 "{"
+          WHITESPACE@26..35 "\n        "
+          MATCH_ARM@35..48
+            PAREN_PAT@35..42
+              L_PAREN@35..36 "("
+              OR_PAT@36..41
+                WILDCARD_PAT@36..37
+                  UNDERSCORE@36..37 "_"
+                WHITESPACE@37..38 " "
+                PIPE@38..39 "|"
+                WHITESPACE@39..40 " "
+                WILDCARD_PAT@40..41
+                  UNDERSCORE@40..41 "_"
+              R_PAREN@41..42 ")"
+            WHITESPACE@42..43 " "
+            FAT_ARROW@43..45 "=>"
+            WHITESPACE@45..46 " "
+            TUPLE_EXPR@46..48
+              L_PAREN@46..47 "("
+              R_PAREN@47..48 ")"
+          COMMA@48..49 ","
+          WHITESPACE@49..58 "\n        "
+          MATCH_ARM@58..72
+            REF_PAT@58..66
+              AMP@58..59 "&"
+              PAREN_PAT@59..66
+                L_PAREN@59..60 "("
+                OR_PAT@60..65
+                  WILDCARD_PAT@60..61
+                    UNDERSCORE@60..61 "_"
+                  WHITESPACE@61..62 " "
+                  PIPE@62..63 "|"
+                  WHITESPACE@63..64 " "
+                  WILDCARD_PAT@64..65
+                    UNDERSCORE@64..65 "_"
+                R_PAREN@65..66 ")"
+            WHITESPACE@66..67 " "
+            FAT_ARROW@67..69 "=>"
+            WHITESPACE@69..70 " "
+            TUPLE_EXPR@70..72
+              L_PAREN@70..71 "("
+              R_PAREN@71..72 ")"
+          COMMA@72..73 ","
+          WHITESPACE@73..82 "\n        "
+          MATCH_ARM@82..96
+            TUPLE_PAT@82..90
+              L_PAREN@82..83 "("
+              OR_PAT@83..88
+                WILDCARD_PAT@83..84
+                  UNDERSCORE@83..84 "_"
+                WHITESPACE@84..85 " "
+                PIPE@85..86 "|"
+                WHITESPACE@86..87 " "
+                WILDCARD_PAT@87..88
+                  UNDERSCORE@87..88 "_"
+              COMMA@88..89 ","
+              R_PAREN@89..90 ")"
+            WHITESPACE@90..91 " "
+            FAT_ARROW@91..93 "=>"
+            WHITESPACE@93..94 " "
+            TUPLE_EXPR@94..96
+              L_PAREN@94..95 "("
+              R_PAREN@95..96 ")"
+          COMMA@96..97 ","
+          WHITESPACE@97..106 "\n        "
+          MATCH_ARM@106..120
+            SLICE_PAT@106..114
+              L_BRACK@106..107 "["
+              OR_PAT@107..112
+                WILDCARD_PAT@107..108
+                  UNDERSCORE@107..108 "_"
+                WHITESPACE@108..109 " "
+                PIPE@109..110 "|"
+                WHITESPACE@110..111 " "
+                WILDCARD_PAT@111..112
+                  UNDERSCORE@111..112 "_"
+              COMMA@112..113 ","
+              R_BRACK@113..114 "]"
+            WHITESPACE@114..115 " "
+            FAT_ARROW@115..117 "=>"
+            WHITESPACE@117..118 " "
+            TUPLE_EXPR@118..120
+              L_PAREN@118..119 "("
+              R_PAREN@119..120 ")"
+          COMMA@120..121 ","
+          WHITESPACE@121..126 "\n    "
+          R_CURLY@126..127 "}"
+      WHITESPACE@127..128 "\n"
+      R_CURLY@128..129 "}"
+  WHITESPACE@129..130 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0156_or_pattern.rs b/crates/syntax/test_data/parser/inline/ok/0156_or_pattern.rs
new file mode 100644
index 00000000000..a2631660550
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0156_or_pattern.rs
@@ -0,0 +1,8 @@
+fn main() {
+    match () {
+        (_ | _) => (),
+        &(_ | _) => (),
+        (_ | _,) => (),
+        [_ | _,] => (),
+    }
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rast b/crates/syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rast
new file mode 100644
index 00000000000..6abb4fe5ac4
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rast
@@ -0,0 +1,26 @@
+SOURCE_FILE@0..23
+  TYPE_ALIAS@0..22
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..8
+      IDENT@5..8 "Foo"
+    WHITESPACE@8..9 " "
+    EQ@9..10 "="
+    WHITESPACE@10..11 " "
+    FN_PTR_TYPE@11..21
+      FN_KW@11..13 "fn"
+      PARAM_LIST@13..21
+        L_PAREN@13..14 "("
+        PARAM@14..20
+          WILDCARD_PAT@14..15
+            UNDERSCORE@14..15 "_"
+          COLON@15..16 ":"
+          WHITESPACE@16..17 " "
+          PATH_TYPE@17..20
+            PATH@17..20
+              PATH_SEGMENT@17..20
+                NAME_REF@17..20
+                  IDENT@17..20 "bar"
+        R_PAREN@20..21 ")"
+    SEMICOLON@21..22 ";"
+  WHITESPACE@22..23 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rs b/crates/syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rs
new file mode 100644
index 00000000000..1ebbe5b0355
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rs
@@ -0,0 +1 @@
+type Foo = fn(_: bar);
diff --git a/crates/syntax/test_data/parser/inline/ok/0157_variant_discriminant.rast b/crates/syntax/test_data/parser/inline/ok/0157_variant_discriminant.rast
new file mode 100644
index 00000000000..a2e05eb2e2a
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0157_variant_discriminant.rast
@@ -0,0 +1,30 @@
+SOURCE_FILE@0..23
+  ENUM@0..22
+    ENUM_KW@0..4 "enum"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "E"
+    WHITESPACE@6..7 " "
+    VARIANT_LIST@7..22
+      L_CURLY@7..8 "{"
+      WHITESPACE@8..9 " "
+      VARIANT@9..20
+        NAME@9..10
+          IDENT@9..10 "X"
+        TUPLE_FIELD_LIST@10..15
+          L_PAREN@10..11 "("
+          TUPLE_FIELD@11..14
+            PATH_TYPE@11..14
+              PATH@11..14
+                PATH_SEGMENT@11..14
+                  NAME_REF@11..14
+                    IDENT@11..14 "i32"
+          R_PAREN@14..15 ")"
+        WHITESPACE@15..16 " "
+        EQ@16..17 "="
+        WHITESPACE@17..18 " "
+        LITERAL@18..20
+          INT_NUMBER@18..20 "10"
+      WHITESPACE@20..21 " "
+      R_CURLY@21..22 "}"
+  WHITESPACE@22..23 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0157_variant_discriminant.rs b/crates/syntax/test_data/parser/inline/ok/0157_variant_discriminant.rs
new file mode 100644
index 00000000000..c8c5c0f174e
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0157_variant_discriminant.rs
@@ -0,0 +1 @@
+enum E { X(i32) = 10 }
diff --git a/crates/syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.rast b/crates/syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.rast
new file mode 100644
index 00000000000..8ae24b9c101
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.rast
@@ -0,0 +1,36 @@
+SOURCE_FILE@0..28
+  FN@0..27
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..27
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..25
+        BIN_EXPR@15..24
+          PATH_EXPR@15..16
+            PATH@15..16
+              PATH_SEGMENT@15..16
+                NAME_REF@15..16
+                  IDENT@15..16 "v"
+          WHITESPACE@16..17 " "
+          EQ@17..18 "="
+          WHITESPACE@18..19 " "
+          BIN_EXPR@19..24
+            BLOCK_EXPR@19..22
+              L_CURLY@19..20 "{"
+              LITERAL@20..21
+                INT_NUMBER@20..21 "1"
+              R_CURLY@21..22 "}"
+            AMP@22..23 "&"
+            LITERAL@23..24
+              INT_NUMBER@23..24 "2"
+        SEMICOLON@24..25 ";"
+      WHITESPACE@25..26 "\n"
+      R_CURLY@26..27 "}"
+  WHITESPACE@27..28 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.rs b/crates/syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.rs
new file mode 100644
index 00000000000..05acc30f126
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.rs
@@ -0,0 +1,3 @@
+fn foo() {
+    v = {1}&2;
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0158_lambda_ret_block.rast b/crates/syntax/test_data/parser/inline/ok/0158_lambda_ret_block.rast
new file mode 100644
index 00000000000..aa4099a9293
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0158_lambda_ret_block.rast
@@ -0,0 +1,43 @@
+SOURCE_FILE@0..34
+  FN@0..33
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..33
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..12 " "
+      EXPR_STMT@12..31
+        CALL_EXPR@12..30
+          CLOSURE_EXPR@12..28
+            PARAM_LIST@12..14
+              PIPE@12..13 "|"
+              PIPE@13..14 "|"
+            WHITESPACE@14..15 " "
+            RET_TYPE@15..21
+              THIN_ARROW@15..17 "->"
+              WHITESPACE@17..18 " "
+              PATH_TYPE@18..21
+                PATH@18..21
+                  PATH_SEGMENT@18..21
+                    NAME_REF@18..21
+                      IDENT@18..21 "i32"
+            WHITESPACE@21..22 " "
+            BLOCK_EXPR@22..28
+              L_CURLY@22..23 "{"
+              WHITESPACE@23..24 " "
+              LITERAL@24..26
+                INT_NUMBER@24..26 "92"
+              WHITESPACE@26..27 " "
+              R_CURLY@27..28 "}"
+          ARG_LIST@28..30
+            L_PAREN@28..29 "("
+            R_PAREN@29..30 ")"
+        SEMICOLON@30..31 ";"
+      WHITESPACE@31..32 " "
+      R_CURLY@32..33 "}"
+  WHITESPACE@33..34 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0158_lambda_ret_block.rs b/crates/syntax/test_data/parser/inline/ok/0158_lambda_ret_block.rs
new file mode 100644
index 00000000000..061118d3aab
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0158_lambda_ret_block.rs
@@ -0,0 +1 @@
+fn main() { || -> i32 { 92 }(); }
diff --git a/crates/syntax/test_data/parser/inline/ok/0159_try_macro_fallback.rast b/crates/syntax/test_data/parser/inline/ok/0159_try_macro_fallback.rast
new file mode 100644
index 00000000000..fb46d4ce401
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0159_try_macro_fallback.rast
@@ -0,0 +1,34 @@
+SOURCE_FILE@0..27
+  FN@0..26
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..26
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..11 " "
+      EXPR_STMT@11..24
+        MACRO_CALL@11..23
+          PATH@11..14
+            PATH_SEGMENT@11..14
+              NAME_REF@11..14
+                IDENT@11..14 "try"
+          BANG@14..15 "!"
+          TOKEN_TREE@15..23
+            L_PAREN@15..16 "("
+            IDENT@16..18 "Ok"
+            TOKEN_TREE@18..22
+              L_PAREN@18..19 "("
+              TOKEN_TREE@19..21
+                L_PAREN@19..20 "("
+                R_PAREN@20..21 ")"
+              R_PAREN@21..22 ")"
+            R_PAREN@22..23 ")"
+        SEMICOLON@23..24 ";"
+      WHITESPACE@24..25 " "
+      R_CURLY@25..26 "}"
+  WHITESPACE@26..27 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0159_try_macro_fallback.rs b/crates/syntax/test_data/parser/inline/ok/0159_try_macro_fallback.rs
new file mode 100644
index 00000000000..61a6b46a0b3
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0159_try_macro_fallback.rs
@@ -0,0 +1 @@
+fn foo() { try!(Ok(())); }
diff --git a/crates/syntax/test_data/parser/inline/ok/0160_try_macro_rules.rast b/crates/syntax/test_data/parser/inline/ok/0160_try_macro_rules.rast
new file mode 100644
index 00000000000..05b89d1c369
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0160_try_macro_rules.rast
@@ -0,0 +1,27 @@
+SOURCE_FILE@0..30
+  MACRO_CALL@0..29
+    PATH@0..11
+      PATH_SEGMENT@0..11
+        NAME_REF@0..11
+          IDENT@0..11 "macro_rules"
+    BANG@11..12 "!"
+    WHITESPACE@12..13 " "
+    NAME@13..16
+      IDENT@13..16 "try"
+    WHITESPACE@16..17 " "
+    TOKEN_TREE@17..29
+      L_CURLY@17..18 "{"
+      WHITESPACE@18..19 " "
+      TOKEN_TREE@19..21
+        L_PAREN@19..20 "("
+        R_PAREN@20..21 ")"
+      WHITESPACE@21..22 " "
+      EQ@22..23 "="
+      R_ANGLE@23..24 ">"
+      WHITESPACE@24..25 " "
+      TOKEN_TREE@25..27
+        L_CURLY@25..26 "{"
+        R_CURLY@26..27 "}"
+      WHITESPACE@27..28 " "
+      R_CURLY@28..29 "}"
+  WHITESPACE@29..30 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0160_try_macro_rules.rs b/crates/syntax/test_data/parser/inline/ok/0160_try_macro_rules.rs
new file mode 100644
index 00000000000..2e2ab6e60b6
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0160_try_macro_rules.rs
@@ -0,0 +1 @@
+macro_rules! try { () => {} }
diff --git a/crates/syntax/test_data/parser/inline/ok/0161_labeled_block.rast b/crates/syntax/test_data/parser/inline/ok/0161_labeled_block.rast
new file mode 100644
index 00000000000..9e9a5f9c5b5
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0161_labeled_block.rast
@@ -0,0 +1,26 @@
+SOURCE_FILE@0..23
+  FN@0..22
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..4
+      IDENT@3..4 "f"
+    PARAM_LIST@4..6
+      L_PAREN@4..5 "("
+      R_PAREN@5..6 ")"
+    WHITESPACE@6..7 " "
+    BLOCK_EXPR@7..22
+      L_CURLY@7..8 "{"
+      WHITESPACE@8..9 " "
+      EXPR_STMT@9..20
+        EFFECT_EXPR@9..19
+          LABEL@9..16
+            LIFETIME@9..15 "\'label"
+            COLON@15..16 ":"
+          WHITESPACE@16..17 " "
+          BLOCK_EXPR@17..19
+            L_CURLY@17..18 "{"
+            R_CURLY@18..19 "}"
+        SEMICOLON@19..20 ";"
+      WHITESPACE@20..21 " "
+      R_CURLY@21..22 "}"
+  WHITESPACE@22..23 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0161_labeled_block.rs b/crates/syntax/test_data/parser/inline/ok/0161_labeled_block.rs
new file mode 100644
index 00000000000..18b4ff4b1ba
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0161_labeled_block.rs
@@ -0,0 +1 @@
+fn f() { 'label: {}; }
diff --git a/crates/syntax/test_data/parser/inline/ok/0162_unsafe_block.rast b/crates/syntax/test_data/parser/inline/ok/0162_unsafe_block.rast
new file mode 100644
index 00000000000..ca9a1183d6a
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0162_unsafe_block.rast
@@ -0,0 +1,23 @@
+SOURCE_FILE@0..22
+  FN@0..21
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..4
+      IDENT@3..4 "f"
+    PARAM_LIST@4..6
+      L_PAREN@4..5 "("
+      R_PAREN@5..6 ")"
+    WHITESPACE@6..7 " "
+    BLOCK_EXPR@7..21
+      L_CURLY@7..8 "{"
+      WHITESPACE@8..9 " "
+      EFFECT_EXPR@9..19
+        UNSAFE_KW@9..15 "unsafe"
+        WHITESPACE@15..16 " "
+        BLOCK_EXPR@16..19
+          L_CURLY@16..17 "{"
+          WHITESPACE@17..18 " "
+          R_CURLY@18..19 "}"
+      WHITESPACE@19..20 " "
+      R_CURLY@20..21 "}"
+  WHITESPACE@21..22 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0162_unsafe_block.rs b/crates/syntax/test_data/parser/inline/ok/0162_unsafe_block.rs
new file mode 100644
index 00000000000..dfb9b2a1c18
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0162_unsafe_block.rs
@@ -0,0 +1 @@
+fn f() { unsafe { } }
diff --git a/crates/syntax/test_data/parser/inline/ok/0163_default_unsafe_item.rast b/crates/syntax/test_data/parser/inline/ok/0163_default_unsafe_item.rast
new file mode 100644
index 00000000000..f2e2014605a
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0163_default_unsafe_item.rast
@@ -0,0 +1,44 @@
+SOURCE_FILE@0..65
+  IMPL@0..64
+    DEFAULT_KW@0..7 "default"
+    WHITESPACE@7..8 " "
+    UNSAFE_KW@8..14 "unsafe"
+    WHITESPACE@14..15 " "
+    IMPL_KW@15..19 "impl"
+    WHITESPACE@19..20 " "
+    PATH_TYPE@20..21
+      PATH@20..21
+        PATH_SEGMENT@20..21
+          NAME_REF@20..21
+            IDENT@20..21 "T"
+    WHITESPACE@21..22 " "
+    FOR_KW@22..25 "for"
+    WHITESPACE@25..26 " "
+    PATH_TYPE@26..29
+      PATH@26..29
+        PATH_SEGMENT@26..29
+          NAME_REF@26..29
+            IDENT@26..29 "Foo"
+    WHITESPACE@29..30 " "
+    ASSOC_ITEM_LIST@30..64
+      L_CURLY@30..31 "{"
+      WHITESPACE@31..36 "\n    "
+      FN@36..62
+        DEFAULT_KW@36..43 "default"
+        WHITESPACE@43..44 " "
+        UNSAFE_KW@44..50 "unsafe"
+        WHITESPACE@50..51 " "
+        FN_KW@51..53 "fn"
+        WHITESPACE@53..54 " "
+        NAME@54..57
+          IDENT@54..57 "foo"
+        PARAM_LIST@57..59
+          L_PAREN@57..58 "("
+          R_PAREN@58..59 ")"
+        WHITESPACE@59..60 " "
+        BLOCK_EXPR@60..62
+          L_CURLY@60..61 "{"
+          R_CURLY@61..62 "}"
+      WHITESPACE@62..63 "\n"
+      R_CURLY@63..64 "}"
+  WHITESPACE@64..65 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0163_default_unsafe_item.rs b/crates/syntax/test_data/parser/inline/ok/0163_default_unsafe_item.rs
new file mode 100644
index 00000000000..96340f84ab3
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0163_default_unsafe_item.rs
@@ -0,0 +1,3 @@
+default unsafe impl T for Foo {
+    default unsafe fn foo() {}
+}
diff --git a/crates/syntax/test_data/parser/inline/ok/0164_default_item.rast b/crates/syntax/test_data/parser/inline/ok/0164_default_item.rast
new file mode 100644
index 00000000000..9282772f34d
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0164_default_item.rast
@@ -0,0 +1,24 @@
+SOURCE_FILE@0..26
+  IMPL@0..25
+    DEFAULT_KW@0..7 "default"
+    WHITESPACE@7..8 " "
+    IMPL_KW@8..12 "impl"
+    WHITESPACE@12..13 " "
+    PATH_TYPE@13..14
+      PATH@13..14
+        PATH_SEGMENT@13..14
+          NAME_REF@13..14
+            IDENT@13..14 "T"
+    WHITESPACE@14..15 " "
+    FOR_KW@15..18 "for"
+    WHITESPACE@18..19 " "
+    PATH_TYPE@19..22
+      PATH@19..22
+        PATH_SEGMENT@19..22
+          NAME_REF@19..22
+            IDENT@19..22 "Foo"
+    WHITESPACE@22..23 " "
+    ASSOC_ITEM_LIST@23..25
+      L_CURLY@23..24 "{"
+      R_CURLY@24..25 "}"
+  WHITESPACE@25..26 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0164_default_item.rs b/crates/syntax/test_data/parser/inline/ok/0164_default_item.rs
new file mode 100644
index 00000000000..a6836cbd577
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0164_default_item.rs
@@ -0,0 +1 @@
+default impl T for Foo {}
diff --git a/crates/syntax/test_data/parser/inline/ok/0164_type_path_in_pattern.rast b/crates/syntax/test_data/parser/inline/ok/0164_type_path_in_pattern.rast
new file mode 100644
index 00000000000..f8910677b46
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0164_type_path_in_pattern.rast
@@ -0,0 +1,38 @@
+SOURCE_FILE@0..33
+  FN@0..32
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..32
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..12 " "
+      LET_STMT@12..30
+        LET_KW@12..15 "let"
+        WHITESPACE@15..16 " "
+        PATH_PAT@16..24
+          PATH@16..24
+            PATH@16..19
+              PATH_SEGMENT@16..19
+                L_ANGLE@16..17 "<"
+                INFER_TYPE@17..18
+                  UNDERSCORE@17..18 "_"
+                R_ANGLE@18..19 ">"
+            COLON2@19..21 "::"
+            PATH_SEGMENT@21..24
+              NAME_REF@21..24
+                IDENT@21..24 "Foo"
+        WHITESPACE@24..25 " "
+        EQ@25..26 "="
+        WHITESPACE@26..27 " "
+        TUPLE_EXPR@27..29
+          L_PAREN@27..28 "("
+          R_PAREN@28..29 ")"
+        SEMICOLON@29..30 ";"
+      WHITESPACE@30..31 " "
+      R_CURLY@31..32 "}"
+  WHITESPACE@32..33 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0164_type_path_in_pattern.rs b/crates/syntax/test_data/parser/inline/ok/0164_type_path_in_pattern.rs
new file mode 100644
index 00000000000..ebe26834d88
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0164_type_path_in_pattern.rs
@@ -0,0 +1 @@
+fn main() { let <_>::Foo = (); }
diff --git a/crates/syntax/test_data/parser/ok/0000_empty.rast b/crates/syntax/test_data/parser/ok/0000_empty.rast
new file mode 100644
index 00000000000..6b234b0b241
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0000_empty.rast
@@ -0,0 +1 @@
+SOURCE_FILE@0..0
diff --git a/crates/syntax/test_data/parser/ok/0000_empty.rs b/crates/syntax/test_data/parser/ok/0000_empty.rs
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0000_empty.rs
diff --git a/crates/syntax/test_data/parser/ok/0001_struct_item.rast b/crates/syntax/test_data/parser/ok/0001_struct_item.rast
new file mode 100644
index 00000000000..a171fe7a86d
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0001_struct_item.rast
@@ -0,0 +1,39 @@
+SOURCE_FILE@0..32
+  STRUCT@0..31
+    STRUCT_KW@0..6 "struct"
+    WHITESPACE@6..7 " "
+    NAME@7..8
+      IDENT@7..8 "S"
+    GENERIC_PARAM_LIST@8..17
+      L_ANGLE@8..9 "<"
+      TYPE_PARAM@9..16
+        NAME@9..10
+          IDENT@9..10 "T"
+        COLON@10..11 ":"
+        WHITESPACE@11..12 " "
+        TYPE_BOUND_LIST@12..16
+          TYPE_BOUND@12..16
+            PATH_TYPE@12..16
+              PATH@12..16
+                PATH_SEGMENT@12..16
+                  NAME_REF@12..16
+                    IDENT@12..16 "Copy"
+      R_ANGLE@16..17 ">"
+    WHITESPACE@17..18 " "
+    RECORD_FIELD_LIST@18..31
+      L_CURLY@18..19 "{"
+      WHITESPACE@19..24 "\n    "
+      RECORD_FIELD@24..28
+        NAME@24..25
+          IDENT@24..25 "f"
+        COLON@25..26 ":"
+        WHITESPACE@26..27 " "
+        PATH_TYPE@27..28
+          PATH@27..28
+            PATH_SEGMENT@27..28
+              NAME_REF@27..28
+                IDENT@27..28 "T"
+      COMMA@28..29 ","
+      WHITESPACE@29..30 "\n"
+      R_CURLY@30..31 "}"
+  WHITESPACE@31..32 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0001_struct_item.rs b/crates/syntax/test_data/parser/ok/0001_struct_item.rs
new file mode 100644
index 00000000000..512aeb3e7a0
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0001_struct_item.rs
@@ -0,0 +1,3 @@
+struct S<T: Copy> {
+    f: T,
+}
diff --git a/crates/syntax/test_data/parser/ok/0002_struct_item_field.rast b/crates/syntax/test_data/parser/ok/0002_struct_item_field.rast
new file mode 100644
index 00000000000..362892b91f1
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0002_struct_item_field.rast
@@ -0,0 +1,22 @@
+SOURCE_FILE@0..25
+  STRUCT@0..25
+    STRUCT_KW@0..6 "struct"
+    WHITESPACE@6..7 " "
+    NAME@7..8
+      IDENT@7..8 "S"
+    WHITESPACE@8..9 " "
+    RECORD_FIELD_LIST@9..25
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      RECORD_FIELD@15..23
+        NAME@15..18
+          IDENT@15..18 "foo"
+        COLON@18..19 ":"
+        WHITESPACE@19..20 " "
+        PATH_TYPE@20..23
+          PATH@20..23
+            PATH_SEGMENT@20..23
+              NAME_REF@20..23
+                IDENT@20..23 "u32"
+      WHITESPACE@23..24 "\n"
+      R_CURLY@24..25 "}"
diff --git a/crates/syntax/test_data/parser/ok/0002_struct_item_field.rs b/crates/syntax/test_data/parser/ok/0002_struct_item_field.rs
new file mode 100644
index 00000000000..cc3866d2511
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0002_struct_item_field.rs
@@ -0,0 +1,3 @@
+struct S {
+    foo: u32
+}
\ No newline at end of file
diff --git a/crates/syntax/test_data/parser/ok/0004_file_shebang.rast b/crates/syntax/test_data/parser/ok/0004_file_shebang.rast
new file mode 100644
index 00000000000..67e21df13a1
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0004_file_shebang.rast
@@ -0,0 +1,2 @@
+SOURCE_FILE@0..20
+  SHEBANG@0..20 "#!/use/bin/env rusti"
diff --git a/crates/syntax/test_data/parser/ok/0004_file_shebang.rs b/crates/syntax/test_data/parser/ok/0004_file_shebang.rs
new file mode 100644
index 00000000000..53dc9e61733
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0004_file_shebang.rs
@@ -0,0 +1 @@
+#!/use/bin/env rusti
\ No newline at end of file
diff --git a/crates/syntax/test_data/parser/ok/0005_fn_item.rast b/crates/syntax/test_data/parser/ok/0005_fn_item.rast
new file mode 100644
index 00000000000..a7a2b11a723
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0005_fn_item.rast
@@ -0,0 +1,15 @@
+SOURCE_FILE@0..13
+  FN@0..12
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..12
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..11 "\n"
+      R_CURLY@11..12 "}"
+  WHITESPACE@12..13 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0005_fn_item.rs b/crates/syntax/test_data/parser/ok/0005_fn_item.rs
new file mode 100644
index 00000000000..03210551cb1
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0005_fn_item.rs
@@ -0,0 +1,2 @@
+fn foo() {
+}
diff --git a/crates/syntax/test_data/parser/ok/0006_inner_attributes.rast b/crates/syntax/test_data/parser/ok/0006_inner_attributes.rast
new file mode 100644
index 00000000000..42587243a96
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0006_inner_attributes.rast
@@ -0,0 +1,184 @@
+SOURCE_FILE@0..236
+  ATTR@0..8
+    POUND@0..1 "#"
+    BANG@1..2 "!"
+    L_BRACK@2..3 "["
+    PATH@3..7
+      PATH_SEGMENT@3..7
+        NAME_REF@3..7
+          IDENT@3..7 "attr"
+    R_BRACK@7..8 "]"
+  WHITESPACE@8..9 "\n"
+  ATTR@9..23
+    POUND@9..10 "#"
+    BANG@10..11 "!"
+    L_BRACK@11..12 "["
+    PATH@12..16
+      PATH_SEGMENT@12..16
+        NAME_REF@12..16
+          IDENT@12..16 "attr"
+    TOKEN_TREE@16..22
+      L_PAREN@16..17 "("
+      TRUE_KW@17..21 "true"
+      R_PAREN@21..22 ")"
+    R_BRACK@22..23 "]"
+  WHITESPACE@23..24 "\n"
+  ATTR@24..39
+    POUND@24..25 "#"
+    BANG@25..26 "!"
+    L_BRACK@26..27 "["
+    PATH@27..31
+      PATH_SEGMENT@27..31
+        NAME_REF@27..31
+          IDENT@27..31 "attr"
+    TOKEN_TREE@31..38
+      L_PAREN@31..32 "("
+      IDENT@32..37 "ident"
+      R_PAREN@37..38 ")"
+    R_BRACK@38..39 "]"
+  WHITESPACE@39..40 "\n"
+  ATTR@40..116
+    POUND@40..41 "#"
+    BANG@41..42 "!"
+    L_BRACK@42..43 "["
+    PATH@43..47
+      PATH_SEGMENT@43..47
+        NAME_REF@43..47
+          IDENT@43..47 "attr"
+    TOKEN_TREE@47..115
+      L_PAREN@47..48 "("
+      IDENT@48..53 "ident"
+      COMMA@53..54 ","
+      WHITESPACE@54..55 " "
+      INT_NUMBER@55..58 "100"
+      COMMA@58..59 ","
+      WHITESPACE@59..60 " "
+      TRUE_KW@60..64 "true"
+      COMMA@64..65 ","
+      WHITESPACE@65..66 " "
+      STRING@66..72 "\"true\""
+      COMMA@72..73 ","
+      WHITESPACE@73..74 " "
+      IDENT@74..79 "ident"
+      WHITESPACE@79..80 " "
+      EQ@80..81 "="
+      WHITESPACE@81..82 " "
+      INT_NUMBER@82..85 "100"
+      COMMA@85..86 ","
+      WHITESPACE@86..87 " "
+      IDENT@87..92 "ident"
+      WHITESPACE@92..93 " "
+      EQ@93..94 "="
+      WHITESPACE@94..95 " "
+      STRING@95..102 "\"hello\""
+      COMMA@102..103 ","
+      WHITESPACE@103..104 " "
+      IDENT@104..109 "ident"
+      TOKEN_TREE@109..114
+        L_PAREN@109..110 "("
+        INT_NUMBER@110..113 "100"
+        R_PAREN@113..114 ")"
+      R_PAREN@114..115 ")"
+    R_BRACK@115..116 "]"
+  WHITESPACE@116..117 "\n"
+  ATTR@117..130
+    POUND@117..118 "#"
+    BANG@118..119 "!"
+    L_BRACK@119..120 "["
+    PATH@120..124
+      PATH_SEGMENT@120..124
+        NAME_REF@120..124
+          IDENT@120..124 "attr"
+    TOKEN_TREE@124..129
+      L_PAREN@124..125 "("
+      INT_NUMBER@125..128 "100"
+      R_PAREN@128..129 ")"
+    R_BRACK@129..130 "]"
+  WHITESPACE@130..131 "\n"
+  ATTR@131..155
+    POUND@131..132 "#"
+    BANG@132..133 "!"
+    L_BRACK@133..134 "["
+    PATH@134..138
+      PATH_SEGMENT@134..138
+        NAME_REF@134..138
+          IDENT@134..138 "attr"
+    TOKEN_TREE@138..154
+      L_PAREN@138..139 "("
+      IDENT@139..146 "enabled"
+      WHITESPACE@146..147 " "
+      EQ@147..148 "="
+      WHITESPACE@148..149 " "
+      TRUE_KW@149..153 "true"
+      R_PAREN@153..154 ")"
+    R_BRACK@154..155 "]"
+  WHITESPACE@155..156 "\n"
+  ATTR@156..173
+    POUND@156..157 "#"
+    BANG@157..158 "!"
+    L_BRACK@158..159 "["
+    PATH@159..166
+      PATH_SEGMENT@159..166
+        NAME_REF@159..166
+          IDENT@159..166 "enabled"
+    TOKEN_TREE@166..172
+      L_PAREN@166..167 "("
+      TRUE_KW@167..171 "true"
+      R_PAREN@171..172 ")"
+    R_BRACK@172..173 "]"
+  WHITESPACE@173..174 "\n"
+  ATTR@174..191
+    POUND@174..175 "#"
+    BANG@175..176 "!"
+    L_BRACK@176..177 "["
+    PATH@177..181
+      PATH_SEGMENT@177..181
+        NAME_REF@177..181
+          IDENT@177..181 "attr"
+    TOKEN_TREE@181..190
+      L_PAREN@181..182 "("
+      STRING@182..189 "\"hello\""
+      R_PAREN@189..190 ")"
+    R_BRACK@190..191 "]"
+  WHITESPACE@191..192 "\n"
+  ATTR@192..214
+    POUND@192..193 "#"
+    BANG@193..194 "!"
+    L_BRACK@194..195 "["
+    PATH@195..199
+      PATH_SEGMENT@195..199
+        NAME_REF@195..199
+          IDENT@195..199 "repr"
+    TOKEN_TREE@199..213
+      L_PAREN@199..200 "("
+      IDENT@200..201 "C"
+      COMMA@201..202 ","
+      WHITESPACE@202..203 " "
+      IDENT@203..208 "align"
+      WHITESPACE@208..209 " "
+      EQ@209..210 "="
+      WHITESPACE@210..211 " "
+      INT_NUMBER@211..212 "4"
+      R_PAREN@212..213 ")"
+    R_BRACK@213..214 "]"
+  WHITESPACE@214..215 "\n"
+  ATTR@215..236
+    POUND@215..216 "#"
+    BANG@216..217 "!"
+    L_BRACK@217..218 "["
+    PATH@218..222
+      PATH_SEGMENT@218..222
+        NAME_REF@218..222
+          IDENT@218..222 "repr"
+    TOKEN_TREE@222..235
+      L_PAREN@222..223 "("
+      IDENT@223..224 "C"
+      COMMA@224..225 ","
+      WHITESPACE@225..226 " "
+      IDENT@226..231 "align"
+      TOKEN_TREE@231..234
+        L_PAREN@231..232 "("
+        INT_NUMBER@232..233 "4"
+        R_PAREN@233..234 ")"
+      R_PAREN@234..235 ")"
+    R_BRACK@235..236 "]"
diff --git a/crates/syntax/test_data/parser/ok/0006_inner_attributes.rs b/crates/syntax/test_data/parser/ok/0006_inner_attributes.rs
new file mode 100644
index 00000000000..e81f8b1e84f
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0006_inner_attributes.rs
@@ -0,0 +1,10 @@
+#![attr]
+#![attr(true)]
+#![attr(ident)]
+#![attr(ident, 100, true, "true", ident = 100, ident = "hello", ident(100))]
+#![attr(100)]
+#![attr(enabled = true)]
+#![enabled(true)]
+#![attr("hello")]
+#![repr(C, align = 4)]
+#![repr(C, align(4))]
\ No newline at end of file
diff --git a/crates/syntax/test_data/parser/ok/0007_extern_crate.rast b/crates/syntax/test_data/parser/ok/0007_extern_crate.rast
new file mode 100644
index 00000000000..594c2f8f20a
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0007_extern_crate.rast
@@ -0,0 +1,39 @@
+SOURCE_FILE@0..69
+  EXTERN_CRATE@0..17
+    EXTERN_KW@0..6 "extern"
+    WHITESPACE@6..7 " "
+    CRATE_KW@7..12 "crate"
+    WHITESPACE@12..13 " "
+    NAME_REF@13..16
+      IDENT@13..16 "foo"
+    SEMICOLON@16..17 ";"
+  WHITESPACE@17..18 "\n"
+  EXTERN_CRATE@18..42
+    EXTERN_KW@18..24 "extern"
+    WHITESPACE@24..25 " "
+    CRATE_KW@25..30 "crate"
+    WHITESPACE@30..31 " "
+    NAME_REF@31..34
+      IDENT@31..34 "foo"
+    WHITESPACE@34..35 " "
+    RENAME@35..41
+      AS_KW@35..37 "as"
+      WHITESPACE@37..38 " "
+      NAME@38..41
+        IDENT@38..41 "bar"
+    SEMICOLON@41..42 ";"
+  WHITESPACE@42..43 "\n"
+  EXTERN_CRATE@43..68
+    EXTERN_KW@43..49 "extern"
+    WHITESPACE@49..50 " "
+    CRATE_KW@50..55 "crate"
+    WHITESPACE@55..56 " "
+    SELF_KW@56..60 "self"
+    WHITESPACE@60..61 " "
+    RENAME@61..67
+      AS_KW@61..63 "as"
+      WHITESPACE@63..64 " "
+      NAME@64..67
+        IDENT@64..67 "baz"
+    SEMICOLON@67..68 ";"
+  WHITESPACE@68..69 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0007_extern_crate.rs b/crates/syntax/test_data/parser/ok/0007_extern_crate.rs
new file mode 100644
index 00000000000..ab81a608cb5
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0007_extern_crate.rs
@@ -0,0 +1,3 @@
+extern crate foo;
+extern crate foo as bar;
+extern crate self as baz;
diff --git a/crates/syntax/test_data/parser/ok/0008_mod_item.rast b/crates/syntax/test_data/parser/ok/0008_mod_item.rast
new file mode 100644
index 00000000000..b2c1d791f14
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0008_mod_item.rast
@@ -0,0 +1,92 @@
+SOURCE_FILE@0..118
+  MODULE@0..6
+    MOD_KW@0..3 "mod"
+    WHITESPACE@3..4 " "
+    NAME@4..5
+      IDENT@4..5 "a"
+    SEMICOLON@5..6 ";"
+  WHITESPACE@6..8 "\n\n"
+  MODULE@8..17
+    MOD_KW@8..11 "mod"
+    WHITESPACE@11..12 " "
+    NAME@12..13
+      IDENT@12..13 "b"
+    WHITESPACE@13..14 " "
+    ITEM_LIST@14..17
+      L_CURLY@14..15 "{"
+      WHITESPACE@15..16 "\n"
+      R_CURLY@16..17 "}"
+  WHITESPACE@17..19 "\n\n"
+  MODULE@19..65
+    MOD_KW@19..22 "mod"
+    WHITESPACE@22..23 " "
+    NAME@23..24
+      IDENT@23..24 "c"
+    WHITESPACE@24..25 " "
+    ITEM_LIST@25..65
+      L_CURLY@25..26 "{"
+      WHITESPACE@26..31 "\n    "
+      FN@31..47
+        FN_KW@31..33 "fn"
+        WHITESPACE@33..34 " "
+        NAME@34..37
+          IDENT@34..37 "foo"
+        PARAM_LIST@37..39
+          L_PAREN@37..38 "("
+          R_PAREN@38..39 ")"
+        WHITESPACE@39..40 " "
+        BLOCK_EXPR@40..47
+          L_CURLY@40..41 "{"
+          WHITESPACE@41..46 "\n    "
+          R_CURLY@46..47 "}"
+      WHITESPACE@47..52 "\n    "
+      STRUCT@52..63
+        STRUCT_KW@52..58 "struct"
+        WHITESPACE@58..59 " "
+        NAME@59..60
+          IDENT@59..60 "S"
+        WHITESPACE@60..61 " "
+        RECORD_FIELD_LIST@61..63
+          L_CURLY@61..62 "{"
+          R_CURLY@62..63 "}"
+      WHITESPACE@63..64 "\n"
+      R_CURLY@64..65 "}"
+  WHITESPACE@65..67 "\n\n"
+  MODULE@67..118
+    MOD_KW@67..70 "mod"
+    WHITESPACE@70..71 " "
+    NAME@71..72
+      IDENT@71..72 "d"
+    WHITESPACE@72..73 " "
+    ITEM_LIST@73..118
+      L_CURLY@73..74 "{"
+      WHITESPACE@74..79 "\n    "
+      ATTR@79..87
+        POUND@79..80 "#"
+        BANG@80..81 "!"
+        L_BRACK@81..82 "["
+        PATH@82..86
+          PATH_SEGMENT@82..86
+            NAME_REF@82..86
+              IDENT@82..86 "attr"
+        R_BRACK@86..87 "]"
+      WHITESPACE@87..92 "\n    "
+      MODULE@92..98
+        MOD_KW@92..95 "mod"
+        WHITESPACE@95..96 " "
+        NAME@96..97
+          IDENT@96..97 "e"
+        SEMICOLON@97..98 ";"
+      WHITESPACE@98..103 "\n    "
+      MODULE@103..116
+        MOD_KW@103..106 "mod"
+        WHITESPACE@106..107 " "
+        NAME@107..108
+          IDENT@107..108 "f"
+        WHITESPACE@108..109 " "
+        ITEM_LIST@109..116
+          L_CURLY@109..110 "{"
+          WHITESPACE@110..115 "\n    "
+          R_CURLY@115..116 "}"
+      WHITESPACE@116..117 "\n"
+      R_CURLY@117..118 "}"
diff --git a/crates/syntax/test_data/parser/ok/0008_mod_item.rs b/crates/syntax/test_data/parser/ok/0008_mod_item.rs
new file mode 100644
index 00000000000..d22993bc150
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0008_mod_item.rs
@@ -0,0 +1,17 @@
+mod a;
+
+mod b {
+}
+
+mod c {
+    fn foo() {
+    }
+    struct S {}
+}
+
+mod d {
+    #![attr]
+    mod e;
+    mod f {
+    }
+}
\ No newline at end of file
diff --git a/crates/syntax/test_data/parser/ok/0009_use_item.rast b/crates/syntax/test_data/parser/ok/0009_use_item.rast
new file mode 100644
index 00000000000..6be1cf9fc83
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0009_use_item.rast
@@ -0,0 +1,21 @@
+SOURCE_FILE@0..19
+  USE@0..8
+    USE_KW@0..3 "use"
+    WHITESPACE@3..4 " "
+    USE_TREE@4..7
+      PATH@4..7
+        PATH_SEGMENT@4..7
+          NAME_REF@4..7
+            IDENT@4..7 "foo"
+    SEMICOLON@7..8 ";"
+  WHITESPACE@8..9 "\n"
+  USE@9..19
+    USE_KW@9..12 "use"
+    WHITESPACE@12..13 " "
+    USE_TREE@13..18
+      PATH@13..18
+        PATH_SEGMENT@13..18
+          COLON2@13..15 "::"
+          NAME_REF@15..18
+            IDENT@15..18 "bar"
+    SEMICOLON@18..19 ";"
diff --git a/crates/syntax/test_data/parser/ok/0009_use_item.rs b/crates/syntax/test_data/parser/ok/0009_use_item.rs
new file mode 100644
index 00000000000..05a6aff83fc
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0009_use_item.rs
@@ -0,0 +1,2 @@
+use foo;
+use ::bar;
\ No newline at end of file
diff --git a/crates/syntax/test_data/parser/ok/0010_use_path_segments.rast b/crates/syntax/test_data/parser/ok/0010_use_path_segments.rast
new file mode 100644
index 00000000000..4d49e793374
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0010_use_path_segments.rast
@@ -0,0 +1,42 @@
+SOURCE_FILE@0..40
+  USE@0..20
+    USE_KW@0..3 "use"
+    WHITESPACE@3..4 " "
+    USE_TREE@4..19
+      PATH@4..19
+        PATH@4..14
+          PATH@4..9
+            PATH_SEGMENT@4..9
+              COLON2@4..6 "::"
+              NAME_REF@6..9
+                IDENT@6..9 "foo"
+          COLON2@9..11 "::"
+          PATH_SEGMENT@11..14
+            NAME_REF@11..14
+              IDENT@11..14 "bar"
+        COLON2@14..16 "::"
+        PATH_SEGMENT@16..19
+          NAME_REF@16..19
+            IDENT@16..19 "baz"
+    SEMICOLON@19..20 ";"
+  WHITESPACE@20..21 "\n"
+  USE@21..39
+    USE_KW@21..24 "use"
+    WHITESPACE@24..25 " "
+    USE_TREE@25..38
+      PATH@25..38
+        PATH@25..33
+          PATH@25..28
+            PATH_SEGMENT@25..28
+              NAME_REF@25..28
+                IDENT@25..28 "foo"
+          COLON2@28..30 "::"
+          PATH_SEGMENT@30..33
+            NAME_REF@30..33
+              IDENT@30..33 "bar"
+        COLON2@33..35 "::"
+        PATH_SEGMENT@35..38
+          NAME_REF@35..38
+            IDENT@35..38 "baz"
+    SEMICOLON@38..39 ";"
+  WHITESPACE@39..40 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0010_use_path_segments.rs b/crates/syntax/test_data/parser/ok/0010_use_path_segments.rs
new file mode 100644
index 00000000000..1e71b7a6c5d
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0010_use_path_segments.rs
@@ -0,0 +1,2 @@
+use ::foo::bar::baz;
+use foo::bar::baz;
diff --git a/crates/syntax/test_data/parser/ok/0011_outer_attribute.rast b/crates/syntax/test_data/parser/ok/0011_outer_attribute.rast
new file mode 100644
index 00000000000..478fdba758a
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0011_outer_attribute.rast
@@ -0,0 +1,57 @@
+SOURCE_FILE@0..60
+  FN@0..34
+    ATTR@0..12
+      POUND@0..1 "#"
+      L_BRACK@1..2 "["
+      PATH@2..5
+        PATH_SEGMENT@2..5
+          NAME_REF@2..5
+            IDENT@2..5 "cfg"
+      TOKEN_TREE@5..11
+        L_PAREN@5..6 "("
+        IDENT@6..10 "test"
+        R_PAREN@10..11 ")"
+      R_BRACK@11..12 "]"
+    WHITESPACE@12..13 "\n"
+    ATTR@13..22
+      POUND@13..14 "#"
+      L_BRACK@14..15 "["
+      PATH@15..21
+        PATH_SEGMENT@15..21
+          NAME_REF@15..21
+            IDENT@15..21 "ignore"
+      R_BRACK@21..22 "]"
+    WHITESPACE@22..23 "\n"
+    FN_KW@23..25 "fn"
+    WHITESPACE@25..26 " "
+    NAME@26..29
+      IDENT@26..29 "foo"
+    PARAM_LIST@29..31
+      L_PAREN@29..30 "("
+      R_PAREN@30..31 ")"
+    WHITESPACE@31..32 " "
+    BLOCK_EXPR@32..34
+      L_CURLY@32..33 "{"
+      R_CURLY@33..34 "}"
+  WHITESPACE@34..36 "\n\n"
+  MODULE@36..59
+    ATTR@36..52
+      POUND@36..37 "#"
+      L_BRACK@37..38 "["
+      PATH@38..42
+        PATH_SEGMENT@38..42
+          NAME_REF@38..42
+            IDENT@38..42 "path"
+      WHITESPACE@42..43 " "
+      EQ@43..44 "="
+      WHITESPACE@44..45 " "
+      LITERAL@45..51
+        STRING@45..51 "\"a.rs\""
+      R_BRACK@51..52 "]"
+    WHITESPACE@52..53 "\n"
+    MOD_KW@53..56 "mod"
+    WHITESPACE@56..57 " "
+    NAME@57..58
+      IDENT@57..58 "b"
+    SEMICOLON@58..59 ";"
+  WHITESPACE@59..60 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0011_outer_attribute.rs b/crates/syntax/test_data/parser/ok/0011_outer_attribute.rs
new file mode 100644
index 00000000000..3d2e01d5c6f
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0011_outer_attribute.rs
@@ -0,0 +1,6 @@
+#[cfg(test)]
+#[ignore]
+fn foo() {}
+
+#[path = "a.rs"]
+mod b;
diff --git a/crates/syntax/test_data/parser/ok/0012_visibility.rast b/crates/syntax/test_data/parser/ok/0012_visibility.rast
new file mode 100644
index 00000000000..83a93b5a9e5
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0012_visibility.rast
@@ -0,0 +1,102 @@
+SOURCE_FILE@0..98
+  FN@0..9
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..4
+      IDENT@3..4 "a"
+    PARAM_LIST@4..6
+      L_PAREN@4..5 "("
+      R_PAREN@5..6 ")"
+    WHITESPACE@6..7 " "
+    BLOCK_EXPR@7..9
+      L_CURLY@7..8 "{"
+      R_CURLY@8..9 "}"
+  WHITESPACE@9..10 "\n"
+  FN@10..23
+    VISIBILITY@10..13
+      PUB_KW@10..13 "pub"
+    WHITESPACE@13..14 " "
+    FN_KW@14..16 "fn"
+    WHITESPACE@16..17 " "
+    NAME@17..18
+      IDENT@17..18 "b"
+    PARAM_LIST@18..20
+      L_PAREN@18..19 "("
+      R_PAREN@19..20 ")"
+    WHITESPACE@20..21 " "
+    BLOCK_EXPR@21..23
+      L_CURLY@21..22 "{"
+      R_CURLY@22..23 "}"
+  WHITESPACE@23..24 "\n"
+  FN@24..44
+    VISIBILITY@24..34
+      PUB_KW@24..27 "pub"
+      L_PAREN@27..28 "("
+      CRATE_KW@28..33 "crate"
+      R_PAREN@33..34 ")"
+    WHITESPACE@34..35 " "
+    FN_KW@35..37 "fn"
+    WHITESPACE@37..38 " "
+    NAME@38..39
+      IDENT@38..39 "c"
+    PARAM_LIST@39..41
+      L_PAREN@39..40 "("
+      R_PAREN@40..41 ")"
+    WHITESPACE@41..42 " "
+    BLOCK_EXPR@42..44
+      L_CURLY@42..43 "{"
+      R_CURLY@43..44 "}"
+  WHITESPACE@44..45 "\n"
+  FN@45..65
+    VISIBILITY@45..55
+      PUB_KW@45..48 "pub"
+      L_PAREN@48..49 "("
+      SUPER_KW@49..54 "super"
+      R_PAREN@54..55 ")"
+    WHITESPACE@55..56 " "
+    FN_KW@56..58 "fn"
+    WHITESPACE@58..59 " "
+    NAME@59..60
+      IDENT@59..60 "d"
+    PARAM_LIST@60..62
+      L_PAREN@60..61 "("
+      R_PAREN@61..62 ")"
+    WHITESPACE@62..63 " "
+    BLOCK_EXPR@63..65
+      L_CURLY@63..64 "{"
+      R_CURLY@64..65 "}"
+  WHITESPACE@65..66 "\n"
+  FN@66..97
+    VISIBILITY@66..87
+      PUB_KW@66..69 "pub"
+      L_PAREN@69..70 "("
+      IN_KW@70..72 "in"
+      WHITESPACE@72..73 " "
+      PATH@73..86
+        PATH@73..81
+          PATH@73..76
+            PATH_SEGMENT@73..76
+              NAME_REF@73..76
+                IDENT@73..76 "foo"
+          COLON2@76..78 "::"
+          PATH_SEGMENT@78..81
+            NAME_REF@78..81
+              IDENT@78..81 "bar"
+        COLON2@81..83 "::"
+        PATH_SEGMENT@83..86
+          NAME_REF@83..86
+            IDENT@83..86 "baz"
+      R_PAREN@86..87 ")"
+    WHITESPACE@87..88 " "
+    FN_KW@88..90 "fn"
+    WHITESPACE@90..91 " "
+    NAME@91..92
+      IDENT@91..92 "e"
+    PARAM_LIST@92..94
+      L_PAREN@92..93 "("
+      R_PAREN@93..94 ")"
+    WHITESPACE@94..95 " "
+    BLOCK_EXPR@95..97
+      L_CURLY@95..96 "{"
+      R_CURLY@96..97 "}"
+  WHITESPACE@97..98 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0012_visibility.rs b/crates/syntax/test_data/parser/ok/0012_visibility.rs
new file mode 100644
index 00000000000..75b1db12134
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0012_visibility.rs
@@ -0,0 +1,5 @@
+fn a() {}
+pub fn b() {}
+pub(crate) fn c() {}
+pub(super) fn d() {}
+pub(in foo::bar::baz) fn e() {}
diff --git a/crates/syntax/test_data/parser/ok/0013_use_path_self_super.rast b/crates/syntax/test_data/parser/ok/0013_use_path_self_super.rast
new file mode 100644
index 00000000000..66ab1366095
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0013_use_path_self_super.rast
@@ -0,0 +1,33 @@
+SOURCE_FILE@0..38
+  USE@0..14
+    USE_KW@0..3 "use"
+    WHITESPACE@3..4 " "
+    USE_TREE@4..13
+      PATH@4..13
+        PATH@4..8
+          PATH_SEGMENT@4..8
+            SELF_KW@4..8 "self"
+        COLON2@8..10 "::"
+        PATH_SEGMENT@10..13
+          NAME_REF@10..13
+            IDENT@10..13 "foo"
+    SEMICOLON@13..14 ";"
+  WHITESPACE@14..15 "\n"
+  USE@15..37
+    USE_KW@15..18 "use"
+    WHITESPACE@18..19 " "
+    USE_TREE@19..36
+      PATH@19..36
+        PATH@19..31
+          PATH@19..24
+            PATH_SEGMENT@19..24
+              SUPER_KW@19..24 "super"
+          COLON2@24..26 "::"
+          PATH_SEGMENT@26..31
+            SUPER_KW@26..31 "super"
+        COLON2@31..33 "::"
+        PATH_SEGMENT@33..36
+          NAME_REF@33..36
+            IDENT@33..36 "bar"
+    SEMICOLON@36..37 ";"
+  WHITESPACE@37..38 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0013_use_path_self_super.rs b/crates/syntax/test_data/parser/ok/0013_use_path_self_super.rs
new file mode 100644
index 00000000000..9d9eb99175b
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0013_use_path_self_super.rs
@@ -0,0 +1,2 @@
+use self::foo;
+use super::super::bar;
diff --git a/crates/syntax/test_data/parser/ok/0014_use_tree.rast b/crates/syntax/test_data/parser/ok/0014_use_tree.rast
new file mode 100644
index 00000000000..4389d2d4bce
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0014_use_tree.rast
@@ -0,0 +1,95 @@
+SOURCE_FILE@0..81
+  USE@0..6
+    USE_KW@0..3 "use"
+    WHITESPACE@3..4 " "
+    USE_TREE@4..5
+      STAR@4..5 "*"
+    SEMICOLON@5..6 ";"
+  WHITESPACE@6..7 "\n"
+  USE@7..15
+    USE_KW@7..10 "use"
+    WHITESPACE@10..11 " "
+    USE_TREE@11..14
+      COLON2@11..13 "::"
+      STAR@13..14 "*"
+    SEMICOLON@14..15 ";"
+  WHITESPACE@15..16 "\n"
+  USE@16..25
+    USE_KW@16..19 "use"
+    WHITESPACE@19..20 " "
+    USE_TREE@20..24
+      COLON2@20..22 "::"
+      USE_TREE_LIST@22..24
+        L_CURLY@22..23 "{"
+        R_CURLY@23..24 "}"
+    SEMICOLON@24..25 ";"
+  WHITESPACE@25..26 "\n"
+  USE@26..33
+    USE_KW@26..29 "use"
+    WHITESPACE@29..30 " "
+    USE_TREE@30..32
+      USE_TREE_LIST@30..32
+        L_CURLY@30..31 "{"
+        R_CURLY@31..32 "}"
+    SEMICOLON@32..33 ";"
+  WHITESPACE@33..34 "\n"
+  USE@34..45
+    USE_KW@34..37 "use"
+    WHITESPACE@37..38 " "
+    USE_TREE@38..44
+      PATH@38..41
+        PATH_SEGMENT@38..41
+          NAME_REF@38..41
+            IDENT@38..41 "foo"
+      COLON2@41..43 "::"
+      STAR@43..44 "*"
+    SEMICOLON@44..45 ";"
+  WHITESPACE@45..46 "\n"
+  USE@46..58
+    USE_KW@46..49 "use"
+    WHITESPACE@49..50 " "
+    USE_TREE@50..57
+      PATH@50..53
+        PATH_SEGMENT@50..53
+          NAME_REF@50..53
+            IDENT@50..53 "foo"
+      COLON2@53..55 "::"
+      USE_TREE_LIST@55..57
+        L_CURLY@55..56 "{"
+        R_CURLY@56..57 "}"
+    SEMICOLON@57..58 ";"
+  WHITESPACE@58..59 "\n"
+  USE@59..80
+    USE_KW@59..62 "use"
+    WHITESPACE@62..63 " "
+    USE_TREE@63..79
+      PATH@63..68
+        PATH_SEGMENT@63..68
+          COLON2@63..65 "::"
+          NAME_REF@65..68
+            IDENT@65..68 "foo"
+      COLON2@68..70 "::"
+      USE_TREE_LIST@70..79
+        L_CURLY@70..71 "{"
+        USE_TREE@71..72
+          PATH@71..72
+            PATH_SEGMENT@71..72
+              NAME_REF@71..72
+                IDENT@71..72 "a"
+        COMMA@72..73 ","
+        WHITESPACE@73..74 " "
+        USE_TREE@74..75
+          PATH@74..75
+            PATH_SEGMENT@74..75
+              NAME_REF@74..75
+                IDENT@74..75 "b"
+        COMMA@75..76 ","
+        WHITESPACE@76..77 " "
+        USE_TREE@77..78
+          PATH@77..78
+            PATH_SEGMENT@77..78
+              NAME_REF@77..78
+                IDENT@77..78 "c"
+        R_CURLY@78..79 "}"
+    SEMICOLON@79..80 ";"
+  WHITESPACE@80..81 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0014_use_tree.rs b/crates/syntax/test_data/parser/ok/0014_use_tree.rs
new file mode 100644
index 00000000000..5e4aa3a3321
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0014_use_tree.rs
@@ -0,0 +1,7 @@
+use *;
+use ::*;
+use ::{};
+use {};
+use foo::*;
+use foo::{};
+use ::foo::{a, b, c};
diff --git a/crates/syntax/test_data/parser/ok/0015_use_tree.rast b/crates/syntax/test_data/parser/ok/0015_use_tree.rast
new file mode 100644
index 00000000000..d7e93f7eb75
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0015_use_tree.rast
@@ -0,0 +1,65 @@
+SOURCE_FILE@0..55
+  USE@0..15
+    USE_KW@0..3 "use"
+    WHITESPACE@3..4 " "
+    USE_TREE@4..14
+      PATH@4..7
+        PATH_SEGMENT@4..7
+          NAME_REF@4..7
+            IDENT@4..7 "foo"
+      WHITESPACE@7..8 " "
+      RENAME@8..14
+        AS_KW@8..10 "as"
+        WHITESPACE@10..11 " "
+        NAME@11..14
+          IDENT@11..14 "bar"
+    SEMICOLON@14..15 ";"
+  WHITESPACE@15..16 "\n"
+  USE@16..54
+    USE_KW@16..19 "use"
+    WHITESPACE@19..20 " "
+    USE_TREE@20..53
+      PATH@20..23
+        PATH_SEGMENT@20..23
+          NAME_REF@20..23
+            IDENT@20..23 "foo"
+      COLON2@23..25 "::"
+      USE_TREE_LIST@25..53
+        L_CURLY@25..26 "{"
+        USE_TREE@26..32
+          PATH@26..27
+            PATH_SEGMENT@26..27
+              NAME_REF@26..27
+                IDENT@26..27 "a"
+          WHITESPACE@27..28 " "
+          RENAME@28..32
+            AS_KW@28..30 "as"
+            WHITESPACE@30..31 " "
+            NAME@31..32
+              IDENT@31..32 "b"
+        COMMA@32..33 ","
+        WHITESPACE@33..34 " "
+        USE_TREE@34..35
+          STAR@34..35 "*"
+        COMMA@35..36 ","
+        WHITESPACE@36..37 " "
+        USE_TREE@37..40
+          COLON2@37..39 "::"
+          STAR@39..40 "*"
+        COMMA@40..41 ","
+        WHITESPACE@41..42 " "
+        USE_TREE@42..52
+          PATH@42..47
+            PATH_SEGMENT@42..47
+              COLON2@42..44 "::"
+              NAME_REF@44..47
+                IDENT@44..47 "foo"
+          WHITESPACE@47..48 " "
+          RENAME@48..52
+            AS_KW@48..50 "as"
+            WHITESPACE@50..51 " "
+            NAME@51..52
+              IDENT@51..52 "x"
+        R_CURLY@52..53 "}"
+    SEMICOLON@53..54 ";"
+  WHITESPACE@54..55 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0015_use_tree.rs b/crates/syntax/test_data/parser/ok/0015_use_tree.rs
new file mode 100644
index 00000000000..46a0783a2bd
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0015_use_tree.rs
@@ -0,0 +1,2 @@
+use foo as bar;
+use foo::{a as b, *, ::*, ::foo as x};
diff --git a/crates/syntax/test_data/parser/ok/0016_struct_flavors.rast b/crates/syntax/test_data/parser/ok/0016_struct_flavors.rast
new file mode 100644
index 00000000000..b15f41dd7e9
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0016_struct_flavors.rast
@@ -0,0 +1,93 @@
+SOURCE_FILE@0..97
+  STRUCT@0..9
+    STRUCT_KW@0..6 "struct"
+    WHITESPACE@6..7 " "
+    NAME@7..8
+      IDENT@7..8 "A"
+    SEMICOLON@8..9 ";"
+  WHITESPACE@9..10 "\n"
+  STRUCT@10..21
+    STRUCT_KW@10..16 "struct"
+    WHITESPACE@16..17 " "
+    NAME@17..18
+      IDENT@17..18 "B"
+    WHITESPACE@18..19 " "
+    RECORD_FIELD_LIST@19..21
+      L_CURLY@19..20 "{"
+      R_CURLY@20..21 "}"
+  WHITESPACE@21..22 "\n"
+  STRUCT@22..33
+    STRUCT_KW@22..28 "struct"
+    WHITESPACE@28..29 " "
+    NAME@29..30
+      IDENT@29..30 "C"
+    TUPLE_FIELD_LIST@30..32
+      L_PAREN@30..31 "("
+      R_PAREN@31..32 ")"
+    SEMICOLON@32..33 ";"
+  WHITESPACE@33..35 "\n\n"
+  STRUCT@35..74
+    STRUCT_KW@35..41 "struct"
+    WHITESPACE@41..42 " "
+    NAME@42..43
+      IDENT@42..43 "D"
+    WHITESPACE@43..44 " "
+    RECORD_FIELD_LIST@44..74
+      L_CURLY@44..45 "{"
+      WHITESPACE@45..50 "\n    "
+      RECORD_FIELD@50..56
+        NAME@50..51
+          IDENT@50..51 "a"
+        COLON@51..52 ":"
+        WHITESPACE@52..53 " "
+        PATH_TYPE@53..56
+          PATH@53..56
+            PATH_SEGMENT@53..56
+              NAME_REF@53..56
+                IDENT@53..56 "u32"
+      COMMA@56..57 ","
+      WHITESPACE@57..62 "\n    "
+      RECORD_FIELD@62..72
+        VISIBILITY@62..65
+          PUB_KW@62..65 "pub"
+        WHITESPACE@65..66 " "
+        NAME@66..67
+          IDENT@66..67 "b"
+        COLON@67..68 ":"
+        WHITESPACE@68..69 " "
+        PATH_TYPE@69..72
+          PATH@69..72
+            PATH_SEGMENT@69..72
+              NAME_REF@69..72
+                IDENT@69..72 "u32"
+      WHITESPACE@72..73 "\n"
+      R_CURLY@73..74 "}"
+  WHITESPACE@74..76 "\n\n"
+  STRUCT@76..96
+    STRUCT_KW@76..82 "struct"
+    WHITESPACE@82..83 " "
+    NAME@83..84
+      IDENT@83..84 "E"
+    TUPLE_FIELD_LIST@84..95
+      L_PAREN@84..85 "("
+      TUPLE_FIELD@85..90
+        VISIBILITY@85..88
+          PUB_KW@85..88 "pub"
+        WHITESPACE@88..89 " "
+        PATH_TYPE@89..90
+          PATH@89..90
+            PATH_SEGMENT@89..90
+              NAME_REF@89..90
+                IDENT@89..90 "x"
+      COMMA@90..91 ","
+      WHITESPACE@91..92 " "
+      TUPLE_FIELD@92..93
+        PATH_TYPE@92..93
+          PATH@92..93
+            PATH_SEGMENT@92..93
+              NAME_REF@92..93
+                IDENT@92..93 "y"
+      COMMA@93..94 ","
+      R_PAREN@94..95 ")"
+    SEMICOLON@95..96 ";"
+  WHITESPACE@96..97 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0016_struct_flavors.rs b/crates/syntax/test_data/parser/ok/0016_struct_flavors.rs
new file mode 100644
index 00000000000..69638350c46
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0016_struct_flavors.rs
@@ -0,0 +1,10 @@
+struct A;
+struct B {}
+struct C();
+
+struct D {
+    a: u32,
+    pub b: u32
+}
+
+struct E(pub x, y,);
diff --git a/crates/syntax/test_data/parser/ok/0017_attr_trailing_comma.rast b/crates/syntax/test_data/parser/ok/0017_attr_trailing_comma.rast
new file mode 100644
index 00000000000..a3e091ad369
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0017_attr_trailing_comma.rast
@@ -0,0 +1,28 @@
+SOURCE_FILE@0..23
+  FN@0..22
+    ATTR@0..10
+      POUND@0..1 "#"
+      L_BRACK@1..2 "["
+      PATH@2..5
+        PATH_SEGMENT@2..5
+          NAME_REF@2..5
+            IDENT@2..5 "foo"
+      TOKEN_TREE@5..9
+        L_PAREN@5..6 "("
+        IDENT@6..7 "a"
+        COMMA@7..8 ","
+        R_PAREN@8..9 ")"
+      R_BRACK@9..10 "]"
+    WHITESPACE@10..11 "\n"
+    FN_KW@11..13 "fn"
+    WHITESPACE@13..14 " "
+    NAME@14..17
+      IDENT@14..17 "foo"
+    PARAM_LIST@17..19
+      L_PAREN@17..18 "("
+      R_PAREN@18..19 ")"
+    WHITESPACE@19..20 " "
+    BLOCK_EXPR@20..22
+      L_CURLY@20..21 "{"
+      R_CURLY@21..22 "}"
+  WHITESPACE@22..23 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0017_attr_trailing_comma.rs b/crates/syntax/test_data/parser/ok/0017_attr_trailing_comma.rs
new file mode 100644
index 00000000000..fe0a7bb97e3
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0017_attr_trailing_comma.rs
@@ -0,0 +1,2 @@
+#[foo(a,)]
+fn foo() {}
diff --git a/crates/syntax/test_data/parser/ok/0018_struct_type_params.rast b/crates/syntax/test_data/parser/ok/0018_struct_type_params.rast
new file mode 100644
index 00000000000..630aa0708bb
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0018_struct_type_params.rast
@@ -0,0 +1,257 @@
+SOURCE_FILE@0..290
+  STRUCT@0..13
+    STRUCT_KW@0..6 "struct"
+    WHITESPACE@6..7 " "
+    NAME@7..9
+      IDENT@7..9 "S1"
+    GENERIC_PARAM_LIST@9..12
+      L_ANGLE@9..10 "<"
+      TYPE_PARAM@10..11
+        NAME@10..11
+          IDENT@10..11 "T"
+      R_ANGLE@11..12 ">"
+    SEMICOLON@12..13 ";"
+  WHITESPACE@13..14 "\n"
+  STRUCT@14..32
+    STRUCT_KW@14..20 "struct"
+    WHITESPACE@20..21 " "
+    NAME@21..23
+      IDENT@21..23 "S2"
+    GENERIC_PARAM_LIST@23..26
+      L_ANGLE@23..24 "<"
+      TYPE_PARAM@24..25
+        NAME@24..25
+          IDENT@24..25 "T"
+      R_ANGLE@25..26 ">"
+    TUPLE_FIELD_LIST@26..31
+      L_PAREN@26..27 "("
+      TUPLE_FIELD@27..30
+        PATH_TYPE@27..30
+          PATH@27..30
+            PATH_SEGMENT@27..30
+              NAME_REF@27..30
+                IDENT@27..30 "u32"
+      R_PAREN@30..31 ")"
+    SEMICOLON@31..32 ";"
+  WHITESPACE@32..33 "\n"
+  STRUCT@33..56
+    STRUCT_KW@33..39 "struct"
+    WHITESPACE@39..40 " "
+    NAME@40..42
+      IDENT@40..42 "S3"
+    GENERIC_PARAM_LIST@42..45
+      L_ANGLE@42..43 "<"
+      TYPE_PARAM@43..44
+        NAME@43..44
+          IDENT@43..44 "T"
+      R_ANGLE@44..45 ">"
+    WHITESPACE@45..46 " "
+    RECORD_FIELD_LIST@46..56
+      L_CURLY@46..47 "{"
+      WHITESPACE@47..48 " "
+      RECORD_FIELD@48..54
+        NAME@48..49
+          IDENT@48..49 "u"
+        COLON@49..50 ":"
+        WHITESPACE@50..51 " "
+        PATH_TYPE@51..54
+          PATH@51..54
+            PATH_SEGMENT@51..54
+              NAME_REF@51..54
+                IDENT@51..54 "u32"
+      WHITESPACE@54..55 " "
+      R_CURLY@55..56 "}"
+  WHITESPACE@56..58 "\n\n"
+  STRUCT@58..70
+    STRUCT_KW@58..64 "struct"
+    WHITESPACE@64..65 " "
+    NAME@65..67
+      IDENT@65..67 "S4"
+    GENERIC_PARAM_LIST@67..69
+      L_ANGLE@67..68 "<"
+      R_ANGLE@68..69 ">"
+    SEMICOLON@69..70 ";"
+  WHITESPACE@70..71 "\n"
+  STRUCT@71..85
+    STRUCT_KW@71..77 "struct"
+    WHITESPACE@77..78 " "
+    NAME@78..80
+      IDENT@78..80 "S5"
+    GENERIC_PARAM_LIST@80..84
+      L_ANGLE@80..81 "<"
+      LIFETIME_PARAM@81..83
+        LIFETIME@81..83 "\'a"
+      R_ANGLE@83..84 ">"
+    SEMICOLON@84..85 ";"
+  WHITESPACE@85..86 "\n"
+  STRUCT@86..101
+    STRUCT_KW@86..92 "struct"
+    WHITESPACE@92..93 " "
+    NAME@93..95
+      IDENT@93..95 "S6"
+    GENERIC_PARAM_LIST@95..100
+      L_ANGLE@95..96 "<"
+      LIFETIME_PARAM@96..99
+        LIFETIME@96..98 "\'a"
+        COLON@98..99 ":"
+      R_ANGLE@99..100 ">"
+    SEMICOLON@100..101 ";"
+  WHITESPACE@101..102 "\n"
+  STRUCT@102..120
+    STRUCT_KW@102..108 "struct"
+    WHITESPACE@108..109 " "
+    NAME@109..111
+      IDENT@109..111 "S7"
+    GENERIC_PARAM_LIST@111..119
+      L_ANGLE@111..112 "<"
+      LIFETIME_PARAM@112..118
+        LIFETIME@112..114 "\'a"
+        COLON@114..115 ":"
+        WHITESPACE@115..116 " "
+        LIFETIME@116..118 "\'b"
+      R_ANGLE@118..119 ">"
+    SEMICOLON@119..120 ";"
+  WHITESPACE@120..121 "\n"
+  STRUCT@121..142
+    STRUCT_KW@121..127 "struct"
+    WHITESPACE@127..128 " "
+    NAME@128..130
+      IDENT@128..130 "S8"
+    GENERIC_PARAM_LIST@130..141
+      L_ANGLE@130..131 "<"
+      LIFETIME_PARAM@131..139
+        LIFETIME@131..133 "\'a"
+        COLON@133..134 ":"
+        WHITESPACE@134..135 " "
+        LIFETIME@135..137 "\'b"
+        WHITESPACE@137..138 " "
+        PLUS@138..139 "+"
+      WHITESPACE@139..140 " "
+      R_ANGLE@140..141 ">"
+    SEMICOLON@141..142 ";"
+  WHITESPACE@142..143 "\n"
+  STRUCT@143..166
+    STRUCT_KW@143..149 "struct"
+    WHITESPACE@149..150 " "
+    NAME@150..152
+      IDENT@150..152 "S9"
+    GENERIC_PARAM_LIST@152..165
+      L_ANGLE@152..153 "<"
+      LIFETIME_PARAM@153..164
+        LIFETIME@153..155 "\'a"
+        COLON@155..156 ":"
+        WHITESPACE@156..157 " "
+        LIFETIME@157..159 "\'b"
+        WHITESPACE@159..160 " "
+        PLUS@160..161 "+"
+        WHITESPACE@161..162 " "
+        LIFETIME@162..164 "\'c"
+      R_ANGLE@164..165 ">"
+    SEMICOLON@165..166 ";"
+  WHITESPACE@166..167 "\n"
+  STRUCT@167..183
+    STRUCT_KW@167..173 "struct"
+    WHITESPACE@173..174 " "
+    NAME@174..177
+      IDENT@174..177 "S10"
+    GENERIC_PARAM_LIST@177..182
+      L_ANGLE@177..178 "<"
+      LIFETIME_PARAM@178..180
+        LIFETIME@178..180 "\'a"
+      COMMA@180..181 ","
+      R_ANGLE@181..182 ">"
+    SEMICOLON@182..183 ";"
+  WHITESPACE@183..184 "\n"
+  STRUCT@184..203
+    STRUCT_KW@184..190 "struct"
+    WHITESPACE@190..191 " "
+    NAME@191..194
+      IDENT@191..194 "S11"
+    GENERIC_PARAM_LIST@194..202
+      L_ANGLE@194..195 "<"
+      LIFETIME_PARAM@195..197
+        LIFETIME@195..197 "\'a"
+      COMMA@197..198 ","
+      WHITESPACE@198..199 " "
+      LIFETIME_PARAM@199..201
+        LIFETIME@199..201 "\'b"
+      R_ANGLE@201..202 ">"
+    SEMICOLON@202..203 ";"
+  WHITESPACE@203..204 "\n"
+  STRUCT@204..233
+    STRUCT_KW@204..210 "struct"
+    WHITESPACE@210..211 " "
+    NAME@211..214
+      IDENT@211..214 "S12"
+    GENERIC_PARAM_LIST@214..232
+      L_ANGLE@214..215 "<"
+      LIFETIME_PARAM@215..222
+        LIFETIME@215..217 "\'a"
+        COLON@217..218 ":"
+        WHITESPACE@218..219 " "
+        LIFETIME@219..221 "\'b"
+        PLUS@221..222 "+"
+      COMMA@222..223 ","
+      WHITESPACE@223..224 " "
+      LIFETIME_PARAM@224..230
+        LIFETIME@224..226 "\'b"
+        COLON@226..227 ":"
+        WHITESPACE@227..228 " "
+        LIFETIME@228..230 "\'c"
+      COMMA@230..231 ","
+      R_ANGLE@231..232 ">"
+    SEMICOLON@232..233 ";"
+  WHITESPACE@233..235 "\n\n"
+  STRUCT@235..249
+    STRUCT_KW@235..241 "struct"
+    WHITESPACE@241..242 " "
+    NAME@242..245
+      IDENT@242..245 "S13"
+    GENERIC_PARAM_LIST@245..248
+      L_ANGLE@245..246 "<"
+      TYPE_PARAM@246..247
+        NAME@246..247
+          IDENT@246..247 "T"
+      R_ANGLE@247..248 ">"
+    SEMICOLON@248..249 ";"
+  WHITESPACE@249..250 "\n"
+  STRUCT@250..267
+    STRUCT_KW@250..256 "struct"
+    WHITESPACE@256..257 " "
+    NAME@257..260
+      IDENT@257..260 "S14"
+    GENERIC_PARAM_LIST@260..266
+      L_ANGLE@260..261 "<"
+      TYPE_PARAM@261..262
+        NAME@261..262
+          IDENT@261..262 "T"
+      COMMA@262..263 ","
+      WHITESPACE@263..264 " "
+      TYPE_PARAM@264..265
+        NAME@264..265
+          IDENT@264..265 "U"
+      R_ANGLE@265..266 ">"
+    SEMICOLON@266..267 ";"
+  WHITESPACE@267..268 "\n"
+  STRUCT@268..289
+    STRUCT_KW@268..274 "struct"
+    WHITESPACE@274..275 " "
+    NAME@275..278
+      IDENT@275..278 "S15"
+    GENERIC_PARAM_LIST@278..288
+      L_ANGLE@278..279 "<"
+      LIFETIME_PARAM@279..281
+        LIFETIME@279..281 "\'a"
+      COMMA@281..282 ","
+      WHITESPACE@282..283 " "
+      TYPE_PARAM@283..284
+        NAME@283..284
+          IDENT@283..284 "T"
+      COMMA@284..285 ","
+      WHITESPACE@285..286 " "
+      TYPE_PARAM@286..287
+        NAME@286..287
+          IDENT@286..287 "U"
+      R_ANGLE@287..288 ">"
+    SEMICOLON@288..289 ";"
+  WHITESPACE@289..290 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0018_struct_type_params.rs b/crates/syntax/test_data/parser/ok/0018_struct_type_params.rs
new file mode 100644
index 00000000000..88c544923b5
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0018_struct_type_params.rs
@@ -0,0 +1,17 @@
+struct S1<T>;
+struct S2<T>(u32);
+struct S3<T> { u: u32 }
+
+struct S4<>;
+struct S5<'a>;
+struct S6<'a:>;
+struct S7<'a: 'b>;
+struct S8<'a: 'b + >;
+struct S9<'a: 'b + 'c>;
+struct S10<'a,>;
+struct S11<'a, 'b>;
+struct S12<'a: 'b+, 'b: 'c,>;
+
+struct S13<T>;
+struct S14<T, U>;
+struct S15<'a, T, U>;
diff --git a/crates/syntax/test_data/parser/ok/0019_enums.rast b/crates/syntax/test_data/parser/ok/0019_enums.rast
new file mode 100644
index 00000000000..c3df008146d
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0019_enums.rast
@@ -0,0 +1,155 @@
+SOURCE_FILE@0..182
+  ENUM@0..11
+    ENUM_KW@0..4 "enum"
+    WHITESPACE@4..5 " "
+    NAME@5..7
+      IDENT@5..7 "E1"
+    WHITESPACE@7..8 " "
+    VARIANT_LIST@8..11
+      L_CURLY@8..9 "{"
+      WHITESPACE@9..10 "\n"
+      R_CURLY@10..11 "}"
+  WHITESPACE@11..13 "\n\n"
+  ENUM@13..27
+    ENUM_KW@13..17 "enum"
+    WHITESPACE@17..18 " "
+    NAME@18..20
+      IDENT@18..20 "E2"
+    GENERIC_PARAM_LIST@20..23
+      L_ANGLE@20..21 "<"
+      TYPE_PARAM@21..22
+        NAME@21..22
+          IDENT@21..22 "T"
+      R_ANGLE@22..23 ">"
+    WHITESPACE@23..24 " "
+    VARIANT_LIST@24..27
+      L_CURLY@24..25 "{"
+      WHITESPACE@25..26 "\n"
+      R_CURLY@26..27 "}"
+  WHITESPACE@27..29 "\n\n"
+  ENUM@29..46
+    ENUM_KW@29..33 "enum"
+    WHITESPACE@33..34 " "
+    NAME@34..36
+      IDENT@34..36 "E3"
+    WHITESPACE@36..37 " "
+    VARIANT_LIST@37..46
+      L_CURLY@37..38 "{"
+      WHITESPACE@38..43 "\n    "
+      VARIANT@43..44
+        NAME@43..44
+          IDENT@43..44 "X"
+      WHITESPACE@44..45 "\n"
+      R_CURLY@45..46 "}"
+  WHITESPACE@46..48 "\n\n"
+  ENUM@48..66
+    ENUM_KW@48..52 "enum"
+    WHITESPACE@52..53 " "
+    NAME@53..55
+      IDENT@53..55 "E4"
+    WHITESPACE@55..56 " "
+    VARIANT_LIST@56..66
+      L_CURLY@56..57 "{"
+      WHITESPACE@57..62 "\n    "
+      VARIANT@62..63
+        NAME@62..63
+          IDENT@62..63 "X"
+      COMMA@63..64 ","
+      WHITESPACE@64..65 "\n"
+      R_CURLY@65..66 "}"
+  WHITESPACE@66..68 "\n\n"
+  ENUM@68..181
+    ENUM_KW@68..72 "enum"
+    WHITESPACE@72..73 " "
+    NAME@73..75
+      IDENT@73..75 "E5"
+    WHITESPACE@75..76 " "
+    VARIANT_LIST@76..181
+      L_CURLY@76..77 "{"
+      WHITESPACE@77..82 "\n    "
+      VARIANT@82..83
+        NAME@82..83
+          IDENT@82..83 "A"
+      COMMA@83..84 ","
+      WHITESPACE@84..89 "\n    "
+      VARIANT@89..95
+        NAME@89..90
+          IDENT@89..90 "B"
+        WHITESPACE@90..91 " "
+        EQ@91..92 "="
+        WHITESPACE@92..93 " "
+        LITERAL@93..95
+          INT_NUMBER@93..95 "92"
+      COMMA@95..96 ","
+      WHITESPACE@96..101 "\n    "
+      VARIANT@101..146
+        NAME@101..102
+          IDENT@101..102 "C"
+        WHITESPACE@102..103 " "
+        RECORD_FIELD_LIST@103..146
+          L_CURLY@103..104 "{"
+          WHITESPACE@104..113 "\n        "
+          RECORD_FIELD@113..119
+            NAME@113..114
+              IDENT@113..114 "a"
+            COLON@114..115 ":"
+            WHITESPACE@115..116 " "
+            PATH_TYPE@116..119
+              PATH@116..119
+                PATH_SEGMENT@116..119
+                  NAME_REF@116..119
+                    IDENT@116..119 "u32"
+          COMMA@119..120 ","
+          WHITESPACE@120..129 "\n        "
+          RECORD_FIELD@129..139
+            VISIBILITY@129..132
+              PUB_KW@129..132 "pub"
+            WHITESPACE@132..133 " "
+            NAME@133..134
+              IDENT@133..134 "b"
+            COLON@134..135 ":"
+            WHITESPACE@135..136 " "
+            PATH_TYPE@136..139
+              PATH@136..139
+                PATH_SEGMENT@136..139
+                  NAME_REF@136..139
+                    IDENT@136..139 "f64"
+          COMMA@139..140 ","
+          WHITESPACE@140..145 "\n    "
+          R_CURLY@145..146 "}"
+      COMMA@146..147 ","
+      WHITESPACE@147..152 "\n    "
+      VARIANT@152..156
+        NAME@152..153
+          IDENT@152..153 "F"
+        WHITESPACE@153..154 " "
+        RECORD_FIELD_LIST@154..156
+          L_CURLY@154..155 "{"
+          R_CURLY@155..156 "}"
+      COMMA@156..157 ","
+      WHITESPACE@157..162 "\n    "
+      VARIANT@162..169
+        NAME@162..163
+          IDENT@162..163 "D"
+        TUPLE_FIELD_LIST@163..169
+          L_PAREN@163..164 "("
+          TUPLE_FIELD@164..167
+            PATH_TYPE@164..167
+              PATH@164..167
+                PATH_SEGMENT@164..167
+                  NAME_REF@164..167
+                    IDENT@164..167 "u32"
+          COMMA@167..168 ","
+          R_PAREN@168..169 ")"
+      COMMA@169..170 ","
+      WHITESPACE@170..175 "\n    "
+      VARIANT@175..178
+        NAME@175..176
+          IDENT@175..176 "E"
+        TUPLE_FIELD_LIST@176..178
+          L_PAREN@176..177 "("
+          R_PAREN@177..178 ")"
+      COMMA@178..179 ","
+      WHITESPACE@179..180 "\n"
+      R_CURLY@180..181 "}"
+  WHITESPACE@181..182 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0019_enums.rs b/crates/syntax/test_data/parser/ok/0019_enums.rs
new file mode 100644
index 00000000000..7a1afa0e62f
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0019_enums.rs
@@ -0,0 +1,25 @@
+enum E1 {
+}
+
+enum E2<T> {
+}
+
+enum E3 {
+    X
+}
+
+enum E4 {
+    X,
+}
+
+enum E5 {
+    A,
+    B = 92,
+    C {
+        a: u32,
+        pub b: f64,
+    },
+    F {},
+    D(u32,),
+    E(),
+}
diff --git a/crates/syntax/test_data/parser/ok/0020_type_param_bounds.rast b/crates/syntax/test_data/parser/ok/0020_type_param_bounds.rast
new file mode 100644
index 00000000000..9bdc50e1e79
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0020_type_param_bounds.rast
@@ -0,0 +1,268 @@
+SOURCE_FILE@0..250
+  STRUCT@0..12
+    STRUCT_KW@0..6 "struct"
+    WHITESPACE@6..7 " "
+    NAME@7..8
+      IDENT@7..8 "A"
+    GENERIC_PARAM_LIST@8..11
+      L_ANGLE@8..9 "<"
+      TYPE_PARAM@9..10
+        NAME@9..10
+          IDENT@9..10 "T"
+      R_ANGLE@10..11 ">"
+    SEMICOLON@11..12 ";"
+  WHITESPACE@12..13 "\n"
+  STRUCT@13..26
+    STRUCT_KW@13..19 "struct"
+    WHITESPACE@19..20 " "
+    NAME@20..21
+      IDENT@20..21 "B"
+    GENERIC_PARAM_LIST@21..25
+      L_ANGLE@21..22 "<"
+      TYPE_PARAM@22..24
+        NAME@22..23
+          IDENT@22..23 "T"
+        COLON@23..24 ":"
+        TYPE_BOUND_LIST@24..24
+      R_ANGLE@24..25 ">"
+    SEMICOLON@25..26 ";"
+  WHITESPACE@26..27 "\n"
+  STRUCT@27..43
+    STRUCT_KW@27..33 "struct"
+    WHITESPACE@33..34 " "
+    NAME@34..35
+      IDENT@34..35 "C"
+    GENERIC_PARAM_LIST@35..42
+      L_ANGLE@35..36 "<"
+      TYPE_PARAM@36..41
+        NAME@36..37
+          IDENT@36..37 "T"
+        COLON@37..38 ":"
+        WHITESPACE@38..39 " "
+        TYPE_BOUND_LIST@39..41
+          TYPE_BOUND@39..41
+            LIFETIME@39..41 "\'a"
+      R_ANGLE@41..42 ">"
+    SEMICOLON@42..43 ";"
+  WHITESPACE@43..44 "\n"
+  STRUCT@44..63
+    STRUCT_KW@44..50 "struct"
+    WHITESPACE@50..51 " "
+    NAME@51..52
+      IDENT@51..52 "D"
+    GENERIC_PARAM_LIST@52..62
+      L_ANGLE@52..53 "<"
+      TYPE_PARAM@53..60
+        NAME@53..54
+          IDENT@53..54 "T"
+        COLON@54..55 ":"
+        WHITESPACE@55..56 " "
+        TYPE_BOUND_LIST@56..60
+          TYPE_BOUND@56..58
+            LIFETIME@56..58 "\'a"
+          WHITESPACE@58..59 " "
+          PLUS@59..60 "+"
+      WHITESPACE@60..61 " "
+      R_ANGLE@61..62 ">"
+    SEMICOLON@62..63 ";"
+  WHITESPACE@63..64 "\n"
+  STRUCT@64..86
+    STRUCT_KW@64..70 "struct"
+    WHITESPACE@70..71 " "
+    NAME@71..72
+      IDENT@71..72 "E"
+    GENERIC_PARAM_LIST@72..85
+      L_ANGLE@72..73 "<"
+      TYPE_PARAM@73..83
+        NAME@73..74
+          IDENT@73..74 "T"
+        COLON@74..75 ":"
+        WHITESPACE@75..76 " "
+        TYPE_BOUND_LIST@76..83
+          TYPE_BOUND@76..78
+            LIFETIME@76..78 "\'a"
+          WHITESPACE@78..79 " "
+          PLUS@79..80 "+"
+          WHITESPACE@80..81 " "
+          TYPE_BOUND@81..83
+            LIFETIME@81..83 "\'d"
+      WHITESPACE@83..84 " "
+      R_ANGLE@84..85 ">"
+    SEMICOLON@85..86 ";"
+  WHITESPACE@86..87 "\n"
+  STRUCT@87..116
+    STRUCT_KW@87..93 "struct"
+    WHITESPACE@93..94 " "
+    NAME@94..95
+      IDENT@94..95 "F"
+    GENERIC_PARAM_LIST@95..115
+      L_ANGLE@95..96 "<"
+      TYPE_PARAM@96..114
+        NAME@96..97
+          IDENT@96..97 "T"
+        COLON@97..98 ":"
+        WHITESPACE@98..99 " "
+        TYPE_BOUND_LIST@99..114
+          TYPE_BOUND@99..101
+            LIFETIME@99..101 "\'a"
+          WHITESPACE@101..102 " "
+          PLUS@102..103 "+"
+          WHITESPACE@103..104 " "
+          TYPE_BOUND@104..106
+            LIFETIME@104..106 "\'d"
+          WHITESPACE@106..107 " "
+          PLUS@107..108 "+"
+          WHITESPACE@108..109 " "
+          TYPE_BOUND@109..114
+            PATH_TYPE@109..114
+              PATH@109..114
+                PATH_SEGMENT@109..114
+                  NAME_REF@109..114
+                    IDENT@109..114 "Clone"
+      R_ANGLE@114..115 ">"
+    SEMICOLON@115..116 ";"
+  WHITESPACE@116..117 "\n"
+  STRUCT@117..143
+    STRUCT_KW@117..123 "struct"
+    WHITESPACE@123..124 " "
+    NAME@124..125
+      IDENT@124..125 "G"
+    GENERIC_PARAM_LIST@125..142
+      L_ANGLE@125..126 "<"
+      TYPE_PARAM@126..141
+        NAME@126..127
+          IDENT@126..127 "T"
+        COLON@127..128 ":"
+        WHITESPACE@128..129 " "
+        TYPE_BOUND_LIST@129..141
+          TYPE_BOUND@129..134
+            PATH_TYPE@129..134
+              PATH@129..134
+                PATH_SEGMENT@129..134
+                  NAME_REF@129..134
+                    IDENT@129..134 "Clone"
+          WHITESPACE@134..135 " "
+          PLUS@135..136 "+"
+          WHITESPACE@136..137 " "
+          TYPE_BOUND@137..141
+            PATH_TYPE@137..141
+              PATH@137..141
+                PATH_SEGMENT@137..141
+                  NAME_REF@137..141
+                    IDENT@137..141 "Copy"
+      R_ANGLE@141..142 ">"
+    SEMICOLON@142..143 ";"
+  WHITESPACE@143..144 "\n"
+  STRUCT@144..180
+    STRUCT_KW@144..150 "struct"
+    WHITESPACE@150..151 " "
+    NAME@151..152
+      IDENT@151..152 "H"
+    GENERIC_PARAM_LIST@152..179
+      L_ANGLE@152..153 "<"
+      TYPE_PARAM@153..178
+        NAME@153..154
+          IDENT@153..154 "T"
+        COLON@154..155 ":"
+        WHITESPACE@155..156 " "
+        TYPE_BOUND_LIST@156..178
+          TYPE_BOUND@156..161
+            PATH_TYPE@156..161
+              PATH@156..161
+                PATH_SEGMENT@156..161
+                  COLON2@156..158 "::"
+                  NAME_REF@158..161
+                    IDENT@158..161 "Foo"
+          WHITESPACE@161..162 " "
+          PLUS@162..163 "+"
+          WHITESPACE@163..164 " "
+          TYPE_BOUND@164..173
+            PATH_TYPE@164..173
+              PATH@164..173
+                PATH@164..168
+                  PATH_SEGMENT@164..168
+                    SELF_KW@164..168 "self"
+                COLON2@168..170 "::"
+                PATH_SEGMENT@170..173
+                  NAME_REF@170..173
+                    IDENT@170..173 "Bar"
+          WHITESPACE@173..174 " "
+          PLUS@174..175 "+"
+          WHITESPACE@175..176 " "
+          TYPE_BOUND@176..178
+            LIFETIME@176..178 "\'a"
+      R_ANGLE@178..179 ">"
+    SEMICOLON@179..180 ";"
+  WHITESPACE@180..181 "\n"
+  STRUCT@181..199
+    STRUCT_KW@181..187 "struct"
+    WHITESPACE@187..188 " "
+    NAME@188..189
+      IDENT@188..189 "I"
+    GENERIC_PARAM_LIST@189..198
+      L_ANGLE@189..190 "<"
+      TYPE_PARAM@190..192
+        NAME@190..191
+          IDENT@190..191 "T"
+        COLON@191..192 ":"
+        TYPE_BOUND_LIST@192..192
+      COMMA@192..193 ","
+      WHITESPACE@193..194 " "
+      TYPE_PARAM@194..196
+        NAME@194..195
+          IDENT@194..195 "U"
+        COLON@195..196 ":"
+        TYPE_BOUND_LIST@196..196
+      COMMA@196..197 ","
+      R_ANGLE@197..198 ">"
+    SEMICOLON@198..199 ";"
+  WHITESPACE@199..200 "\n"
+  STRUCT@200..250
+    STRUCT_KW@200..206 "struct"
+    WHITESPACE@206..207 " "
+    NAME@207..208
+      IDENT@207..208 "K"
+    GENERIC_PARAM_LIST@208..249
+      L_ANGLE@208..209 "<"
+      LIFETIME_PARAM@209..215
+        LIFETIME@209..211 "\'a"
+        COLON@211..212 ":"
+        WHITESPACE@212..213 " "
+        LIFETIME@213..215 "\'d"
+      COMMA@215..216 ","
+      WHITESPACE@216..217 " "
+      LIFETIME_PARAM@217..228
+        LIFETIME@217..219 "\'d"
+        COLON@219..220 ":"
+        WHITESPACE@220..221 " "
+        LIFETIME@221..223 "\'a"
+        WHITESPACE@223..224 " "
+        PLUS@224..225 "+"
+        WHITESPACE@225..226 " "
+        LIFETIME@226..228 "\'b"
+      COMMA@228..229 ","
+      WHITESPACE@229..230 " "
+      TYPE_PARAM@230..248
+        NAME@230..231
+          IDENT@230..231 "T"
+        COLON@231..232 ":"
+        WHITESPACE@232..233 " "
+        TYPE_BOUND_LIST@233..248
+          TYPE_BOUND@233..235
+            LIFETIME@233..235 "\'a"
+          WHITESPACE@235..236 " "
+          PLUS@236..237 "+"
+          WHITESPACE@237..238 " "
+          TYPE_BOUND@238..240
+            LIFETIME@238..240 "\'d"
+          WHITESPACE@240..241 " "
+          PLUS@241..242 "+"
+          WHITESPACE@242..243 " "
+          TYPE_BOUND@243..248
+            PATH_TYPE@243..248
+              PATH@243..248
+                PATH_SEGMENT@243..248
+                  NAME_REF@243..248
+                    IDENT@243..248 "Clone"
+      R_ANGLE@248..249 ">"
+    SEMICOLON@249..250 ";"
diff --git a/crates/syntax/test_data/parser/ok/0020_type_param_bounds.rs b/crates/syntax/test_data/parser/ok/0020_type_param_bounds.rs
new file mode 100644
index 00000000000..7128989789a
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0020_type_param_bounds.rs
@@ -0,0 +1,10 @@
+struct A<T>;
+struct B<T:>;
+struct C<T: 'a>;
+struct D<T: 'a + >;
+struct E<T: 'a + 'd >;
+struct F<T: 'a + 'd + Clone>;
+struct G<T: Clone + Copy>;
+struct H<T: ::Foo + self::Bar + 'a>;
+struct I<T:, U:,>;
+struct K<'a: 'd, 'd: 'a + 'b, T: 'a + 'd + Clone>;
\ No newline at end of file
diff --git a/crates/syntax/test_data/parser/ok/0022_empty_extern_block.rast b/crates/syntax/test_data/parser/ok/0022_empty_extern_block.rast
new file mode 100644
index 00000000000..26abae3b29d
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0022_empty_extern_block.rast
@@ -0,0 +1,21 @@
+SOURCE_FILE@0..27
+  EXTERN_BLOCK@0..10
+    ABI@0..6
+      EXTERN_KW@0..6 "extern"
+    WHITESPACE@6..7 " "
+    EXTERN_ITEM_LIST@7..10
+      L_CURLY@7..8 "{"
+      WHITESPACE@8..9 "\n"
+      R_CURLY@9..10 "}"
+  WHITESPACE@10..12 "\n\n"
+  EXTERN_BLOCK@12..26
+    ABI@12..22
+      EXTERN_KW@12..18 "extern"
+      WHITESPACE@18..19 " "
+      STRING@19..22 "\"C\""
+    WHITESPACE@22..23 " "
+    EXTERN_ITEM_LIST@23..26
+      L_CURLY@23..24 "{"
+      WHITESPACE@24..25 "\n"
+      R_CURLY@25..26 "}"
+  WHITESPACE@26..27 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0022_empty_extern_block.rs b/crates/syntax/test_data/parser/ok/0022_empty_extern_block.rs
new file mode 100644
index 00000000000..f5fe0e6ef30
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0022_empty_extern_block.rs
@@ -0,0 +1,5 @@
+extern {
+}
+
+extern "C" {
+}
diff --git a/crates/syntax/test_data/parser/ok/0023_static_items.rast b/crates/syntax/test_data/parser/ok/0023_static_items.rast
new file mode 100644
index 00000000000..9374cf5e965
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0023_static_items.rast
@@ -0,0 +1,41 @@
+SOURCE_FILE@0..47
+  STATIC@0..20
+    STATIC_KW@0..6 "static"
+    WHITESPACE@6..7 " "
+    NAME@7..10
+      IDENT@7..10 "FOO"
+    COLON@10..11 ":"
+    WHITESPACE@11..12 " "
+    PATH_TYPE@12..15
+      PATH@12..15
+        PATH_SEGMENT@12..15
+          NAME_REF@12..15
+            IDENT@12..15 "u32"
+    WHITESPACE@15..16 " "
+    EQ@16..17 "="
+    WHITESPACE@17..18 " "
+    LITERAL@18..19
+      INT_NUMBER@18..19 "1"
+    SEMICOLON@19..20 ";"
+  WHITESPACE@20..21 "\n"
+  STATIC@21..46
+    STATIC_KW@21..27 "static"
+    WHITESPACE@27..28 " "
+    MUT_KW@28..31 "mut"
+    WHITESPACE@31..32 " "
+    NAME@32..35
+      IDENT@32..35 "BAR"
+    COLON@35..36 ":"
+    WHITESPACE@36..37 " "
+    PATH_TYPE@37..40
+      PATH@37..40
+        PATH_SEGMENT@37..40
+          NAME_REF@37..40
+            IDENT@37..40 "i32"
+    WHITESPACE@40..41 " "
+    EQ@41..42 "="
+    WHITESPACE@42..43 " "
+    LITERAL@43..45
+      INT_NUMBER@43..45 "92"
+    SEMICOLON@45..46 ";"
+  WHITESPACE@46..47 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0023_static_items.rs b/crates/syntax/test_data/parser/ok/0023_static_items.rs
new file mode 100644
index 00000000000..5fb92ce33f0
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0023_static_items.rs
@@ -0,0 +1,2 @@
+static FOO: u32 = 1;
+static mut BAR: i32 = 92;
diff --git a/crates/syntax/test_data/parser/ok/0024_const_item.rast b/crates/syntax/test_data/parser/ok/0024_const_item.rast
new file mode 100644
index 00000000000..dd1b9c9a0a4
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0024_const_item.rast
@@ -0,0 +1,59 @@
+SOURCE_FILE@0..64
+  CONST@0..17
+    CONST_KW@0..5 "const"
+    WHITESPACE@5..6 " "
+    UNDERSCORE@6..7 "_"
+    COLON@7..8 ":"
+    WHITESPACE@8..9 " "
+    PATH_TYPE@9..12
+      PATH@9..12
+        PATH_SEGMENT@9..12
+          NAME_REF@9..12
+            IDENT@9..12 "u32"
+    WHITESPACE@12..13 " "
+    EQ@13..14 "="
+    WHITESPACE@14..15 " "
+    LITERAL@15..16
+      INT_NUMBER@15..16 "0"
+    SEMICOLON@16..17 ";"
+  WHITESPACE@17..18 "\n"
+  CONST@18..38
+    CONST_KW@18..23 "const"
+    WHITESPACE@23..24 " "
+    NAME@24..27
+      IDENT@24..27 "FOO"
+    COLON@27..28 ":"
+    WHITESPACE@28..29 " "
+    PATH_TYPE@29..32
+      PATH@29..32
+        PATH_SEGMENT@29..32
+          NAME_REF@29..32
+            IDENT@29..32 "u32"
+    WHITESPACE@32..33 " "
+    EQ@33..34 "="
+    WHITESPACE@34..35 " "
+    LITERAL@35..37
+      INT_NUMBER@35..37 "92"
+    SEMICOLON@37..38 ";"
+  WHITESPACE@38..39 "\n"
+  CONST@39..63
+    CONST_KW@39..44 "const"
+    WHITESPACE@44..45 " "
+    MUT_KW@45..48 "mut"
+    WHITESPACE@48..49 " "
+    NAME@49..52
+      IDENT@49..52 "BAR"
+    COLON@52..53 ":"
+    WHITESPACE@53..54 " "
+    PATH_TYPE@54..57
+      PATH@54..57
+        PATH_SEGMENT@54..57
+          NAME_REF@54..57
+            IDENT@54..57 "u32"
+    WHITESPACE@57..58 " "
+    EQ@58..59 "="
+    WHITESPACE@59..60 " "
+    LITERAL@60..62
+      INT_NUMBER@60..62 "62"
+    SEMICOLON@62..63 ";"
+  WHITESPACE@63..64 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0024_const_item.rs b/crates/syntax/test_data/parser/ok/0024_const_item.rs
new file mode 100644
index 00000000000..a806a209dc1
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0024_const_item.rs
@@ -0,0 +1,3 @@
+const _: u32 = 0;
+const FOO: u32 = 92;
+const mut BAR: u32 = 62;
diff --git a/crates/syntax/test_data/parser/ok/0025_extern_fn_in_block.rast b/crates/syntax/test_data/parser/ok/0025_extern_fn_in_block.rast
new file mode 100644
index 00000000000..bb6527b484a
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0025_extern_fn_in_block.rast
@@ -0,0 +1,31 @@
+SOURCE_FILE@0..35
+  FN@0..34
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..34
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      FN@16..32
+        ABI@16..22
+          EXTERN_KW@16..22 "extern"
+        WHITESPACE@22..23 " "
+        FN_KW@23..25 "fn"
+        WHITESPACE@25..26 " "
+        NAME@26..27
+          IDENT@26..27 "f"
+        PARAM_LIST@27..29
+          L_PAREN@27..28 "("
+          R_PAREN@28..29 ")"
+        WHITESPACE@29..30 " "
+        BLOCK_EXPR@30..32
+          L_CURLY@30..31 "{"
+          R_CURLY@31..32 "}"
+      WHITESPACE@32..33 "\n"
+      R_CURLY@33..34 "}"
+  WHITESPACE@34..35 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0025_extern_fn_in_block.rs b/crates/syntax/test_data/parser/ok/0025_extern_fn_in_block.rs
new file mode 100644
index 00000000000..289809809a6
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0025_extern_fn_in_block.rs
@@ -0,0 +1,3 @@
+fn main() {
+    extern fn f() {}
+}
diff --git a/crates/syntax/test_data/parser/ok/0026_const_fn_in_block.rast b/crates/syntax/test_data/parser/ok/0026_const_fn_in_block.rast
new file mode 100644
index 00000000000..5bcf54deb69
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0026_const_fn_in_block.rast
@@ -0,0 +1,30 @@
+SOURCE_FILE@0..34
+  FN@0..33
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..33
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      FN@16..31
+        CONST_KW@16..21 "const"
+        WHITESPACE@21..22 " "
+        FN_KW@22..24 "fn"
+        WHITESPACE@24..25 " "
+        NAME@25..26
+          IDENT@25..26 "f"
+        PARAM_LIST@26..28
+          L_PAREN@26..27 "("
+          R_PAREN@27..28 ")"
+        WHITESPACE@28..29 " "
+        BLOCK_EXPR@29..31
+          L_CURLY@29..30 "{"
+          R_CURLY@30..31 "}"
+      WHITESPACE@31..32 "\n"
+      R_CURLY@32..33 "}"
+  WHITESPACE@33..34 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0026_const_fn_in_block.rs b/crates/syntax/test_data/parser/ok/0026_const_fn_in_block.rs
new file mode 100644
index 00000000000..7641a3d28e6
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0026_const_fn_in_block.rs
@@ -0,0 +1,3 @@
+fn main() {
+    const fn f() {}
+}
diff --git a/crates/syntax/test_data/parser/ok/0027_unsafe_fn_in_block.rast b/crates/syntax/test_data/parser/ok/0027_unsafe_fn_in_block.rast
new file mode 100644
index 00000000000..a7cc122951f
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0027_unsafe_fn_in_block.rast
@@ -0,0 +1,41 @@
+SOURCE_FILE@0..53
+  FN@0..52
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..52
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      FN@16..32
+        UNSAFE_KW@16..22 "unsafe"
+        WHITESPACE@22..23 " "
+        FN_KW@23..25 "fn"
+        WHITESPACE@25..26 " "
+        NAME@26..27
+          IDENT@26..27 "f"
+        PARAM_LIST@27..29
+          L_PAREN@27..28 "("
+          R_PAREN@28..29 ")"
+        WHITESPACE@29..30 " "
+        BLOCK_EXPR@30..32
+          L_CURLY@30..31 "{"
+          R_CURLY@31..32 "}"
+      WHITESPACE@32..37 "\n    "
+      EFFECT_EXPR@37..50
+        UNSAFE_KW@37..43 "unsafe"
+        WHITESPACE@43..44 " "
+        BLOCK_EXPR@44..50
+          L_CURLY@44..45 "{"
+          WHITESPACE@45..46 " "
+          LITERAL@46..48
+            INT_NUMBER@46..48 "92"
+          WHITESPACE@48..49 " "
+          R_CURLY@49..50 "}"
+      WHITESPACE@50..51 "\n"
+      R_CURLY@51..52 "}"
+  WHITESPACE@52..53 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0027_unsafe_fn_in_block.rs b/crates/syntax/test_data/parser/ok/0027_unsafe_fn_in_block.rs
new file mode 100644
index 00000000000..f3c5ff93863
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0027_unsafe_fn_in_block.rs
@@ -0,0 +1,4 @@
+fn main() {
+    unsafe fn f() {}
+    unsafe { 92 }
+}
diff --git a/crates/syntax/test_data/parser/ok/0028_operator_binding_power.rast b/crates/syntax/test_data/parser/ok/0028_operator_binding_power.rast
new file mode 100644
index 00000000000..3271a4695d2
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0028_operator_binding_power.rast
@@ -0,0 +1,185 @@
+SOURCE_FILE@0..248
+  FN@0..247
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..16
+      IDENT@3..16 "binding_power"
+    PARAM_LIST@16..18
+      L_PAREN@16..17 "("
+      R_PAREN@17..18 ")"
+    WHITESPACE@18..19 " "
+    BLOCK_EXPR@19..247
+      L_CURLY@19..20 "{"
+      WHITESPACE@20..25 "\n    "
+      LET_STMT@25..55
+        LET_KW@25..28 "let"
+        WHITESPACE@28..29 " "
+        IDENT_PAT@29..30
+          NAME@29..30
+            IDENT@29..30 "x"
+        WHITESPACE@30..31 " "
+        EQ@31..32 "="
+        WHITESPACE@32..33 " "
+        BIN_EXPR@33..54
+          BIN_EXPR@33..46
+            LITERAL@33..34
+              INT_NUMBER@33..34 "1"
+            WHITESPACE@34..35 " "
+            PLUS@35..36 "+"
+            WHITESPACE@36..37 " "
+            BIN_EXPR@37..46
+              BIN_EXPR@37..42
+                LITERAL@37..38
+                  INT_NUMBER@37..38 "2"
+                WHITESPACE@38..39 " "
+                STAR@39..40 "*"
+                WHITESPACE@40..41 " "
+                LITERAL@41..42
+                  INT_NUMBER@41..42 "3"
+              WHITESPACE@42..43 " "
+              PERCENT@43..44 "%"
+              WHITESPACE@44..45 " "
+              LITERAL@45..46
+                INT_NUMBER@45..46 "4"
+          WHITESPACE@46..47 " "
+          MINUS@47..48 "-"
+          WHITESPACE@48..49 " "
+          BIN_EXPR@49..54
+            LITERAL@49..50
+              INT_NUMBER@49..50 "5"
+            WHITESPACE@50..51 " "
+            SLASH@51..52 "/"
+            WHITESPACE@52..53 " "
+            LITERAL@53..54
+              INT_NUMBER@53..54 "6"
+        SEMICOLON@54..55 ";"
+      WHITESPACE@55..60 "\n    "
+      EXPR_STMT@60..70
+        BIN_EXPR@60..69
+          LITERAL@60..61
+            INT_NUMBER@60..61 "1"
+          WHITESPACE@61..62 " "
+          PLUS@62..63 "+"
+          WHITESPACE@63..64 " "
+          BIN_EXPR@64..69
+            LITERAL@64..65
+              INT_NUMBER@64..65 "2"
+            WHITESPACE@65..66 " "
+            STAR@66..67 "*"
+            WHITESPACE@67..68 " "
+            LITERAL@68..69
+              INT_NUMBER@68..69 "3"
+        SEMICOLON@69..70 ";"
+      WHITESPACE@70..75 "\n    "
+      EXPR_STMT@75..86
+        BIN_EXPR@75..85
+          LITERAL@75..76
+            INT_NUMBER@75..76 "1"
+          WHITESPACE@76..77 " "
+          SHL@77..79 "<<"
+          WHITESPACE@79..80 " "
+          BIN_EXPR@80..85
+            LITERAL@80..81
+              INT_NUMBER@80..81 "2"
+            WHITESPACE@81..82 " "
+            PLUS@82..83 "+"
+            WHITESPACE@83..84 " "
+            LITERAL@84..85
+              INT_NUMBER@84..85 "3"
+        SEMICOLON@85..86 ";"
+      WHITESPACE@86..91 "\n    "
+      EXPR_STMT@91..102
+        BIN_EXPR@91..101
+          LITERAL@91..92
+            INT_NUMBER@91..92 "1"
+          WHITESPACE@92..93 " "
+          AMP@93..94 "&"
+          WHITESPACE@94..95 " "
+          BIN_EXPR@95..101
+            LITERAL@95..96
+              INT_NUMBER@95..96 "2"
+            WHITESPACE@96..97 " "
+            SHR@97..99 ">>"
+            WHITESPACE@99..100 " "
+            LITERAL@100..101
+              INT_NUMBER@100..101 "3"
+        SEMICOLON@101..102 ";"
+      WHITESPACE@102..107 "\n    "
+      EXPR_STMT@107..117
+        BIN_EXPR@107..116
+          LITERAL@107..108
+            INT_NUMBER@107..108 "1"
+          WHITESPACE@108..109 " "
+          CARET@109..110 "^"
+          WHITESPACE@110..111 " "
+          BIN_EXPR@111..116
+            LITERAL@111..112
+              INT_NUMBER@111..112 "2"
+            WHITESPACE@112..113 " "
+            AMP@113..114 "&"
+            WHITESPACE@114..115 " "
+            LITERAL@115..116
+              INT_NUMBER@115..116 "3"
+        SEMICOLON@116..117 ";"
+      WHITESPACE@117..122 "\n    "
+      EXPR_STMT@122..132
+        BIN_EXPR@122..131
+          LITERAL@122..123
+            INT_NUMBER@122..123 "1"
+          WHITESPACE@123..124 " "
+          PIPE@124..125 "|"
+          WHITESPACE@125..126 " "
+          BIN_EXPR@126..131
+            LITERAL@126..127
+              INT_NUMBER@126..127 "2"
+            WHITESPACE@127..128 " "
+            CARET@128..129 "^"
+            WHITESPACE@129..130 " "
+            LITERAL@130..131
+              INT_NUMBER@130..131 "3"
+        SEMICOLON@131..132 ";"
+      WHITESPACE@132..137 "\n    "
+      EXPR_STMT@137..148
+        BIN_EXPR@137..147
+          LITERAL@137..138
+            INT_NUMBER@137..138 "1"
+          WHITESPACE@138..139 " "
+          EQ2@139..141 "=="
+          WHITESPACE@141..142 " "
+          BIN_EXPR@142..147
+            LITERAL@142..143
+              INT_NUMBER@142..143 "2"
+            WHITESPACE@143..144 " "
+            PIPE@144..145 "|"
+            WHITESPACE@145..146 " "
+            LITERAL@146..147
+              INT_NUMBER@146..147 "3"
+        SEMICOLON@147..148 ";"
+      WHITESPACE@148..153 "\n    "
+      EXPR_STMT@153..165
+        BIN_EXPR@153..164
+          LITERAL@153..154
+            INT_NUMBER@153..154 "1"
+          WHITESPACE@154..155 " "
+          AMP2@155..157 "&&"
+          WHITESPACE@157..158 " "
+          BIN_EXPR@158..164
+            LITERAL@158..159
+              INT_NUMBER@158..159 "2"
+            WHITESPACE@159..160 " "
+            EQ2@160..162 "=="
+            WHITESPACE@162..163 " "
+            LITERAL@163..164
+              INT_NUMBER@163..164 "3"
+        SEMICOLON@164..165 ";"
+      WHITESPACE@165..170 "\n    "
+      COMMENT@170..184 "//1 || 2 && 2;"
+      WHITESPACE@184..189 "\n    "
+      COMMENT@189..203 "//1 .. 2 || 3;"
+      WHITESPACE@203..208 "\n    "
+      COMMENT@208..221 "//1 = 2 .. 3;"
+      WHITESPACE@221..226 "\n    "
+      COMMENT@226..245 "//---&*1 - --2 * 9;"
+      WHITESPACE@245..246 "\n"
+      R_CURLY@246..247 "}"
+  WHITESPACE@247..248 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0028_operator_binding_power.rs b/crates/syntax/test_data/parser/ok/0028_operator_binding_power.rs
new file mode 100644
index 00000000000..cc9598470d8
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0028_operator_binding_power.rs
@@ -0,0 +1,14 @@
+fn binding_power() {
+    let x = 1 + 2 * 3 % 4 - 5 / 6;
+    1 + 2 * 3;
+    1 << 2 + 3;
+    1 & 2 >> 3;
+    1 ^ 2 & 3;
+    1 | 2 ^ 3;
+    1 == 2 | 3;
+    1 && 2 == 3;
+    //1 || 2 && 2;
+    //1 .. 2 || 3;
+    //1 = 2 .. 3;
+    //---&*1 - --2 * 9;
+}
diff --git a/crates/syntax/test_data/parser/ok/0029_range_forms.rast b/crates/syntax/test_data/parser/ok/0029_range_forms.rast
new file mode 100644
index 00000000000..a732f11c430
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0029_range_forms.rast
@@ -0,0 +1,151 @@
+SOURCE_FILE@0..153
+  FN@0..152
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..152
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..23
+        RANGE_EXPR@15..22
+          DOT2@15..17 ".."
+          BIN_EXPR@17..22
+            LITERAL@17..18
+              INT_NUMBER@17..18 "1"
+            WHITESPACE@18..19 " "
+            PLUS@19..20 "+"
+            WHITESPACE@20..21 " "
+            LITERAL@21..22
+              INT_NUMBER@21..22 "1"
+        SEMICOLON@22..23 ";"
+      WHITESPACE@23..28 "\n    "
+      EXPR_STMT@28..36
+        BIN_EXPR@28..35
+          RANGE_EXPR@28..31
+            DOT2@28..30 ".."
+            PATH_EXPR@30..31
+              PATH@30..31
+                PATH_SEGMENT@30..31
+                  NAME_REF@30..31
+                    IDENT@30..31 "z"
+          WHITESPACE@31..32 " "
+          EQ@32..33 "="
+          WHITESPACE@33..34 " "
+          LITERAL@34..35
+            INT_NUMBER@34..35 "2"
+        SEMICOLON@35..36 ";"
+      WHITESPACE@36..41 "\n    "
+      EXPR_STMT@41..59
+        BIN_EXPR@41..58
+          PATH_EXPR@41..42
+            PATH@41..42
+              PATH_SEGMENT@41..42
+                NAME_REF@41..42
+                  IDENT@41..42 "x"
+          WHITESPACE@42..43 " "
+          EQ@43..44 "="
+          WHITESPACE@44..45 " "
+          RANGE_EXPR@45..58
+            LITERAL@45..50
+              FALSE_KW@45..50 "false"
+            DOT2@50..52 ".."
+            BIN_EXPR@52..58
+              LITERAL@52..53
+                INT_NUMBER@52..53 "1"
+              WHITESPACE@53..54 " "
+              EQ2@54..56 "=="
+              WHITESPACE@56..57 " "
+              LITERAL@57..58
+                INT_NUMBER@57..58 "1"
+        SEMICOLON@58..59 ";"
+      WHITESPACE@59..64 "\n    "
+      LET_STMT@64..76
+        LET_KW@64..67 "let"
+        WHITESPACE@67..68 " "
+        IDENT_PAT@68..69
+          NAME@68..69
+            IDENT@68..69 "x"
+        WHITESPACE@69..70 " "
+        EQ@70..71 "="
+        WHITESPACE@71..72 " "
+        RANGE_EXPR@72..75
+          LITERAL@72..73
+            INT_NUMBER@72..73 "1"
+          DOT2@73..75 ".."
+        SEMICOLON@75..76 ";"
+      WHITESPACE@76..86 "\n    \n    "
+      EXPR_STMT@86..95
+        RANGE_EXPR@86..94
+          DOT2EQ@86..89 "..="
+          BIN_EXPR@89..94
+            LITERAL@89..90
+              INT_NUMBER@89..90 "1"
+            WHITESPACE@90..91 " "
+            PLUS@91..92 "+"
+            WHITESPACE@92..93 " "
+            LITERAL@93..94
+              INT_NUMBER@93..94 "1"
+        SEMICOLON@94..95 ";"
+      WHITESPACE@95..100 "\n    "
+      EXPR_STMT@100..109
+        BIN_EXPR@100..108
+          RANGE_EXPR@100..104
+            DOT2EQ@100..103 "..="
+            PATH_EXPR@103..104
+              PATH@103..104
+                PATH_SEGMENT@103..104
+                  NAME_REF@103..104
+                    IDENT@103..104 "z"
+          WHITESPACE@104..105 " "
+          EQ@105..106 "="
+          WHITESPACE@106..107 " "
+          LITERAL@107..108
+            INT_NUMBER@107..108 "2"
+        SEMICOLON@108..109 ";"
+      WHITESPACE@109..114 "\n    "
+      EXPR_STMT@114..133
+        BIN_EXPR@114..132
+          PATH_EXPR@114..115
+            PATH@114..115
+              PATH_SEGMENT@114..115
+                NAME_REF@114..115
+                  IDENT@114..115 "x"
+          WHITESPACE@115..116 " "
+          EQ@116..117 "="
+          WHITESPACE@117..118 " "
+          RANGE_EXPR@118..132
+            LITERAL@118..123
+              FALSE_KW@118..123 "false"
+            DOT2EQ@123..126 "..="
+            BIN_EXPR@126..132
+              LITERAL@126..127
+                INT_NUMBER@126..127 "1"
+              WHITESPACE@127..128 " "
+              EQ2@128..130 "=="
+              WHITESPACE@130..131 " "
+              LITERAL@131..132
+                INT_NUMBER@131..132 "1"
+        SEMICOLON@132..133 ";"
+      WHITESPACE@133..138 "\n    "
+      LET_STMT@138..150
+        LET_KW@138..141 "let"
+        WHITESPACE@141..142 " "
+        IDENT_PAT@142..143
+          NAME@142..143
+            IDENT@142..143 "x"
+        WHITESPACE@143..144 " "
+        EQ@144..145 "="
+        WHITESPACE@145..146 " "
+        RANGE_EXPR@146..149
+          LITERAL@146..147
+            INT_NUMBER@146..147 "1"
+          DOT2@147..149 ".."
+        SEMICOLON@149..150 ";"
+      WHITESPACE@150..151 "\n"
+      R_CURLY@151..152 "}"
+  WHITESPACE@152..153 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0029_range_forms.rs b/crates/syntax/test_data/parser/ok/0029_range_forms.rs
new file mode 100644
index 00000000000..f9ff444d400
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0029_range_forms.rs
@@ -0,0 +1,11 @@
+fn foo() {
+    ..1 + 1;
+    ..z = 2;
+    x = false..1 == 1;
+    let x = 1..;
+    
+    ..=1 + 1;
+    ..=z = 2;
+    x = false..=1 == 1;
+    let x = 1..;
+}
diff --git a/crates/syntax/test_data/parser/ok/0030_string_suffixes.rast b/crates/syntax/test_data/parser/ok/0030_string_suffixes.rast
new file mode 100644
index 00000000000..80f7f5942c0
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0030_string_suffixes.rast
@@ -0,0 +1,63 @@
+SOURCE_FILE@0..112
+  FN@0..111
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..111
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      LET_STMT@16..31
+        LET_KW@16..19 "let"
+        WHITESPACE@19..20 " "
+        WILDCARD_PAT@20..21
+          UNDERSCORE@20..21 "_"
+        WHITESPACE@21..22 " "
+        EQ@22..23 "="
+        WHITESPACE@23..24 " "
+        LITERAL@24..30
+          CHAR@24..30 "\'c\'u32"
+        SEMICOLON@30..31 ";"
+      WHITESPACE@31..36 "\n    "
+      LET_STMT@36..60
+        LET_KW@36..39 "let"
+        WHITESPACE@39..40 " "
+        WILDCARD_PAT@40..41
+          UNDERSCORE@40..41 "_"
+        WHITESPACE@41..42 " "
+        EQ@42..43 "="
+        WHITESPACE@43..44 " "
+        LITERAL@44..59
+          STRING@44..59 "\"string\"invalid"
+        SEMICOLON@59..60 ";"
+      WHITESPACE@60..65 "\n    "
+      LET_STMT@65..83
+        LET_KW@65..68 "let"
+        WHITESPACE@68..69 " "
+        WILDCARD_PAT@69..70
+          UNDERSCORE@69..70 "_"
+        WHITESPACE@70..71 " "
+        EQ@71..72 "="
+        WHITESPACE@72..73 " "
+        LITERAL@73..82
+          BYTE@73..82 "b\'b\'_suff"
+        SEMICOLON@82..83 ";"
+      WHITESPACE@83..88 "\n    "
+      LET_STMT@88..109
+        LET_KW@88..91 "let"
+        WHITESPACE@91..92 " "
+        WILDCARD_PAT@92..93
+          UNDERSCORE@92..93 "_"
+        WHITESPACE@93..94 " "
+        EQ@94..95 "="
+        WHITESPACE@95..96 " "
+        LITERAL@96..108
+          BYTE_STRING@96..108 "b\"bs\"invalid"
+        SEMICOLON@108..109 ";"
+      WHITESPACE@109..110 "\n"
+      R_CURLY@110..111 "}"
+  WHITESPACE@111..112 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0030_string_suffixes.rs b/crates/syntax/test_data/parser/ok/0030_string_suffixes.rs
new file mode 100644
index 00000000000..261aad1fb6b
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0030_string_suffixes.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let _ = 'c'u32;
+    let _ = "string"invalid;
+    let _ = b'b'_suff;
+    let _ = b"bs"invalid;
+}
diff --git a/crates/syntax/test_data/parser/ok/0030_traits.rast b/crates/syntax/test_data/parser/ok/0030_traits.rast
new file mode 100644
index 00000000000..d07c6683a3d
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0030_traits.rast
@@ -0,0 +1,61 @@
+SOURCE_FILE@0..96
+  TRAIT@0..36
+    TRAIT_KW@0..5 "trait"
+    WHITESPACE@5..6 " "
+    NAME@6..14
+      IDENT@6..14 "Runnable"
+    WHITESPACE@14..15 " "
+    ASSOC_ITEM_LIST@15..36
+      L_CURLY@15..16 "{"
+      WHITESPACE@16..21 "\n    "
+      FN@21..34
+        FN_KW@21..23 "fn"
+        WHITESPACE@23..24 " "
+        NAME@24..31
+          IDENT@24..31 "handler"
+        PARAM_LIST@31..33
+          L_PAREN@31..32 "("
+          R_PAREN@32..33 ")"
+        SEMICOLON@33..34 ";"
+      WHITESPACE@34..35 "\n"
+      R_CURLY@35..36 "}"
+  WHITESPACE@36..38 "\n\n"
+  TRAIT@38..95
+    TRAIT_KW@38..43 "trait"
+    WHITESPACE@43..44 " "
+    NAME@44..57
+      IDENT@44..57 "TraitWithExpr"
+    WHITESPACE@57..58 " "
+    ASSOC_ITEM_LIST@58..95
+      L_CURLY@58..59 "{"
+      WHITESPACE@59..64 "\n    "
+      FN@64..93
+        FN_KW@64..66 "fn"
+        WHITESPACE@66..67 " "
+        NAME@67..79
+          IDENT@67..79 "fn_with_expr"
+        PARAM_LIST@79..92
+          L_PAREN@79..80 "("
+          PARAM@80..91
+            IDENT_PAT@80..81
+              NAME@80..81
+                IDENT@80..81 "x"
+            COLON@81..82 ":"
+            WHITESPACE@82..83 " "
+            ARRAY_TYPE@83..91
+              L_BRACK@83..84 "["
+              PATH_TYPE@84..87
+                PATH@84..87
+                  PATH_SEGMENT@84..87
+                    NAME_REF@84..87
+                      IDENT@84..87 "i32"
+              SEMICOLON@87..88 ";"
+              WHITESPACE@88..89 " "
+              LITERAL@89..90
+                INT_NUMBER@89..90 "1"
+              R_BRACK@90..91 "]"
+          R_PAREN@91..92 ")"
+        SEMICOLON@92..93 ";"
+      WHITESPACE@93..94 "\n"
+      R_CURLY@94..95 "}"
+  WHITESPACE@95..96 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0030_traits.rs b/crates/syntax/test_data/parser/ok/0030_traits.rs
new file mode 100644
index 00000000000..ac30843eff6
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0030_traits.rs
@@ -0,0 +1,7 @@
+trait Runnable {
+    fn handler();
+}
+
+trait TraitWithExpr {
+    fn fn_with_expr(x: [i32; 1]);
+}
diff --git a/crates/syntax/test_data/parser/ok/0031_extern.rast b/crates/syntax/test_data/parser/ok/0031_extern.rast
new file mode 100644
index 00000000000..8150d445f37
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0031_extern.rast
@@ -0,0 +1,973 @@
+SOURCE_FILE@0..1598
+  EXTERN_BLOCK@0..1597
+    ABI@0..6
+      EXTERN_KW@0..6 "extern"
+    WHITESPACE@6..7 " "
+    EXTERN_ITEM_LIST@7..1597
+      L_CURLY@7..8 "{"
+      WHITESPACE@8..13 "\n    "
+      FN@13..87
+        VISIBILITY@13..16
+          PUB_KW@13..16 "pub"
+        WHITESPACE@16..17 " "
+        FN_KW@17..19 "fn"
+        WHITESPACE@19..20 " "
+        NAME@20..26
+          IDENT@20..26 "socket"
+        PARAM_LIST@26..75
+          L_PAREN@26..27 "("
+          PARAM@27..42
+            IDENT_PAT@27..33
+              NAME@27..33
+                IDENT@27..33 "domain"
+            COLON@33..34 ":"
+            WHITESPACE@34..35 " "
+            PATH_TYPE@35..42
+              PATH@35..42
+                PATH_SEGMENT@35..42
+                  COLON2@35..37 "::"
+                  NAME_REF@37..42
+                    IDENT@37..42 "c_int"
+          COMMA@42..43 ","
+          WHITESPACE@43..44 " "
+          PARAM@44..55
+            IDENT_PAT@44..46
+              NAME@44..46
+                IDENT@44..46 "ty"
+            COLON@46..47 ":"
+            WHITESPACE@47..48 " "
+            PATH_TYPE@48..55
+              PATH@48..55
+                PATH_SEGMENT@48..55
+                  COLON2@48..50 "::"
+                  NAME_REF@50..55
+                    IDENT@50..55 "c_int"
+          COMMA@55..56 ","
+          WHITESPACE@56..57 " "
+          PARAM@57..74
+            IDENT_PAT@57..65
+              NAME@57..65
+                IDENT@57..65 "protocol"
+            COLON@65..66 ":"
+            WHITESPACE@66..67 " "
+            PATH_TYPE@67..74
+              PATH@67..74
+                PATH_SEGMENT@67..74
+                  COLON2@67..69 "::"
+                  NAME_REF@69..74
+                    IDENT@69..74 "c_int"
+          R_PAREN@74..75 ")"
+        WHITESPACE@75..76 " "
+        RET_TYPE@76..86
+          THIN_ARROW@76..78 "->"
+          WHITESPACE@78..79 " "
+          PATH_TYPE@79..86
+            PATH@79..86
+              PATH_SEGMENT@79..86
+                COLON2@79..81 "::"
+                NAME_REF@81..86
+                  IDENT@81..86 "c_int"
+        SEMICOLON@86..87 ";"
+      WHITESPACE@87..92 "\n    "
+      FN@92..167
+        VISIBILITY@92..95
+          PUB_KW@92..95 "pub"
+        WHITESPACE@95..96 " "
+        FN_KW@96..98 "fn"
+        WHITESPACE@98..99 " "
+        NAME@99..103
+          IDENT@99..103 "bind"
+        PARAM_LIST@103..155
+          L_PAREN@103..104 "("
+          PARAM@104..115
+            IDENT_PAT@104..106
+              NAME@104..106
+                IDENT@104..106 "fd"
+            COLON@106..107 ":"
+            WHITESPACE@107..108 " "
+            PATH_TYPE@108..115
+              PATH@108..115
+                PATH_SEGMENT@108..115
+                  COLON2@108..110 "::"
+                  NAME_REF@110..115
+                    IDENT@110..115 "c_int"
+          COMMA@115..116 ","
+          WHITESPACE@116..117 " "
+          PARAM@117..138
+            IDENT_PAT@117..121
+              NAME@117..121
+                IDENT@117..121 "addr"
+            COLON@121..122 ":"
+            WHITESPACE@122..123 " "
+            PTR_TYPE@123..138
+              STAR@123..124 "*"
+              CONST_KW@124..129 "const"
+              WHITESPACE@129..130 " "
+              PATH_TYPE@130..138
+                PATH@130..138
+                  PATH_SEGMENT@130..138
+                    NAME_REF@130..138
+                      IDENT@130..138 "sockaddr"
+          COMMA@138..139 ","
+          WHITESPACE@139..140 " "
+          PARAM@140..154
+            IDENT_PAT@140..143
+              NAME@140..143
+                IDENT@140..143 "len"
+            COLON@143..144 ":"
+            WHITESPACE@144..145 " "
+            PATH_TYPE@145..154
+              PATH@145..154
+                PATH_SEGMENT@145..154
+                  NAME_REF@145..154
+                    IDENT@145..154 "socklen_t"
+          R_PAREN@154..155 ")"
+        WHITESPACE@155..156 " "
+        RET_TYPE@156..166
+          THIN_ARROW@156..158 "->"
+          WHITESPACE@158..159 " "
+          PATH_TYPE@159..166
+            PATH@159..166
+              PATH_SEGMENT@159..166
+                COLON2@159..161 "::"
+                NAME_REF@161..166
+                  IDENT@161..166 "c_int"
+        SEMICOLON@166..167 ";"
+      WHITESPACE@167..172 "\n    "
+      FN@172..276
+        VISIBILITY@172..175
+          PUB_KW@172..175 "pub"
+        WHITESPACE@175..176 " "
+        FN_KW@176..178 "fn"
+        WHITESPACE@178..179 " "
+        NAME@179..186
+          IDENT@179..186 "connect"
+        PARAM_LIST@186..264
+          L_PAREN@186..187 "("
+          PARAM@187..202
+            IDENT_PAT@187..193
+              NAME@187..193
+                IDENT@187..193 "socket"
+            COLON@193..194 ":"
+            WHITESPACE@194..195 " "
+            PATH_TYPE@195..202
+              PATH@195..202
+                PATH_SEGMENT@195..202
+                  COLON2@195..197 "::"
+                  NAME_REF@197..202
+                    IDENT@197..202 "c_int"
+          COMMA@202..203 ","
+          WHITESPACE@203..204 " "
+          PARAM@204..228
+            IDENT_PAT@204..211
+              NAME@204..211
+                IDENT@204..211 "address"
+            COLON@211..212 ":"
+            WHITESPACE@212..213 " "
+            PTR_TYPE@213..228
+              STAR@213..214 "*"
+              CONST_KW@214..219 "const"
+              WHITESPACE@219..220 " "
+              PATH_TYPE@220..228
+                PATH@220..228
+                  PATH_SEGMENT@220..228
+                    NAME_REF@220..228
+                      IDENT@220..228 "sockaddr"
+          COMMA@228..229 ","
+          WHITESPACE@229..249 "\n                   "
+          PARAM@249..263
+            IDENT_PAT@249..252
+              NAME@249..252
+                IDENT@249..252 "len"
+            COLON@252..253 ":"
+            WHITESPACE@253..254 " "
+            PATH_TYPE@254..263
+              PATH@254..263
+                PATH_SEGMENT@254..263
+                  NAME_REF@254..263
+                    IDENT@254..263 "socklen_t"
+          R_PAREN@263..264 ")"
+        WHITESPACE@264..265 " "
+        RET_TYPE@265..275
+          THIN_ARROW@265..267 "->"
+          WHITESPACE@267..268 " "
+          PATH_TYPE@268..275
+            PATH@268..275
+              PATH_SEGMENT@268..275
+                COLON2@268..270 "::"
+                NAME_REF@270..275
+                  IDENT@270..275 "c_int"
+        SEMICOLON@275..276 ";"
+      WHITESPACE@276..281 "\n    "
+      FN@281..341
+        VISIBILITY@281..284
+          PUB_KW@281..284 "pub"
+        WHITESPACE@284..285 " "
+        FN_KW@285..287 "fn"
+        WHITESPACE@287..288 " "
+        NAME@288..294
+          IDENT@288..294 "listen"
+        PARAM_LIST@294..329
+          L_PAREN@294..295 "("
+          PARAM@295..310
+            IDENT_PAT@295..301
+              NAME@295..301
+                IDENT@295..301 "socket"
+            COLON@301..302 ":"
+            WHITESPACE@302..303 " "
+            PATH_TYPE@303..310
+              PATH@303..310
+                PATH_SEGMENT@303..310
+                  COLON2@303..305 "::"
+                  NAME_REF@305..310
+                    IDENT@305..310 "c_int"
+          COMMA@310..311 ","
+          WHITESPACE@311..312 " "
+          PARAM@312..328
+            IDENT_PAT@312..319
+              NAME@312..319
+                IDENT@312..319 "backlog"
+            COLON@319..320 ":"
+            WHITESPACE@320..321 " "
+            PATH_TYPE@321..328
+              PATH@321..328
+                PATH_SEGMENT@321..328
+                  COLON2@321..323 "::"
+                  NAME_REF@323..328
+                    IDENT@323..328 "c_int"
+          R_PAREN@328..329 ")"
+        WHITESPACE@329..330 " "
+        RET_TYPE@330..340
+          THIN_ARROW@330..332 "->"
+          WHITESPACE@332..333 " "
+          PATH_TYPE@333..340
+            PATH@333..340
+              PATH_SEGMENT@333..340
+                COLON2@333..335 "::"
+                NAME_REF@335..340
+                  IDENT@335..340 "c_int"
+        SEMICOLON@340..341 ";"
+      WHITESPACE@341..346 "\n    "
+      FN@346..469
+        VISIBILITY@346..349
+          PUB_KW@346..349 "pub"
+        WHITESPACE@349..350 " "
+        FN_KW@350..352 "fn"
+        WHITESPACE@352..353 " "
+        NAME@353..364
+          IDENT@353..364 "getsockname"
+        PARAM_LIST@364..457
+          L_PAREN@364..365 "("
+          PARAM@365..380
+            IDENT_PAT@365..371
+              NAME@365..371
+                IDENT@365..371 "socket"
+            COLON@371..372 ":"
+            WHITESPACE@372..373 " "
+            PATH_TYPE@373..380
+              PATH@373..380
+                PATH_SEGMENT@373..380
+                  COLON2@373..375 "::"
+                  NAME_REF@375..380
+                    IDENT@375..380 "c_int"
+          COMMA@380..381 ","
+          WHITESPACE@381..382 " "
+          PARAM@382..404
+            IDENT_PAT@382..389
+              NAME@382..389
+                IDENT@382..389 "address"
+            COLON@389..390 ":"
+            WHITESPACE@390..391 " "
+            PTR_TYPE@391..404
+              STAR@391..392 "*"
+              MUT_KW@392..395 "mut"
+              WHITESPACE@395..396 " "
+              PATH_TYPE@396..404
+                PATH@396..404
+                  PATH_SEGMENT@396..404
+                    NAME_REF@396..404
+                      IDENT@396..404 "sockaddr"
+          COMMA@404..405 ","
+          WHITESPACE@405..429 "\n                       "
+          PARAM@429..456
+            IDENT_PAT@429..440
+              NAME@429..440
+                IDENT@429..440 "address_len"
+            COLON@440..441 ":"
+            WHITESPACE@441..442 " "
+            PTR_TYPE@442..456
+              STAR@442..443 "*"
+              MUT_KW@443..446 "mut"
+              WHITESPACE@446..447 " "
+              PATH_TYPE@447..456
+                PATH@447..456
+                  PATH_SEGMENT@447..456
+                    NAME_REF@447..456
+                      IDENT@447..456 "socklen_t"
+          R_PAREN@456..457 ")"
+        WHITESPACE@457..458 " "
+        RET_TYPE@458..468
+          THIN_ARROW@458..460 "->"
+          WHITESPACE@460..461 " "
+          PATH_TYPE@461..468
+            PATH@461..468
+              PATH_SEGMENT@461..468
+                COLON2@461..463 "::"
+                NAME_REF@463..468
+                  IDENT@463..468 "c_int"
+        SEMICOLON@468..469 ";"
+      WHITESPACE@469..474 "\n    "
+      FN@474..691
+        VISIBILITY@474..477
+          PUB_KW@474..477 "pub"
+        WHITESPACE@477..478 " "
+        FN_KW@478..480 "fn"
+        WHITESPACE@480..481 " "
+        NAME@481..491
+          IDENT@481..491 "getsockopt"
+        PARAM_LIST@491..679
+          L_PAREN@491..492 "("
+          PARAM@492..507
+            IDENT_PAT@492..498
+              NAME@492..498
+                IDENT@492..498 "sockfd"
+            COLON@498..499 ":"
+            WHITESPACE@499..500 " "
+            PATH_TYPE@500..507
+              PATH@500..507
+                PATH_SEGMENT@500..507
+                  COLON2@500..502 "::"
+                  NAME_REF@502..507
+                    IDENT@502..507 "c_int"
+          COMMA@507..508 ","
+          WHITESPACE@508..531 "\n                      "
+          PARAM@531..545
+            IDENT_PAT@531..536
+              NAME@531..536
+                IDENT@531..536 "level"
+            COLON@536..537 ":"
+            WHITESPACE@537..538 " "
+            PATH_TYPE@538..545
+              PATH@538..545
+                PATH_SEGMENT@538..545
+                  COLON2@538..540 "::"
+                  NAME_REF@540..545
+                    IDENT@540..545 "c_int"
+          COMMA@545..546 ","
+          WHITESPACE@546..569 "\n                      "
+          PARAM@569..585
+            IDENT_PAT@569..576
+              NAME@569..576
+                IDENT@569..576 "optname"
+            COLON@576..577 ":"
+            WHITESPACE@577..578 " "
+            PATH_TYPE@578..585
+              PATH@578..585
+                PATH_SEGMENT@578..585
+                  COLON2@578..580 "::"
+                  NAME_REF@580..585
+                    IDENT@580..585 "c_int"
+          COMMA@585..586 ","
+          WHITESPACE@586..609 "\n                      "
+          PARAM@609..630
+            IDENT_PAT@609..615
+              NAME@609..615
+                IDENT@609..615 "optval"
+            COLON@615..616 ":"
+            WHITESPACE@616..617 " "
+            PTR_TYPE@617..630
+              STAR@617..618 "*"
+              MUT_KW@618..621 "mut"
+              WHITESPACE@621..622 " "
+              PATH_TYPE@622..630
+                PATH@622..630
+                  PATH_SEGMENT@622..630
+                    COLON2@622..624 "::"
+                    NAME_REF@624..630
+                      IDENT@624..630 "c_void"
+          COMMA@630..631 ","
+          WHITESPACE@631..654 "\n                      "
+          PARAM@654..678
+            IDENT_PAT@654..660
+              NAME@654..660
+                IDENT@654..660 "optlen"
+            COLON@660..661 ":"
+            WHITESPACE@661..662 " "
+            PTR_TYPE@662..678
+              STAR@662..663 "*"
+              MUT_KW@663..666 "mut"
+              WHITESPACE@666..667 " "
+              PATH_TYPE@667..678
+                PATH@667..678
+                  PATH_SEGMENT@667..678
+                    COLON2@667..669 "::"
+                    NAME_REF@669..678
+                      IDENT@669..678 "socklen_t"
+          R_PAREN@678..679 ")"
+        WHITESPACE@679..680 " "
+        RET_TYPE@680..690
+          THIN_ARROW@680..682 "->"
+          WHITESPACE@682..683 " "
+          PATH_TYPE@683..690
+            PATH@683..690
+              PATH_SEGMENT@683..690
+                COLON2@683..685 "::"
+                NAME_REF@685..690
+                  IDENT@685..690 "c_int"
+        SEMICOLON@690..691 ";"
+      WHITESPACE@691..696 "\n    "
+      FN@696..864
+        VISIBILITY@696..699
+          PUB_KW@696..699 "pub"
+        WHITESPACE@699..700 " "
+        FN_KW@700..702 "fn"
+        WHITESPACE@702..703 " "
+        NAME@703..713
+          IDENT@703..713 "setsockopt"
+        PARAM_LIST@713..852
+          L_PAREN@713..714 "("
+          PARAM@714..729
+            IDENT_PAT@714..720
+              NAME@714..720
+                IDENT@714..720 "socket"
+            COLON@720..721 ":"
+            WHITESPACE@721..722 " "
+            PATH_TYPE@722..729
+              PATH@722..729
+                PATH_SEGMENT@722..729
+                  COLON2@722..724 "::"
+                  NAME_REF@724..729
+                    IDENT@724..729 "c_int"
+          COMMA@729..730 ","
+          WHITESPACE@730..731 " "
+          PARAM@731..745
+            IDENT_PAT@731..736
+              NAME@731..736
+                IDENT@731..736 "level"
+            COLON@736..737 ":"
+            WHITESPACE@737..738 " "
+            PATH_TYPE@738..745
+              PATH@738..745
+                PATH_SEGMENT@738..745
+                  COLON2@738..740 "::"
+                  NAME_REF@740..745
+                    IDENT@740..745 "c_int"
+          COMMA@745..746 ","
+          WHITESPACE@746..747 " "
+          PARAM@747..760
+            IDENT_PAT@747..751
+              NAME@747..751
+                IDENT@747..751 "name"
+            COLON@751..752 ":"
+            WHITESPACE@752..753 " "
+            PATH_TYPE@753..760
+              PATH@753..760
+                PATH_SEGMENT@753..760
+                  COLON2@753..755 "::"
+                  NAME_REF@755..760
+                    IDENT@755..760 "c_int"
+          COMMA@760..761 ","
+          WHITESPACE@761..784 "\n                      "
+          PARAM@784..806
+            IDENT_PAT@784..789
+              NAME@784..789
+                IDENT@784..789 "value"
+            COLON@789..790 ":"
+            WHITESPACE@790..791 " "
+            PTR_TYPE@791..806
+              STAR@791..792 "*"
+              CONST_KW@792..797 "const"
+              WHITESPACE@797..798 " "
+              PATH_TYPE@798..806
+                PATH@798..806
+                  PATH_SEGMENT@798..806
+                    COLON2@798..800 "::"
+                    NAME_REF@800..806
+                      IDENT@800..806 "c_void"
+          COMMA@806..807 ","
+          WHITESPACE@807..830 "\n                      "
+          PARAM@830..851
+            IDENT_PAT@830..840
+              NAME@830..840
+                IDENT@830..840 "option_len"
+            COLON@840..841 ":"
+            WHITESPACE@841..842 " "
+            PATH_TYPE@842..851
+              PATH@842..851
+                PATH_SEGMENT@842..851
+                  NAME_REF@842..851
+                    IDENT@842..851 "socklen_t"
+          R_PAREN@851..852 ")"
+        WHITESPACE@852..853 " "
+        RET_TYPE@853..863
+          THIN_ARROW@853..855 "->"
+          WHITESPACE@855..856 " "
+          PATH_TYPE@856..863
+            PATH@856..863
+              PATH_SEGMENT@856..863
+                COLON2@856..858 "::"
+                NAME_REF@858..863
+                  IDENT@858..863 "c_int"
+        SEMICOLON@863..864 ";"
+      WHITESPACE@864..869 "\n    "
+      FN@869..992
+        VISIBILITY@869..872
+          PUB_KW@869..872 "pub"
+        WHITESPACE@872..873 " "
+        FN_KW@873..875 "fn"
+        WHITESPACE@875..876 " "
+        NAME@876..887
+          IDENT@876..887 "getpeername"
+        PARAM_LIST@887..980
+          L_PAREN@887..888 "("
+          PARAM@888..903
+            IDENT_PAT@888..894
+              NAME@888..894
+                IDENT@888..894 "socket"
+            COLON@894..895 ":"
+            WHITESPACE@895..896 " "
+            PATH_TYPE@896..903
+              PATH@896..903
+                PATH_SEGMENT@896..903
+                  COLON2@896..898 "::"
+                  NAME_REF@898..903
+                    IDENT@898..903 "c_int"
+          COMMA@903..904 ","
+          WHITESPACE@904..905 " "
+          PARAM@905..927
+            IDENT_PAT@905..912
+              NAME@905..912
+                IDENT@905..912 "address"
+            COLON@912..913 ":"
+            WHITESPACE@913..914 " "
+            PTR_TYPE@914..927
+              STAR@914..915 "*"
+              MUT_KW@915..918 "mut"
+              WHITESPACE@918..919 " "
+              PATH_TYPE@919..927
+                PATH@919..927
+                  PATH_SEGMENT@919..927
+                    NAME_REF@919..927
+                      IDENT@919..927 "sockaddr"
+          COMMA@927..928 ","
+          WHITESPACE@928..952 "\n                       "
+          PARAM@952..979
+            IDENT_PAT@952..963
+              NAME@952..963
+                IDENT@952..963 "address_len"
+            COLON@963..964 ":"
+            WHITESPACE@964..965 " "
+            PTR_TYPE@965..979
+              STAR@965..966 "*"
+              MUT_KW@966..969 "mut"
+              WHITESPACE@969..970 " "
+              PATH_TYPE@970..979
+                PATH@970..979
+                  PATH_SEGMENT@970..979
+                    NAME_REF@970..979
+                      IDENT@970..979 "socklen_t"
+          R_PAREN@979..980 ")"
+        WHITESPACE@980..981 " "
+        RET_TYPE@981..991
+          THIN_ARROW@981..983 "->"
+          WHITESPACE@983..984 " "
+          PATH_TYPE@984..991
+            PATH@984..991
+              PATH_SEGMENT@984..991
+                COLON2@984..986 "::"
+                NAME_REF@986..991
+                  IDENT@986..991 "c_int"
+        SEMICOLON@991..992 ";"
+      WHITESPACE@992..997 "\n    "
+      FN@997..1173
+        VISIBILITY@997..1000
+          PUB_KW@997..1000 "pub"
+        WHITESPACE@1000..1001 " "
+        FN_KW@1001..1003 "fn"
+        WHITESPACE@1003..1004 " "
+        NAME@1004..1010
+          IDENT@1004..1010 "sendto"
+        PARAM_LIST@1010..1159
+          L_PAREN@1010..1011 "("
+          PARAM@1011..1026
+            IDENT_PAT@1011..1017
+              NAME@1011..1017
+                IDENT@1011..1017 "socket"
+            COLON@1017..1018 ":"
+            WHITESPACE@1018..1019 " "
+            PATH_TYPE@1019..1026
+              PATH@1019..1026
+                PATH_SEGMENT@1019..1026
+                  COLON2@1019..1021 "::"
+                  NAME_REF@1021..1026
+                    IDENT@1021..1026 "c_int"
+          COMMA@1026..1027 ","
+          WHITESPACE@1027..1028 " "
+          PARAM@1028..1048
+            IDENT_PAT@1028..1031
+              NAME@1028..1031
+                IDENT@1028..1031 "buf"
+            COLON@1031..1032 ":"
+            WHITESPACE@1032..1033 " "
+            PTR_TYPE@1033..1048
+              STAR@1033..1034 "*"
+              CONST_KW@1034..1039 "const"
+              WHITESPACE@1039..1040 " "
+              PATH_TYPE@1040..1048
+                PATH@1040..1048
+                  PATH_SEGMENT@1040..1048
+                    COLON2@1040..1042 "::"
+                    NAME_REF@1042..1048
+                      IDENT@1042..1048 "c_void"
+          COMMA@1048..1049 ","
+          WHITESPACE@1049..1050 " "
+          PARAM@1050..1063
+            IDENT_PAT@1050..1053
+              NAME@1050..1053
+                IDENT@1050..1053 "len"
+            COLON@1053..1054 ":"
+            WHITESPACE@1054..1055 " "
+            PATH_TYPE@1055..1063
+              PATH@1055..1063
+                PATH_SEGMENT@1055..1063
+                  COLON2@1055..1057 "::"
+                  NAME_REF@1057..1063
+                    IDENT@1057..1063 "size_t"
+          COMMA@1063..1064 ","
+          WHITESPACE@1064..1083 "\n                  "
+          PARAM@1083..1097
+            IDENT_PAT@1083..1088
+              NAME@1083..1088
+                IDENT@1083..1088 "flags"
+            COLON@1088..1089 ":"
+            WHITESPACE@1089..1090 " "
+            PATH_TYPE@1090..1097
+              PATH@1090..1097
+                PATH_SEGMENT@1090..1097
+                  COLON2@1090..1092 "::"
+                  NAME_REF@1092..1097
+                    IDENT@1092..1097 "c_int"
+          COMMA@1097..1098 ","
+          WHITESPACE@1098..1099 " "
+          PARAM@1099..1120
+            IDENT_PAT@1099..1103
+              NAME@1099..1103
+                IDENT@1099..1103 "addr"
+            COLON@1103..1104 ":"
+            WHITESPACE@1104..1105 " "
+            PTR_TYPE@1105..1120
+              STAR@1105..1106 "*"
+              CONST_KW@1106..1111 "const"
+              WHITESPACE@1111..1112 " "
+              PATH_TYPE@1112..1120
+                PATH@1112..1120
+                  PATH_SEGMENT@1112..1120
+                    NAME_REF@1112..1120
+                      IDENT@1112..1120 "sockaddr"
+          COMMA@1120..1121 ","
+          WHITESPACE@1121..1140 "\n                  "
+          PARAM@1140..1158
+            IDENT_PAT@1140..1147
+              NAME@1140..1147
+                IDENT@1140..1147 "addrlen"
+            COLON@1147..1148 ":"
+            WHITESPACE@1148..1149 " "
+            PATH_TYPE@1149..1158
+              PATH@1149..1158
+                PATH_SEGMENT@1149..1158
+                  NAME_REF@1149..1158
+                    IDENT@1149..1158 "socklen_t"
+          R_PAREN@1158..1159 ")"
+        WHITESPACE@1159..1160 " "
+        RET_TYPE@1160..1172
+          THIN_ARROW@1160..1162 "->"
+          WHITESPACE@1162..1163 " "
+          PATH_TYPE@1163..1172
+            PATH@1163..1172
+              PATH_SEGMENT@1163..1172
+                COLON2@1163..1165 "::"
+                NAME_REF@1165..1172
+                  IDENT@1165..1172 "ssize_t"
+        SEMICOLON@1172..1173 ";"
+      WHITESPACE@1173..1178 "\n    "
+      FN@1178..1289
+        VISIBILITY@1178..1181
+          PUB_KW@1178..1181 "pub"
+        WHITESPACE@1181..1182 " "
+        FN_KW@1182..1184 "fn"
+        WHITESPACE@1184..1185 " "
+        NAME@1185..1189
+          IDENT@1185..1189 "send"
+        PARAM_LIST@1189..1275
+          L_PAREN@1189..1190 "("
+          PARAM@1190..1205
+            IDENT_PAT@1190..1196
+              NAME@1190..1196
+                IDENT@1190..1196 "socket"
+            COLON@1196..1197 ":"
+            WHITESPACE@1197..1198 " "
+            PATH_TYPE@1198..1205
+              PATH@1198..1205
+                PATH_SEGMENT@1198..1205
+                  COLON2@1198..1200 "::"
+                  NAME_REF@1200..1205
+                    IDENT@1200..1205 "c_int"
+          COMMA@1205..1206 ","
+          WHITESPACE@1206..1207 " "
+          PARAM@1207..1227
+            IDENT_PAT@1207..1210
+              NAME@1207..1210
+                IDENT@1207..1210 "buf"
+            COLON@1210..1211 ":"
+            WHITESPACE@1211..1212 " "
+            PTR_TYPE@1212..1227
+              STAR@1212..1213 "*"
+              CONST_KW@1213..1218 "const"
+              WHITESPACE@1218..1219 " "
+              PATH_TYPE@1219..1227
+                PATH@1219..1227
+                  PATH_SEGMENT@1219..1227
+                    COLON2@1219..1221 "::"
+                    NAME_REF@1221..1227
+                      IDENT@1221..1227 "c_void"
+          COMMA@1227..1228 ","
+          WHITESPACE@1228..1229 " "
+          PARAM@1229..1242
+            IDENT_PAT@1229..1232
+              NAME@1229..1232
+                IDENT@1229..1232 "len"
+            COLON@1232..1233 ":"
+            WHITESPACE@1233..1234 " "
+            PATH_TYPE@1234..1242
+              PATH@1234..1242
+                PATH_SEGMENT@1234..1242
+                  COLON2@1234..1236 "::"
+                  NAME_REF@1236..1242
+                    IDENT@1236..1242 "size_t"
+          COMMA@1242..1243 ","
+          WHITESPACE@1243..1260 "\n                "
+          PARAM@1260..1274
+            IDENT_PAT@1260..1265
+              NAME@1260..1265
+                IDENT@1260..1265 "flags"
+            COLON@1265..1266 ":"
+            WHITESPACE@1266..1267 " "
+            PATH_TYPE@1267..1274
+              PATH@1267..1274
+                PATH_SEGMENT@1267..1274
+                  COLON2@1267..1269 "::"
+                  NAME_REF@1269..1274
+                    IDENT@1269..1274 "c_int"
+          R_PAREN@1274..1275 ")"
+        WHITESPACE@1275..1276 " "
+        RET_TYPE@1276..1288
+          THIN_ARROW@1276..1278 "->"
+          WHITESPACE@1278..1279 " "
+          PATH_TYPE@1279..1288
+            PATH@1279..1288
+              PATH_SEGMENT@1279..1288
+                COLON2@1279..1281 "::"
+                NAME_REF@1281..1288
+                  IDENT@1281..1288 "ssize_t"
+        SEMICOLON@1288..1289 ";"
+      WHITESPACE@1289..1294 "\n    "
+      FN@1294..1481
+        VISIBILITY@1294..1297
+          PUB_KW@1294..1297 "pub"
+        WHITESPACE@1297..1298 " "
+        FN_KW@1298..1300 "fn"
+        WHITESPACE@1300..1301 " "
+        NAME@1301..1309
+          IDENT@1301..1309 "recvfrom"
+        PARAM_LIST@1309..1467
+          L_PAREN@1309..1310 "("
+          PARAM@1310..1325
+            IDENT_PAT@1310..1316
+              NAME@1310..1316
+                IDENT@1310..1316 "socket"
+            COLON@1316..1317 ":"
+            WHITESPACE@1317..1318 " "
+            PATH_TYPE@1318..1325
+              PATH@1318..1325
+                PATH_SEGMENT@1318..1325
+                  COLON2@1318..1320 "::"
+                  NAME_REF@1320..1325
+                    IDENT@1320..1325 "c_int"
+          COMMA@1325..1326 ","
+          WHITESPACE@1326..1327 " "
+          PARAM@1327..1345
+            IDENT_PAT@1327..1330
+              NAME@1327..1330
+                IDENT@1327..1330 "buf"
+            COLON@1330..1331 ":"
+            WHITESPACE@1331..1332 " "
+            PTR_TYPE@1332..1345
+              STAR@1332..1333 "*"
+              MUT_KW@1333..1336 "mut"
+              WHITESPACE@1336..1337 " "
+              PATH_TYPE@1337..1345
+                PATH@1337..1345
+                  PATH_SEGMENT@1337..1345
+                    COLON2@1337..1339 "::"
+                    NAME_REF@1339..1345
+                      IDENT@1339..1345 "c_void"
+          COMMA@1345..1346 ","
+          WHITESPACE@1346..1347 " "
+          PARAM@1347..1360
+            IDENT_PAT@1347..1350
+              NAME@1347..1350
+                IDENT@1347..1350 "len"
+            COLON@1350..1351 ":"
+            WHITESPACE@1351..1352 " "
+            PATH_TYPE@1352..1360
+              PATH@1352..1360
+                PATH_SEGMENT@1352..1360
+                  COLON2@1352..1354 "::"
+                  NAME_REF@1354..1360
+                    IDENT@1354..1360 "size_t"
+          COMMA@1360..1361 ","
+          WHITESPACE@1361..1382 "\n                    "
+          PARAM@1382..1396
+            IDENT_PAT@1382..1387
+              NAME@1382..1387
+                IDENT@1382..1387 "flags"
+            COLON@1387..1388 ":"
+            WHITESPACE@1388..1389 " "
+            PATH_TYPE@1389..1396
+              PATH@1389..1396
+                PATH_SEGMENT@1389..1396
+                  COLON2@1389..1391 "::"
+                  NAME_REF@1391..1396
+                    IDENT@1391..1396 "c_int"
+          COMMA@1396..1397 ","
+          WHITESPACE@1397..1398 " "
+          PARAM@1398..1419
+            IDENT_PAT@1398..1402
+              NAME@1398..1402
+                IDENT@1398..1402 "addr"
+            COLON@1402..1403 ":"
+            WHITESPACE@1403..1404 " "
+            PTR_TYPE@1404..1419
+              STAR@1404..1405 "*"
+              MUT_KW@1405..1408 "mut"
+              WHITESPACE@1408..1409 " "
+              PATH_TYPE@1409..1419
+                PATH@1409..1419
+                  PATH_SEGMENT@1409..1419
+                    COLON2@1409..1411 "::"
+                    NAME_REF@1411..1419
+                      IDENT@1411..1419 "sockaddr"
+          COMMA@1419..1420 ","
+          WHITESPACE@1420..1441 "\n                    "
+          PARAM@1441..1466
+            IDENT_PAT@1441..1448
+              NAME@1441..1448
+                IDENT@1441..1448 "addrlen"
+            COLON@1448..1449 ":"
+            WHITESPACE@1449..1450 " "
+            PTR_TYPE@1450..1466
+              STAR@1450..1451 "*"
+              MUT_KW@1451..1454 "mut"
+              WHITESPACE@1454..1455 " "
+              PATH_TYPE@1455..1466
+                PATH@1455..1466
+                  PATH_SEGMENT@1455..1466
+                    COLON2@1455..1457 "::"
+                    NAME_REF@1457..1466
+                      IDENT@1457..1466 "socklen_t"
+          R_PAREN@1466..1467 ")"
+        WHITESPACE@1467..1468 " "
+        RET_TYPE@1468..1480
+          THIN_ARROW@1468..1470 "->"
+          WHITESPACE@1470..1471 " "
+          PATH_TYPE@1471..1480
+            PATH@1471..1480
+              PATH_SEGMENT@1471..1480
+                COLON2@1471..1473 "::"
+                NAME_REF@1473..1480
+                  IDENT@1473..1480 "ssize_t"
+        SEMICOLON@1480..1481 ";"
+      WHITESPACE@1481..1486 "\n    "
+      FN@1486..1595
+        VISIBILITY@1486..1489
+          PUB_KW@1486..1489 "pub"
+        WHITESPACE@1489..1490 " "
+        FN_KW@1490..1492 "fn"
+        WHITESPACE@1492..1493 " "
+        NAME@1493..1497
+          IDENT@1493..1497 "recv"
+        PARAM_LIST@1497..1581
+          L_PAREN@1497..1498 "("
+          PARAM@1498..1513
+            IDENT_PAT@1498..1504
+              NAME@1498..1504
+                IDENT@1498..1504 "socket"
+            COLON@1504..1505 ":"
+            WHITESPACE@1505..1506 " "
+            PATH_TYPE@1506..1513
+              PATH@1506..1513
+                PATH_SEGMENT@1506..1513
+                  COLON2@1506..1508 "::"
+                  NAME_REF@1508..1513
+                    IDENT@1508..1513 "c_int"
+          COMMA@1513..1514 ","
+          WHITESPACE@1514..1515 " "
+          PARAM@1515..1533
+            IDENT_PAT@1515..1518
+              NAME@1515..1518
+                IDENT@1515..1518 "buf"
+            COLON@1518..1519 ":"
+            WHITESPACE@1519..1520 " "
+            PTR_TYPE@1520..1533
+              STAR@1520..1521 "*"
+              MUT_KW@1521..1524 "mut"
+              WHITESPACE@1524..1525 " "
+              PATH_TYPE@1525..1533
+                PATH@1525..1533
+                  PATH_SEGMENT@1525..1533
+                    COLON2@1525..1527 "::"
+                    NAME_REF@1527..1533
+                      IDENT@1527..1533 "c_void"
+          COMMA@1533..1534 ","
+          WHITESPACE@1534..1535 " "
+          PARAM@1535..1548
+            IDENT_PAT@1535..1538
+              NAME@1535..1538
+                IDENT@1535..1538 "len"
+            COLON@1538..1539 ":"
+            WHITESPACE@1539..1540 " "
+            PATH_TYPE@1540..1548
+              PATH@1540..1548
+                PATH_SEGMENT@1540..1548
+                  COLON2@1540..1542 "::"
+                  NAME_REF@1542..1548
+                    IDENT@1542..1548 "size_t"
+          COMMA@1548..1549 ","
+          WHITESPACE@1549..1566 "\n                "
+          PARAM@1566..1580
+            IDENT_PAT@1566..1571
+              NAME@1566..1571
+                IDENT@1566..1571 "flags"
+            COLON@1571..1572 ":"
+            WHITESPACE@1572..1573 " "
+            PATH_TYPE@1573..1580
+              PATH@1573..1580
+                PATH_SEGMENT@1573..1580
+                  COLON2@1573..1575 "::"
+                  NAME_REF@1575..1580
+                    IDENT@1575..1580 "c_int"
+          R_PAREN@1580..1581 ")"
+        WHITESPACE@1581..1582 " "
+        RET_TYPE@1582..1594
+          THIN_ARROW@1582..1584 "->"
+          WHITESPACE@1584..1585 " "
+          PATH_TYPE@1585..1594
+            PATH@1585..1594
+              PATH_SEGMENT@1585..1594
+                COLON2@1585..1587 "::"
+                NAME_REF@1587..1594
+                  IDENT@1587..1594 "ssize_t"
+        SEMICOLON@1594..1595 ";"
+      WHITESPACE@1595..1596 "\n"
+      R_CURLY@1596..1597 "}"
+  WHITESPACE@1597..1598 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0031_extern.rs b/crates/syntax/test_data/parser/ok/0031_extern.rs
new file mode 100644
index 00000000000..b33ac273ca6
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0031_extern.rs
@@ -0,0 +1,29 @@
+extern {
+    pub fn socket(domain: ::c_int, ty: ::c_int, protocol: ::c_int) -> ::c_int;
+    pub fn bind(fd: ::c_int, addr: *const sockaddr, len: socklen_t) -> ::c_int;
+    pub fn connect(socket: ::c_int, address: *const sockaddr,
+                   len: socklen_t) -> ::c_int;
+    pub fn listen(socket: ::c_int, backlog: ::c_int) -> ::c_int;
+    pub fn getsockname(socket: ::c_int, address: *mut sockaddr,
+                       address_len: *mut socklen_t) -> ::c_int;
+    pub fn getsockopt(sockfd: ::c_int,
+                      level: ::c_int,
+                      optname: ::c_int,
+                      optval: *mut ::c_void,
+                      optlen: *mut ::socklen_t) -> ::c_int;
+    pub fn setsockopt(socket: ::c_int, level: ::c_int, name: ::c_int,
+                      value: *const ::c_void,
+                      option_len: socklen_t) -> ::c_int;
+    pub fn getpeername(socket: ::c_int, address: *mut sockaddr,
+                       address_len: *mut socklen_t) -> ::c_int;
+    pub fn sendto(socket: ::c_int, buf: *const ::c_void, len: ::size_t,
+                  flags: ::c_int, addr: *const sockaddr,
+                  addrlen: socklen_t) -> ::ssize_t;
+    pub fn send(socket: ::c_int, buf: *const ::c_void, len: ::size_t,
+                flags: ::c_int) -> ::ssize_t;
+    pub fn recvfrom(socket: ::c_int, buf: *mut ::c_void, len: ::size_t,
+                    flags: ::c_int, addr: *mut ::sockaddr,
+                    addrlen: *mut ::socklen_t) -> ::ssize_t;
+    pub fn recv(socket: ::c_int, buf: *mut ::c_void, len: ::size_t,
+                flags: ::c_int) -> ::ssize_t;
+}
diff --git a/crates/syntax/test_data/parser/ok/0032_where_for.rast b/crates/syntax/test_data/parser/ok/0032_where_for.rast
new file mode 100644
index 00000000000..d59548f2107
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0032_where_for.rast
@@ -0,0 +1,90 @@
+SOURCE_FILE@0..116
+  FN@0..115
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..21
+      IDENT@3..21 "test_serialization"
+    GENERIC_PARAM_LIST@21..26
+      L_ANGLE@21..22 "<"
+      TYPE_PARAM@22..25
+        NAME@22..25
+          IDENT@22..25 "SER"
+      R_ANGLE@25..26 ">"
+    PARAM_LIST@26..28
+      L_PAREN@26..27 "("
+      R_PAREN@27..28 ")"
+    WHITESPACE@28..29 "\n"
+    WHERE_CLAUSE@29..112
+      WHERE_KW@29..34 "where"
+      WHITESPACE@34..39 "\n    "
+      WHERE_PRED@39..111
+        PATH_TYPE@39..42
+          PATH@39..42
+            PATH_SEGMENT@39..42
+              NAME_REF@39..42
+                IDENT@39..42 "SER"
+        COLON@42..43 ":"
+        WHITESPACE@43..44 " "
+        TYPE_BOUND_LIST@44..111
+          TYPE_BOUND@44..53
+            PATH_TYPE@44..53
+              PATH@44..53
+                PATH_SEGMENT@44..53
+                  NAME_REF@44..53
+                    IDENT@44..53 "Serialize"
+          WHITESPACE@53..54 " "
+          PLUS@54..55 "+"
+          WHITESPACE@55..56 " "
+          TYPE_BOUND@56..81
+            FOR_TYPE@56..81
+              FOR_KW@56..59 "for"
+              GENERIC_PARAM_LIST@59..64
+                L_ANGLE@59..60 "<"
+                LIFETIME_PARAM@60..63
+                  LIFETIME@60..63 "\'de"
+                R_ANGLE@63..64 ">"
+              WHITESPACE@64..65 " "
+              PATH_TYPE@65..81
+                PATH@65..81
+                  PATH_SEGMENT@65..81
+                    NAME_REF@65..76
+                      IDENT@65..76 "Deserialize"
+                    GENERIC_ARG_LIST@76..81
+                      L_ANGLE@76..77 "<"
+                      LIFETIME_ARG@77..80
+                        LIFETIME@77..80 "\'de"
+                      R_ANGLE@80..81 ">"
+          WHITESPACE@81..82 " "
+          PLUS@82..83 "+"
+          WHITESPACE@83..84 " "
+          TYPE_BOUND@84..93
+            PATH_TYPE@84..93
+              PATH@84..93
+                PATH_SEGMENT@84..93
+                  NAME_REF@84..93
+                    IDENT@84..93 "PartialEq"
+          WHITESPACE@93..94 " "
+          PLUS@94..95 "+"
+          WHITESPACE@95..96 " "
+          TYPE_BOUND@96..111
+            PATH_TYPE@96..111
+              PATH@96..111
+                PATH@96..104
+                  PATH@96..99
+                    PATH_SEGMENT@96..99
+                      NAME_REF@96..99
+                        IDENT@96..99 "std"
+                  COLON2@99..101 "::"
+                  PATH_SEGMENT@101..104
+                    NAME_REF@101..104
+                      IDENT@101..104 "fmt"
+                COLON2@104..106 "::"
+                PATH_SEGMENT@106..111
+                  NAME_REF@106..111
+                    IDENT@106..111 "Debug"
+      COMMA@111..112 ","
+    WHITESPACE@112..113 "\n"
+    BLOCK_EXPR@113..115
+      L_CURLY@113..114 "{"
+      R_CURLY@114..115 "}"
+  WHITESPACE@115..116 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0032_where_for.rs b/crates/syntax/test_data/parser/ok/0032_where_for.rs
new file mode 100644
index 00000000000..588170fbef5
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0032_where_for.rs
@@ -0,0 +1,4 @@
+fn test_serialization<SER>()
+where
+    SER: Serialize + for<'de> Deserialize<'de> + PartialEq + std::fmt::Debug,
+{}
diff --git a/crates/syntax/test_data/parser/ok/0033_label_break.rast b/crates/syntax/test_data/parser/ok/0033_label_break.rast
new file mode 100644
index 00000000000..88800ca7a3f
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0033_label_break.rast
@@ -0,0 +1,215 @@
+SOURCE_FILE@0..506
+  FN@0..505
+    COMMENT@0..33 "// format with label  ..."
+    WHITESPACE@33..34 "\n"
+    FN_KW@34..36 "fn"
+    WHITESPACE@36..37 " "
+    NAME@37..41
+      IDENT@37..41 "main"
+    PARAM_LIST@41..43
+      L_PAREN@41..42 "("
+      R_PAREN@42..43 ")"
+    WHITESPACE@43..44 " "
+    BLOCK_EXPR@44..505
+      L_CURLY@44..45 "{"
+      WHITESPACE@45..50 "\n    "
+      EXPR_STMT@50..66
+        EFFECT_EXPR@50..66
+          LABEL@50..63
+            LIFETIME@50..62 "\'empty_block"
+            COLON@62..63 ":"
+          WHITESPACE@63..64 " "
+          BLOCK_EXPR@64..66
+            L_CURLY@64..65 "{"
+            R_CURLY@65..66 "}"
+      WHITESPACE@66..72 "\n\n    "
+      EXPR_STMT@72..295
+        EFFECT_EXPR@72..295
+          LABEL@72..79
+            LIFETIME@72..78 "\'block"
+            COLON@78..79 ":"
+          WHITESPACE@79..80 " "
+          BLOCK_EXPR@80..295
+            L_CURLY@80..81 "{"
+            WHITESPACE@81..90 "\n        "
+            EXPR_STMT@90..101
+              CALL_EXPR@90..100
+                PATH_EXPR@90..98
+                  PATH@90..98
+                    PATH_SEGMENT@90..98
+                      NAME_REF@90..98
+                        IDENT@90..98 "do_thing"
+                ARG_LIST@98..100
+                  L_PAREN@98..99 "("
+                  R_PAREN@99..100 ")"
+              SEMICOLON@100..101 ";"
+            WHITESPACE@101..110 "\n        "
+            EXPR_STMT@110..170
+              IF_EXPR@110..170
+                IF_KW@110..112 "if"
+                WHITESPACE@112..113 " "
+                CONDITION@113..132
+                  CALL_EXPR@113..132
+                    PATH_EXPR@113..130
+                      PATH@113..130
+                        PATH_SEGMENT@113..130
+                          NAME_REF@113..130
+                            IDENT@113..130 "condition_not_met"
+                    ARG_LIST@130..132
+                      L_PAREN@130..131 "("
+                      R_PAREN@131..132 ")"
+                WHITESPACE@132..133 " "
+                BLOCK_EXPR@133..170
+                  L_CURLY@133..134 "{"
+                  WHITESPACE@134..147 "\n            "
+                  EXPR_STMT@147..160
+                    BREAK_EXPR@147..159
+                      BREAK_KW@147..152 "break"
+                      WHITESPACE@152..153 " "
+                      LIFETIME@153..159 "\'block"
+                    SEMICOLON@159..160 ";"
+                  WHITESPACE@160..169 "\n        "
+                  R_CURLY@169..170 "}"
+            WHITESPACE@170..179 "\n        "
+            EXPR_STMT@179..195
+              CALL_EXPR@179..194
+                PATH_EXPR@179..192
+                  PATH@179..192
+                    PATH_SEGMENT@179..192
+                      NAME_REF@179..192
+                        IDENT@179..192 "do_next_thing"
+                ARG_LIST@192..194
+                  L_PAREN@192..193 "("
+                  R_PAREN@193..194 ")"
+              SEMICOLON@194..195 ";"
+            WHITESPACE@195..204 "\n        "
+            EXPR_STMT@204..264
+              IF_EXPR@204..264
+                IF_KW@204..206 "if"
+                WHITESPACE@206..207 " "
+                CONDITION@207..226
+                  CALL_EXPR@207..226
+                    PATH_EXPR@207..224
+                      PATH@207..224
+                        PATH_SEGMENT@207..224
+                          NAME_REF@207..224
+                            IDENT@207..224 "condition_not_met"
+                    ARG_LIST@224..226
+                      L_PAREN@224..225 "("
+                      R_PAREN@225..226 ")"
+                WHITESPACE@226..227 " "
+                BLOCK_EXPR@227..264
+                  L_CURLY@227..228 "{"
+                  WHITESPACE@228..241 "\n            "
+                  EXPR_STMT@241..254
+                    BREAK_EXPR@241..253
+                      BREAK_KW@241..246 "break"
+                      WHITESPACE@246..247 " "
+                      LIFETIME@247..253 "\'block"
+                    SEMICOLON@253..254 ";"
+                  WHITESPACE@254..263 "\n        "
+                  R_CURLY@263..264 "}"
+            WHITESPACE@264..273 "\n        "
+            EXPR_STMT@273..289
+              CALL_EXPR@273..288
+                PATH_EXPR@273..286
+                  PATH@273..286
+                    PATH_SEGMENT@273..286
+                      NAME_REF@273..286
+                        IDENT@273..286 "do_last_thing"
+                ARG_LIST@286..288
+                  L_PAREN@286..287 "("
+                  R_PAREN@287..288 ")"
+              SEMICOLON@288..289 ";"
+            WHITESPACE@289..294 "\n    "
+            R_CURLY@294..295 "}"
+      WHITESPACE@295..301 "\n\n    "
+      LET_STMT@301..503
+        LET_KW@301..304 "let"
+        WHITESPACE@304..305 " "
+        IDENT_PAT@305..311
+          NAME@305..311
+            IDENT@305..311 "result"
+        WHITESPACE@311..312 " "
+        EQ@312..313 "="
+        WHITESPACE@313..314 " "
+        EFFECT_EXPR@314..502
+          LABEL@314..321
+            LIFETIME@314..320 "\'block"
+            COLON@320..321 ":"
+          WHITESPACE@321..322 " "
+          BLOCK_EXPR@322..502
+            L_CURLY@322..323 "{"
+            WHITESPACE@323..332 "\n        "
+            EXPR_STMT@332..403
+              IF_EXPR@332..403
+                IF_KW@332..334 "if"
+                WHITESPACE@334..335 " "
+                CONDITION@335..340
+                  CALL_EXPR@335..340
+                    PATH_EXPR@335..338
+                      PATH@335..338
+                        PATH_SEGMENT@335..338
+                          NAME_REF@335..338
+                            IDENT@335..338 "foo"
+                    ARG_LIST@338..340
+                      L_PAREN@338..339 "("
+                      R_PAREN@339..340 ")"
+                WHITESPACE@340..341 " "
+                BLOCK_EXPR@341..403
+                  L_CURLY@341..342 "{"
+                  WHITESPACE@342..355 "\n            "
+                  COMMENT@355..365 "// comment"
+                  WHITESPACE@365..378 "\n            "
+                  EXPR_STMT@378..393
+                    BREAK_EXPR@378..392
+                      BREAK_KW@378..383 "break"
+                      WHITESPACE@383..384 " "
+                      LIFETIME@384..390 "\'block"
+                      WHITESPACE@390..391 " "
+                      LITERAL@391..392
+                        INT_NUMBER@391..392 "1"
+                    SEMICOLON@392..393 ";"
+                  WHITESPACE@393..402 "\n        "
+                  R_CURLY@402..403 "}"
+            WHITESPACE@403..412 "\n        "
+            EXPR_STMT@412..486
+              IF_EXPR@412..486
+                IF_KW@412..414 "if"
+                WHITESPACE@414..415 " "
+                CONDITION@415..420
+                  CALL_EXPR@415..420
+                    PATH_EXPR@415..418
+                      PATH@415..418
+                        PATH_SEGMENT@415..418
+                          NAME_REF@415..418
+                            IDENT@415..418 "bar"
+                    ARG_LIST@418..420
+                      L_PAREN@418..419 "("
+                      R_PAREN@419..420 ")"
+                WHITESPACE@420..421 " "
+                BLOCK_EXPR@421..486
+                  L_CURLY@421..422 "{"
+                  WHITESPACE@422..435 "\n            "
+                  COMMENT@435..448 "/* comment */"
+                  WHITESPACE@448..461 "\n            "
+                  EXPR_STMT@461..476
+                    BREAK_EXPR@461..475
+                      BREAK_KW@461..466 "break"
+                      WHITESPACE@466..467 " "
+                      LIFETIME@467..473 "\'block"
+                      WHITESPACE@473..474 " "
+                      LITERAL@474..475
+                        INT_NUMBER@474..475 "2"
+                    SEMICOLON@475..476 ";"
+                  WHITESPACE@476..485 "\n        "
+                  R_CURLY@485..486 "}"
+            WHITESPACE@486..495 "\n        "
+            LITERAL@495..496
+              INT_NUMBER@495..496 "3"
+            WHITESPACE@496..501 "\n    "
+            R_CURLY@501..502 "}"
+        SEMICOLON@502..503 ";"
+      WHITESPACE@503..504 "\n"
+      R_CURLY@504..505 "}"
+  WHITESPACE@505..506 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0033_label_break.rs b/crates/syntax/test_data/parser/ok/0033_label_break.rs
new file mode 100644
index 00000000000..728d78137c9
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0033_label_break.rs
@@ -0,0 +1,28 @@
+// format with label break value.
+fn main() {
+    'empty_block: {}
+
+    'block: {
+        do_thing();
+        if condition_not_met() {
+            break 'block;
+        }
+        do_next_thing();
+        if condition_not_met() {
+            break 'block;
+        }
+        do_last_thing();
+    }
+
+    let result = 'block: {
+        if foo() {
+            // comment
+            break 'block 1;
+        }
+        if bar() {
+            /* comment */
+            break 'block 2;
+        }
+        3
+    };
+}
diff --git a/crates/syntax/test_data/parser/ok/0034_crate_path_in_call.rast b/crates/syntax/test_data/parser/ok/0034_crate_path_in_call.rast
new file mode 100644
index 00000000000..5ad8c570d26
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0034_crate_path_in_call.rast
@@ -0,0 +1,41 @@
+SOURCE_FILE@0..62
+  FN@0..61
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..61
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      EXPR_STMT@16..59
+        CALL_EXPR@16..58
+          PATH_EXPR@16..26
+            PATH@16..26
+              PATH_SEGMENT@16..26
+                NAME_REF@16..26
+                  IDENT@16..26 "make_query"
+          ARG_LIST@26..58
+            L_PAREN@26..27 "("
+            PATH_EXPR@27..57
+              PATH@27..57
+                PATH@27..44
+                  PATH@27..32
+                    PATH_SEGMENT@27..32
+                      CRATE_KW@27..32 "crate"
+                  COLON2@32..34 "::"
+                  PATH_SEGMENT@34..44
+                    NAME_REF@34..44
+                      IDENT@34..44 "module_map"
+                COLON2@44..46 "::"
+                PATH_SEGMENT@46..57
+                  NAME_REF@46..57
+                    IDENT@46..57 "module_tree"
+            R_PAREN@57..58 ")"
+        SEMICOLON@58..59 ";"
+      WHITESPACE@59..60 "\n"
+      R_CURLY@60..61 "}"
+  WHITESPACE@61..62 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0034_crate_path_in_call.rs b/crates/syntax/test_data/parser/ok/0034_crate_path_in_call.rs
new file mode 100644
index 00000000000..f1ed30220ae
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0034_crate_path_in_call.rs
@@ -0,0 +1,3 @@
+fn main() {
+    make_query(crate::module_map::module_tree);
+}
diff --git a/crates/syntax/test_data/parser/ok/0035_weird_exprs.rast b/crates/syntax/test_data/parser/ok/0035_weird_exprs.rast
new file mode 100644
index 00000000000..7c61b5006de
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0035_weird_exprs.rast
@@ -0,0 +1,2291 @@
+SOURCE_FILE@0..3813
+  COMMENT@0..55 "//! Adapted from a `r ..."
+  WHITESPACE@55..56 "\n"
+  COMMENT@56..173 "//! https://github.co ..."
+  WHITESPACE@173..174 "\n"
+  COMMENT@174..178 "//! "
+  WHITESPACE@178..179 "\n"
+  COMMENT@179..269 "//! Reported to rust- ..."
+  WHITESPACE@269..271 "\n\n"
+  ATTR@271..302
+    POUND@271..272 "#"
+    BANG@272..273 "!"
+    L_BRACK@273..274 "["
+    PATH@274..279
+      PATH_SEGMENT@274..279
+        NAME_REF@274..279
+          IDENT@274..279 "allow"
+    TOKEN_TREE@279..301
+      L_PAREN@279..280 "("
+      IDENT@280..300 "non_camel_case_types"
+      R_PAREN@300..301 ")"
+    R_BRACK@301..302 "]"
+  WHITESPACE@302..303 "\n"
+  ATTR@303..323
+    POUND@303..304 "#"
+    BANG@304..305 "!"
+    L_BRACK@305..306 "["
+    PATH@306..311
+      PATH_SEGMENT@306..311
+        NAME_REF@306..311
+          IDENT@306..311 "allow"
+    TOKEN_TREE@311..322
+      L_PAREN@311..312 "("
+      IDENT@312..321 "dead_code"
+      R_PAREN@321..322 ")"
+    R_BRACK@322..323 "]"
+  WHITESPACE@323..324 "\n"
+  ATTR@324..351
+    POUND@324..325 "#"
+    BANG@325..326 "!"
+    L_BRACK@326..327 "["
+    PATH@327..332
+      PATH_SEGMENT@327..332
+        NAME_REF@327..332
+          IDENT@327..332 "allow"
+    TOKEN_TREE@332..350
+      L_PAREN@332..333 "("
+      IDENT@333..349 "unreachable_code"
+      R_PAREN@349..350 ")"
+    R_BRACK@350..351 "]"
+  WHITESPACE@351..352 "\n"
+  ATTR@352..376
+    POUND@352..353 "#"
+    BANG@353..354 "!"
+    L_BRACK@354..355 "["
+    PATH@355..360
+      PATH_SEGMENT@355..360
+        NAME_REF@355..360
+          IDENT@355..360 "allow"
+    TOKEN_TREE@360..375
+      L_PAREN@360..361 "("
+      IDENT@361..374 "unused_parens"
+      R_PAREN@374..375 ")"
+    R_BRACK@375..376 "]"
+  WHITESPACE@376..378 "\n\n"
+  ATTR@378..405
+    POUND@378..379 "#"
+    BANG@379..380 "!"
+    L_BRACK@380..381 "["
+    PATH@381..396
+      PATH_SEGMENT@381..396
+        NAME_REF@381..396
+          IDENT@381..396 "recursion_limit"
+    WHITESPACE@396..397 " "
+    EQ@397..398 "="
+    WHITESPACE@398..399 " "
+    LITERAL@399..404
+      STRING@399..404 "\"128\""
+    R_BRACK@404..405 "]"
+  WHITESPACE@405..407 "\n\n"
+  USE@407..427
+    USE_KW@407..410 "use"
+    WHITESPACE@410..411 " "
+    USE_TREE@411..426
+      PATH@411..426
+        PATH@411..420
+          PATH@411..414
+            PATH_SEGMENT@411..414
+              NAME_REF@411..414
+                IDENT@411..414 "std"
+          COLON2@414..416 "::"
+          PATH_SEGMENT@416..420
+            NAME_REF@416..420
+              IDENT@416..420 "cell"
+        COLON2@420..422 "::"
+        PATH_SEGMENT@422..426
+          NAME_REF@422..426
+            IDENT@422..426 "Cell"
+    SEMICOLON@426..427 ";"
+  WHITESPACE@427..428 "\n"
+  USE@428..447
+    USE_KW@428..431 "use"
+    WHITESPACE@431..432 " "
+    USE_TREE@432..446
+      PATH@432..446
+        PATH@432..440
+          PATH@432..435
+            PATH_SEGMENT@432..435
+              NAME_REF@432..435
+                IDENT@432..435 "std"
+          COLON2@435..437 "::"
+          PATH_SEGMENT@437..440
+            NAME_REF@437..440
+              IDENT@437..440 "mem"
+        COLON2@440..442 "::"
+        PATH_SEGMENT@442..446
+          NAME_REF@442..446
+            IDENT@442..446 "swap"
+    SEMICOLON@446..447 ";"
+  WHITESPACE@447..449 "\n\n"
+  COMMENT@449..518 "// Just a grab bag of ..."
+  WHITESPACE@518..520 "\n\n"
+  FN@520..572
+    FN_KW@520..522 "fn"
+    WHITESPACE@522..523 " "
+    NAME@523..530
+      IDENT@523..530 "strange"
+    PARAM_LIST@530..532
+      L_PAREN@530..531 "("
+      R_PAREN@531..532 ")"
+    WHITESPACE@532..533 " "
+    RET_TYPE@533..540
+      THIN_ARROW@533..535 "->"
+      WHITESPACE@535..536 " "
+      PATH_TYPE@536..540
+        PATH@536..540
+          PATH_SEGMENT@536..540
+            NAME_REF@536..540
+              IDENT@536..540 "bool"
+    WHITESPACE@540..541 " "
+    BLOCK_EXPR@541..572
+      L_CURLY@541..542 "{"
+      WHITESPACE@542..543 " "
+      LET_STMT@543..570
+        LET_KW@543..546 "let"
+        WHITESPACE@546..547 " "
+        IDENT_PAT@547..549
+          NAME@547..549
+            IDENT@547..549 "_x"
+        COLON@549..550 ":"
+        WHITESPACE@550..551 " "
+        PATH_TYPE@551..555
+          PATH@551..555
+            PATH_SEGMENT@551..555
+              NAME_REF@551..555
+                IDENT@551..555 "bool"
+        WHITESPACE@555..556 " "
+        EQ@556..557 "="
+        WHITESPACE@557..558 " "
+        RETURN_EXPR@558..569
+          RETURN_KW@558..564 "return"
+          WHITESPACE@564..565 " "
+          LITERAL@565..569
+            TRUE_KW@565..569 "true"
+        SEMICOLON@569..570 ";"
+      WHITESPACE@570..571 " "
+      R_CURLY@571..572 "}"
+  WHITESPACE@572..574 "\n\n"
+  FN@574..624
+    FN_KW@574..576 "fn"
+    WHITESPACE@576..577 " "
+    NAME@577..582
+      IDENT@577..582 "funny"
+    PARAM_LIST@582..584
+      L_PAREN@582..583 "("
+      R_PAREN@583..584 ")"
+    WHITESPACE@584..585 " "
+    BLOCK_EXPR@585..624
+      L_CURLY@585..586 "{"
+      WHITESPACE@586..591 "\n    "
+      FN@591..607
+        FN_KW@591..593 "fn"
+        WHITESPACE@593..594 " "
+        NAME@594..595
+          IDENT@594..595 "f"
+        PARAM_LIST@595..603
+          L_PAREN@595..596 "("
+          PARAM@596..602
+            IDENT_PAT@596..598
+              NAME@596..598
+                IDENT@596..598 "_x"
+            COLON@598..599 ":"
+            WHITESPACE@599..600 " "
+            TUPLE_TYPE@600..602
+              L_PAREN@600..601 "("
+              R_PAREN@601..602 ")"
+          R_PAREN@602..603 ")"
+        WHITESPACE@603..604 " "
+        BLOCK_EXPR@604..607
+          L_CURLY@604..605 "{"
+          WHITESPACE@605..606 " "
+          R_CURLY@606..607 "}"
+      WHITESPACE@607..612 "\n    "
+      EXPR_STMT@612..622
+        CALL_EXPR@612..621
+          PATH_EXPR@612..613
+            PATH@612..613
+              PATH_SEGMENT@612..613
+                NAME_REF@612..613
+                  IDENT@612..613 "f"
+          ARG_LIST@613..621
+            L_PAREN@613..614 "("
+            RETURN_EXPR@614..620
+              RETURN_KW@614..620 "return"
+            R_PAREN@620..621 ")"
+        SEMICOLON@621..622 ";"
+      WHITESPACE@622..623 "\n"
+      R_CURLY@623..624 "}"
+  WHITESPACE@624..626 "\n\n"
+  FN@626..816
+    FN_KW@626..628 "fn"
+    WHITESPACE@628..629 " "
+    NAME@629..633
+      IDENT@629..633 "what"
+    PARAM_LIST@633..635
+      L_PAREN@633..634 "("
+      R_PAREN@634..635 ")"
+    WHITESPACE@635..636 " "
+    BLOCK_EXPR@636..816
+      L_CURLY@636..637 "{"
+      WHITESPACE@637..642 "\n    "
+      FN@642..720
+        FN_KW@642..644 "fn"
+        WHITESPACE@644..645 " "
+        NAME@645..648
+          IDENT@645..648 "the"
+        PARAM_LIST@648..664
+          L_PAREN@648..649 "("
+          PARAM@649..663
+            IDENT_PAT@649..650
+              NAME@649..650
+                IDENT@649..650 "x"
+            COLON@650..651 ":"
+            WHITESPACE@651..652 " "
+            REF_TYPE@652..663
+              AMP@652..653 "&"
+              PATH_TYPE@653..663
+                PATH@653..663
+                  PATH_SEGMENT@653..663
+                    NAME_REF@653..657
+                      IDENT@653..657 "Cell"
+                    GENERIC_ARG_LIST@657..663
+                      L_ANGLE@657..658 "<"
+                      TYPE_ARG@658..662
+                        PATH_TYPE@658..662
+                          PATH@658..662
+                            PATH_SEGMENT@658..662
+                              NAME_REF@658..662
+                                IDENT@658..662 "bool"
+                      R_ANGLE@662..663 ">"
+          R_PAREN@663..664 ")"
+        WHITESPACE@664..665 " "
+        BLOCK_EXPR@665..720
+          L_CURLY@665..666 "{"
+          WHITESPACE@666..675 "\n        "
+          EXPR_STMT@675..714
+            RETURN_EXPR@675..713
+              RETURN_KW@675..681 "return"
+              WHITESPACE@681..682 " "
+              WHILE_EXPR@682..713
+                WHILE_KW@682..687 "while"
+                WHITESPACE@687..688 " "
+                CONDITION@688..696
+                  PREFIX_EXPR@688..696
+                    BANG@688..689 "!"
+                    METHOD_CALL_EXPR@689..696
+                      PATH_EXPR@689..690
+                        PATH@689..690
+                          PATH_SEGMENT@689..690
+                            NAME_REF@689..690
+                              IDENT@689..690 "x"
+                      DOT@690..691 "."
+                      NAME_REF@691..694
+                        IDENT@691..694 "get"
+                      ARG_LIST@694..696
+                        L_PAREN@694..695 "("
+                        R_PAREN@695..696 ")"
+                WHITESPACE@696..697 " "
+                BLOCK_EXPR@697..713
+                  L_CURLY@697..698 "{"
+                  WHITESPACE@698..699 " "
+                  EXPR_STMT@699..711
+                    METHOD_CALL_EXPR@699..710
+                      PATH_EXPR@699..700
+                        PATH@699..700
+                          PATH_SEGMENT@699..700
+                            NAME_REF@699..700
+                              IDENT@699..700 "x"
+                      DOT@700..701 "."
+                      NAME_REF@701..704
+                        IDENT@701..704 "set"
+                      ARG_LIST@704..710
+                        L_PAREN@704..705 "("
+                        LITERAL@705..709
+                          TRUE_KW@705..709 "true"
+                        R_PAREN@709..710 ")"
+                    SEMICOLON@710..711 ";"
+                  WHITESPACE@711..712 " "
+                  R_CURLY@712..713 "}"
+            SEMICOLON@713..714 ";"
+          WHITESPACE@714..719 "\n    "
+          R_CURLY@719..720 "}"
+      WHITESPACE@720..725 "\n    "
+      LET_STMT@725..751
+        LET_KW@725..728 "let"
+        WHITESPACE@728..729 " "
+        IDENT_PAT@729..730
+          NAME@729..730
+            IDENT@729..730 "i"
+        WHITESPACE@730..731 " "
+        EQ@731..732 "="
+        WHITESPACE@732..733 " "
+        REF_EXPR@733..750
+          AMP@733..734 "&"
+          CALL_EXPR@734..750
+            PATH_EXPR@734..743
+              PATH@734..743
+                PATH@734..738
+                  PATH_SEGMENT@734..738
+                    NAME_REF@734..738
+                      IDENT@734..738 "Cell"
+                COLON2@738..740 "::"
+                PATH_SEGMENT@740..743
+                  NAME_REF@740..743
+                    IDENT@740..743 "new"
+            ARG_LIST@743..750
+              L_PAREN@743..744 "("
+              LITERAL@744..749
+                FALSE_KW@744..749 "false"
+              R_PAREN@749..750 ")"
+        SEMICOLON@750..751 ";"
+      WHITESPACE@751..756 "\n    "
+      LET_STMT@756..778
+        LET_KW@756..759 "let"
+        WHITESPACE@759..760 " "
+        IDENT_PAT@760..764
+          NAME@760..764
+            IDENT@760..764 "dont"
+        WHITESPACE@764..765 " "
+        EQ@765..766 "="
+        WHITESPACE@766..767 " "
+        BLOCK_EXPR@767..777
+          L_CURLY@767..768 "{"
+          CLOSURE_EXPR@768..776
+            PARAM_LIST@768..770
+              PIPE@768..769 "|"
+              PIPE@769..770 "|"
+            CALL_EXPR@770..776
+              PATH_EXPR@770..773
+                PATH@770..773
+                  PATH_SEGMENT@770..773
+                    NAME_REF@770..773
+                      IDENT@770..773 "the"
+              ARG_LIST@773..776
+                L_PAREN@773..774 "("
+                PATH_EXPR@774..775
+                  PATH@774..775
+                    PATH_SEGMENT@774..775
+                      NAME_REF@774..775
+                        IDENT@774..775 "i"
+                R_PAREN@775..776 ")"
+          R_CURLY@776..777 "}"
+        SEMICOLON@777..778 ";"
+      WHITESPACE@778..783 "\n    "
+      EXPR_STMT@783..790
+        CALL_EXPR@783..789
+          PATH_EXPR@783..787
+            PATH@783..787
+              PATH_SEGMENT@783..787
+                NAME_REF@783..787
+                  IDENT@783..787 "dont"
+          ARG_LIST@787..789
+            L_PAREN@787..788 "("
+            R_PAREN@788..789 ")"
+        SEMICOLON@789..790 ";"
+      WHITESPACE@790..795 "\n    "
+      EXPR_STMT@795..814
+        MACRO_CALL@795..813
+          PATH@795..801
+            PATH_SEGMENT@795..801
+              NAME_REF@795..801
+                IDENT@795..801 "assert"
+          BANG@801..802 "!"
+          TOKEN_TREE@802..813
+            L_PAREN@802..803 "("
+            TOKEN_TREE@803..812
+              L_PAREN@803..804 "("
+              IDENT@804..805 "i"
+              DOT@805..806 "."
+              IDENT@806..809 "get"
+              TOKEN_TREE@809..811
+                L_PAREN@809..810 "("
+                R_PAREN@810..811 ")"
+              R_PAREN@811..812 ")"
+            R_PAREN@812..813 ")"
+        SEMICOLON@813..814 ";"
+      WHITESPACE@814..815 "\n"
+      R_CURLY@815..816 "}"
+  WHITESPACE@816..818 "\n\n"
+  FN@818..1322
+    FN_KW@818..820 "fn"
+    WHITESPACE@820..821 " "
+    NAME@821..832
+      IDENT@821..832 "zombiejesus"
+    PARAM_LIST@832..834
+      L_PAREN@832..833 "("
+      R_PAREN@833..834 ")"
+    WHITESPACE@834..835 " "
+    BLOCK_EXPR@835..1322
+      L_CURLY@835..836 "{"
+      WHITESPACE@836..841 "\n    "
+      LOOP_EXPR@841..1320
+        LOOP_KW@841..845 "loop"
+        WHITESPACE@845..846 " "
+        BLOCK_EXPR@846..1320
+          L_CURLY@846..847 "{"
+          WHITESPACE@847..856 "\n        "
+          EXPR_STMT@856..1283
+            WHILE_EXPR@856..1283
+              WHILE_KW@856..861 "while"
+              WHITESPACE@861..862 " "
+              CONDITION@862..870
+                PAREN_EXPR@862..870
+                  L_PAREN@862..863 "("
+                  RETURN_EXPR@863..869
+                    RETURN_KW@863..869 "return"
+                  R_PAREN@869..870 ")"
+              WHITESPACE@870..871 " "
+              BLOCK_EXPR@871..1283
+                L_CURLY@871..872 "{"
+                WHITESPACE@872..885 "\n            "
+                IF_EXPR@885..1273
+                  IF_KW@885..887 "if"
+                  WHITESPACE@887..888 " "
+                  CONDITION@888..896
+                    PAREN_EXPR@888..896
+                      L_PAREN@888..889 "("
+                      RETURN_EXPR@889..895
+                        RETURN_KW@889..895 "return"
+                      R_PAREN@895..896 ")"
+                  WHITESPACE@896..897 " "
+                  BLOCK_EXPR@897..1216
+                    L_CURLY@897..898 "{"
+                    WHITESPACE@898..915 "\n                "
+                    EXPR_STMT@915..1202
+                      MATCH_EXPR@915..1201
+                        MATCH_KW@915..920 "match"
+                        WHITESPACE@920..921 " "
+                        PAREN_EXPR@921..929
+                          L_PAREN@921..922 "("
+                          RETURN_EXPR@922..928
+                            RETURN_KW@922..928 "return"
+                          R_PAREN@928..929 ")"
+                        WHITESPACE@929..930 " "
+                        MATCH_ARM_LIST@930..1201
+                          L_CURLY@930..931 "{"
+                          WHITESPACE@931..952 "\n                    "
+                          MATCH_ARM@952..1147
+                            LITERAL_PAT@952..953
+                              LITERAL@952..953
+                                INT_NUMBER@952..953 "1"
+                            WHITESPACE@953..954 " "
+                            FAT_ARROW@954..956 "=>"
+                            WHITESPACE@956..957 " "
+                            BLOCK_EXPR@957..1147
+                              L_CURLY@957..958 "{"
+                              WHITESPACE@958..983 "\n                     ..."
+                              IF_EXPR@983..1125
+                                IF_KW@983..985 "if"
+                                WHITESPACE@985..986 " "
+                                CONDITION@986..994
+                                  PAREN_EXPR@986..994
+                                    L_PAREN@986..987 "("
+                                    RETURN_EXPR@987..993
+                                      RETURN_KW@987..993 "return"
+                                    R_PAREN@993..994 ")"
+                                WHITESPACE@994..995 " "
+                                BLOCK_EXPR@995..1057
+                                  L_CURLY@995..996 "{"
+                                  WHITESPACE@996..1025 "\n                     ..."
+                                  RETURN_EXPR@1025..1031
+                                    RETURN_KW@1025..1031 "return"
+                                  WHITESPACE@1031..1056 "\n                     ..."
+                                  R_CURLY@1056..1057 "}"
+                                WHITESPACE@1057..1058 " "
+                                ELSE_KW@1058..1062 "else"
+                                WHITESPACE@1062..1063 " "
+                                BLOCK_EXPR@1063..1125
+                                  L_CURLY@1063..1064 "{"
+                                  WHITESPACE@1064..1093 "\n                     ..."
+                                  RETURN_EXPR@1093..1099
+                                    RETURN_KW@1093..1099 "return"
+                                  WHITESPACE@1099..1124 "\n                     ..."
+                                  R_CURLY@1124..1125 "}"
+                              WHITESPACE@1125..1146 "\n                    "
+                              R_CURLY@1146..1147 "}"
+                          WHITESPACE@1147..1168 "\n                    "
+                          MATCH_ARM@1168..1183
+                            WILDCARD_PAT@1168..1169
+                              UNDERSCORE@1168..1169 "_"
+                            WHITESPACE@1169..1170 " "
+                            FAT_ARROW@1170..1172 "=>"
+                            WHITESPACE@1172..1173 " "
+                            BLOCK_EXPR@1173..1183
+                              L_CURLY@1173..1174 "{"
+                              WHITESPACE@1174..1175 " "
+                              RETURN_EXPR@1175..1181
+                                RETURN_KW@1175..1181 "return"
+                              WHITESPACE@1181..1182 " "
+                              R_CURLY@1182..1183 "}"
+                          WHITESPACE@1183..1200 "\n                "
+                          R_CURLY@1200..1201 "}"
+                      SEMICOLON@1201..1202 ";"
+                    WHITESPACE@1202..1215 "\n            "
+                    R_CURLY@1215..1216 "}"
+                  WHITESPACE@1216..1217 " "
+                  ELSE_KW@1217..1221 "else"
+                  WHITESPACE@1221..1222 " "
+                  IF_EXPR@1222..1273
+                    IF_KW@1222..1224 "if"
+                    WHITESPACE@1224..1225 " "
+                    CONDITION@1225..1233
+                      PAREN_EXPR@1225..1233
+                        L_PAREN@1225..1226 "("
+                        RETURN_EXPR@1226..1232
+                          RETURN_KW@1226..1232 "return"
+                        R_PAREN@1232..1233 ")"
+                    WHITESPACE@1233..1234 " "
+                    BLOCK_EXPR@1234..1273
+                      L_CURLY@1234..1235 "{"
+                      WHITESPACE@1235..1252 "\n                "
+                      EXPR_STMT@1252..1259
+                        RETURN_EXPR@1252..1258
+                          RETURN_KW@1252..1258 "return"
+                        SEMICOLON@1258..1259 ";"
+                      WHITESPACE@1259..1272 "\n            "
+                      R_CURLY@1272..1273 "}"
+                WHITESPACE@1273..1282 "\n        "
+                R_CURLY@1282..1283 "}"
+          WHITESPACE@1283..1292 "\n        "
+          IF_EXPR@1292..1314
+            IF_KW@1292..1294 "if"
+            WHITESPACE@1294..1295 " "
+            CONDITION@1295..1303
+              PAREN_EXPR@1295..1303
+                L_PAREN@1295..1296 "("
+                RETURN_EXPR@1296..1302
+                  RETURN_KW@1296..1302 "return"
+                R_PAREN@1302..1303 ")"
+            WHITESPACE@1303..1304 " "
+            BLOCK_EXPR@1304..1314
+              L_CURLY@1304..1305 "{"
+              WHITESPACE@1305..1306 " "
+              EXPR_STMT@1306..1312
+                BREAK_EXPR@1306..1311
+                  BREAK_KW@1306..1311 "break"
+                SEMICOLON@1311..1312 ";"
+              WHITESPACE@1312..1313 " "
+              R_CURLY@1313..1314 "}"
+          WHITESPACE@1314..1319 "\n    "
+          R_CURLY@1319..1320 "}"
+      WHITESPACE@1320..1321 "\n"
+      R_CURLY@1321..1322 "}"
+  WHITESPACE@1322..1324 "\n\n"
+  FN@1324..1539
+    FN_KW@1324..1326 "fn"
+    WHITESPACE@1326..1327 " "
+    NAME@1327..1334
+      IDENT@1327..1334 "notsure"
+    PARAM_LIST@1334..1336
+      L_PAREN@1334..1335 "("
+      R_PAREN@1335..1336 ")"
+    WHITESPACE@1336..1337 " "
+    BLOCK_EXPR@1337..1539
+      L_CURLY@1337..1338 "{"
+      WHITESPACE@1338..1343 "\n    "
+      LET_STMT@1343..1361
+        LET_KW@1343..1346 "let"
+        WHITESPACE@1346..1347 " "
+        IDENT_PAT@1347..1353
+          MUT_KW@1347..1350 "mut"
+          WHITESPACE@1350..1351 " "
+          NAME@1351..1353
+            IDENT@1351..1353 "_x"
+        COLON@1353..1354 ":"
+        WHITESPACE@1354..1355 " "
+        PATH_TYPE@1355..1360
+          PATH@1355..1360
+            PATH_SEGMENT@1355..1360
+              NAME_REF@1355..1360
+                IDENT@1355..1360 "isize"
+        SEMICOLON@1360..1361 ";"
+      WHITESPACE@1361..1366 "\n    "
+      LET_STMT@1366..1400
+        LET_KW@1366..1369 "let"
+        WHITESPACE@1369..1370 " "
+        IDENT_PAT@1370..1376
+          MUT_KW@1370..1373 "mut"
+          WHITESPACE@1373..1374 " "
+          NAME@1374..1376
+            IDENT@1374..1376 "_y"
+        WHITESPACE@1376..1377 " "
+        EQ@1377..1378 "="
+        WHITESPACE@1378..1379 " "
+        BIN_EXPR@1379..1399
+          PAREN_EXPR@1379..1387
+            L_PAREN@1379..1380 "("
+            BIN_EXPR@1380..1386
+              PATH_EXPR@1380..1382
+                PATH@1380..1382
+                  PATH_SEGMENT@1380..1382
+                    NAME_REF@1380..1382
+                      IDENT@1380..1382 "_x"
+              WHITESPACE@1382..1383 " "
+              EQ@1383..1384 "="
+              WHITESPACE@1384..1385 " "
+              LITERAL@1385..1386
+                INT_NUMBER@1385..1386 "0"
+            R_PAREN@1386..1387 ")"
+          WHITESPACE@1387..1388 " "
+          EQ2@1388..1390 "=="
+          WHITESPACE@1390..1391 " "
+          PAREN_EXPR@1391..1399
+            L_PAREN@1391..1392 "("
+            BIN_EXPR@1392..1398
+              PATH_EXPR@1392..1394
+                PATH@1392..1394
+                  PATH_SEGMENT@1392..1394
+                    NAME_REF@1392..1394
+                      IDENT@1392..1394 "_x"
+              WHITESPACE@1394..1395 " "
+              EQ@1395..1396 "="
+              WHITESPACE@1396..1397 " "
+              LITERAL@1397..1398
+                INT_NUMBER@1397..1398 "0"
+            R_PAREN@1398..1399 ")"
+        SEMICOLON@1399..1400 ";"
+      WHITESPACE@1400..1405 "\n    "
+      LET_STMT@1405..1438
+        LET_KW@1405..1408 "let"
+        WHITESPACE@1408..1409 " "
+        IDENT_PAT@1409..1415
+          MUT_KW@1409..1412 "mut"
+          WHITESPACE@1412..1413 " "
+          NAME@1413..1415
+            IDENT@1413..1415 "_z"
+        WHITESPACE@1415..1416 " "
+        EQ@1416..1417 "="
+        WHITESPACE@1417..1418 " "
+        BIN_EXPR@1418..1437
+          PAREN_EXPR@1418..1426
+            L_PAREN@1418..1419 "("
+            BIN_EXPR@1419..1425
+              PATH_EXPR@1419..1421
+                PATH@1419..1421
+                  PATH_SEGMENT@1419..1421
+                    NAME_REF@1419..1421
+                      IDENT@1419..1421 "_x"
+              WHITESPACE@1421..1422 " "
+              EQ@1422..1423 "="
+              WHITESPACE@1423..1424 " "
+              LITERAL@1424..1425
+                INT_NUMBER@1424..1425 "0"
+            R_PAREN@1425..1426 ")"
+          WHITESPACE@1426..1427 " "
+          L_ANGLE@1427..1428 "<"
+          WHITESPACE@1428..1429 " "
+          PAREN_EXPR@1429..1437
+            L_PAREN@1429..1430 "("
+            BIN_EXPR@1430..1436
+              PATH_EXPR@1430..1432
+                PATH@1430..1432
+                  PATH_SEGMENT@1430..1432
+                    NAME_REF@1430..1432
+                      IDENT@1430..1432 "_x"
+              WHITESPACE@1432..1433 " "
+              EQ@1433..1434 "="
+              WHITESPACE@1434..1435 " "
+              LITERAL@1435..1436
+                INT_NUMBER@1435..1436 "0"
+            R_PAREN@1436..1437 ")"
+        SEMICOLON@1437..1438 ";"
+      WHITESPACE@1438..1443 "\n    "
+      LET_STMT@1443..1474
+        LET_KW@1443..1446 "let"
+        WHITESPACE@1446..1447 " "
+        IDENT_PAT@1447..1449
+          NAME@1447..1449
+            IDENT@1447..1449 "_a"
+        WHITESPACE@1449..1450 " "
+        EQ@1450..1451 "="
+        WHITESPACE@1451..1452 " "
+        BIN_EXPR@1452..1473
+          PAREN_EXPR@1452..1461
+            L_PAREN@1452..1453 "("
+            BIN_EXPR@1453..1460
+              PATH_EXPR@1453..1455
+                PATH@1453..1455
+                  PATH_SEGMENT@1453..1455
+                    NAME_REF@1453..1455
+                      IDENT@1453..1455 "_x"
+              WHITESPACE@1455..1456 " "
+              PLUSEQ@1456..1458 "+="
+              WHITESPACE@1458..1459 " "
+              LITERAL@1459..1460
+                INT_NUMBER@1459..1460 "0"
+            R_PAREN@1460..1461 ")"
+          WHITESPACE@1461..1462 " "
+          EQ2@1462..1464 "=="
+          WHITESPACE@1464..1465 " "
+          PAREN_EXPR@1465..1473
+            L_PAREN@1465..1466 "("
+            BIN_EXPR@1466..1472
+              PATH_EXPR@1466..1468
+                PATH@1466..1468
+                  PATH_SEGMENT@1466..1468
+                    NAME_REF@1466..1468
+                      IDENT@1466..1468 "_x"
+              WHITESPACE@1468..1469 " "
+              EQ@1469..1470 "="
+              WHITESPACE@1470..1471 " "
+              LITERAL@1471..1472
+                INT_NUMBER@1471..1472 "0"
+            R_PAREN@1472..1473 ")"
+        SEMICOLON@1473..1474 ";"
+      WHITESPACE@1474..1479 "\n    "
+      LET_STMT@1479..1537
+        LET_KW@1479..1482 "let"
+        WHITESPACE@1482..1483 " "
+        IDENT_PAT@1483..1485
+          NAME@1483..1485
+            IDENT@1483..1485 "_b"
+        WHITESPACE@1485..1486 " "
+        EQ@1486..1487 "="
+        WHITESPACE@1487..1488 " "
+        BIN_EXPR@1488..1536
+          CALL_EXPR@1488..1510
+            PATH_EXPR@1488..1492
+              PATH@1488..1492
+                PATH_SEGMENT@1488..1492
+                  NAME_REF@1488..1492
+                    IDENT@1488..1492 "swap"
+            ARG_LIST@1492..1510
+              L_PAREN@1492..1493 "("
+              REF_EXPR@1493..1500
+                AMP@1493..1494 "&"
+                MUT_KW@1494..1497 "mut"
+                WHITESPACE@1497..1498 " "
+                PATH_EXPR@1498..1500
+                  PATH@1498..1500
+                    PATH_SEGMENT@1498..1500
+                      NAME_REF@1498..1500
+                        IDENT@1498..1500 "_y"
+              COMMA@1500..1501 ","
+              WHITESPACE@1501..1502 " "
+              REF_EXPR@1502..1509
+                AMP@1502..1503 "&"
+                MUT_KW@1503..1506 "mut"
+                WHITESPACE@1506..1507 " "
+                PATH_EXPR@1507..1509
+                  PATH@1507..1509
+                    PATH_SEGMENT@1507..1509
+                      NAME_REF@1507..1509
+                        IDENT@1507..1509 "_z"
+              R_PAREN@1509..1510 ")"
+          WHITESPACE@1510..1511 " "
+          EQ2@1511..1513 "=="
+          WHITESPACE@1513..1514 " "
+          CALL_EXPR@1514..1536
+            PATH_EXPR@1514..1518
+              PATH@1514..1518
+                PATH_SEGMENT@1514..1518
+                  NAME_REF@1514..1518
+                    IDENT@1514..1518 "swap"
+            ARG_LIST@1518..1536
+              L_PAREN@1518..1519 "("
+              REF_EXPR@1519..1526
+                AMP@1519..1520 "&"
+                MUT_KW@1520..1523 "mut"
+                WHITESPACE@1523..1524 " "
+                PATH_EXPR@1524..1526
+                  PATH@1524..1526
+                    PATH_SEGMENT@1524..1526
+                      NAME_REF@1524..1526
+                        IDENT@1524..1526 "_y"
+              COMMA@1526..1527 ","
+              WHITESPACE@1527..1528 " "
+              REF_EXPR@1528..1535
+                AMP@1528..1529 "&"
+                MUT_KW@1529..1532 "mut"
+                WHITESPACE@1532..1533 " "
+                PATH_EXPR@1533..1535
+                  PATH@1533..1535
+                    PATH_SEGMENT@1533..1535
+                      NAME_REF@1533..1535
+                        IDENT@1533..1535 "_z"
+              R_PAREN@1535..1536 ")"
+        SEMICOLON@1536..1537 ";"
+      WHITESPACE@1537..1538 "\n"
+      R_CURLY@1538..1539 "}"
+  WHITESPACE@1539..1541 "\n\n"
+  FN@1541..1741
+    FN_KW@1541..1543 "fn"
+    WHITESPACE@1543..1544 " "
+    NAME@1544..1557
+      IDENT@1544..1557 "canttouchthis"
+    PARAM_LIST@1557..1559
+      L_PAREN@1557..1558 "("
+      R_PAREN@1558..1559 ")"
+    WHITESPACE@1559..1560 " "
+    RET_TYPE@1560..1568
+      THIN_ARROW@1560..1562 "->"
+      WHITESPACE@1562..1563 " "
+      PATH_TYPE@1563..1568
+        PATH@1563..1568
+          PATH_SEGMENT@1563..1568
+            NAME_REF@1563..1568
+              IDENT@1563..1568 "usize"
+    WHITESPACE@1568..1569 " "
+    BLOCK_EXPR@1569..1741
+      L_CURLY@1569..1570 "{"
+      WHITESPACE@1570..1575 "\n    "
+      FN@1575..1598
+        FN_KW@1575..1577 "fn"
+        WHITESPACE@1577..1578 " "
+        NAME@1578..1579
+          IDENT@1578..1579 "p"
+        PARAM_LIST@1579..1581
+          L_PAREN@1579..1580 "("
+          R_PAREN@1580..1581 ")"
+        WHITESPACE@1581..1582 " "
+        RET_TYPE@1582..1589
+          THIN_ARROW@1582..1584 "->"
+          WHITESPACE@1584..1585 " "
+          PATH_TYPE@1585..1589
+            PATH@1585..1589
+              PATH_SEGMENT@1585..1589
+                NAME_REF@1585..1589
+                  IDENT@1585..1589 "bool"
+        WHITESPACE@1589..1590 " "
+        BLOCK_EXPR@1590..1598
+          L_CURLY@1590..1591 "{"
+          WHITESPACE@1591..1592 " "
+          LITERAL@1592..1596
+            TRUE_KW@1592..1596 "true"
+          WHITESPACE@1596..1597 " "
+          R_CURLY@1597..1598 "}"
+      WHITESPACE@1598..1603 "\n    "
+      LET_STMT@1603..1648
+        LET_KW@1603..1606 "let"
+        WHITESPACE@1606..1607 " "
+        IDENT_PAT@1607..1609
+          NAME@1607..1609
+            IDENT@1607..1609 "_a"
+        WHITESPACE@1609..1610 " "
+        EQ@1610..1611 "="
+        WHITESPACE@1611..1612 " "
+        PAREN_EXPR@1612..1647
+          L_PAREN@1612..1613 "("
+          BIN_EXPR@1613..1646
+            MACRO_CALL@1613..1628
+              PATH@1613..1619
+                PATH_SEGMENT@1613..1619
+                  NAME_REF@1613..1619
+                    IDENT@1613..1619 "assert"
+              BANG@1619..1620 "!"
+              TOKEN_TREE@1620..1628
+                L_PAREN@1620..1621 "("
+                TOKEN_TREE@1621..1627
+                  L_PAREN@1621..1622 "("
+                  TRUE_KW@1622..1626 "true"
+                  R_PAREN@1626..1627 ")"
+                R_PAREN@1627..1628 ")"
+            WHITESPACE@1628..1629 " "
+            EQ2@1629..1631 "=="
+            WHITESPACE@1631..1632 " "
+            PAREN_EXPR@1632..1646
+              L_PAREN@1632..1633 "("
+              MACRO_CALL@1633..1645
+                PATH@1633..1639
+                  PATH_SEGMENT@1633..1639
+                    NAME_REF@1633..1639
+                      IDENT@1633..1639 "assert"
+                BANG@1639..1640 "!"
+                TOKEN_TREE@1640..1645
+                  L_PAREN@1640..1641 "("
+                  IDENT@1641..1642 "p"
+                  TOKEN_TREE@1642..1644
+                    L_PAREN@1642..1643 "("
+                    R_PAREN@1643..1644 ")"
+                  R_PAREN@1644..1645 ")"
+              R_PAREN@1645..1646 ")"
+          R_PAREN@1646..1647 ")"
+        SEMICOLON@1647..1648 ";"
+      WHITESPACE@1648..1653 "\n    "
+      LET_STMT@1653..1685
+        LET_KW@1653..1656 "let"
+        WHITESPACE@1656..1657 " "
+        IDENT_PAT@1657..1659
+          NAME@1657..1659
+            IDENT@1657..1659 "_c"
+        WHITESPACE@1659..1660 " "
+        EQ@1660..1661 "="
+        WHITESPACE@1661..1662 " "
+        PAREN_EXPR@1662..1684
+          L_PAREN@1662..1663 "("
+          BIN_EXPR@1663..1683
+            MACRO_CALL@1663..1677
+              PATH@1663..1669
+                PATH_SEGMENT@1663..1669
+                  NAME_REF@1663..1669
+                    IDENT@1663..1669 "assert"
+              BANG@1669..1670 "!"
+              TOKEN_TREE@1670..1677
+                L_PAREN@1670..1671 "("
+                TOKEN_TREE@1671..1676
+                  L_PAREN@1671..1672 "("
+                  IDENT@1672..1673 "p"
+                  TOKEN_TREE@1673..1675
+                    L_PAREN@1673..1674 "("
+                    R_PAREN@1674..1675 ")"
+                  R_PAREN@1675..1676 ")"
+                R_PAREN@1676..1677 ")"
+            WHITESPACE@1677..1678 " "
+            EQ2@1678..1680 "=="
+            WHITESPACE@1680..1681 " "
+            TUPLE_EXPR@1681..1683
+              L_PAREN@1681..1682 "("
+              R_PAREN@1682..1683 ")"
+          R_PAREN@1683..1684 ")"
+        SEMICOLON@1684..1685 ";"
+      WHITESPACE@1685..1690 "\n    "
+      LET_STMT@1690..1739
+        LET_KW@1690..1693 "let"
+        WHITESPACE@1693..1694 " "
+        IDENT_PAT@1694..1696
+          NAME@1694..1696
+            IDENT@1694..1696 "_b"
+        COLON@1696..1697 ":"
+        WHITESPACE@1697..1698 " "
+        PATH_TYPE@1698..1702
+          PATH@1698..1702
+            PATH_SEGMENT@1698..1702
+              NAME_REF@1698..1702
+                IDENT@1698..1702 "bool"
+        WHITESPACE@1702..1703 " "
+        EQ@1703..1704 "="
+        WHITESPACE@1704..1705 " "
+        PAREN_EXPR@1705..1738
+          L_PAREN@1705..1706 "("
+          BIN_EXPR@1706..1737
+            MACRO_CALL@1706..1723
+              PATH@1706..1713
+                PATH_SEGMENT@1706..1713
+                  NAME_REF@1706..1713
+                    IDENT@1706..1713 "println"
+              BANG@1713..1714 "!"
+              TOKEN_TREE@1714..1723
+                L_PAREN@1714..1715 "("
+                STRING@1715..1719 "\"{}\""
+                COMMA@1719..1720 ","
+                WHITESPACE@1720..1721 " "
+                INT_NUMBER@1721..1722 "0"
+                R_PAREN@1722..1723 ")"
+            WHITESPACE@1723..1724 " "
+            EQ2@1724..1726 "=="
+            WHITESPACE@1726..1727 " "
+            PAREN_EXPR@1727..1737
+              L_PAREN@1727..1728 "("
+              RETURN_EXPR@1728..1736
+                RETURN_KW@1728..1734 "return"
+                WHITESPACE@1734..1735 " "
+                LITERAL@1735..1736
+                  INT_NUMBER@1735..1736 "0"
+              R_PAREN@1736..1737 ")"
+          R_PAREN@1737..1738 ")"
+        SEMICOLON@1738..1739 ";"
+      WHITESPACE@1739..1740 "\n"
+      R_CURLY@1740..1741 "}"
+  WHITESPACE@1741..1743 "\n\n"
+  FN@1743..1904
+    FN_KW@1743..1745 "fn"
+    WHITESPACE@1745..1746 " "
+    NAME@1746..1755
+      IDENT@1746..1755 "angrydome"
+    PARAM_LIST@1755..1757
+      L_PAREN@1755..1756 "("
+      R_PAREN@1756..1757 ")"
+    WHITESPACE@1757..1758 " "
+    BLOCK_EXPR@1758..1904
+      L_CURLY@1758..1759 "{"
+      WHITESPACE@1759..1764 "\n    "
+      EXPR_STMT@1764..1785
+        LOOP_EXPR@1764..1785
+          LOOP_KW@1764..1768 "loop"
+          WHITESPACE@1768..1769 " "
+          BLOCK_EXPR@1769..1785
+            L_CURLY@1769..1770 "{"
+            WHITESPACE@1770..1771 " "
+            IF_EXPR@1771..1783
+              IF_KW@1771..1773 "if"
+              WHITESPACE@1773..1774 " "
+              CONDITION@1774..1779
+                BREAK_EXPR@1774..1779
+                  BREAK_KW@1774..1779 "break"
+              WHITESPACE@1779..1780 " "
+              BLOCK_EXPR@1780..1783
+                L_CURLY@1780..1781 "{"
+                WHITESPACE@1781..1782 " "
+                R_CURLY@1782..1783 "}"
+            WHITESPACE@1783..1784 " "
+            R_CURLY@1784..1785 "}"
+      WHITESPACE@1785..1790 "\n    "
+      LET_STMT@1790..1804
+        LET_KW@1790..1793 "let"
+        WHITESPACE@1793..1794 " "
+        IDENT_PAT@1794..1799
+          MUT_KW@1794..1797 "mut"
+          WHITESPACE@1797..1798 " "
+          NAME@1798..1799
+            IDENT@1798..1799 "i"
+        WHITESPACE@1799..1800 " "
+        EQ@1800..1801 "="
+        WHITESPACE@1801..1802 " "
+        LITERAL@1802..1803
+          INT_NUMBER@1802..1803 "0"
+        SEMICOLON@1803..1804 ";"
+      WHITESPACE@1804..1809 "\n    "
+      LOOP_EXPR@1809..1902
+        LOOP_KW@1809..1813 "loop"
+        WHITESPACE@1813..1814 " "
+        BLOCK_EXPR@1814..1902
+          L_CURLY@1814..1815 "{"
+          WHITESPACE@1815..1816 " "
+          EXPR_STMT@1816..1823
+            BIN_EXPR@1816..1822
+              PATH_EXPR@1816..1817
+                PATH@1816..1817
+                  PATH_SEGMENT@1816..1817
+                    NAME_REF@1816..1817
+                      IDENT@1816..1817 "i"
+              WHITESPACE@1817..1818 " "
+              PLUSEQ@1818..1820 "+="
+              WHITESPACE@1820..1821 " "
+              LITERAL@1821..1822
+                INT_NUMBER@1821..1822 "1"
+            SEMICOLON@1822..1823 ";"
+          WHITESPACE@1823..1824 " "
+          EXPR_STMT@1824..1887
+            IF_EXPR@1824..1887
+              IF_KW@1824..1826 "if"
+              WHITESPACE@1826..1827 " "
+              CONDITION@1827..1833
+                BIN_EXPR@1827..1833
+                  PATH_EXPR@1827..1828
+                    PATH@1827..1828
+                      PATH_SEGMENT@1827..1828
+                        NAME_REF@1827..1828
+                          IDENT@1827..1828 "i"
+                  WHITESPACE@1828..1829 " "
+                  EQ2@1829..1831 "=="
+                  WHITESPACE@1831..1832 " "
+                  LITERAL@1832..1833
+                    INT_NUMBER@1832..1833 "1"
+              WHITESPACE@1833..1834 " "
+              BLOCK_EXPR@1834..1887
+                L_CURLY@1834..1835 "{"
+                WHITESPACE@1835..1836 " "
+                MATCH_EXPR@1836..1885
+                  MATCH_KW@1836..1841 "match"
+                  WHITESPACE@1841..1842 " "
+                  PAREN_EXPR@1842..1852
+                    L_PAREN@1842..1843 "("
+                    CONTINUE_EXPR@1843..1851
+                      CONTINUE_KW@1843..1851 "continue"
+                    R_PAREN@1851..1852 ")"
+                  WHITESPACE@1852..1853 " "
+                  MATCH_ARM_LIST@1853..1885
+                    L_CURLY@1853..1854 "{"
+                    WHITESPACE@1854..1855 " "
+                    MATCH_ARM@1855..1863
+                      LITERAL_PAT@1855..1856
+                        LITERAL@1855..1856
+                          INT_NUMBER@1855..1856 "1"
+                      WHITESPACE@1856..1857 " "
+                      FAT_ARROW@1857..1859 "=>"
+                      WHITESPACE@1859..1860 " "
+                      BLOCK_EXPR@1860..1863
+                        L_CURLY@1860..1861 "{"
+                        WHITESPACE@1861..1862 " "
+                        R_CURLY@1862..1863 "}"
+                    COMMA@1863..1864 ","
+                    WHITESPACE@1864..1865 " "
+                    MATCH_ARM@1865..1883
+                      WILDCARD_PAT@1865..1866
+                        UNDERSCORE@1865..1866 "_"
+                      WHITESPACE@1866..1867 " "
+                      FAT_ARROW@1867..1869 "=>"
+                      WHITESPACE@1869..1870 " "
+                      MACRO_CALL@1870..1883
+                        PATH@1870..1875
+                          PATH_SEGMENT@1870..1875
+                            NAME_REF@1870..1875
+                              IDENT@1870..1875 "panic"
+                        BANG@1875..1876 "!"
+                        TOKEN_TREE@1876..1883
+                          L_PAREN@1876..1877 "("
+                          STRING@1877..1882 "\"wat\""
+                          R_PAREN@1882..1883 ")"
+                    WHITESPACE@1883..1884 " "
+                    R_CURLY@1884..1885 "}"
+                WHITESPACE@1885..1886 " "
+                R_CURLY@1886..1887 "}"
+          WHITESPACE@1887..1894 "\n      "
+          EXPR_STMT@1894..1900
+            BREAK_EXPR@1894..1899
+              BREAK_KW@1894..1899 "break"
+            SEMICOLON@1899..1900 ";"
+          WHITESPACE@1900..1901 " "
+          R_CURLY@1901..1902 "}"
+      WHITESPACE@1902..1903 "\n"
+      R_CURLY@1903..1904 "}"
+  WHITESPACE@1904..1906 "\n\n"
+  FN@1906..1960
+    FN_KW@1906..1908 "fn"
+    WHITESPACE@1908..1909 " "
+    NAME@1909..1921
+      IDENT@1909..1921 "evil_lincoln"
+    PARAM_LIST@1921..1923
+      L_PAREN@1921..1922 "("
+      R_PAREN@1922..1923 ")"
+    WHITESPACE@1923..1924 " "
+    BLOCK_EXPR@1924..1960
+      L_CURLY@1924..1925 "{"
+      WHITESPACE@1925..1926 " "
+      LET_STMT@1926..1958
+        LET_KW@1926..1929 "let"
+        WHITESPACE@1929..1930 " "
+        IDENT_PAT@1930..1935
+          NAME@1930..1935
+            IDENT@1930..1935 "_evil"
+        WHITESPACE@1935..1936 " "
+        EQ@1936..1937 "="
+        WHITESPACE@1937..1938 " "
+        MACRO_CALL@1938..1957
+          PATH@1938..1945
+            PATH_SEGMENT@1938..1945
+              NAME_REF@1938..1945
+                IDENT@1938..1945 "println"
+          BANG@1945..1946 "!"
+          TOKEN_TREE@1946..1957
+            L_PAREN@1946..1947 "("
+            STRING@1947..1956 "\"lincoln\""
+            R_PAREN@1956..1957 ")"
+        SEMICOLON@1957..1958 ";"
+      WHITESPACE@1958..1959 " "
+      R_CURLY@1959..1960 "}"
+  WHITESPACE@1960..1962 "\n\n"
+  FN@1962..2198
+    FN_KW@1962..1964 "fn"
+    WHITESPACE@1964..1965 " "
+    NAME@1965..1969
+      IDENT@1965..1969 "dots"
+    PARAM_LIST@1969..1971
+      L_PAREN@1969..1970 "("
+      R_PAREN@1970..1971 ")"
+    WHITESPACE@1971..1972 " "
+    BLOCK_EXPR@1972..2198
+      L_CURLY@1972..1973 "{"
+      WHITESPACE@1973..1978 "\n    "
+      EXPR_STMT@1978..2196
+        MACRO_CALL@1978..2195
+          PATH@1978..1987
+            PATH_SEGMENT@1978..1987
+              NAME_REF@1978..1987
+                IDENT@1978..1987 "assert_eq"
+          BANG@1987..1988 "!"
+          TOKEN_TREE@1988..2195
+            L_PAREN@1988..1989 "("
+            IDENT@1989..1995 "String"
+            COLON@1995..1996 ":"
+            COLON@1996..1997 ":"
+            IDENT@1997..2001 "from"
+            TOKEN_TREE@2001..2055
+              L_PAREN@2001..2002 "("
+              STRING@2002..2054 "\".................... ..."
+              R_PAREN@2054..2055 ")"
+            COMMA@2055..2056 ","
+            WHITESPACE@2056..2072 "\n               "
+            IDENT@2072..2078 "format"
+            BANG@2078..2079 "!"
+            TOKEN_TREE@2079..2194
+              L_PAREN@2079..2080 "("
+              STRING@2080..2086 "\"{:?}\""
+              COMMA@2086..2087 ","
+              WHITESPACE@2087..2088 " "
+              DOT@2088..2089 "."
+              DOT@2089..2090 "."
+              WHITESPACE@2090..2091 " "
+              DOT@2091..2092 "."
+              DOT@2092..2093 "."
+              WHITESPACE@2093..2094 " "
+              DOT@2094..2095 "."
+              DOT@2095..2096 "."
+              WHITESPACE@2096..2097 " "
+              DOT@2097..2098 "."
+              DOT@2098..2099 "."
+              WHITESPACE@2099..2100 " "
+              DOT@2100..2101 "."
+              DOT@2101..2102 "."
+              WHITESPACE@2102..2103 " "
+              DOT@2103..2104 "."
+              DOT@2104..2105 "."
+              WHITESPACE@2105..2106 " "
+              DOT@2106..2107 "."
+              DOT@2107..2108 "."
+              WHITESPACE@2108..2109 " "
+              DOT@2109..2110 "."
+              DOT@2110..2111 "."
+              WHITESPACE@2111..2112 " "
+              DOT@2112..2113 "."
+              DOT@2113..2114 "."
+              WHITESPACE@2114..2115 " "
+              DOT@2115..2116 "."
+              DOT@2116..2117 "."
+              WHITESPACE@2117..2118 " "
+              DOT@2118..2119 "."
+              DOT@2119..2120 "."
+              WHITESPACE@2120..2121 " "
+              DOT@2121..2122 "."
+              DOT@2122..2123 "."
+              WHITESPACE@2123..2124 " "
+              DOT@2124..2125 "."
+              DOT@2125..2126 "."
+              WHITESPACE@2126..2158 "\n                     ..."
+              DOT@2158..2159 "."
+              DOT@2159..2160 "."
+              WHITESPACE@2160..2161 " "
+              DOT@2161..2162 "."
+              DOT@2162..2163 "."
+              WHITESPACE@2163..2164 " "
+              DOT@2164..2165 "."
+              DOT@2165..2166 "."
+              WHITESPACE@2166..2167 " "
+              DOT@2167..2168 "."
+              DOT@2168..2169 "."
+              WHITESPACE@2169..2170 " "
+              DOT@2170..2171 "."
+              DOT@2171..2172 "."
+              WHITESPACE@2172..2173 " "
+              DOT@2173..2174 "."
+              DOT@2174..2175 "."
+              WHITESPACE@2175..2176 " "
+              DOT@2176..2177 "."
+              DOT@2177..2178 "."
+              WHITESPACE@2178..2179 " "
+              DOT@2179..2180 "."
+              DOT@2180..2181 "."
+              WHITESPACE@2181..2182 " "
+              DOT@2182..2183 "."
+              DOT@2183..2184 "."
+              WHITESPACE@2184..2185 " "
+              DOT@2185..2186 "."
+              DOT@2186..2187 "."
+              WHITESPACE@2187..2188 " "
+              DOT@2188..2189 "."
+              DOT@2189..2190 "."
+              WHITESPACE@2190..2191 " "
+              DOT@2191..2192 "."
+              DOT@2192..2193 "."
+              R_PAREN@2193..2194 ")"
+            R_PAREN@2194..2195 ")"
+        SEMICOLON@2195..2196 ";"
+      WHITESPACE@2196..2197 "\n"
+      R_CURLY@2197..2198 "}"
+  WHITESPACE@2198..2200 "\n\n"
+  FN@2200..2693
+    FN_KW@2200..2202 "fn"
+    WHITESPACE@2202..2203 " "
+    NAME@2203..2205
+      IDENT@2203..2205 "u8"
+    PARAM_LIST@2205..2213
+      L_PAREN@2205..2206 "("
+      PARAM@2206..2212
+        IDENT_PAT@2206..2208
+          NAME@2206..2208
+            IDENT@2206..2208 "u8"
+        COLON@2208..2209 ":"
+        WHITESPACE@2209..2210 " "
+        PATH_TYPE@2210..2212
+          PATH@2210..2212
+            PATH_SEGMENT@2210..2212
+              NAME_REF@2210..2212
+                IDENT@2210..2212 "u8"
+      R_PAREN@2212..2213 ")"
+    WHITESPACE@2213..2214 " "
+    BLOCK_EXPR@2214..2693
+      L_CURLY@2214..2215 "{"
+      WHITESPACE@2215..2220 "\n    "
+      IF_EXPR@2220..2691
+        IF_KW@2220..2222 "if"
+        WHITESPACE@2222..2223 " "
+        CONDITION@2223..2232
+          BIN_EXPR@2223..2232
+            PATH_EXPR@2223..2225
+              PATH@2223..2225
+                PATH_SEGMENT@2223..2225
+                  NAME_REF@2223..2225
+                    IDENT@2223..2225 "u8"
+            WHITESPACE@2225..2226 " "
+            NEQ@2226..2228 "!="
+            WHITESPACE@2228..2229 " "
+            LITERAL@2229..2232
+              INT_NUMBER@2229..2232 "0u8"
+        WHITESPACE@2232..2233 " "
+        BLOCK_EXPR@2233..2691
+          L_CURLY@2233..2234 "{"
+          WHITESPACE@2234..2243 "\n        "
+          EXPR_STMT@2243..2685
+            MACRO_CALL@2243..2684
+              PATH@2243..2252
+                PATH_SEGMENT@2243..2252
+                  NAME_REF@2243..2252
+                    IDENT@2243..2252 "assert_eq"
+              BANG@2252..2253 "!"
+              TOKEN_TREE@2253..2684
+                L_PAREN@2253..2254 "("
+                INT_NUMBER@2254..2257 "8u8"
+                COMMA@2257..2258 ","
+                WHITESPACE@2258..2259 " "
+                TOKEN_TREE@2259..2683
+                  L_CURLY@2259..2260 "{"
+                  WHITESPACE@2260..2273 "\n            "
+                  IDENT@2273..2284 "macro_rules"
+                  BANG@2284..2285 "!"
+                  WHITESPACE@2285..2286 " "
+                  IDENT@2286..2288 "u8"
+                  WHITESPACE@2288..2289 " "
+                  TOKEN_TREE@2289..2567
+                    L_CURLY@2289..2290 "{"
+                    WHITESPACE@2290..2307 "\n                "
+                    TOKEN_TREE@2307..2311
+                      L_PAREN@2307..2308 "("
+                      IDENT@2308..2310 "u8"
+                      R_PAREN@2310..2311 ")"
+                    WHITESPACE@2311..2312 " "
+                    EQ@2312..2313 "="
+                    R_ANGLE@2313..2314 ">"
+                    WHITESPACE@2314..2315 " "
+                    TOKEN_TREE@2315..2552
+                      L_CURLY@2315..2316 "{"
+                      WHITESPACE@2316..2337 "\n                    "
+                      MOD_KW@2337..2340 "mod"
+                      WHITESPACE@2340..2341 " "
+                      IDENT@2341..2343 "u8"
+                      WHITESPACE@2343..2344 " "
+                      TOKEN_TREE@2344..2534
+                        L_CURLY@2344..2345 "{"
+                        WHITESPACE@2345..2370 "\n                     ..."
+                        PUB_KW@2370..2373 "pub"
+                        WHITESPACE@2373..2374 " "
+                        FN_KW@2374..2376 "fn"
+                        WHITESPACE@2376..2377 " "
+                        IDENT@2377..2379 "u8"
+                        L_ANGLE@2379..2380 "<"
+                        LIFETIME@2380..2383 "\'u8"
+                        COLON@2383..2384 ":"
+                        WHITESPACE@2384..2385 " "
+                        LIFETIME@2385..2388 "\'u8"
+                        WHITESPACE@2388..2389 " "
+                        PLUS@2389..2390 "+"
+                        WHITESPACE@2390..2391 " "
+                        LIFETIME@2391..2394 "\'u8"
+                        R_ANGLE@2394..2395 ">"
+                        TOKEN_TREE@2395..2408
+                          L_PAREN@2395..2396 "("
+                          IDENT@2396..2398 "u8"
+                          COLON@2398..2399 ":"
+                          WHITESPACE@2399..2400 " "
+                          AMP@2400..2401 "&"
+                          LIFETIME@2401..2404 "\'u8"
+                          WHITESPACE@2404..2405 " "
+                          IDENT@2405..2407 "u8"
+                          R_PAREN@2407..2408 ")"
+                        WHITESPACE@2408..2409 " "
+                        MINUS@2409..2410 "-"
+                        R_ANGLE@2410..2411 ">"
+                        WHITESPACE@2411..2412 " "
+                        AMP@2412..2413 "&"
+                        LIFETIME@2413..2416 "\'u8"
+                        WHITESPACE@2416..2417 " "
+                        IDENT@2417..2419 "u8"
+                        WHITESPACE@2419..2420 " "
+                        TOKEN_TREE@2420..2512
+                          L_CURLY@2420..2421 "{"
+                          WHITESPACE@2421..2450 "\n                     ..."
+                          STRING@2450..2454 "\"u8\""
+                          SEMICOLON@2454..2455 ";"
+                          WHITESPACE@2455..2484 "\n                     ..."
+                          IDENT@2484..2486 "u8"
+                          WHITESPACE@2486..2511 "\n                     ..."
+                          R_CURLY@2511..2512 "}"
+                        WHITESPACE@2512..2533 "\n                    "
+                        R_CURLY@2533..2534 "}"
+                      WHITESPACE@2534..2551 "\n                "
+                      R_CURLY@2551..2552 "}"
+                    SEMICOLON@2552..2553 ";"
+                    WHITESPACE@2553..2566 "\n            "
+                    R_CURLY@2566..2567 "}"
+                  WHITESPACE@2567..2581 "\n\n            "
+                  IDENT@2581..2583 "u8"
+                  BANG@2583..2584 "!"
+                  TOKEN_TREE@2584..2588
+                    L_PAREN@2584..2585 "("
+                    IDENT@2585..2587 "u8"
+                    R_PAREN@2587..2588 ")"
+                  SEMICOLON@2588..2589 ";"
+                  WHITESPACE@2589..2602 "\n            "
+                  LET_KW@2602..2605 "let"
+                  WHITESPACE@2605..2606 " "
+                  AMP@2606..2607 "&"
+                  IDENT@2607..2609 "u8"
+                  COLON@2609..2610 ":"
+                  WHITESPACE@2610..2611 " "
+                  AMP@2611..2612 "&"
+                  IDENT@2612..2614 "u8"
+                  WHITESPACE@2614..2615 " "
+                  EQ@2615..2616 "="
+                  WHITESPACE@2616..2617 " "
+                  IDENT@2617..2619 "u8"
+                  COLON@2619..2620 ":"
+                  COLON@2620..2621 ":"
+                  IDENT@2621..2623 "u8"
+                  TOKEN_TREE@2623..2629
+                    L_PAREN@2623..2624 "("
+                    AMP@2624..2625 "&"
+                    INT_NUMBER@2625..2628 "8u8"
+                    R_PAREN@2628..2629 ")"
+                  SEMICOLON@2629..2630 ";"
+                  WHITESPACE@2630..2643 "\n            "
+                  CRATE_KW@2643..2648 "crate"
+                  COLON@2648..2649 ":"
+                  COLON@2649..2650 ":"
+                  IDENT@2650..2652 "u8"
+                  TOKEN_TREE@2652..2657
+                    L_PAREN@2652..2653 "("
+                    INT_NUMBER@2653..2656 "0u8"
+                    R_PAREN@2656..2657 ")"
+                  SEMICOLON@2657..2658 ";"
+                  WHITESPACE@2658..2671 "\n            "
+                  IDENT@2671..2673 "u8"
+                  WHITESPACE@2673..2682 "\n        "
+                  R_CURLY@2682..2683 "}"
+                R_PAREN@2683..2684 ")"
+            SEMICOLON@2684..2685 ";"
+          WHITESPACE@2685..2690 "\n    "
+          R_CURLY@2690..2691 "}"
+      WHITESPACE@2691..2692 "\n"
+      R_CURLY@2692..2693 "}"
+  WHITESPACE@2693..2695 "\n\n"
+  FN@2695..2832
+    FN_KW@2695..2697 "fn"
+    WHITESPACE@2697..2698 " "
+    NAME@2698..2703
+      IDENT@2698..2703 "fishy"
+    PARAM_LIST@2703..2705
+      L_PAREN@2703..2704 "("
+      R_PAREN@2704..2705 ")"
+    WHITESPACE@2705..2706 " "
+    BLOCK_EXPR@2706..2832
+      L_CURLY@2706..2707 "{"
+      WHITESPACE@2707..2712 "\n    "
+      EXPR_STMT@2712..2830
+        MACRO_CALL@2712..2829
+          PATH@2712..2721
+            PATH_SEGMENT@2712..2721
+              NAME_REF@2712..2721
+                IDENT@2712..2721 "assert_eq"
+          BANG@2721..2722 "!"
+          TOKEN_TREE@2722..2829
+            L_PAREN@2722..2723 "("
+            IDENT@2723..2729 "String"
+            COLON@2729..2730 ":"
+            COLON@2730..2731 ":"
+            IDENT@2731..2735 "from"
+            TOKEN_TREE@2735..2742
+              L_PAREN@2735..2736 "("
+              STRING@2736..2741 "\"><>\""
+              R_PAREN@2741..2742 ")"
+            COMMA@2742..2743 ","
+            WHITESPACE@2743..2759 "\n               "
+            IDENT@2759..2765 "String"
+            COLON@2765..2766 ":"
+            COLON@2766..2767 ":"
+            L_ANGLE@2767..2768 "<"
+            R_ANGLE@2768..2769 ">"
+            COLON@2769..2770 ":"
+            COLON@2770..2771 ":"
+            IDENT@2771..2775 "from"
+            COLON@2775..2776 ":"
+            COLON@2776..2777 ":"
+            L_ANGLE@2777..2778 "<"
+            R_ANGLE@2778..2779 ">"
+            TOKEN_TREE@2779..2786
+              L_PAREN@2779..2780 "("
+              STRING@2780..2785 "\"><>\""
+              R_PAREN@2785..2786 ")"
+            DOT@2786..2787 "."
+            IDENT@2787..2792 "chars"
+            COLON@2792..2793 ":"
+            COLON@2793..2794 ":"
+            L_ANGLE@2794..2795 "<"
+            R_ANGLE@2795..2796 ">"
+            TOKEN_TREE@2796..2798
+              L_PAREN@2796..2797 "("
+              R_PAREN@2797..2798 ")"
+            DOT@2798..2799 "."
+            IDENT@2799..2802 "rev"
+            COLON@2802..2803 ":"
+            COLON@2803..2804 ":"
+            L_ANGLE@2804..2805 "<"
+            R_ANGLE@2805..2806 ">"
+            TOKEN_TREE@2806..2808
+              L_PAREN@2806..2807 "("
+              R_PAREN@2807..2808 ")"
+            DOT@2808..2809 "."
+            IDENT@2809..2816 "collect"
+            COLON@2816..2817 ":"
+            COLON@2817..2818 ":"
+            L_ANGLE@2818..2819 "<"
+            IDENT@2819..2825 "String"
+            R_ANGLE@2825..2826 ">"
+            TOKEN_TREE@2826..2828
+              L_PAREN@2826..2827 "("
+              R_PAREN@2827..2828 ")"
+            R_PAREN@2828..2829 ")"
+        SEMICOLON@2829..2830 ";"
+      WHITESPACE@2830..2831 "\n"
+      R_CURLY@2831..2832 "}"
+  WHITESPACE@2832..2834 "\n\n"
+  FN@2834..2906
+    FN_KW@2834..2836 "fn"
+    WHITESPACE@2836..2837 " "
+    NAME@2837..2842
+      IDENT@2837..2842 "union"
+    PARAM_LIST@2842..2844
+      L_PAREN@2842..2843 "("
+      R_PAREN@2843..2844 ")"
+    WHITESPACE@2844..2845 " "
+    BLOCK_EXPR@2845..2906
+      L_CURLY@2845..2846 "{"
+      WHITESPACE@2846..2851 "\n    "
+      UNION@2851..2904
+        UNION_KW@2851..2856 "union"
+        WHITESPACE@2856..2857 " "
+        NAME@2857..2862
+          IDENT@2857..2862 "union"
+        GENERIC_PARAM_LIST@2862..2870
+          L_ANGLE@2862..2863 "<"
+          LIFETIME_PARAM@2863..2869
+            LIFETIME@2863..2869 "\'union"
+          R_ANGLE@2869..2870 ">"
+        WHITESPACE@2870..2871 " "
+        RECORD_FIELD_LIST@2871..2904
+          L_CURLY@2871..2872 "{"
+          WHITESPACE@2872..2873 " "
+          RECORD_FIELD@2873..2901
+            NAME@2873..2878
+              IDENT@2873..2878 "union"
+            COLON@2878..2879 ":"
+            WHITESPACE@2879..2880 " "
+            REF_TYPE@2880..2901
+              AMP@2880..2881 "&"
+              LIFETIME@2881..2887 "\'union"
+              WHITESPACE@2887..2888 " "
+              PATH_TYPE@2888..2901
+                PATH@2888..2901
+                  PATH_SEGMENT@2888..2901
+                    NAME_REF@2888..2893
+                      IDENT@2888..2893 "union"
+                    GENERIC_ARG_LIST@2893..2901
+                      L_ANGLE@2893..2894 "<"
+                      LIFETIME_ARG@2894..2900
+                        LIFETIME@2894..2900 "\'union"
+                      R_ANGLE@2900..2901 ">"
+          COMMA@2901..2902 ","
+          WHITESPACE@2902..2903 " "
+          R_CURLY@2903..2904 "}"
+      WHITESPACE@2904..2905 "\n"
+      R_CURLY@2905..2906 "}"
+  WHITESPACE@2906..2908 "\n\n"
+  FN@2908..3042
+    FN_KW@2908..2910 "fn"
+    WHITESPACE@2910..2911 " "
+    NAME@2911..2929
+      IDENT@2911..2929 "special_characters"
+    PARAM_LIST@2929..2931
+      L_PAREN@2929..2930 "("
+      R_PAREN@2930..2931 ")"
+    WHITESPACE@2931..2932 " "
+    BLOCK_EXPR@2932..3042
+      L_CURLY@2932..2933 "{"
+      WHITESPACE@2933..2938 "\n    "
+      LET_STMT@2938..3021
+        LET_KW@2938..2941 "let"
+        WHITESPACE@2941..2942 " "
+        IDENT_PAT@2942..2945
+          NAME@2942..2945
+            IDENT@2942..2945 "val"
+        WHITESPACE@2945..2946 " "
+        EQ@2946..2947 "="
+        WHITESPACE@2947..2948 " "
+        PREFIX_EXPR@2948..3013
+          BANG@2948..2949 "!"
+          PAREN_EXPR@2949..3013
+            L_PAREN@2949..2950 "("
+            BIN_EXPR@2950..3012
+              CALL_EXPR@2950..2995
+                PAREN_EXPR@2950..2971
+                  L_PAREN@2950..2951 "("
+                  CLOSURE_EXPR@2951..2970
+                    PARAM_LIST@2951..2968
+                      PIPE@2951..2952 "|"
+                      PARAM@2952..2962
+                        TUPLE_PAT@2952..2956
+                          L_PAREN@2952..2953 "("
+                          REST_PAT@2953..2955
+                            DOT2@2953..2955 ".."
+                          R_PAREN@2955..2956 ")"
+                        COLON@2956..2957 ":"
+                        TUPLE_TYPE@2957..2962
+                          L_PAREN@2957..2958 "("
+                          INFER_TYPE@2958..2959
+                            UNDERSCORE@2958..2959 "_"
+                          COMMA@2959..2960 ","
+                          INFER_TYPE@2960..2961
+                            UNDERSCORE@2960..2961 "_"
+                          R_PAREN@2961..2962 ")"
+                      COMMA@2962..2963 ","
+                      PARAM@2963..2967
+                        IDENT_PAT@2963..2967
+                          NAME@2963..2965
+                            IDENT@2963..2965 "__"
+                          AT@2965..2966 "@"
+                          WILDCARD_PAT@2966..2967
+                            UNDERSCORE@2966..2967 "_"
+                      PIPE@2967..2968 "|"
+                    PATH_EXPR@2968..2970
+                      PATH@2968..2970
+                        PATH_SEGMENT@2968..2970
+                          NAME_REF@2968..2970
+                            IDENT@2968..2970 "__"
+                  R_PAREN@2970..2971 ")"
+                ARG_LIST@2971..2995
+                  L_PAREN@2971..2972 "("
+                  TUPLE_EXPR@2972..2987
+                    L_PAREN@2972..2973 "("
+                    REF_EXPR@2973..2979
+                      AMP@2973..2974 "&"
+                      PREFIX_EXPR@2974..2979
+                        STAR@2974..2975 "*"
+                        LITERAL@2975..2979
+                          STRING@2975..2979 "\"\\\\\""
+                    COMMA@2979..2980 ","
+                    LITERAL@2980..2986
+                      CHAR@2980..2986 "\'🤔\'"
+                    R_PAREN@2986..2987 ")"
+                  COMMENT@2987..2991 "/**/"
+                  COMMA@2991..2992 ","
+                  BLOCK_EXPR@2992..2994
+                    L_CURLY@2992..2993 "{"
+                    R_CURLY@2993..2994 "}"
+                  R_PAREN@2994..2995 ")"
+              EQ2@2995..2997 "=="
+              BLOCK_EXPR@2997..3012
+                L_CURLY@2997..2998 "{"
+                EXPR_STMT@2998..3011
+                  REF_EXPR@2998..3010
+                    AMP@2998..2999 "&"
+                    INDEX_EXPR@2999..3010
+                      ARRAY_EXPR@2999..3006
+                        L_BRACK@2999..3000 "["
+                        RANGE_EXPR@3000..3005
+                          DOT2EQ@3000..3003 "..="
+                          RANGE_EXPR@3003..3005
+                            DOT2@3003..3005 ".."
+                        R_BRACK@3005..3006 "]"
+                      L_BRACK@3006..3007 "["
+                      RANGE_EXPR@3007..3009
+                        DOT2@3007..3009 ".."
+                      R_BRACK@3009..3010 "]"
+                  SEMICOLON@3010..3011 ";"
+                R_CURLY@3011..3012 "}"
+            R_PAREN@3012..3013 ")"
+        COMMENT@3013..3015 "//"
+        WHITESPACE@3015..3020 "\n    "
+        SEMICOLON@3020..3021 ";"
+      WHITESPACE@3021..3026 "\n    "
+      EXPR_STMT@3026..3040
+        MACRO_CALL@3026..3039
+          PATH@3026..3032
+            PATH_SEGMENT@3026..3032
+              NAME_REF@3026..3032
+                IDENT@3026..3032 "assert"
+          BANG@3032..3033 "!"
+          TOKEN_TREE@3033..3039
+            L_PAREN@3033..3034 "("
+            BANG@3034..3035 "!"
+            IDENT@3035..3038 "val"
+            R_PAREN@3038..3039 ")"
+        SEMICOLON@3039..3040 ";"
+      WHITESPACE@3040..3041 "\n"
+      R_CURLY@3041..3042 "}"
+  WHITESPACE@3042..3044 "\n\n"
+  FN@3044..3514
+    FN_KW@3044..3046 "fn"
+    WHITESPACE@3046..3047 " "
+    NAME@3047..3057
+      IDENT@3047..3057 "punch_card"
+    PARAM_LIST@3057..3059
+      L_PAREN@3057..3058 "("
+      R_PAREN@3058..3059 ")"
+    WHITESPACE@3059..3060 " "
+    RET_TYPE@3060..3083
+      THIN_ARROW@3060..3062 "->"
+      WHITESPACE@3062..3063 " "
+      IMPL_TRAIT_TYPE@3063..3083
+        IMPL_KW@3063..3067 "impl"
+        WHITESPACE@3067..3068 " "
+        TYPE_BOUND_LIST@3068..3083
+          TYPE_BOUND@3068..3083
+            PATH_TYPE@3068..3083
+              PATH@3068..3083
+                PATH@3068..3076
+                  PATH@3068..3071
+                    PATH_SEGMENT@3068..3071
+                      NAME_REF@3068..3071
+                        IDENT@3068..3071 "std"
+                  COLON2@3071..3073 "::"
+                  PATH_SEGMENT@3073..3076
+                    NAME_REF@3073..3076
+                      IDENT@3073..3076 "fmt"
+                COLON2@3076..3078 "::"
+                PATH_SEGMENT@3078..3083
+                  NAME_REF@3078..3083
+                    IDENT@3078..3083 "Debug"
+    WHITESPACE@3083..3084 " "
+    BLOCK_EXPR@3084..3514
+      L_CURLY@3084..3085 "{"
+      WHITESPACE@3085..3090 "\n    "
+      RANGE_EXPR@3090..3512
+        DOT2EQ@3090..3093 "..="
+        RANGE_EXPR@3093..3512
+          DOT2EQ@3093..3096 "..="
+          RANGE_EXPR@3096..3512
+            DOT2@3096..3098 ".."
+            WHITESPACE@3098..3099 " "
+            RANGE_EXPR@3099..3512
+              DOT2@3099..3101 ".."
+              WHITESPACE@3101..3105 "    "
+              RANGE_EXPR@3105..3512
+                DOT2@3105..3107 ".."
+                WHITESPACE@3107..3108 " "
+                RANGE_EXPR@3108..3512
+                  DOT2@3108..3110 ".."
+                  WHITESPACE@3110..3111 " "
+                  RANGE_EXPR@3111..3512
+                    DOT2@3111..3113 ".."
+                    WHITESPACE@3113..3114 " "
+                    RANGE_EXPR@3114..3512
+                      DOT2@3114..3116 ".."
+                      WHITESPACE@3116..3120 "    "
+                      RANGE_EXPR@3120..3512
+                        DOT2@3120..3122 ".."
+                        WHITESPACE@3122..3123 " "
+                        RANGE_EXPR@3123..3512
+                          DOT2@3123..3125 ".."
+                          WHITESPACE@3125..3126 " "
+                          RANGE_EXPR@3126..3512
+                            DOT2@3126..3128 ".."
+                            WHITESPACE@3128..3129 " "
+                            RANGE_EXPR@3129..3512
+                              DOT2@3129..3131 ".."
+                              WHITESPACE@3131..3135 "    "
+                              RANGE_EXPR@3135..3512
+                                DOT2@3135..3137 ".."
+                                WHITESPACE@3137..3138 " "
+                                RANGE_EXPR@3138..3512
+                                  DOT2EQ@3138..3141 "..="
+                                  RANGE_EXPR@3141..3512
+                                    DOT2@3141..3143 ".."
+                                    WHITESPACE@3143..3144 " "
+                                    RANGE_EXPR@3144..3512
+                                      DOT2@3144..3146 ".."
+                                      WHITESPACE@3146..3151 "\n    "
+                                      RANGE_EXPR@3151..3512
+                                        DOT2EQ@3151..3154 "..="
+                                        RANGE_EXPR@3154..3512
+                                          DOT2@3154..3156 ".."
+                                          WHITESPACE@3156..3157 " "
+                                          RANGE_EXPR@3157..3512
+                                            DOT2EQ@3157..3160 "..="
+                                            RANGE_EXPR@3160..3512
+                                              DOT2@3160..3162 ".."
+                                              WHITESPACE@3162..3166 "    "
+                                              RANGE_EXPR@3166..3512
+                                                DOT2@3166..3168 ".."
+                                                WHITESPACE@3168..3169 " "
+                                                RANGE_EXPR@3169..3512
+                                                  DOT2@3169..3171 ".."
+                                                  WHITESPACE@3171..3172 " "
+                                                  RANGE_EXPR@3172..3512
+                                                    DOT2@3172..3174 ".."
+                                                    WHITESPACE@3174..3175 " "
+                                                    RANGE_EXPR@3175..3512
+                                                      DOT2@3175..3177 ".."
+                                                      WHITESPACE@3177..3181 "    "
+                                                      RANGE_EXPR@3181..3512
+                                                        DOT2@3181..3183 ".."
+                                                        WHITESPACE@3183..3184 " "
+                                                        RANGE_EXPR@3184..3512
+                                                          DOT2@3184..3186 ".."
+                                                          WHITESPACE@3186..3187 " "
+                                                          RANGE_EXPR@3187..3512
+                                                            DOT2@3187..3189 ".."
+                                                            WHITESPACE@3189..3190 " "
+                                                            RANGE_EXPR@3190..3512
+                                                              DOT2@3190..3192 ".."
+                                                              WHITESPACE@3192..3196 "    "
+                                                              RANGE_EXPR@3196..3512
+                                                                DOT2EQ@3196..3199 "..="
+                                                                RANGE_EXPR@3199..3512
+                                                                  DOT2EQ@3199..3202 "..="
+                                                                  RANGE_EXPR@3202..3512
+                                                                    DOT2EQ@3202..3205 "..="
+                                                                    RANGE_EXPR@3205..3512
+                                                                      DOT2@3205..3207 ".."
+                                                                      WHITESPACE@3207..3212 "\n    "
+                                                                      RANGE_EXPR@3212..3512
+                                                                        DOT2EQ@3212..3215 "..="
+                                                                        RANGE_EXPR@3215..3512
+                                                                          DOT2@3215..3217 ".."
+                                                                          WHITESPACE@3217..3218 " "
+                                                                          RANGE_EXPR@3218..3512
+                                                                            DOT2EQ@3218..3221 "..="
+                                                                            RANGE_EXPR@3221..3512
+                                                                              DOT2@3221..3223 ".."
+                                                                              WHITESPACE@3223..3227 "    "
+                                                                              RANGE_EXPR@3227..3512
+                                                                                DOT2EQ@3227..3230 "..="
+                                                                                RANGE_EXPR@3230..3512
+                                                                                  DOT2@3230..3232 ".."
+                                                                                  WHITESPACE@3232..3233 " "
+                                                                                  RANGE_EXPR@3233..3512
+                                                                                    DOT2EQ@3233..3236 "..="
+                                                                                    RANGE_EXPR@3236..3512
+                                                                                      DOT2@3236..3238 ".."
+                                                                                      WHITESPACE@3238..3242 "    "
+                                                                                      RANGE_EXPR@3242..3512
+                                                                                        DOT2@3242..3244 ".."
+                                                                                        WHITESPACE@3244..3245 " "
+                                                                                        RANGE_EXPR@3245..3512
+                                                                                          DOT2EQ@3245..3248 "..="
+                                                                                          RANGE_EXPR@3248..3512
+                                                                                            DOT2EQ@3248..3251 "..="
+                                                                                            RANGE_EXPR@3251..3512
+                                                                                              DOT2@3251..3253 ".."
+                                                                                              WHITESPACE@3253..3257 "    "
+                                                                                              RANGE_EXPR@3257..3512
+                                                                                                DOT2@3257..3259 ".."
+                                                                                                WHITESPACE@3259..3260 " "
+                                                                                                RANGE_EXPR@3260..3512
+                                                                                                  DOT2EQ@3260..3263 "..="
+                                                                                                  RANGE_EXPR@3263..3512
+                                                                                                    DOT2@3263..3265 ".."
+                                                                                                    WHITESPACE@3265..3266 " "
+                                                                                                    RANGE_EXPR@3266..3512
+                                                                                                      DOT2@3266..3268 ".."
+                                                                                                      WHITESPACE@3268..3273 "\n    "
+                                                                                                      RANGE_EXPR@3273..3512
+                                                                                                        DOT2EQ@3273..3276 "..="
+                                                                                                        RANGE_EXPR@3276..3512
+                                                                                                          DOT2EQ@3276..3279 "..="
+                                                                                                          RANGE_EXPR@3279..3512
+                                                                                                            DOT2@3279..3281 ".."
+                                                                                                            WHITESPACE@3281..3282 " "
+                                                                                                            RANGE_EXPR@3282..3512
+                                                                                                              DOT2@3282..3284 ".."
+                                                                                                              WHITESPACE@3284..3288 "    "
+                                                                                                              RANGE_EXPR@3288..3512
+                                                                                                                DOT2EQ@3288..3291 "..="
+                                                                                                                RANGE_EXPR@3291..3512
+                                                                                                                  DOT2@3291..3293 ".."
+                                                                                                                  WHITESPACE@3293..3294 " "
+                                                                                                                  RANGE_EXPR@3294..3512
+                                                                                                                    DOT2EQ@3294..3297 "..="
+                                                                                                                    RANGE_EXPR@3297..3512
+                                                                                                                      DOT2@3297..3299 ".."
+                                                                                                                      WHITESPACE@3299..3303 "    "
+                                                                                                                      RANGE_EXPR@3303..3512
+                                                                                                                        DOT2EQ@3303..3306 "..="
+                                                                                                                        RANGE_EXPR@3306..3512
+                                                                                                                          DOT2@3306..3308 ".."
+                                                                                                                          WHITESPACE@3308..3309 " "
+                                                                                                                          RANGE_EXPR@3309..3512
+                                                                                                                            DOT2@3309..3311 ".."
+                                                                                                                            WHITESPACE@3311..3312 " "
+                                                                                                                            RANGE_EXPR@3312..3512
+                                                                                                                              DOT2@3312..3314 ".."
+                                                                                                                              WHITESPACE@3314..3318 "    "
+                                                                                                                              RANGE_EXPR@3318..3512
+                                                                                                                                DOT2@3318..3320 ".."
+                                                                                                                                WHITESPACE@3320..3321 " "
+                                                                                                                                RANGE_EXPR@3321..3512
+                                                                                                                                  DOT2EQ@3321..3324 "..="
+                                                                                                                                  RANGE_EXPR@3324..3512
+                                                                                                                                    DOT2@3324..3326 ".."
+                                                                                                                                    WHITESPACE@3326..3327 " "
+                                                                                                                                    RANGE_EXPR@3327..3512
+                                                                                                                                      DOT2@3327..3329 ".."
+                                                                                                                                      WHITESPACE@3329..3334 "\n    "
+                                                                                                                                      RANGE_EXPR@3334..3512
+                                                                                                                                        DOT2EQ@3334..3337 "..="
+                                                                                                                                        RANGE_EXPR@3337..3512
+                                                                                                                                          DOT2@3337..3339 ".."
+                                                                                                                                          WHITESPACE@3339..3340 " "
+                                                                                                                                          RANGE_EXPR@3340..3512
+                                                                                                                                            DOT2EQ@3340..3343 "..="
+                                                                                                                                            RANGE_EXPR@3343..3512
+                                                                                                                                              DOT2@3343..3345 ".."
+                                                                                                                                              WHITESPACE@3345..3349 "    "
+                                                                                                                                              RANGE_EXPR@3349..3512
+                                                                                                                                                DOT2EQ@3349..3352 "..="
+                                                                                                                                                RANGE_EXPR@3352..3512
+                                                                                                                                                  DOT2@3352..3354 ".."
+                                                                                                                                                  WHITESPACE@3354..3355 " "
+                                                                                                                                                  RANGE_EXPR@3355..3512
+                                                                                                                                                    DOT2EQ@3355..3358 "..="
+                                                                                                                                                    RANGE_EXPR@3358..3512
+                                                                                                                                                      DOT2@3358..3360 ".."
+                                                                                                                                                      WHITESPACE@3360..3364 "    "
+                                                                                                                                                      RANGE_EXPR@3364..3512
+                                                                                                                                                        DOT2@3364..3366 ".."
+                                                                                                                                                        WHITESPACE@3366..3367 " "
+                                                                                                                                                        RANGE_EXPR@3367..3512
+                                                                                                                                                          DOT2EQ@3367..3370 "..="
+                                                                                                                                                          RANGE_EXPR@3370..3512
+                                                                                                                                                            DOT2@3370..3372 ".."
+                                                                                                                                                            WHITESPACE@3372..3373 " "
+                                                                                                                                                            RANGE_EXPR@3373..3512
+                                                                                                                                                              DOT2@3373..3375 ".."
+                                                                                                                                                              WHITESPACE@3375..3379 "    "
+                                                                                                                                                              RANGE_EXPR@3379..3512
+                                                                                                                                                                DOT2@3379..3381 ".."
+                                                                                                                                                                WHITESPACE@3381..3382 " "
+                                                                                                                                                                RANGE_EXPR@3382..3512
+                                                                                                                                                                  DOT2EQ@3382..3385 "..="
+                                                                                                                                                                  RANGE_EXPR@3385..3512
+                                                                                                                                                                    DOT2@3385..3387 ".."
+                                                                                                                                                                    WHITESPACE@3387..3388 " "
+                                                                                                                                                                    RANGE_EXPR@3388..3512
+                                                                                                                                                                      DOT2@3388..3390 ".."
+                                                                                                                                                                      WHITESPACE@3390..3395 "\n    "
+                                                                                                                                                                      RANGE_EXPR@3395..3512
+                                                                                                                                                                        DOT2EQ@3395..3398 "..="
+                                                                                                                                                                        RANGE_EXPR@3398..3512
+                                                                                                                                                                          DOT2@3398..3400 ".."
+                                                                                                                                                                          WHITESPACE@3400..3401 " "
+                                                                                                                                                                          RANGE_EXPR@3401..3512
+                                                                                                                                                                            DOT2EQ@3401..3404 "..="
+                                                                                                                                                                            RANGE_EXPR@3404..3512
+                                                                                                                                                                              DOT2@3404..3406 ".."
+                                                                                                                                                                              WHITESPACE@3406..3410 "    "
+                                                                                                                                                                              RANGE_EXPR@3410..3512
+                                                                                                                                                                                DOT2EQ@3410..3413 "..="
+                                                                                                                                                                                RANGE_EXPR@3413..3512
+                                                                                                                                                                                  DOT2@3413..3415 ".."
+                                                                                                                                                                                  WHITESPACE@3415..3416 " "
+                                                                                                                                                                                  RANGE_EXPR@3416..3512
+                                                                                                                                                                                    DOT2EQ@3416..3419 "..="
+                                                                                                                                                                                    RANGE_EXPR@3419..3512
+                                                                                                                                                                                      DOT2@3419..3421 ".."
+                                                                                                                                                                                      WHITESPACE@3421..3425 "    "
+                                                                                                                                                                                      RANGE_EXPR@3425..3512
+                                                                                                                                                                                        DOT2@3425..3427 ".."
+                                                                                                                                                                                        WHITESPACE@3427..3428 " "
+                                                                                                                                                                                        RANGE_EXPR@3428..3512
+                                                                                                                                                                                          DOT2@3428..3430 ".."
+                                                                                                                                                                                          WHITESPACE@3430..3431 " "
+                                                                                                                                                                                          RANGE_EXPR@3431..3512
+                                                                                                                                                                                            DOT2EQ@3431..3434 "..="
+                                                                                                                                                                                            RANGE_EXPR@3434..3512
+                                                                                                                                                                                              DOT2@3434..3436 ".."
+                                                                                                                                                                                              WHITESPACE@3436..3440 "    "
+                                                                                                                                                                                              RANGE_EXPR@3440..3512
+                                                                                                                                                                                                DOT2@3440..3442 ".."
+                                                                                                                                                                                                WHITESPACE@3442..3443 " "
+                                                                                                                                                                                                RANGE_EXPR@3443..3512
+                                                                                                                                                                                                  DOT2EQ@3443..3446 "..="
+                                                                                                                                                                                                  RANGE_EXPR@3446..3512
+                                                                                                                                                                                                    DOT2@3446..3448 ".."
+                                                                                                                                                                                                    WHITESPACE@3448..3449 " "
+                                                                                                                                                                                                    RANGE_EXPR@3449..3512
+                                                                                                                                                                                                      DOT2@3449..3451 ".."
+                                                                                                                                                                                                      WHITESPACE@3451..3456 "\n    "
+                                                                                                                                                                                                      RANGE_EXPR@3456..3512
+                                                                                                                                                                                                        DOT2EQ@3456..3459 "..="
+                                                                                                                                                                                                        RANGE_EXPR@3459..3512
+                                                                                                                                                                                                          DOT2@3459..3461 ".."
+                                                                                                                                                                                                          WHITESPACE@3461..3462 " "
+                                                                                                                                                                                                          RANGE_EXPR@3462..3512
+                                                                                                                                                                                                            DOT2EQ@3462..3465 "..="
+                                                                                                                                                                                                            RANGE_EXPR@3465..3512
+                                                                                                                                                                                                              DOT2@3465..3467 ".."
+                                                                                                                                                                                                              WHITESPACE@3467..3471 "    "
+                                                                                                                                                                                                              RANGE_EXPR@3471..3512
+                                                                                                                                                                                                                DOT2@3471..3473 ".."
+                                                                                                                                                                                                                WHITESPACE@3473..3474 " "
+                                                                                                                                                                                                                RANGE_EXPR@3474..3512
+                                                                                                                                                                                                                  DOT2EQ@3474..3477 "..="
+                                                                                                                                                                                                                  RANGE_EXPR@3477..3512
+                                                                                                                                                                                                                    DOT2EQ@3477..3480 "..="
+                                                                                                                                                                                                                    RANGE_EXPR@3480..3512
+                                                                                                                                                                                                                      DOT2@3480..3482 ".."
+                                                                                                                                                                                                                      WHITESPACE@3482..3486 "    "
+                                                                                                                                                                                                                      RANGE_EXPR@3486..3512
+                                                                                                                                                                                                                        DOT2EQ@3486..3489 "..="
+                                                                                                                                                                                                                        RANGE_EXPR@3489..3512
+                                                                                                                                                                                                                          DOT2EQ@3489..3492 "..="
+                                                                                                                                                                                                                          RANGE_EXPR@3492..3512
+                                                                                                                                                                                                                            DOT2@3492..3494 ".."
+                                                                                                                                                                                                                            WHITESPACE@3494..3495 " "
+                                                                                                                                                                                                                            RANGE_EXPR@3495..3512
+                                                                                                                                                                                                                              DOT2@3495..3497 ".."
+                                                                                                                                                                                                                              WHITESPACE@3497..3501 "    "
+                                                                                                                                                                                                                              RANGE_EXPR@3501..3512
+                                                                                                                                                                                                                                DOT2@3501..3503 ".."
+                                                                                                                                                                                                                                WHITESPACE@3503..3504 " "
+                                                                                                                                                                                                                                RANGE_EXPR@3504..3512
+                                                                                                                                                                                                                                  DOT2EQ@3504..3507 "..="
+                                                                                                                                                                                                                                  RANGE_EXPR@3507..3512
+                                                                                                                                                                                                                                    DOT2@3507..3509 ".."
+                                                                                                                                                                                                                                    WHITESPACE@3509..3510 " "
+                                                                                                                                                                                                                                    RANGE_EXPR@3510..3512
+                                                                                                                                                                                                                                      DOT2@3510..3512 ".."
+      WHITESPACE@3512..3513 "\n"
+      R_CURLY@3513..3514 "}"
+  WHITESPACE@3514..3516 "\n\n"
+  FN@3516..3552
+    FN_KW@3516..3518 "fn"
+    WHITESPACE@3518..3519 " "
+    NAME@3519..3525
+      IDENT@3519..3525 "ktulhu"
+    PARAM_LIST@3525..3527
+      L_PAREN@3525..3526 "("
+      R_PAREN@3526..3527 ")"
+    WHITESPACE@3527..3528 " "
+    BLOCK_EXPR@3528..3552
+      L_CURLY@3528..3529 "{"
+      WHITESPACE@3529..3534 "\n    "
+      SEMICOLON@3534..3535 ";"
+      SEMICOLON@3535..3536 ";"
+      SEMICOLON@3536..3537 ";"
+      EXPR_STMT@3537..3540
+        TUPLE_EXPR@3537..3539
+          L_PAREN@3537..3538 "("
+          R_PAREN@3538..3539 ")"
+        SEMICOLON@3539..3540 ";"
+      SEMICOLON@3540..3541 ";"
+      SEMICOLON@3541..3542 ";"
+      SEMICOLON@3542..3543 ";"
+      SEMICOLON@3543..3544 ";"
+      SEMICOLON@3544..3545 ";"
+      SEMICOLON@3545..3546 ";"
+      SEMICOLON@3546..3547 ";"
+      SEMICOLON@3547..3548 ";"
+      TUPLE_EXPR@3548..3550
+        L_PAREN@3548..3549 "("
+        R_PAREN@3549..3550 ")"
+      WHITESPACE@3550..3551 "\n"
+      R_CURLY@3551..3552 "}"
+  WHITESPACE@3552..3554 "\n\n"
+  FN@3554..3812
+    VISIBILITY@3554..3557
+      PUB_KW@3554..3557 "pub"
+    WHITESPACE@3557..3558 " "
+    FN_KW@3558..3560 "fn"
+    WHITESPACE@3560..3561 " "
+    NAME@3561..3565
+      IDENT@3561..3565 "main"
+    PARAM_LIST@3565..3567
+      L_PAREN@3565..3566 "("
+      R_PAREN@3566..3567 ")"
+    WHITESPACE@3567..3568 " "
+    BLOCK_EXPR@3568..3812
+      L_CURLY@3568..3569 "{"
+      WHITESPACE@3569..3574 "\n    "
+      EXPR_STMT@3574..3584
+        CALL_EXPR@3574..3583
+          PATH_EXPR@3574..3581
+            PATH@3574..3581
+              PATH_SEGMENT@3574..3581
+                NAME_REF@3574..3581
+                  IDENT@3574..3581 "strange"
+          ARG_LIST@3581..3583
+            L_PAREN@3581..3582 "("
+            R_PAREN@3582..3583 ")"
+        SEMICOLON@3583..3584 ";"
+      WHITESPACE@3584..3589 "\n    "
+      EXPR_STMT@3589..3597
+        CALL_EXPR@3589..3596
+          PATH_EXPR@3589..3594
+            PATH@3589..3594
+              PATH_SEGMENT@3589..3594
+                NAME_REF@3589..3594
+                  IDENT@3589..3594 "funny"
+          ARG_LIST@3594..3596
+            L_PAREN@3594..3595 "("
+            R_PAREN@3595..3596 ")"
+        SEMICOLON@3596..3597 ";"
+      WHITESPACE@3597..3602 "\n    "
+      EXPR_STMT@3602..3609
+        CALL_EXPR@3602..3608
+          PATH_EXPR@3602..3606
+            PATH@3602..3606
+              PATH_SEGMENT@3602..3606
+                NAME_REF@3602..3606
+                  IDENT@3602..3606 "what"
+          ARG_LIST@3606..3608
+            L_PAREN@3606..3607 "("
+            R_PAREN@3607..3608 ")"
+        SEMICOLON@3608..3609 ";"
+      WHITESPACE@3609..3614 "\n    "
+      EXPR_STMT@3614..3628
+        CALL_EXPR@3614..3627
+          PATH_EXPR@3614..3625
+            PATH@3614..3625
+              PATH_SEGMENT@3614..3625
+                NAME_REF@3614..3625
+                  IDENT@3614..3625 "zombiejesus"
+          ARG_LIST@3625..3627
+            L_PAREN@3625..3626 "("
+            R_PAREN@3626..3627 ")"
+        SEMICOLON@3627..3628 ";"
+      WHITESPACE@3628..3633 "\n    "
+      EXPR_STMT@3633..3643
+        CALL_EXPR@3633..3642
+          PATH_EXPR@3633..3640
+            PATH@3633..3640
+              PATH_SEGMENT@3633..3640
+                NAME_REF@3633..3640
+                  IDENT@3633..3640 "notsure"
+          ARG_LIST@3640..3642
+            L_PAREN@3640..3641 "("
+            R_PAREN@3641..3642 ")"
+        SEMICOLON@3642..3643 ";"
+      WHITESPACE@3643..3648 "\n    "
+      EXPR_STMT@3648..3664
+        CALL_EXPR@3648..3663
+          PATH_EXPR@3648..3661
+            PATH@3648..3661
+              PATH_SEGMENT@3648..3661
+                NAME_REF@3648..3661
+                  IDENT@3648..3661 "canttouchthis"
+          ARG_LIST@3661..3663
+            L_PAREN@3661..3662 "("
+            R_PAREN@3662..3663 ")"
+        SEMICOLON@3663..3664 ";"
+      WHITESPACE@3664..3669 "\n    "
+      EXPR_STMT@3669..3681
+        CALL_EXPR@3669..3680
+          PATH_EXPR@3669..3678
+            PATH@3669..3678
+              PATH_SEGMENT@3669..3678
+                NAME_REF@3669..3678
+                  IDENT@3669..3678 "angrydome"
+          ARG_LIST@3678..3680
+            L_PAREN@3678..3679 "("
+            R_PAREN@3679..3680 ")"
+        SEMICOLON@3680..3681 ";"
+      WHITESPACE@3681..3686 "\n    "
+      EXPR_STMT@3686..3701
+        CALL_EXPR@3686..3700
+          PATH_EXPR@3686..3698
+            PATH@3686..3698
+              PATH_SEGMENT@3686..3698
+                NAME_REF@3686..3698
+                  IDENT@3686..3698 "evil_lincoln"
+          ARG_LIST@3698..3700
+            L_PAREN@3698..3699 "("
+            R_PAREN@3699..3700 ")"
+        SEMICOLON@3700..3701 ";"
+      WHITESPACE@3701..3706 "\n    "
+      EXPR_STMT@3706..3713
+        CALL_EXPR@3706..3712
+          PATH_EXPR@3706..3710
+            PATH@3706..3710
+              PATH_SEGMENT@3706..3710
+                NAME_REF@3706..3710
+                  IDENT@3706..3710 "dots"
+          ARG_LIST@3710..3712
+            L_PAREN@3710..3711 "("
+            R_PAREN@3711..3712 ")"
+        SEMICOLON@3712..3713 ";"
+      WHITESPACE@3713..3718 "\n    "
+      EXPR_STMT@3718..3726
+        CALL_EXPR@3718..3725
+          PATH_EXPR@3718..3720
+            PATH@3718..3720
+              PATH_SEGMENT@3718..3720
+                NAME_REF@3718..3720
+                  IDENT@3718..3720 "u8"
+          ARG_LIST@3720..3725
+            L_PAREN@3720..3721 "("
+            LITERAL@3721..3724
+              INT_NUMBER@3721..3724 "8u8"
+            R_PAREN@3724..3725 ")"
+        SEMICOLON@3725..3726 ";"
+      WHITESPACE@3726..3731 "\n    "
+      EXPR_STMT@3731..3739
+        CALL_EXPR@3731..3738
+          PATH_EXPR@3731..3736
+            PATH@3731..3736
+              PATH_SEGMENT@3731..3736
+                NAME_REF@3731..3736
+                  IDENT@3731..3736 "fishy"
+          ARG_LIST@3736..3738
+            L_PAREN@3736..3737 "("
+            R_PAREN@3737..3738 ")"
+        SEMICOLON@3738..3739 ";"
+      WHITESPACE@3739..3744 "\n    "
+      EXPR_STMT@3744..3752
+        CALL_EXPR@3744..3751
+          PATH_EXPR@3744..3749
+            PATH@3744..3749
+              PATH_SEGMENT@3744..3749
+                NAME_REF@3744..3749
+                  IDENT@3744..3749 "union"
+          ARG_LIST@3749..3751
+            L_PAREN@3749..3750 "("
+            R_PAREN@3750..3751 ")"
+        SEMICOLON@3751..3752 ";"
+      WHITESPACE@3752..3757 "\n    "
+      EXPR_STMT@3757..3778
+        CALL_EXPR@3757..3777
+          PATH_EXPR@3757..3775
+            PATH@3757..3775
+              PATH_SEGMENT@3757..3775
+                NAME_REF@3757..3775
+                  IDENT@3757..3775 "special_characters"
+          ARG_LIST@3775..3777
+            L_PAREN@3775..3776 "("
+            R_PAREN@3776..3777 ")"
+        SEMICOLON@3777..3778 ";"
+      WHITESPACE@3778..3783 "\n    "
+      EXPR_STMT@3783..3796
+        CALL_EXPR@3783..3795
+          PATH_EXPR@3783..3793
+            PATH@3783..3793
+              PATH_SEGMENT@3783..3793
+                NAME_REF@3783..3793
+                  IDENT@3783..3793 "punch_card"
+          ARG_LIST@3793..3795
+            L_PAREN@3793..3794 "("
+            R_PAREN@3794..3795 ")"
+        SEMICOLON@3795..3796 ";"
+      WHITESPACE@3796..3801 "\n    "
+      EXPR_STMT@3801..3810
+        CALL_EXPR@3801..3809
+          PATH_EXPR@3801..3807
+            PATH@3801..3807
+              PATH_SEGMENT@3801..3807
+                NAME_REF@3801..3807
+                  IDENT@3801..3807 "ktulhu"
+          ARG_LIST@3807..3809
+            L_PAREN@3807..3808 "("
+            R_PAREN@3808..3809 ")"
+        SEMICOLON@3809..3810 ";"
+      WHITESPACE@3810..3811 "\n"
+      R_CURLY@3811..3812 "}"
+  WHITESPACE@3812..3813 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0035_weird_exprs.rs b/crates/syntax/test_data/parser/ok/0035_weird_exprs.rs
new file mode 100644
index 00000000000..8c13231631c
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0035_weird_exprs.rs
@@ -0,0 +1,154 @@
+//! Adapted from a `rustc` test, which can be found at 
+//! https://github.com/rust-lang/rust/blob/6d34ec18c7d7e574553f6347ecf08e1e1c45c13d/src/test/run-pass/weird-exprs.rs.
+//! 
+//! Reported to rust-analyzer in https://github.com/rust-analyzer/rust-analyzer/issues/290
+
+#![allow(non_camel_case_types)]
+#![allow(dead_code)]
+#![allow(unreachable_code)]
+#![allow(unused_parens)]
+
+#![recursion_limit = "128"]
+
+use std::cell::Cell;
+use std::mem::swap;
+
+// Just a grab bag of stuff that you wouldn't want to actually write.
+
+fn strange() -> bool { let _x: bool = return true; }
+
+fn funny() {
+    fn f(_x: ()) { }
+    f(return);
+}
+
+fn what() {
+    fn the(x: &Cell<bool>) {
+        return while !x.get() { x.set(true); };
+    }
+    let i = &Cell::new(false);
+    let dont = {||the(i)};
+    dont();
+    assert!((i.get()));
+}
+
+fn zombiejesus() {
+    loop {
+        while (return) {
+            if (return) {
+                match (return) {
+                    1 => {
+                        if (return) {
+                            return
+                        } else {
+                            return
+                        }
+                    }
+                    _ => { return }
+                };
+            } else if (return) {
+                return;
+            }
+        }
+        if (return) { break; }
+    }
+}
+
+fn notsure() {
+    let mut _x: isize;
+    let mut _y = (_x = 0) == (_x = 0);
+    let mut _z = (_x = 0) < (_x = 0);
+    let _a = (_x += 0) == (_x = 0);
+    let _b = swap(&mut _y, &mut _z) == swap(&mut _y, &mut _z);
+}
+
+fn canttouchthis() -> usize {
+    fn p() -> bool { true }
+    let _a = (assert!((true)) == (assert!(p())));
+    let _c = (assert!((p())) == ());
+    let _b: bool = (println!("{}", 0) == (return 0));
+}
+
+fn angrydome() {
+    loop { if break { } }
+    let mut i = 0;
+    loop { i += 1; if i == 1 { match (continue) { 1 => { }, _ => panic!("wat") } }
+      break; }
+}
+
+fn evil_lincoln() { let _evil = println!("lincoln"); }
+
+fn dots() {
+    assert_eq!(String::from(".................................................."),
+               format!("{:?}", .. .. .. .. .. .. .. .. .. .. .. .. ..
+                               .. .. .. .. .. .. .. .. .. .. .. ..));
+}
+
+fn u8(u8: u8) {
+    if u8 != 0u8 {
+        assert_eq!(8u8, {
+            macro_rules! u8 {
+                (u8) => {
+                    mod u8 {
+                        pub fn u8<'u8: 'u8 + 'u8>(u8: &'u8 u8) -> &'u8 u8 {
+                            "u8";
+                            u8
+                        }
+                    }
+                };
+            }
+
+            u8!(u8);
+            let &u8: &u8 = u8::u8(&8u8);
+            crate::u8(0u8);
+            u8
+        });
+    }
+}
+
+fn fishy() {
+    assert_eq!(String::from("><>"),
+               String::<>::from::<>("><>").chars::<>().rev::<>().collect::<String>());
+}
+
+fn union() {
+    union union<'union> { union: &'union union<'union>, }
+}
+
+fn special_characters() {
+    let val = !((|(..):(_,_),__@_|__)((&*"\\",'🤔')/**/,{})=={&[..=..][..];})//
+    ;
+    assert!(!val);
+}
+
+fn punch_card() -> impl std::fmt::Debug {
+    ..=..=.. ..    .. .. .. ..    .. .. .. ..    .. ..=.. ..
+    ..=.. ..=..    .. .. .. ..    .. .. .. ..    ..=..=..=..
+    ..=.. ..=..    ..=.. ..=..    .. ..=..=..    .. ..=.. ..
+    ..=..=.. ..    ..=.. ..=..    ..=.. .. ..    .. ..=.. ..
+    ..=.. ..=..    ..=.. ..=..    .. ..=.. ..    .. ..=.. ..
+    ..=.. ..=..    ..=.. ..=..    .. .. ..=..    .. ..=.. ..
+    ..=.. ..=..    .. ..=..=..    ..=..=.. ..    .. ..=.. ..
+}
+
+fn ktulhu() {
+    ;;;();;;;;;;;;()
+}
+
+pub fn main() {
+    strange();
+    funny();
+    what();
+    zombiejesus();
+    notsure();
+    canttouchthis();
+    angrydome();
+    evil_lincoln();
+    dots();
+    u8(8u8);
+    fishy();
+    union();
+    special_characters();
+    punch_card();
+    ktulhu();
+}
diff --git a/crates/syntax/test_data/parser/ok/0036_fully_qualified.rast b/crates/syntax/test_data/parser/ok/0036_fully_qualified.rast
new file mode 100644
index 00000000000..c4da317b9f9
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0036_fully_qualified.rast
@@ -0,0 +1,92 @@
+SOURCE_FILE@0..157
+  COMMENT@0..60 "// https://github.com ..."
+  WHITESPACE@60..62 "\n\n"
+  FN@62..156
+    VISIBILITY@62..65
+      PUB_KW@62..65 "pub"
+    WHITESPACE@65..66 " "
+    FN_KW@66..68 "fn"
+    WHITESPACE@68..69 " "
+    NAME@69..72
+      IDENT@69..72 "foo"
+    GENERIC_PARAM_LIST@72..85
+      L_ANGLE@72..73 "<"
+      TYPE_PARAM@73..84
+        NAME@73..74
+          IDENT@73..74 "S"
+        COLON@74..75 ":"
+        WHITESPACE@75..76 " "
+        TYPE_BOUND_LIST@76..84
+          TYPE_BOUND@76..84
+            PATH_TYPE@76..84
+              PATH@76..84
+                PATH_SEGMENT@76..84
+                  NAME_REF@76..84
+                    IDENT@76..84 "Iterator"
+      R_ANGLE@84..85 ">"
+    PARAM_LIST@85..87
+      L_PAREN@85..86 "("
+      R_PAREN@86..87 ")"
+    WHITESPACE@87..88 " "
+    RET_TYPE@88..97
+      THIN_ARROW@88..90 "->"
+      WHITESPACE@90..91 " "
+      PATH_TYPE@91..97
+        PATH@91..97
+          PATH_SEGMENT@91..97
+            NAME_REF@91..97
+              IDENT@91..97 "String"
+    WHITESPACE@97..98 "\n"
+    WHERE_CLAUSE@98..134
+      WHERE_KW@98..103 "where"
+      WHITESPACE@103..108 "\n    "
+      WHERE_PRED@108..133
+        PATH_TYPE@108..129
+          PATH@108..129
+            PATH@108..123
+              PATH_SEGMENT@108..123
+                L_ANGLE@108..109 "<"
+                PATH_TYPE@109..110
+                  PATH@109..110
+                    PATH_SEGMENT@109..110
+                      NAME_REF@109..110
+                        IDENT@109..110 "S"
+                WHITESPACE@110..111 " "
+                AS_KW@111..113 "as"
+                WHITESPACE@113..114 " "
+                PATH_TYPE@114..122
+                  PATH@114..122
+                    PATH_SEGMENT@114..122
+                      NAME_REF@114..122
+                        IDENT@114..122 "Iterator"
+                R_ANGLE@122..123 ">"
+            COLON2@123..125 "::"
+            PATH_SEGMENT@125..129
+              NAME_REF@125..129
+                IDENT@125..129 "Item"
+        COLON@129..130 ":"
+        WHITESPACE@130..131 " "
+        TYPE_BOUND_LIST@131..133
+          TYPE_BOUND@131..133
+            PATH_TYPE@131..133
+              PATH@131..133
+                PATH_SEGMENT@131..133
+                  NAME_REF@131..133
+                    IDENT@131..133 "Eq"
+      COMMA@133..134 ","
+    WHITESPACE@134..135 "\n"
+    BLOCK_EXPR@135..156
+      L_CURLY@135..136 "{"
+      WHITESPACE@136..141 "\n    "
+      METHOD_CALL_EXPR@141..154
+        LITERAL@141..143
+          STRING@141..143 "\"\""
+        DOT@143..144 "."
+        NAME_REF@144..152
+          IDENT@144..152 "to_owned"
+        ARG_LIST@152..154
+          L_PAREN@152..153 "("
+          R_PAREN@153..154 ")"
+      WHITESPACE@154..155 "\n"
+      R_CURLY@155..156 "}"
+  WHITESPACE@156..157 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0036_fully_qualified.rs b/crates/syntax/test_data/parser/ok/0036_fully_qualified.rs
new file mode 100644
index 00000000000..6da27933ece
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0036_fully_qualified.rs
@@ -0,0 +1,8 @@
+// https://github.com/rust-analyzer/rust-analyzer/issues/311
+
+pub fn foo<S: Iterator>() -> String
+where
+    <S as Iterator>::Item: Eq,
+{
+    "".to_owned()
+}
diff --git a/crates/syntax/test_data/parser/ok/0037_mod.rast b/crates/syntax/test_data/parser/ok/0037_mod.rast
new file mode 100644
index 00000000000..1d5d94bdea8
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0037_mod.rast
@@ -0,0 +1,16 @@
+SOURCE_FILE@0..93
+  COMMENT@0..60 "// https://github.com ..."
+  WHITESPACE@60..62 "\n\n"
+  MODULE@62..93
+    COMMENT@62..70 "//! docs"
+    WHITESPACE@70..71 "\n"
+    COMMENT@71..82 "// non-docs"
+    WHITESPACE@82..83 "\n"
+    MOD_KW@83..86 "mod"
+    WHITESPACE@86..87 " "
+    NAME@87..90
+      IDENT@87..90 "foo"
+    WHITESPACE@90..91 " "
+    ITEM_LIST@91..93
+      L_CURLY@91..92 "{"
+      R_CURLY@92..93 "}"
diff --git a/crates/syntax/test_data/parser/ok/0037_mod.rs b/crates/syntax/test_data/parser/ok/0037_mod.rs
new file mode 100644
index 00000000000..7e5a1b8358c
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0037_mod.rs
@@ -0,0 +1,5 @@
+// https://github.com/rust-analyzer/rust-analyzer/issues/357
+
+//! docs
+// non-docs
+mod foo {}
\ No newline at end of file
diff --git a/crates/syntax/test_data/parser/ok/0038_where_pred_type.rast b/crates/syntax/test_data/parser/ok/0038_where_pred_type.rast
new file mode 100644
index 00000000000..22168eaf1ac
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0038_where_pred_type.rast
@@ -0,0 +1,42 @@
+SOURCE_FILE@0..34
+  FN@0..34
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "test"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    WHERE_CLAUSE@10..31
+      WHERE_KW@10..15 "where"
+      WHITESPACE@15..16 " "
+      WHERE_PRED@16..31
+        TUPLE_TYPE@16..26
+          L_PAREN@16..17 "("
+          PATH_TYPE@17..20
+            PATH@17..20
+              PATH_SEGMENT@17..20
+                NAME_REF@17..20
+                  IDENT@17..20 "u64"
+          COMMA@20..21 ","
+          WHITESPACE@21..22 " "
+          PATH_TYPE@22..25
+            PATH@22..25
+              PATH_SEGMENT@22..25
+                NAME_REF@22..25
+                  IDENT@22..25 "u64"
+          R_PAREN@25..26 ")"
+        COLON@26..27 ":"
+        WHITESPACE@27..28 " "
+        TYPE_BOUND_LIST@28..31
+          TYPE_BOUND@28..31
+            PATH_TYPE@28..31
+              PATH@28..31
+                PATH_SEGMENT@28..31
+                  NAME_REF@28..31
+                    IDENT@28..31 "Foo"
+    WHITESPACE@31..32 " "
+    BLOCK_EXPR@32..34
+      L_CURLY@32..33 "{"
+      R_CURLY@33..34 "}"
diff --git a/crates/syntax/test_data/parser/ok/0038_where_pred_type.rs b/crates/syntax/test_data/parser/ok/0038_where_pred_type.rs
new file mode 100644
index 00000000000..8bfc341a50a
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0038_where_pred_type.rs
@@ -0,0 +1 @@
+fn test() where (u64, u64): Foo {}
\ No newline at end of file
diff --git a/crates/syntax/test_data/parser/ok/0039_raw_fn_item.rast b/crates/syntax/test_data/parser/ok/0039_raw_fn_item.rast
new file mode 100644
index 00000000000..68a366354e6
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0039_raw_fn_item.rast
@@ -0,0 +1,15 @@
+SOURCE_FILE@0..15
+  FN@0..14
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..8
+      IDENT@3..8 "r#foo"
+    PARAM_LIST@8..10
+      L_PAREN@8..9 "("
+      R_PAREN@9..10 ")"
+    WHITESPACE@10..11 " "
+    BLOCK_EXPR@11..14
+      L_CURLY@11..12 "{"
+      WHITESPACE@12..13 "\n"
+      R_CURLY@13..14 "}"
+  WHITESPACE@14..15 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0039_raw_fn_item.rs b/crates/syntax/test_data/parser/ok/0039_raw_fn_item.rs
new file mode 100644
index 00000000000..8380d1e79bc
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0039_raw_fn_item.rs
@@ -0,0 +1,2 @@
+fn r#foo() {
+}
diff --git a/crates/syntax/test_data/parser/ok/0040_raw_struct_item_field.rast b/crates/syntax/test_data/parser/ok/0040_raw_struct_item_field.rast
new file mode 100644
index 00000000000..8cfc14f491c
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0040_raw_struct_item_field.rast
@@ -0,0 +1,22 @@
+SOURCE_FILE@0..27
+  STRUCT@0..27
+    STRUCT_KW@0..6 "struct"
+    WHITESPACE@6..7 " "
+    NAME@7..8
+      IDENT@7..8 "S"
+    WHITESPACE@8..9 " "
+    RECORD_FIELD_LIST@9..27
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      RECORD_FIELD@15..25
+        NAME@15..20
+          IDENT@15..20 "r#foo"
+        COLON@20..21 ":"
+        WHITESPACE@21..22 " "
+        PATH_TYPE@22..25
+          PATH@22..25
+            PATH_SEGMENT@22..25
+              NAME_REF@22..25
+                IDENT@22..25 "u32"
+      WHITESPACE@25..26 "\n"
+      R_CURLY@26..27 "}"
diff --git a/crates/syntax/test_data/parser/ok/0040_raw_struct_item_field.rs b/crates/syntax/test_data/parser/ok/0040_raw_struct_item_field.rs
new file mode 100644
index 00000000000..098a60a72bf
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0040_raw_struct_item_field.rs
@@ -0,0 +1,3 @@
+struct S {
+    r#foo: u32
+}
\ No newline at end of file
diff --git a/crates/syntax/test_data/parser/ok/0041_raw_keywords.rast b/crates/syntax/test_data/parser/ok/0041_raw_keywords.rast
new file mode 100644
index 00000000000..4035aef6f23
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0041_raw_keywords.rast
@@ -0,0 +1,49 @@
+SOURCE_FILE@0..59
+  FN@0..59
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..59
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..11 " "
+      LET_STMT@11..29
+        LET_KW@11..14 "let"
+        WHITESPACE@14..15 " "
+        IDENT_PAT@15..23
+          NAME@15..23
+            IDENT@15..23 "r#struct"
+        WHITESPACE@23..24 " "
+        EQ@24..25 "="
+        WHITESPACE@25..26 " "
+        LITERAL@26..28
+          INT_NUMBER@26..28 "92"
+        SEMICOLON@28..29 ";"
+      WHITESPACE@29..30 " "
+      LET_STMT@30..57
+        LET_KW@30..33 "let"
+        WHITESPACE@33..34 " "
+        IDENT_PAT@34..41
+          NAME@34..41
+            IDENT@34..41 "r#trait"
+        WHITESPACE@41..42 " "
+        EQ@42..43 "="
+        WHITESPACE@43..44 " "
+        BIN_EXPR@44..56
+          PATH_EXPR@44..52
+            PATH@44..52
+              PATH_SEGMENT@44..52
+                NAME_REF@44..52
+                  IDENT@44..52 "r#struct"
+          WHITESPACE@52..53 " "
+          STAR@53..54 "*"
+          WHITESPACE@54..55 " "
+          LITERAL@55..56
+            INT_NUMBER@55..56 "2"
+        SEMICOLON@56..57 ";"
+      WHITESPACE@57..58 " "
+      R_CURLY@58..59 "}"
diff --git a/crates/syntax/test_data/parser/ok/0041_raw_keywords.rs b/crates/syntax/test_data/parser/ok/0041_raw_keywords.rs
new file mode 100644
index 00000000000..d59a6d3476b
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0041_raw_keywords.rs
@@ -0,0 +1 @@
+fn foo() { let r#struct = 92; let r#trait = r#struct * 2; }
\ No newline at end of file
diff --git a/crates/syntax/test_data/parser/ok/0042_ufcs_call_list.rast b/crates/syntax/test_data/parser/ok/0042_ufcs_call_list.rast
new file mode 100644
index 00000000000..e71e069f1f4
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0042_ufcs_call_list.rast
@@ -0,0 +1,123 @@
+SOURCE_FILE@0..199
+  COMMENT@0..60 "// https://github.com ..."
+  WHITESPACE@60..62 "\n\n"
+  STRUCT@62..73
+    STRUCT_KW@62..68 "struct"
+    WHITESPACE@68..69 " "
+    NAME@69..72
+      IDENT@69..72 "Foo"
+    SEMICOLON@72..73 ";"
+  WHITESPACE@73..75 "\n\n"
+  IMPL@75..141
+    IMPL_KW@75..79 "impl"
+    WHITESPACE@79..80 " "
+    PATH_TYPE@80..83
+      PATH@80..83
+        PATH_SEGMENT@80..83
+          NAME_REF@80..83
+            IDENT@80..83 "Foo"
+    WHITESPACE@83..84 " "
+    ASSOC_ITEM_LIST@84..141
+      L_CURLY@84..85 "{"
+      WHITESPACE@85..90 "\n    "
+      FN@90..139
+        FN_KW@90..92 "fn"
+        WHITESPACE@92..93 " "
+        NAME@93..96
+          IDENT@93..96 "bar"
+        PARAM_LIST@96..98
+          L_PAREN@96..97 "("
+          R_PAREN@97..98 ")"
+        WHITESPACE@98..99 " "
+        RET_TYPE@99..106
+          THIN_ARROW@99..101 "->"
+          WHITESPACE@101..102 " "
+          PATH_TYPE@102..106
+            PATH@102..106
+              PATH_SEGMENT@102..106
+                NAME_REF@102..106
+                  IDENT@102..106 "bool"
+        WHITESPACE@106..107 " "
+        BLOCK_EXPR@107..139
+          L_CURLY@107..108 "{"
+          WHITESPACE@108..117 "\n        "
+          MACRO_CALL@117..133
+            PATH@117..130
+              PATH_SEGMENT@117..130
+                NAME_REF@117..130
+                  IDENT@117..130 "unimplemented"
+            BANG@130..131 "!"
+            TOKEN_TREE@131..133
+              L_PAREN@131..132 "("
+              R_PAREN@132..133 ")"
+          WHITESPACE@133..138 "\n    "
+          R_CURLY@138..139 "}"
+      WHITESPACE@139..140 "\n"
+      R_CURLY@140..141 "}"
+  WHITESPACE@141..143 "\n\n"
+  FN@143..161
+    FN_KW@143..145 "fn"
+    WHITESPACE@145..146 " "
+    NAME@146..149
+      IDENT@146..149 "baz"
+    PARAM_LIST@149..158
+      L_PAREN@149..150 "("
+      PARAM@150..157
+        WILDCARD_PAT@150..151
+          UNDERSCORE@150..151 "_"
+        COLON@151..152 ":"
+        WHITESPACE@152..153 " "
+        PATH_TYPE@153..157
+          PATH@153..157
+            PATH_SEGMENT@153..157
+              NAME_REF@153..157
+                IDENT@153..157 "bool"
+      R_PAREN@157..158 ")"
+    WHITESPACE@158..159 " "
+    BLOCK_EXPR@159..161
+      L_CURLY@159..160 "{"
+      R_CURLY@160..161 "}"
+  WHITESPACE@161..163 "\n\n"
+  FN@163..198
+    FN_KW@163..165 "fn"
+    WHITESPACE@165..166 " "
+    NAME@166..170
+      IDENT@166..170 "main"
+    PARAM_LIST@170..172
+      L_PAREN@170..171 "("
+      R_PAREN@171..172 ")"
+    WHITESPACE@172..173 " "
+    BLOCK_EXPR@173..198
+      L_CURLY@173..174 "{"
+      WHITESPACE@174..179 "\n    "
+      CALL_EXPR@179..196
+        PATH_EXPR@179..182
+          PATH@179..182
+            PATH_SEGMENT@179..182
+              NAME_REF@179..182
+                IDENT@179..182 "baz"
+        ARG_LIST@182..196
+          L_PAREN@182..183 "("
+          CALL_EXPR@183..195
+            PATH_EXPR@183..193
+              PATH@183..193
+                PATH@183..188
+                  PATH_SEGMENT@183..188
+                    L_ANGLE@183..184 "<"
+                    PATH_TYPE@184..187
+                      PATH@184..187
+                        PATH_SEGMENT@184..187
+                          NAME_REF@184..187
+                            IDENT@184..187 "Foo"
+                    R_ANGLE@187..188 ">"
+                COLON2@188..190 "::"
+                PATH_SEGMENT@190..193
+                  NAME_REF@190..193
+                    IDENT@190..193 "bar"
+            ARG_LIST@193..195
+              L_PAREN@193..194 "("
+              R_PAREN@194..195 ")"
+          R_PAREN@195..196 ")"
+      WHITESPACE@196..197 "\n"
+      R_CURLY@197..198 "}"
+  WHITESPACE@198..199 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0042_ufcs_call_list.rs b/crates/syntax/test_data/parser/ok/0042_ufcs_call_list.rs
new file mode 100644
index 00000000000..6c02e65ed7d
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0042_ufcs_call_list.rs
@@ -0,0 +1,15 @@
+// https://github.com/rust-analyzer/rust-analyzer/issues/596
+
+struct Foo;
+
+impl Foo {
+    fn bar() -> bool {
+        unimplemented!()
+    }
+}
+
+fn baz(_: bool) {}
+
+fn main() {
+    baz(<Foo>::bar())
+}
diff --git a/crates/syntax/test_data/parser/ok/0043_complex_assignment.rast b/crates/syntax/test_data/parser/ok/0043_complex_assignment.rast
new file mode 100644
index 00000000000..adc4a22e969
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0043_complex_assignment.rast
@@ -0,0 +1,109 @@
+SOURCE_FILE@0..160
+  COMMENT@0..60 "// https://github.com ..."
+  WHITESPACE@60..62 "\n\n"
+  STRUCT@62..90
+    STRUCT_KW@62..68 "struct"
+    WHITESPACE@68..69 " "
+    NAME@69..73
+      IDENT@69..73 "Repr"
+    WHITESPACE@73..74 " "
+    RECORD_FIELD_LIST@74..90
+      L_CURLY@74..75 "{"
+      WHITESPACE@75..76 " "
+      RECORD_FIELD@76..88
+        NAME@76..79
+          IDENT@76..79 "raw"
+        COLON@79..80 ":"
+        WHITESPACE@80..81 " "
+        ARRAY_TYPE@81..88
+          L_BRACK@81..82 "["
+          PATH_TYPE@82..84
+            PATH@82..84
+              PATH_SEGMENT@82..84
+                NAME_REF@82..84
+                  IDENT@82..84 "u8"
+          SEMICOLON@84..85 ";"
+          WHITESPACE@85..86 " "
+          LITERAL@86..87
+            INT_NUMBER@86..87 "1"
+          R_BRACK@87..88 "]"
+      WHITESPACE@88..89 " "
+      R_CURLY@89..90 "}"
+  WHITESPACE@90..92 "\n\n"
+  FN@92..159
+    FN_KW@92..94 "fn"
+    WHITESPACE@94..95 " "
+    NAME@95..98
+      IDENT@95..98 "abc"
+    PARAM_LIST@98..100
+      L_PAREN@98..99 "("
+      R_PAREN@99..100 ")"
+    WHITESPACE@100..101 " "
+    BLOCK_EXPR@101..159
+      L_CURLY@101..102 "{"
+      WHITESPACE@102..107 "\n    "
+      EXPR_STMT@107..136
+        BIN_EXPR@107..135
+          INDEX_EXPR@107..131
+            FIELD_EXPR@107..128
+              RECORD_EXPR@107..124
+                PATH@107..111
+                  PATH_SEGMENT@107..111
+                    NAME_REF@107..111
+                      IDENT@107..111 "Repr"
+                WHITESPACE@111..112 " "
+                RECORD_EXPR_FIELD_LIST@112..124
+                  L_CURLY@112..113 "{"
+                  WHITESPACE@113..114 " "
+                  RECORD_EXPR_FIELD@114..122
+                    NAME_REF@114..117
+                      IDENT@114..117 "raw"
+                    COLON@117..118 ":"
+                    WHITESPACE@118..119 " "
+                    ARRAY_EXPR@119..122
+                      L_BRACK@119..120 "["
+                      LITERAL@120..121
+                        INT_NUMBER@120..121 "0"
+                      R_BRACK@121..122 "]"
+                  WHITESPACE@122..123 " "
+                  R_CURLY@123..124 "}"
+              DOT@124..125 "."
+              NAME_REF@125..128
+                IDENT@125..128 "raw"
+            L_BRACK@128..129 "["
+            LITERAL@129..130
+              INT_NUMBER@129..130 "0"
+            R_BRACK@130..131 "]"
+          WHITESPACE@131..132 " "
+          EQ@132..133 "="
+          WHITESPACE@133..134 " "
+          LITERAL@134..135
+            INT_NUMBER@134..135 "0"
+        SEMICOLON@135..136 ";"
+      WHITESPACE@136..141 "\n    "
+      EXPR_STMT@141..157
+        CALL_EXPR@141..156
+          RECORD_EXPR@141..154
+            PATH@141..145
+              PATH_SEGMENT@141..145
+                NAME_REF@141..145
+                  IDENT@141..145 "Repr"
+            RECORD_EXPR_FIELD_LIST@145..154
+              L_CURLY@145..146 "{"
+              RECORD_EXPR_FIELD@146..153
+                NAME_REF@146..149
+                  IDENT@146..149 "raw"
+                COLON@149..150 ":"
+                ARRAY_EXPR@150..153
+                  L_BRACK@150..151 "["
+                  LITERAL@151..152
+                    INT_NUMBER@151..152 "0"
+                  R_BRACK@152..153 "]"
+              R_CURLY@153..154 "}"
+          ARG_LIST@154..156
+            L_PAREN@154..155 "("
+            R_PAREN@155..156 ")"
+        SEMICOLON@156..157 ";"
+      WHITESPACE@157..158 "\n"
+      R_CURLY@158..159 "}"
+  WHITESPACE@159..160 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0043_complex_assignment.rs b/crates/syntax/test_data/parser/ok/0043_complex_assignment.rs
new file mode 100644
index 00000000000..7e4a28bf74c
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0043_complex_assignment.rs
@@ -0,0 +1,8 @@
+// https://github.com/rust-analyzer/rust-analyzer/issues/674
+
+struct Repr { raw: [u8; 1] }
+
+fn abc() {
+    Repr { raw: [0] }.raw[0] = 0;
+    Repr{raw:[0]}();
+}
diff --git a/crates/syntax/test_data/parser/ok/0044_let_attrs.rast b/crates/syntax/test_data/parser/ok/0044_let_attrs.rast
new file mode 100644
index 00000000000..af44a4dbe2e
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0044_let_attrs.rast
@@ -0,0 +1,75 @@
+SOURCE_FILE@0..166
+  FN@0..165
+    COMMENT@0..60 "// https://github.com ..."
+    WHITESPACE@60..61 "\n"
+    FN_KW@61..63 "fn"
+    WHITESPACE@63..64 " "
+    NAME@64..68
+      IDENT@64..68 "main"
+    PARAM_LIST@68..70
+      L_PAREN@68..69 "("
+      R_PAREN@69..70 ")"
+    WHITESPACE@70..71 " "
+    BLOCK_EXPR@71..165
+      L_CURLY@71..72 "{"
+      WHITESPACE@72..77 "\n    "
+      LET_STMT@77..163
+        ATTR@77..106
+          POUND@77..78 "#"
+          L_BRACK@78..79 "["
+          PATH@79..82
+            PATH_SEGMENT@79..82
+              NAME_REF@79..82
+                IDENT@79..82 "cfg"
+          TOKEN_TREE@82..105
+            L_PAREN@82..83 "("
+            IDENT@83..90 "feature"
+            WHITESPACE@90..91 " "
+            EQ@91..92 "="
+            WHITESPACE@92..93 " "
+            STRING@93..104 "\"backtrace\""
+            R_PAREN@104..105 ")"
+          R_BRACK@105..106 "]"
+        WHITESPACE@106..111 "\n    "
+        LET_KW@111..114 "let"
+        WHITESPACE@114..115 " "
+        IDENT_PAT@115..124
+          NAME@115..124
+            IDENT@115..124 "exit_code"
+        WHITESPACE@124..125 " "
+        EQ@125..126 "="
+        WHITESPACE@126..127 " "
+        CALL_EXPR@127..162
+          PATH_EXPR@127..146
+            PATH@127..146
+              PATH@127..132
+                PATH_SEGMENT@127..132
+                  NAME_REF@127..132
+                    IDENT@127..132 "panic"
+              COLON2@132..134 "::"
+              PATH_SEGMENT@134..146
+                NAME_REF@134..146
+                  IDENT@134..146 "catch_unwind"
+          ARG_LIST@146..162
+            L_PAREN@146..147 "("
+            CLOSURE_EXPR@147..161
+              MOVE_KW@147..151 "move"
+              WHITESPACE@151..152 " "
+              PARAM_LIST@152..154
+                PIPE@152..153 "|"
+                PIPE@153..154 "|"
+              WHITESPACE@154..155 " "
+              CALL_EXPR@155..161
+                PATH_EXPR@155..159
+                  PATH@155..159
+                    PATH_SEGMENT@155..159
+                      NAME_REF@155..159
+                        IDENT@155..159 "main"
+                ARG_LIST@159..161
+                  L_PAREN@159..160 "("
+                  R_PAREN@160..161 ")"
+            R_PAREN@161..162 ")"
+        SEMICOLON@162..163 ";"
+      WHITESPACE@163..164 "\n"
+      R_CURLY@164..165 "}"
+  WHITESPACE@165..166 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0044_let_attrs.rs b/crates/syntax/test_data/parser/ok/0044_let_attrs.rs
new file mode 100644
index 00000000000..325a97aebdc
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0044_let_attrs.rs
@@ -0,0 +1,5 @@
+// https://github.com/rust-analyzer/rust-analyzer/issues/677
+fn main() {
+    #[cfg(feature = "backtrace")]
+    let exit_code = panic::catch_unwind(move || main());
+}
diff --git a/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rast b/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rast
new file mode 100644
index 00000000000..0ac56df6d0f
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rast
@@ -0,0 +1,177 @@
+SOURCE_FILE@0..686
+  FN@0..461
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..8
+      IDENT@3..8 "block"
+    PARAM_LIST@8..10
+      L_PAREN@8..9 "("
+      R_PAREN@9..10 ")"
+    WHITESPACE@10..11 " "
+    BLOCK_EXPR@11..461
+      L_CURLY@11..12 "{"
+      WHITESPACE@12..17 "\n    "
+      ATTR@17..57
+        POUND@17..18 "#"
+        BANG@18..19 "!"
+        L_BRACK@19..20 "["
+        PATH@20..23
+          PATH_SEGMENT@20..23
+            NAME_REF@20..23
+              IDENT@20..23 "doc"
+        TOKEN_TREE@23..56
+          L_PAREN@23..24 "("
+          STRING@24..55 "\"Inner attributes all ..."
+          R_PAREN@55..56 ")"
+        R_BRACK@56..57 "]"
+      WHITESPACE@57..62 "\n    "
+      COMMENT@62..97 "//! As are ModuleDoc  ..."
+      WHITESPACE@97..102 "\n    "
+      EXPR_STMT@102..295
+        BLOCK_EXPR@102..294
+          L_CURLY@102..103 "{"
+          WHITESPACE@103..112 "\n        "
+          ATTR@112..180
+            POUND@112..113 "#"
+            BANG@113..114 "!"
+            L_BRACK@114..115 "["
+            PATH@115..118
+              PATH_SEGMENT@115..118
+                NAME_REF@115..118
+                  IDENT@115..118 "doc"
+            TOKEN_TREE@118..179
+              L_PAREN@118..119 "("
+              STRING@119..178 "\"Inner attributes are ..."
+              R_PAREN@178..179 ")"
+            R_BRACK@179..180 "]"
+          WHITESPACE@180..189 "\n        "
+          ATTR@189..244
+            POUND@189..190 "#"
+            BANG@190..191 "!"
+            L_BRACK@191..192 "["
+            PATH@192..195
+              PATH_SEGMENT@192..195
+                NAME_REF@192..195
+                  IDENT@192..195 "doc"
+            TOKEN_TREE@195..243
+              L_PAREN@195..196 "("
+              STRING@196..242 "\"Being validated is n ..."
+              R_PAREN@242..243 ")"
+            R_BRACK@243..244 "]"
+          WHITESPACE@244..253 "\n        "
+          COMMENT@253..288 "//! As are ModuleDoc  ..."
+          WHITESPACE@288..293 "\n    "
+          R_CURLY@293..294 "}"
+        SEMICOLON@294..295 ";"
+      WHITESPACE@295..300 "\n    "
+      BLOCK_EXPR@300..459
+        L_CURLY@300..301 "{"
+        WHITESPACE@301..310 "\n        "
+        ATTR@310..409
+          POUND@310..311 "#"
+          BANG@311..312 "!"
+          L_BRACK@312..313 "["
+          PATH@313..316
+            PATH_SEGMENT@313..316
+              NAME_REF@313..316
+                IDENT@313..316 "doc"
+          TOKEN_TREE@316..408
+            L_PAREN@316..317 "("
+            STRING@317..407 "\"Inner attributes are ..."
+            R_PAREN@407..408 ")"
+          R_BRACK@408..409 "]"
+        WHITESPACE@409..418 "\n        "
+        COMMENT@418..453 "//! As are ModuleDoc  ..."
+        WHITESPACE@453..458 "\n    "
+        R_CURLY@458..459 "}"
+      WHITESPACE@459..460 "\n"
+      R_CURLY@460..461 "}"
+  WHITESPACE@461..463 "\n\n"
+  COMMENT@463..523 "// https://github.com ..."
+  WHITESPACE@523..524 "\n"
+  IMPL@524..685
+    IMPL_KW@524..528 "impl"
+    WHITESPACE@528..529 " "
+    PATH_TYPE@529..537
+      PATH@529..537
+        PATH_SEGMENT@529..537
+          NAME_REF@529..537
+            IDENT@529..537 "Whatever"
+    WHITESPACE@537..538 " "
+    ASSOC_ITEM_LIST@538..685
+      L_CURLY@538..539 "{"
+      WHITESPACE@539..544 "\n    "
+      FN@544..683
+        FN_KW@544..546 "fn"
+        WHITESPACE@546..547 " "
+        NAME@547..558
+          IDENT@547..558 "salsa_event"
+        PARAM_LIST@558..601
+          L_PAREN@558..559 "("
+          SELF_PARAM@559..564
+            AMP@559..560 "&"
+            SELF_KW@560..564 "self"
+          COMMA@564..565 ","
+          WHITESPACE@565..566 " "
+          PARAM@566..600
+            IDENT_PAT@566..574
+              NAME@566..574
+                IDENT@566..574 "event_fn"
+            COLON@574..575 ":"
+            WHITESPACE@575..576 " "
+            IMPL_TRAIT_TYPE@576..600
+              IMPL_KW@576..580 "impl"
+              WHITESPACE@580..581 " "
+              TYPE_BOUND_LIST@581..600
+                TYPE_BOUND@581..600
+                  PATH_TYPE@581..600
+                    PATH@581..600
+                      PATH_SEGMENT@581..600
+                        NAME_REF@581..583
+                          IDENT@581..583 "Fn"
+                        PARAM_LIST@583..585
+                          L_PAREN@583..584 "("
+                          R_PAREN@584..585 ")"
+                        WHITESPACE@585..586 " "
+                        RET_TYPE@586..600
+                          THIN_ARROW@586..588 "->"
+                          WHITESPACE@588..589 " "
+                          PATH_TYPE@589..600
+                            PATH@589..600
+                              PATH_SEGMENT@589..600
+                                NAME_REF@589..594
+                                  IDENT@589..594 "Event"
+                                GENERIC_ARG_LIST@594..600
+                                  L_ANGLE@594..595 "<"
+                                  TYPE_ARG@595..599
+                                    PATH_TYPE@595..599
+                                      PATH@595..599
+                                        PATH_SEGMENT@595..599
+                                          NAME_REF@595..599
+                                            IDENT@595..599 "Self"
+                                  R_ANGLE@599..600 ">"
+          R_PAREN@600..601 ")"
+        WHITESPACE@601..602 " "
+        BLOCK_EXPR@602..683
+          L_CURLY@602..603 "{"
+          WHITESPACE@603..612 "\n        "
+          ATTR@612..639
+            POUND@612..613 "#"
+            BANG@613..614 "!"
+            L_BRACK@614..615 "["
+            PATH@615..620
+              PATH_SEGMENT@615..620
+                NAME_REF@615..620
+                  IDENT@615..620 "allow"
+            TOKEN_TREE@620..638
+              L_PAREN@620..621 "("
+              IDENT@621..637 "unused_variables"
+              R_PAREN@637..638 ")"
+            R_BRACK@638..639 "]"
+          WHITESPACE@639..640 " "
+          COMMENT@640..677 "// this is  `inner_at ..."
+          WHITESPACE@677..682 "\n    "
+          R_CURLY@682..683 "}"
+      WHITESPACE@683..684 "\n"
+      R_CURLY@684..685 "}"
+  WHITESPACE@685..686 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rs b/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rs
new file mode 100644
index 00000000000..88df8138edc
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rs
@@ -0,0 +1,20 @@
+fn block() {
+    #![doc("Inner attributes allowed here")]
+    //! As are ModuleDoc style comments
+    {
+        #![doc("Inner attributes are allowed in blocks used as statements")]
+        #![doc("Being validated is not affected by duplcates")]
+        //! As are ModuleDoc style comments
+    };
+    {
+        #![doc("Inner attributes are allowed in blocks when they are the last statement of another block")]
+        //! As are ModuleDoc style comments
+    }
+}
+
+// https://github.com/rust-analyzer/rust-analyzer/issues/689
+impl Whatever {
+    fn salsa_event(&self, event_fn: impl Fn() -> Event<Self>) {
+        #![allow(unused_variables)] // this is  `inner_attr` of the block
+    }
+}
diff --git a/crates/syntax/test_data/parser/ok/0046_extern_inner_attributes.rast b/crates/syntax/test_data/parser/ok/0046_extern_inner_attributes.rast
new file mode 100644
index 00000000000..37594769aaa
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0046_extern_inner_attributes.rast
@@ -0,0 +1,28 @@
+SOURCE_FILE@0..87
+  EXTERN_BLOCK@0..86
+    ABI@0..10
+      EXTERN_KW@0..6 "extern"
+      WHITESPACE@6..7 " "
+      STRING@7..10 "\"C\""
+    WHITESPACE@10..11 " "
+    EXTERN_ITEM_LIST@11..86
+      L_CURLY@11..12 "{"
+      WHITESPACE@12..17 "\n    "
+      COMMENT@17..42 "//! This is a doc com ..."
+      WHITESPACE@42..47 "\n    "
+      ATTR@47..84
+        POUND@47..48 "#"
+        BANG@48..49 "!"
+        L_BRACK@49..50 "["
+        PATH@50..53
+          PATH_SEGMENT@50..53
+            NAME_REF@50..53
+              IDENT@50..53 "doc"
+        TOKEN_TREE@53..83
+          L_PAREN@53..54 "("
+          STRING@54..82 "\"This is also a doc c ..."
+          R_PAREN@82..83 ")"
+        R_BRACK@83..84 "]"
+      WHITESPACE@84..85 "\n"
+      R_CURLY@85..86 "}"
+  WHITESPACE@86..87 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0046_extern_inner_attributes.rs b/crates/syntax/test_data/parser/ok/0046_extern_inner_attributes.rs
new file mode 100644
index 00000000000..fe67e2df43c
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0046_extern_inner_attributes.rs
@@ -0,0 +1,4 @@
+extern "C" {
+    //! This is a doc comment
+    #![doc("This is also a doc comment")]
+}
diff --git a/crates/syntax/test_data/parser/ok/0047_minus_in_inner_pattern.rast b/crates/syntax/test_data/parser/ok/0047_minus_in_inner_pattern.rast
new file mode 100644
index 00000000000..4f8dff90948
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0047_minus_in_inner_pattern.rast
@@ -0,0 +1,320 @@
+SOURCE_FILE@0..395
+  COMMENT@0..60 "// https://github.com ..."
+  WHITESPACE@60..62 "\n\n"
+  FN@62..341
+    FN_KW@62..64 "fn"
+    WHITESPACE@64..65 " "
+    NAME@65..69
+      IDENT@65..69 "main"
+    PARAM_LIST@69..71
+      L_PAREN@69..70 "("
+      R_PAREN@70..71 ")"
+    WHITESPACE@71..72 " "
+    BLOCK_EXPR@72..341
+      L_CURLY@72..73 "{"
+      WHITESPACE@73..78 "\n    "
+      EXPR_STMT@78..141
+        MATCH_EXPR@78..141
+          MATCH_KW@78..83 "match"
+          WHITESPACE@83..84 " "
+          CALL_EXPR@84..92
+            PATH_EXPR@84..88
+              PATH@84..88
+                PATH_SEGMENT@84..88
+                  NAME_REF@84..88
+                    IDENT@84..88 "Some"
+            ARG_LIST@88..92
+              L_PAREN@88..89 "("
+              PREFIX_EXPR@89..91
+                MINUS@89..90 "-"
+                LITERAL@90..91
+                  INT_NUMBER@90..91 "1"
+              R_PAREN@91..92 ")"
+          WHITESPACE@92..93 " "
+          MATCH_ARM_LIST@93..141
+            L_CURLY@93..94 "{"
+            WHITESPACE@94..103 "\n        "
+            MATCH_ARM@103..117
+              TUPLE_STRUCT_PAT@103..111
+                PATH@103..107
+                  PATH_SEGMENT@103..107
+                    NAME_REF@103..107
+                      IDENT@103..107 "Some"
+                L_PAREN@107..108 "("
+                LITERAL_PAT@108..110
+                  MINUS@108..109 "-"
+                  LITERAL@109..110
+                    INT_NUMBER@109..110 "1"
+                R_PAREN@110..111 ")"
+              WHITESPACE@111..112 " "
+              FAT_ARROW@112..114 "=>"
+              WHITESPACE@114..115 " "
+              TUPLE_EXPR@115..117
+                L_PAREN@115..116 "("
+                R_PAREN@116..117 ")"
+            COMMA@117..118 ","
+            WHITESPACE@118..127 "\n        "
+            MATCH_ARM@127..134
+              WILDCARD_PAT@127..128
+                UNDERSCORE@127..128 "_"
+              WHITESPACE@128..129 " "
+              FAT_ARROW@129..131 "=>"
+              WHITESPACE@131..132 " "
+              TUPLE_EXPR@132..134
+                L_PAREN@132..133 "("
+                R_PAREN@133..134 ")"
+            COMMA@134..135 ","
+            WHITESPACE@135..140 "\n    "
+            R_CURLY@140..141 "}"
+      WHITESPACE@141..147 "\n\n    "
+      EXPR_STMT@147..222
+        MATCH_EXPR@147..222
+          MATCH_KW@147..152 "match"
+          WHITESPACE@152..153 " "
+          CALL_EXPR@153..167
+            PATH_EXPR@153..157
+              PATH@153..157
+                PATH_SEGMENT@153..157
+                  NAME_REF@153..157
+                    IDENT@153..157 "Some"
+            ARG_LIST@157..167
+              L_PAREN@157..158 "("
+              TUPLE_EXPR@158..166
+                L_PAREN@158..159 "("
+                PREFIX_EXPR@159..161
+                  MINUS@159..160 "-"
+                  LITERAL@160..161
+                    INT_NUMBER@160..161 "1"
+                COMMA@161..162 ","
+                WHITESPACE@162..163 " "
+                PREFIX_EXPR@163..165
+                  MINUS@163..164 "-"
+                  LITERAL@164..165
+                    INT_NUMBER@164..165 "1"
+                R_PAREN@165..166 ")"
+              R_PAREN@166..167 ")"
+          WHITESPACE@167..168 " "
+          MATCH_ARM_LIST@168..222
+            L_CURLY@168..169 "{"
+            WHITESPACE@169..178 "\n        "
+            MATCH_ARM@178..198
+              TUPLE_STRUCT_PAT@178..192
+                PATH@178..182
+                  PATH_SEGMENT@178..182
+                    NAME_REF@178..182
+                      IDENT@178..182 "Some"
+                L_PAREN@182..183 "("
+                TUPLE_PAT@183..191
+                  L_PAREN@183..184 "("
+                  LITERAL_PAT@184..186
+                    MINUS@184..185 "-"
+                    LITERAL@185..186
+                      INT_NUMBER@185..186 "1"
+                  COMMA@186..187 ","
+                  WHITESPACE@187..188 " "
+                  LITERAL_PAT@188..190
+                    MINUS@188..189 "-"
+                    LITERAL@189..190
+                      INT_NUMBER@189..190 "1"
+                  R_PAREN@190..191 ")"
+                R_PAREN@191..192 ")"
+              WHITESPACE@192..193 " "
+              FAT_ARROW@193..195 "=>"
+              WHITESPACE@195..196 " "
+              TUPLE_EXPR@196..198
+                L_PAREN@196..197 "("
+                R_PAREN@197..198 ")"
+            COMMA@198..199 ","
+            WHITESPACE@199..208 "\n        "
+            MATCH_ARM@208..215
+              WILDCARD_PAT@208..209
+                UNDERSCORE@208..209 "_"
+              WHITESPACE@209..210 " "
+              FAT_ARROW@210..212 "=>"
+              WHITESPACE@212..213 " "
+              TUPLE_EXPR@213..215
+                L_PAREN@213..214 "("
+                R_PAREN@214..215 ")"
+            COMMA@215..216 ","
+            WHITESPACE@216..221 "\n    "
+            R_CURLY@221..222 "}"
+      WHITESPACE@222..228 "\n\n    "
+      EXPR_STMT@228..299
+        MATCH_EXPR@228..299
+          MATCH_KW@228..233 "match"
+          WHITESPACE@233..234 " "
+          CALL_EXPR@234..246
+            PATH_EXPR@234..238
+              PATH@234..238
+                PATH@234..235
+                  PATH_SEGMENT@234..235
+                    NAME_REF@234..235
+                      IDENT@234..235 "A"
+                COLON2@235..237 "::"
+                PATH_SEGMENT@237..238
+                  NAME_REF@237..238
+                    IDENT@237..238 "B"
+            ARG_LIST@238..246
+              L_PAREN@238..239 "("
+              PREFIX_EXPR@239..241
+                MINUS@239..240 "-"
+                LITERAL@240..241
+                  INT_NUMBER@240..241 "1"
+              COMMA@241..242 ","
+              WHITESPACE@242..243 " "
+              PREFIX_EXPR@243..245
+                MINUS@243..244 "-"
+                LITERAL@244..245
+                  INT_NUMBER@244..245 "1"
+              R_PAREN@245..246 ")"
+          WHITESPACE@246..247 " "
+          MATCH_ARM_LIST@247..299
+            L_CURLY@247..248 "{"
+            WHITESPACE@248..257 "\n        "
+            MATCH_ARM@257..275
+              TUPLE_STRUCT_PAT@257..269
+                PATH@257..261
+                  PATH@257..258
+                    PATH_SEGMENT@257..258
+                      NAME_REF@257..258
+                        IDENT@257..258 "A"
+                  COLON2@258..260 "::"
+                  PATH_SEGMENT@260..261
+                    NAME_REF@260..261
+                      IDENT@260..261 "B"
+                L_PAREN@261..262 "("
+                LITERAL_PAT@262..264
+                  MINUS@262..263 "-"
+                  LITERAL@263..264
+                    INT_NUMBER@263..264 "1"
+                COMMA@264..265 ","
+                WHITESPACE@265..266 " "
+                LITERAL_PAT@266..268
+                  MINUS@266..267 "-"
+                  LITERAL@267..268
+                    INT_NUMBER@267..268 "1"
+                R_PAREN@268..269 ")"
+              WHITESPACE@269..270 " "
+              FAT_ARROW@270..272 "=>"
+              WHITESPACE@272..273 " "
+              TUPLE_EXPR@273..275
+                L_PAREN@273..274 "("
+                R_PAREN@274..275 ")"
+            COMMA@275..276 ","
+            WHITESPACE@276..285 "\n        "
+            MATCH_ARM@285..292
+              WILDCARD_PAT@285..286
+                UNDERSCORE@285..286 "_"
+              WHITESPACE@286..287 " "
+              FAT_ARROW@287..289 "=>"
+              WHITESPACE@289..290 " "
+              TUPLE_EXPR@290..292
+                L_PAREN@290..291 "("
+                R_PAREN@291..292 ")"
+            COMMA@292..293 ","
+            WHITESPACE@293..298 "\n    "
+            R_CURLY@298..299 "}"
+      WHITESPACE@299..305 "\n\n    "
+      IF_EXPR@305..339
+        IF_KW@305..307 "if"
+        WHITESPACE@307..308 " "
+        CONDITION@308..331
+          LET_KW@308..311 "let"
+          WHITESPACE@311..312 " "
+          TUPLE_STRUCT_PAT@312..320
+            PATH@312..316
+              PATH_SEGMENT@312..316
+                NAME_REF@312..316
+                  IDENT@312..316 "Some"
+            L_PAREN@316..317 "("
+            LITERAL_PAT@317..319
+              MINUS@317..318 "-"
+              LITERAL@318..319
+                INT_NUMBER@318..319 "1"
+            R_PAREN@319..320 ")"
+          WHITESPACE@320..321 " "
+          EQ@321..322 "="
+          WHITESPACE@322..323 " "
+          CALL_EXPR@323..331
+            PATH_EXPR@323..327
+              PATH@323..327
+                PATH_SEGMENT@323..327
+                  NAME_REF@323..327
+                    IDENT@323..327 "Some"
+            ARG_LIST@327..331
+              L_PAREN@327..328 "("
+              PREFIX_EXPR@328..330
+                MINUS@328..329 "-"
+                LITERAL@329..330
+                  INT_NUMBER@329..330 "1"
+              R_PAREN@330..331 ")"
+        WHITESPACE@331..332 " "
+        BLOCK_EXPR@332..339
+          L_CURLY@332..333 "{"
+          WHITESPACE@333..338 "\n    "
+          R_CURLY@338..339 "}"
+      WHITESPACE@339..340 "\n"
+      R_CURLY@340..341 "}"
+  WHITESPACE@341..343 "\n\n"
+  ENUM@343..367
+    ENUM_KW@343..347 "enum"
+    WHITESPACE@347..348 " "
+    NAME@348..349
+      IDENT@348..349 "A"
+    WHITESPACE@349..350 " "
+    VARIANT_LIST@350..367
+      L_CURLY@350..351 "{"
+      WHITESPACE@351..356 "\n    "
+      VARIANT@356..365
+        NAME@356..357
+          IDENT@356..357 "B"
+        TUPLE_FIELD_LIST@357..365
+          L_PAREN@357..358 "("
+          TUPLE_FIELD@358..360
+            PATH_TYPE@358..360
+              PATH@358..360
+                PATH_SEGMENT@358..360
+                  NAME_REF@358..360
+                    IDENT@358..360 "i8"
+          COMMA@360..361 ","
+          WHITESPACE@361..362 " "
+          TUPLE_FIELD@362..364
+            PATH_TYPE@362..364
+              PATH@362..364
+                PATH_SEGMENT@362..364
+                  NAME_REF@362..364
+                    IDENT@362..364 "i8"
+          R_PAREN@364..365 ")"
+      WHITESPACE@365..366 "\n"
+      R_CURLY@366..367 "}"
+  WHITESPACE@367..369 "\n\n"
+  FN@369..394
+    FN_KW@369..371 "fn"
+    WHITESPACE@371..372 " "
+    NAME@372..375
+      IDENT@372..375 "foo"
+    PARAM_LIST@375..391
+      L_PAREN@375..376 "("
+      PARAM@376..390
+        RANGE_PAT@376..386
+          LITERAL_PAT@376..380
+            MINUS@376..377 "-"
+            LITERAL@377..380
+              INT_NUMBER@377..380 "128"
+          DOT2EQ@380..383 "..="
+          LITERAL_PAT@383..386
+            LITERAL@383..386
+              INT_NUMBER@383..386 "127"
+        COLON@386..387 ":"
+        WHITESPACE@387..388 " "
+        PATH_TYPE@388..390
+          PATH@388..390
+            PATH_SEGMENT@388..390
+              NAME_REF@388..390
+                IDENT@388..390 "i8"
+      R_PAREN@390..391 ")"
+    WHITESPACE@391..392 " "
+    BLOCK_EXPR@392..394
+      L_CURLY@392..393 "{"
+      R_CURLY@393..394 "}"
+  WHITESPACE@394..395 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0047_minus_in_inner_pattern.rs b/crates/syntax/test_data/parser/ok/0047_minus_in_inner_pattern.rs
new file mode 100644
index 00000000000..bbd6b0f6e7c
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0047_minus_in_inner_pattern.rs
@@ -0,0 +1,27 @@
+// https://github.com/rust-analyzer/rust-analyzer/issues/972
+
+fn main() {
+    match Some(-1) {
+        Some(-1) => (),
+        _ => (),
+    }
+
+    match Some((-1, -1)) {
+        Some((-1, -1)) => (),
+        _ => (),
+    }
+
+    match A::B(-1, -1) {
+        A::B(-1, -1) => (),
+        _ => (),
+    }
+
+    if let Some(-1) = Some(-1) {
+    }
+}
+
+enum A {
+    B(i8, i8)
+}
+
+fn foo(-128..=127: i8) {}
diff --git a/crates/syntax/test_data/parser/ok/0048_compound_assignment.rast b/crates/syntax/test_data/parser/ok/0048_compound_assignment.rast
new file mode 100644
index 00000000000..eaab478433f
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0048_compound_assignment.rast
@@ -0,0 +1,200 @@
+SOURCE_FILE@0..257
+  COMMENT@0..58 "// https://github.com ..."
+  WHITESPACE@58..60 "\n\n"
+  FN@60..256
+    FN_KW@60..62 "fn"
+    WHITESPACE@62..63 " "
+    NAME@63..82
+      IDENT@63..82 "compound_assignment"
+    PARAM_LIST@82..84
+      L_PAREN@82..83 "("
+      R_PAREN@83..84 ")"
+    WHITESPACE@84..85 " "
+    BLOCK_EXPR@85..256
+      L_CURLY@85..86 "{"
+      WHITESPACE@86..91 "\n    "
+      LET_STMT@91..105
+        LET_KW@91..94 "let"
+        WHITESPACE@94..95 " "
+        IDENT_PAT@95..100
+          MUT_KW@95..98 "mut"
+          WHITESPACE@98..99 " "
+          NAME@99..100
+            IDENT@99..100 "a"
+        WHITESPACE@100..101 " "
+        EQ@101..102 "="
+        WHITESPACE@102..103 " "
+        LITERAL@103..104
+          INT_NUMBER@103..104 "0"
+        SEMICOLON@104..105 ";"
+      WHITESPACE@105..110 "\n    "
+      EXPR_STMT@110..117
+        BIN_EXPR@110..116
+          PATH_EXPR@110..111
+            PATH@110..111
+              PATH_SEGMENT@110..111
+                NAME_REF@110..111
+                  IDENT@110..111 "a"
+          WHITESPACE@111..112 " "
+          PLUSEQ@112..114 "+="
+          WHITESPACE@114..115 " "
+          LITERAL@115..116
+            INT_NUMBER@115..116 "1"
+        SEMICOLON@116..117 ";"
+      WHITESPACE@117..122 "\n    "
+      EXPR_STMT@122..129
+        BIN_EXPR@122..128
+          PATH_EXPR@122..123
+            PATH@122..123
+              PATH_SEGMENT@122..123
+                NAME_REF@122..123
+                  IDENT@122..123 "a"
+          WHITESPACE@123..124 " "
+          MINUSEQ@124..126 "-="
+          WHITESPACE@126..127 " "
+          LITERAL@127..128
+            INT_NUMBER@127..128 "2"
+        SEMICOLON@128..129 ";"
+      WHITESPACE@129..134 "\n    "
+      EXPR_STMT@134..141
+        BIN_EXPR@134..140
+          PATH_EXPR@134..135
+            PATH@134..135
+              PATH_SEGMENT@134..135
+                NAME_REF@134..135
+                  IDENT@134..135 "a"
+          WHITESPACE@135..136 " "
+          STAREQ@136..138 "*="
+          WHITESPACE@138..139 " "
+          LITERAL@139..140
+            INT_NUMBER@139..140 "3"
+        SEMICOLON@140..141 ";"
+      WHITESPACE@141..146 "\n    "
+      EXPR_STMT@146..153
+        BIN_EXPR@146..152
+          PATH_EXPR@146..147
+            PATH@146..147
+              PATH_SEGMENT@146..147
+                NAME_REF@146..147
+                  IDENT@146..147 "a"
+          WHITESPACE@147..148 " "
+          PERCENTEQ@148..150 "%="
+          WHITESPACE@150..151 " "
+          LITERAL@151..152
+            INT_NUMBER@151..152 "4"
+        SEMICOLON@152..153 ";"
+      WHITESPACE@153..158 "\n    "
+      EXPR_STMT@158..165
+        BIN_EXPR@158..164
+          PATH_EXPR@158..159
+            PATH@158..159
+              PATH_SEGMENT@158..159
+                NAME_REF@158..159
+                  IDENT@158..159 "a"
+          WHITESPACE@159..160 " "
+          SLASHEQ@160..162 "/="
+          WHITESPACE@162..163 " "
+          LITERAL@163..164
+            INT_NUMBER@163..164 "5"
+        SEMICOLON@164..165 ";"
+      WHITESPACE@165..170 "\n    "
+      EXPR_STMT@170..177
+        BIN_EXPR@170..176
+          PATH_EXPR@170..171
+            PATH@170..171
+              PATH_SEGMENT@170..171
+                NAME_REF@170..171
+                  IDENT@170..171 "a"
+          WHITESPACE@171..172 " "
+          PIPEEQ@172..174 "|="
+          WHITESPACE@174..175 " "
+          LITERAL@175..176
+            INT_NUMBER@175..176 "6"
+        SEMICOLON@176..177 ";"
+      WHITESPACE@177..182 "\n    "
+      EXPR_STMT@182..189
+        BIN_EXPR@182..188
+          PATH_EXPR@182..183
+            PATH@182..183
+              PATH_SEGMENT@182..183
+                NAME_REF@182..183
+                  IDENT@182..183 "a"
+          WHITESPACE@183..184 " "
+          AMPEQ@184..186 "&="
+          WHITESPACE@186..187 " "
+          LITERAL@187..188
+            INT_NUMBER@187..188 "7"
+        SEMICOLON@188..189 ";"
+      WHITESPACE@189..194 "\n    "
+      EXPR_STMT@194..201
+        BIN_EXPR@194..200
+          PATH_EXPR@194..195
+            PATH@194..195
+              PATH_SEGMENT@194..195
+                NAME_REF@194..195
+                  IDENT@194..195 "a"
+          WHITESPACE@195..196 " "
+          CARETEQ@196..198 "^="
+          WHITESPACE@198..199 " "
+          LITERAL@199..200
+            INT_NUMBER@199..200 "8"
+        SEMICOLON@200..201 ";"
+      WHITESPACE@201..206 "\n    "
+      EXPR_STMT@206..213
+        BIN_EXPR@206..212
+          PATH_EXPR@206..207
+            PATH@206..207
+              PATH_SEGMENT@206..207
+                NAME_REF@206..207
+                  IDENT@206..207 "a"
+          WHITESPACE@207..208 " "
+          LTEQ@208..210 "<="
+          WHITESPACE@210..211 " "
+          LITERAL@211..212
+            INT_NUMBER@211..212 "9"
+        SEMICOLON@212..213 ";"
+      WHITESPACE@213..218 "\n    "
+      EXPR_STMT@218..226
+        BIN_EXPR@218..225
+          PATH_EXPR@218..219
+            PATH@218..219
+              PATH_SEGMENT@218..219
+                NAME_REF@218..219
+                  IDENT@218..219 "a"
+          WHITESPACE@219..220 " "
+          GTEQ@220..222 ">="
+          WHITESPACE@222..223 " "
+          LITERAL@223..225
+            INT_NUMBER@223..225 "10"
+        SEMICOLON@225..226 ";"
+      WHITESPACE@226..231 "\n    "
+      EXPR_STMT@231..240
+        BIN_EXPR@231..239
+          PATH_EXPR@231..232
+            PATH@231..232
+              PATH_SEGMENT@231..232
+                NAME_REF@231..232
+                  IDENT@231..232 "a"
+          WHITESPACE@232..233 " "
+          SHREQ@233..236 ">>="
+          WHITESPACE@236..237 " "
+          LITERAL@237..239
+            INT_NUMBER@237..239 "11"
+        SEMICOLON@239..240 ";"
+      WHITESPACE@240..245 "\n    "
+      EXPR_STMT@245..254
+        BIN_EXPR@245..253
+          PATH_EXPR@245..246
+            PATH@245..246
+              PATH_SEGMENT@245..246
+                NAME_REF@245..246
+                  IDENT@245..246 "a"
+          WHITESPACE@246..247 " "
+          SHLEQ@247..250 "<<="
+          WHITESPACE@250..251 " "
+          LITERAL@251..253
+            INT_NUMBER@251..253 "12"
+        SEMICOLON@253..254 ";"
+      WHITESPACE@254..255 "\n"
+      R_CURLY@255..256 "}"
+  WHITESPACE@256..257 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0048_compound_assignment.rs b/crates/syntax/test_data/parser/ok/0048_compound_assignment.rs
new file mode 100644
index 00000000000..871720a49a6
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0048_compound_assignment.rs
@@ -0,0 +1,17 @@
+// https://github.com/rust-analyzer/rust-analyzer/pull/983
+
+fn compound_assignment() {
+    let mut a = 0;
+    a += 1;
+    a -= 2;
+    a *= 3;
+    a %= 4;
+    a /= 5;
+    a |= 6;
+    a &= 7;
+    a ^= 8;
+    a <= 9;
+    a >= 10;
+    a >>= 11;
+    a <<= 12;
+}
diff --git a/crates/syntax/test_data/parser/ok/0049_async_block.rast b/crates/syntax/test_data/parser/ok/0049_async_block.rast
new file mode 100644
index 00000000000..57ecad3cfa5
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0049_async_block.rast
@@ -0,0 +1,35 @@
+SOURCE_FILE@0..47
+  FN@0..45
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..45
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..24
+        EFFECT_EXPR@15..23
+          ASYNC_KW@15..20 "async"
+          WHITESPACE@20..21 " "
+          BLOCK_EXPR@21..23
+            L_CURLY@21..22 "{"
+            R_CURLY@22..23 "}"
+        SEMICOLON@23..24 ";"
+      WHITESPACE@24..29 "\n    "
+      EXPR_STMT@29..43
+        EFFECT_EXPR@29..42
+          ASYNC_KW@29..34 "async"
+          WHITESPACE@34..35 " "
+          MOVE_KW@35..39 "move"
+          WHITESPACE@39..40 " "
+          BLOCK_EXPR@40..42
+            L_CURLY@40..41 "{"
+            R_CURLY@41..42 "}"
+        SEMICOLON@42..43 ";"
+      WHITESPACE@43..44 "\n"
+      R_CURLY@44..45 "}"
+  WHITESPACE@45..47 "\n\n"
diff --git a/crates/syntax/test_data/parser/ok/0049_async_block.rs b/crates/syntax/test_data/parser/ok/0049_async_block.rs
new file mode 100644
index 00000000000..4781b322549
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0049_async_block.rs
@@ -0,0 +1,5 @@
+fn foo() {
+    async {};
+    async move {};
+}
+
diff --git a/crates/syntax/test_data/parser/ok/0050_async_block_as_argument.rast b/crates/syntax/test_data/parser/ok/0050_async_block_as_argument.rast
new file mode 100644
index 00000000000..c7ce12e93a0
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0050_async_block_as_argument.rast
@@ -0,0 +1,90 @@
+SOURCE_FILE@0..95
+  FN@0..52
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..49
+      L_PAREN@6..7 "("
+      PARAM@7..48
+        IDENT_PAT@7..8
+          NAME@7..8
+            IDENT@7..8 "x"
+        COLON@8..9 ":"
+        WHITESPACE@9..10 " "
+        IMPL_TRAIT_TYPE@10..48
+          IMPL_KW@10..14 "impl"
+          WHITESPACE@14..15 " "
+          TYPE_BOUND_LIST@15..48
+            TYPE_BOUND@15..48
+              PATH_TYPE@15..48
+                PATH@15..48
+                  PATH@15..26
+                    PATH@15..18
+                      PATH_SEGMENT@15..18
+                        NAME_REF@15..18
+                          IDENT@15..18 "std"
+                    COLON2@18..20 "::"
+                    PATH_SEGMENT@20..26
+                      NAME_REF@20..26
+                        IDENT@20..26 "future"
+                  COLON2@26..28 "::"
+                  PATH_SEGMENT@28..48
+                    NAME_REF@28..34
+                      IDENT@28..34 "Future"
+                    GENERIC_ARG_LIST@34..48
+                      L_ANGLE@34..35 "<"
+                      ASSOC_TYPE_ARG@35..47
+                        NAME_REF@35..41
+                          IDENT@35..41 "Output"
+                        WHITESPACE@41..42 " "
+                        EQ@42..43 "="
+                        WHITESPACE@43..44 " "
+                        PATH_TYPE@44..47
+                          PATH@44..47
+                            PATH_SEGMENT@44..47
+                              NAME_REF@44..47
+                                IDENT@44..47 "i32"
+                      R_ANGLE@47..48 ">"
+      R_PAREN@48..49 ")"
+    WHITESPACE@49..50 " "
+    BLOCK_EXPR@50..52
+      L_CURLY@50..51 "{"
+      R_CURLY@51..52 "}"
+  WHITESPACE@52..54 "\n\n"
+  FN@54..94
+    FN_KW@54..56 "fn"
+    WHITESPACE@56..57 " "
+    NAME@57..61
+      IDENT@57..61 "main"
+    PARAM_LIST@61..63
+      L_PAREN@61..62 "("
+      R_PAREN@62..63 ")"
+    WHITESPACE@63..64 " "
+    BLOCK_EXPR@64..94
+      L_CURLY@64..65 "{"
+      WHITESPACE@65..70 "\n    "
+      CALL_EXPR@70..92
+        PATH_EXPR@70..73
+          PATH@70..73
+            PATH_SEGMENT@70..73
+              NAME_REF@70..73
+                IDENT@70..73 "foo"
+        ARG_LIST@73..92
+          L_PAREN@73..74 "("
+          EFFECT_EXPR@74..91
+            ASYNC_KW@74..79 "async"
+            WHITESPACE@79..80 " "
+            MOVE_KW@80..84 "move"
+            WHITESPACE@84..85 " "
+            BLOCK_EXPR@85..91
+              L_CURLY@85..86 "{"
+              WHITESPACE@86..87 " "
+              LITERAL@87..89
+                INT_NUMBER@87..89 "12"
+              WHITESPACE@89..90 " "
+              R_CURLY@90..91 "}"
+          R_PAREN@91..92 ")"
+      WHITESPACE@92..93 "\n"
+      R_CURLY@93..94 "}"
+  WHITESPACE@94..95 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0050_async_block_as_argument.rs b/crates/syntax/test_data/parser/ok/0050_async_block_as_argument.rs
new file mode 100644
index 00000000000..ec4612cff27
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0050_async_block_as_argument.rs
@@ -0,0 +1,5 @@
+fn foo(x: impl std::future::Future<Output = i32>) {}
+
+fn main() {
+    foo(async move { 12 })
+}
diff --git a/crates/syntax/test_data/parser/ok/0051_parameter_attrs.rast b/crates/syntax/test_data/parser/ok/0051_parameter_attrs.rast
new file mode 100644
index 00000000000..d4f05f27924
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0051_parameter_attrs.rast
@@ -0,0 +1,508 @@
+SOURCE_FILE@0..519
+  FN@0..37
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..5
+      IDENT@3..5 "g1"
+    PARAM_LIST@5..34
+      L_PAREN@5..6 "("
+      ATTR@6..14
+        POUND@6..7 "#"
+        L_BRACK@7..8 "["
+        PATH@8..13
+          PATH_SEGMENT@8..13
+            NAME_REF@8..13
+              IDENT@8..13 "attr1"
+        R_BRACK@13..14 "]"
+      WHITESPACE@14..15 " "
+      ATTR@15..23
+        POUND@15..16 "#"
+        L_BRACK@16..17 "["
+        PATH@17..22
+          PATH_SEGMENT@17..22
+            NAME_REF@17..22
+              IDENT@17..22 "attr2"
+        R_BRACK@22..23 "]"
+      WHITESPACE@23..24 " "
+      PARAM@24..33
+        IDENT_PAT@24..27
+          NAME@24..27
+            IDENT@24..27 "pat"
+        COLON@27..28 ":"
+        WHITESPACE@28..29 " "
+        PATH_TYPE@29..33
+          PATH@29..33
+            PATH_SEGMENT@29..33
+              NAME_REF@29..33
+                IDENT@29..33 "Type"
+      R_PAREN@33..34 ")"
+    WHITESPACE@34..35 " "
+    BLOCK_EXPR@35..37
+      L_CURLY@35..36 "{"
+      R_CURLY@36..37 "}"
+  WHITESPACE@37..38 "\n"
+  FN@38..62
+    FN_KW@38..40 "fn"
+    WHITESPACE@40..41 " "
+    NAME@41..43
+      IDENT@41..43 "g2"
+    PARAM_LIST@43..59
+      L_PAREN@43..44 "("
+      ATTR@44..52
+        POUND@44..45 "#"
+        L_BRACK@45..46 "["
+        PATH@46..51
+          PATH_SEGMENT@46..51
+            NAME_REF@46..51
+              IDENT@46..51 "attr1"
+        R_BRACK@51..52 "]"
+      WHITESPACE@52..53 " "
+      PARAM@53..58
+        IDENT_PAT@53..54
+          NAME@53..54
+            IDENT@53..54 "x"
+        COLON@54..55 ":"
+        WHITESPACE@55..56 " "
+        PATH_TYPE@56..58
+          PATH@56..58
+            PATH_SEGMENT@56..58
+              NAME_REF@56..58
+                IDENT@56..58 "u8"
+      R_PAREN@58..59 ")"
+    WHITESPACE@59..60 " "
+    BLOCK_EXPR@60..62
+      L_CURLY@60..61 "{"
+      R_CURLY@61..62 "}"
+  WHITESPACE@62..64 "\n\n"
+  EXTERN_BLOCK@64..128
+    ABI@64..74
+      EXTERN_KW@64..70 "extern"
+      WHITESPACE@70..71 " "
+      STRING@71..74 "\"C\""
+    WHITESPACE@74..75 " "
+    EXTERN_ITEM_LIST@75..128
+      L_CURLY@75..76 "{"
+      WHITESPACE@76..77 " "
+      FN@77..126
+        FN_KW@77..79 "fn"
+        WHITESPACE@79..80 " "
+        NAME@80..86
+          IDENT@80..86 "printf"
+        PARAM_LIST@86..118
+          L_PAREN@86..87 "("
+          PARAM@87..104
+            IDENT_PAT@87..93
+              NAME@87..93
+                IDENT@87..93 "format"
+            COLON@93..94 ":"
+            WHITESPACE@94..95 " "
+            PTR_TYPE@95..104
+              STAR@95..96 "*"
+              CONST_KW@96..101 "const"
+              WHITESPACE@101..102 " "
+              PATH_TYPE@102..104
+                PATH@102..104
+                  PATH_SEGMENT@102..104
+                    NAME_REF@102..104
+                      IDENT@102..104 "i8"
+          COMMA@104..105 ","
+          WHITESPACE@105..106 " "
+          ATTR@106..113
+            POUND@106..107 "#"
+            L_BRACK@107..108 "["
+            PATH@108..112
+              PATH_SEGMENT@108..112
+                NAME_REF@108..112
+                  IDENT@108..112 "attr"
+            R_BRACK@112..113 "]"
+          WHITESPACE@113..114 " "
+          PARAM@114..117
+            DOT3@114..117 "..."
+          R_PAREN@117..118 ")"
+        WHITESPACE@118..119 " "
+        RET_TYPE@119..125
+          THIN_ARROW@119..121 "->"
+          WHITESPACE@121..122 " "
+          PATH_TYPE@122..125
+            PATH@122..125
+              PATH_SEGMENT@122..125
+                NAME_REF@122..125
+                  IDENT@122..125 "i32"
+        SEMICOLON@125..126 ";"
+      WHITESPACE@126..127 " "
+      R_CURLY@127..128 "}"
+  WHITESPACE@128..130 "\n\n"
+  FN@130..172
+    FN_KW@130..132 "fn"
+    WHITESPACE@132..133 " "
+    NAME@133..136
+      IDENT@133..136 "foo"
+    GENERIC_PARAM_LIST@136..168
+      L_ANGLE@136..137 "<"
+      TYPE_PARAM@137..167
+        NAME@137..138
+          IDENT@137..138 "F"
+        COLON@138..139 ":"
+        WHITESPACE@139..140 " "
+        TYPE_BOUND_LIST@140..167
+          TYPE_BOUND@140..167
+            PATH_TYPE@140..167
+              PATH@140..167
+                PATH_SEGMENT@140..167
+                  NAME_REF@140..145
+                    IDENT@140..145 "FnMut"
+                  PARAM_LIST@145..167
+                    L_PAREN@145..146 "("
+                    ATTR@146..153
+                      POUND@146..147 "#"
+                      L_BRACK@147..148 "["
+                      PATH@148..152
+                        PATH_SEGMENT@148..152
+                          NAME_REF@148..152
+                            IDENT@148..152 "attr"
+                      R_BRACK@152..153 "]"
+                    WHITESPACE@153..154 " "
+                    PARAM@154..166
+                      REF_TYPE@154..166
+                        AMP@154..155 "&"
+                        MUT_KW@155..158 "mut"
+                        WHITESPACE@158..159 " "
+                        PATH_TYPE@159..166
+                          PATH@159..166
+                            PATH_SEGMENT@159..166
+                              NAME_REF@159..162
+                                IDENT@159..162 "Foo"
+                              GENERIC_ARG_LIST@162..166
+                                L_ANGLE@162..163 "<"
+                                LIFETIME_ARG@163..165
+                                  LIFETIME@163..165 "\'a"
+                                R_ANGLE@165..166 ">"
+                    R_PAREN@166..167 ")"
+      R_ANGLE@167..168 ">"
+    PARAM_LIST@168..170
+      L_PAREN@168..169 "("
+      R_PAREN@169..170 ")"
+    BLOCK_EXPR@170..172
+      L_CURLY@170..171 "{"
+      R_CURLY@171..172 "}"
+  WHITESPACE@172..174 "\n\n"
+  TRAIT@174..236
+    TRAIT_KW@174..179 "trait"
+    WHITESPACE@179..180 " "
+    NAME@180..183
+      IDENT@180..183 "Foo"
+    WHITESPACE@183..184 " "
+    ASSOC_ITEM_LIST@184..236
+      L_CURLY@184..185 "{"
+      WHITESPACE@185..190 "\n    "
+      FN@190..234
+        FN_KW@190..192 "fn"
+        WHITESPACE@192..193 " "
+        NAME@193..196
+          IDENT@193..196 "bar"
+        PARAM_LIST@196..233
+          L_PAREN@196..197 "("
+          ATTR@197..204
+            POUND@197..198 "#"
+            L_BRACK@198..199 "["
+            PATH@199..203
+              PATH_SEGMENT@199..203
+                NAME_REF@199..203
+                  IDENT@199..203 "attr"
+            R_BRACK@203..204 "]"
+          WHITESPACE@204..205 " "
+          PARAM@205..211
+            WILDCARD_PAT@205..206
+              UNDERSCORE@205..206 "_"
+            COLON@206..207 ":"
+            WHITESPACE@207..208 " "
+            PATH_TYPE@208..211
+              PATH@208..211
+                PATH_SEGMENT@208..211
+                  NAME_REF@208..211
+                    IDENT@208..211 "u64"
+          COMMA@211..212 ","
+          WHITESPACE@212..213 " "
+          ATTR@213..221
+            POUND@213..214 "#"
+            WHITESPACE@214..215 " "
+            L_BRACK@215..216 "["
+            PATH@216..220
+              PATH_SEGMENT@216..220
+                NAME_REF@216..220
+                  IDENT@216..220 "attr"
+            R_BRACK@220..221 "]"
+          WHITESPACE@221..222 " "
+          PARAM@222..232
+            IDENT_PAT@222..227
+              MUT_KW@222..225 "mut"
+              WHITESPACE@225..226 " "
+              NAME@226..227
+                IDENT@226..227 "x"
+            COLON@227..228 ":"
+            WHITESPACE@228..229 " "
+            PATH_TYPE@229..232
+              PATH@229..232
+                PATH_SEGMENT@229..232
+                  NAME_REF@229..232
+                    IDENT@229..232 "i32"
+          R_PAREN@232..233 ")"
+        SEMICOLON@233..234 ";"
+      WHITESPACE@234..235 "\n"
+      R_CURLY@235..236 "}"
+  WHITESPACE@236..238 "\n\n"
+  IMPL@238..519
+    IMPL_KW@238..242 "impl"
+    WHITESPACE@242..243 " "
+    PATH_TYPE@243..244
+      PATH@243..244
+        PATH_SEGMENT@243..244
+          NAME_REF@243..244
+            IDENT@243..244 "S"
+    WHITESPACE@244..245 " "
+    ASSOC_ITEM_LIST@245..519
+      L_CURLY@245..246 "{"
+      WHITESPACE@246..252 "\n     "
+      FN@252..277
+        FN_KW@252..254 "fn"
+        WHITESPACE@254..255 " "
+        NAME@255..256
+          IDENT@255..256 "f"
+        PARAM_LIST@256..274
+          L_PAREN@256..257 "("
+          ATTR@257..268
+            POUND@257..258 "#"
+            L_BRACK@258..259 "["
+            PATH@259..267
+              PATH_SEGMENT@259..267
+                NAME_REF@259..267
+                  IDENT@259..267 "must_use"
+            R_BRACK@267..268 "]"
+          WHITESPACE@268..269 " "
+          SELF_PARAM@269..273
+            SELF_KW@269..273 "self"
+          R_PAREN@273..274 ")"
+        WHITESPACE@274..275 " "
+        BLOCK_EXPR@275..277
+          L_CURLY@275..276 "{"
+          R_CURLY@276..277 "}"
+      WHITESPACE@277..283 "\n     "
+      FN@283..305
+        FN_KW@283..285 "fn"
+        WHITESPACE@285..286 " "
+        NAME@286..288
+          IDENT@286..288 "g1"
+        PARAM_LIST@288..302
+          L_PAREN@288..289 "("
+          ATTR@289..296
+            POUND@289..290 "#"
+            L_BRACK@290..291 "["
+            PATH@291..295
+              PATH_SEGMENT@291..295
+                NAME_REF@291..295
+                  IDENT@291..295 "attr"
+            R_BRACK@295..296 "]"
+          WHITESPACE@296..297 " "
+          SELF_PARAM@297..301
+            SELF_KW@297..301 "self"
+          R_PAREN@301..302 ")"
+        WHITESPACE@302..303 " "
+        BLOCK_EXPR@303..305
+          L_CURLY@303..304 "{"
+          R_CURLY@304..305 "}"
+      WHITESPACE@305..311 "\n     "
+      FN@311..334
+        FN_KW@311..313 "fn"
+        WHITESPACE@313..314 " "
+        NAME@314..316
+          IDENT@314..316 "g2"
+        PARAM_LIST@316..331
+          L_PAREN@316..317 "("
+          ATTR@317..324
+            POUND@317..318 "#"
+            L_BRACK@318..319 "["
+            PATH@319..323
+              PATH_SEGMENT@319..323
+                NAME_REF@319..323
+                  IDENT@319..323 "attr"
+            R_BRACK@323..324 "]"
+          WHITESPACE@324..325 " "
+          SELF_PARAM@325..330
+            AMP@325..326 "&"
+            SELF_KW@326..330 "self"
+          R_PAREN@330..331 ")"
+        WHITESPACE@331..332 " "
+        BLOCK_EXPR@332..334
+          L_CURLY@332..333 "{"
+          R_CURLY@333..334 "}"
+      WHITESPACE@334..340 "\n     "
+      FN@340..371
+        FN_KW@340..342 "fn"
+        WHITESPACE@342..343 " "
+        NAME@343..345
+          IDENT@343..345 "g3"
+        GENERIC_PARAM_LIST@345..349
+          L_ANGLE@345..346 "<"
+          LIFETIME_PARAM@346..348
+            LIFETIME@346..348 "\'a"
+          R_ANGLE@348..349 ">"
+        PARAM_LIST@349..368
+          L_PAREN@349..350 "("
+          ATTR@350..357
+            POUND@350..351 "#"
+            L_BRACK@351..352 "["
+            PATH@352..356
+              PATH_SEGMENT@352..356
+                NAME_REF@352..356
+                  IDENT@352..356 "attr"
+            R_BRACK@356..357 "]"
+          WHITESPACE@357..358 " "
+          SELF_PARAM@358..367
+            AMP@358..359 "&"
+            MUT_KW@359..362 "mut"
+            WHITESPACE@362..363 " "
+            SELF_KW@363..367 "self"
+          R_PAREN@367..368 ")"
+        WHITESPACE@368..369 " "
+        BLOCK_EXPR@369..371
+          L_CURLY@369..370 "{"
+          R_CURLY@370..371 "}"
+      WHITESPACE@371..377 "\n     "
+      FN@377..407
+        FN_KW@377..379 "fn"
+        WHITESPACE@379..380 " "
+        NAME@380..382
+          IDENT@380..382 "g4"
+        GENERIC_PARAM_LIST@382..386
+          L_ANGLE@382..383 "<"
+          LIFETIME_PARAM@383..385
+            LIFETIME@383..385 "\'a"
+          R_ANGLE@385..386 ">"
+        PARAM_LIST@386..404
+          L_PAREN@386..387 "("
+          ATTR@387..394
+            POUND@387..388 "#"
+            L_BRACK@388..389 "["
+            PATH@389..393
+              PATH_SEGMENT@389..393
+                NAME_REF@389..393
+                  IDENT@389..393 "attr"
+            R_BRACK@393..394 "]"
+          WHITESPACE@394..395 " "
+          SELF_PARAM@395..403
+            AMP@395..396 "&"
+            LIFETIME@396..398 "\'a"
+            WHITESPACE@398..399 " "
+            SELF_KW@399..403 "self"
+          R_PAREN@403..404 ")"
+        WHITESPACE@404..405 " "
+        BLOCK_EXPR@405..407
+          L_CURLY@405..406 "{"
+          R_CURLY@406..407 "}"
+      WHITESPACE@407..413 "\n     "
+      FN@413..447
+        FN_KW@413..415 "fn"
+        WHITESPACE@415..416 " "
+        NAME@416..418
+          IDENT@416..418 "g5"
+        GENERIC_PARAM_LIST@418..422
+          L_ANGLE@418..419 "<"
+          LIFETIME_PARAM@419..421
+            LIFETIME@419..421 "\'a"
+          R_ANGLE@421..422 ">"
+        PARAM_LIST@422..444
+          L_PAREN@422..423 "("
+          ATTR@423..430
+            POUND@423..424 "#"
+            L_BRACK@424..425 "["
+            PATH@425..429
+              PATH_SEGMENT@425..429
+                NAME_REF@425..429
+                  IDENT@425..429 "attr"
+            R_BRACK@429..430 "]"
+          WHITESPACE@430..431 " "
+          SELF_PARAM@431..443
+            AMP@431..432 "&"
+            LIFETIME@432..434 "\'a"
+            WHITESPACE@434..435 " "
+            MUT_KW@435..438 "mut"
+            WHITESPACE@438..439 " "
+            SELF_KW@439..443 "self"
+          R_PAREN@443..444 ")"
+        WHITESPACE@444..445 " "
+        BLOCK_EXPR@445..447
+          L_CURLY@445..446 "{"
+          R_CURLY@446..447 "}"
+      WHITESPACE@447..453 "\n     "
+      FN@453..480
+        FN_KW@453..455 "fn"
+        WHITESPACE@455..456 " "
+        NAME@456..457
+          IDENT@456..457 "c"
+        PARAM_LIST@457..477
+          L_PAREN@457..458 "("
+          ATTR@458..465
+            POUND@458..459 "#"
+            L_BRACK@459..460 "["
+            PATH@460..464
+              PATH_SEGMENT@460..464
+                NAME_REF@460..464
+                  IDENT@460..464 "attr"
+            R_BRACK@464..465 "]"
+          WHITESPACE@465..466 " "
+          SELF_PARAM@466..476
+            SELF_KW@466..470 "self"
+            COLON@470..471 ":"
+            WHITESPACE@471..472 " "
+            PATH_TYPE@472..476
+              PATH@472..476
+                PATH_SEGMENT@472..476
+                  NAME_REF@472..476
+                    IDENT@472..476 "Self"
+          R_PAREN@476..477 ")"
+        WHITESPACE@477..478 " "
+        BLOCK_EXPR@478..480
+          L_CURLY@478..479 "{"
+          R_CURLY@479..480 "}"
+      WHITESPACE@480..486 "\n     "
+      FN@486..517
+        FN_KW@486..488 "fn"
+        WHITESPACE@488..489 " "
+        NAME@489..490
+          IDENT@489..490 "d"
+        PARAM_LIST@490..514
+          L_PAREN@490..491 "("
+          ATTR@491..498
+            POUND@491..492 "#"
+            L_BRACK@492..493 "["
+            PATH@493..497
+              PATH_SEGMENT@493..497
+                NAME_REF@493..497
+                  IDENT@493..497 "attr"
+            R_BRACK@497..498 "]"
+          WHITESPACE@498..499 " "
+          SELF_PARAM@499..513
+            SELF_KW@499..503 "self"
+            COLON@503..504 ":"
+            WHITESPACE@504..505 " "
+            PATH_TYPE@505..513
+              PATH@505..513
+                PATH_SEGMENT@505..513
+                  NAME_REF@505..507
+                    IDENT@505..507 "Rc"
+                  GENERIC_ARG_LIST@507..513
+                    L_ANGLE@507..508 "<"
+                    TYPE_ARG@508..512
+                      PATH_TYPE@508..512
+                        PATH@508..512
+                          PATH_SEGMENT@508..512
+                            NAME_REF@508..512
+                              IDENT@508..512 "Self"
+                    R_ANGLE@512..513 ">"
+          R_PAREN@513..514 ")"
+        WHITESPACE@514..515 " "
+        BLOCK_EXPR@515..517
+          L_CURLY@515..516 "{"
+          R_CURLY@516..517 "}"
+      WHITESPACE@517..518 "\n"
+      R_CURLY@518..519 "}"
diff --git a/crates/syntax/test_data/parser/ok/0051_parameter_attrs.rs b/crates/syntax/test_data/parser/ok/0051_parameter_attrs.rs
new file mode 100644
index 00000000000..de350d8587a
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0051_parameter_attrs.rs
@@ -0,0 +1,21 @@
+fn g1(#[attr1] #[attr2] pat: Type) {}
+fn g2(#[attr1] x: u8) {}
+
+extern "C" { fn printf(format: *const i8, #[attr] ...) -> i32; }
+
+fn foo<F: FnMut(#[attr] &mut Foo<'a>)>(){}
+
+trait Foo {
+    fn bar(#[attr] _: u64, # [attr] mut x: i32);
+}
+
+impl S {
+     fn f(#[must_use] self) {}
+     fn g1(#[attr] self) {}
+     fn g2(#[attr] &self) {}
+     fn g3<'a>(#[attr] &mut self) {}
+     fn g4<'a>(#[attr] &'a self) {}
+     fn g5<'a>(#[attr] &'a mut self) {}
+     fn c(#[attr] self: Self) {}
+     fn d(#[attr] self: Rc<Self>) {}
+}
\ No newline at end of file
diff --git a/crates/syntax/test_data/parser/ok/0052_for_range_block.rast b/crates/syntax/test_data/parser/ok/0052_for_range_block.rast
new file mode 100644
index 00000000000..350823ba36c
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0052_for_range_block.rast
@@ -0,0 +1,78 @@
+SOURCE_FILE@0..80
+  FN@0..79
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..79
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..14 "\n   "
+      FOR_EXPR@14..77
+        FOR_KW@14..17 "for"
+        WHITESPACE@17..18 " "
+        IDENT_PAT@18..20
+          NAME@18..20
+            IDENT@18..20 "_x"
+        WHITESPACE@20..21 " "
+        IN_KW@21..23 "in"
+        WHITESPACE@23..24 " "
+        RANGE_EXPR@24..56
+          LITERAL@24..25
+            INT_NUMBER@24..25 "0"
+          WHITESPACE@25..26 " "
+          DOT2@26..28 ".."
+          WHITESPACE@28..29 " "
+          METHOD_CALL_EXPR@29..56
+            PAREN_EXPR@29..43
+              L_PAREN@29..30 "("
+              RANGE_EXPR@30..42
+                LITERAL@30..31
+                  INT_NUMBER@30..31 "0"
+                WHITESPACE@31..32 " "
+                DOT2@32..34 ".."
+                WHITESPACE@34..35 " "
+                BLOCK_EXPR@35..42
+                  L_CURLY@35..36 "{"
+                  BIN_EXPR@36..41
+                    LITERAL@36..37
+                      INT_NUMBER@36..37 "1"
+                    WHITESPACE@37..38 " "
+                    PLUS@38..39 "+"
+                    WHITESPACE@39..40 " "
+                    LITERAL@40..41
+                      INT_NUMBER@40..41 "2"
+                  R_CURLY@41..42 "}"
+              R_PAREN@42..43 ")"
+            DOT@43..44 "."
+            NAME_REF@44..47
+              IDENT@44..47 "sum"
+            GENERIC_ARG_LIST@47..54
+              COLON2@47..49 "::"
+              L_ANGLE@49..50 "<"
+              TYPE_ARG@50..53
+                PATH_TYPE@50..53
+                  PATH@50..53
+                    PATH_SEGMENT@50..53
+                      NAME_REF@50..53
+                        IDENT@50..53 "u32"
+              R_ANGLE@53..54 ">"
+            ARG_LIST@54..56
+              L_PAREN@54..55 "("
+              R_PAREN@55..56 ")"
+        WHITESPACE@56..57 " "
+        BLOCK_EXPR@57..77
+          L_CURLY@57..58 "{"
+          WHITESPACE@58..66 "\n       "
+          EXPR_STMT@66..72
+            BREAK_EXPR@66..71
+              BREAK_KW@66..71 "break"
+            SEMICOLON@71..72 ";"
+          WHITESPACE@72..76 "\n   "
+          R_CURLY@76..77 "}"
+      WHITESPACE@77..78 "\n"
+      R_CURLY@78..79 "}"
+  WHITESPACE@79..80 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0052_for_range_block.rs b/crates/syntax/test_data/parser/ok/0052_for_range_block.rs
new file mode 100644
index 00000000000..b51b1963008
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0052_for_range_block.rs
@@ -0,0 +1,5 @@
+fn foo() {
+   for _x in 0 .. (0 .. {1 + 2}).sum::<u32>() {
+       break;
+   }
+}
diff --git a/crates/syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast b/crates/syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast
new file mode 100644
index 00000000000..be60f7a8ed8
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast
@@ -0,0 +1,39 @@
+SOURCE_FILE@0..65
+  MACRO_CALL@0..64
+    COMMENT@0..13 "/// Some docs"
+    WHITESPACE@13..14 "\n"
+    ATTR@14..29
+      POUND@14..15 "#"
+      L_BRACK@15..16 "["
+      PATH@16..28
+        PATH_SEGMENT@16..28
+          NAME_REF@16..28
+            IDENT@16..28 "macro_export"
+      R_BRACK@28..29 "]"
+    WHITESPACE@29..30 "\n"
+    PATH@30..41
+      PATH_SEGMENT@30..41
+        NAME_REF@30..41
+          IDENT@30..41 "macro_rules"
+    BANG@41..42 "!"
+    WHITESPACE@42..43 " "
+    NAME@43..46
+      IDENT@43..46 "foo"
+    WHITESPACE@46..47 " "
+    TOKEN_TREE@47..64
+      L_CURLY@47..48 "{"
+      WHITESPACE@48..53 "\n    "
+      TOKEN_TREE@53..55
+        L_PAREN@53..54 "("
+        R_PAREN@54..55 ")"
+      WHITESPACE@55..56 " "
+      EQ@56..57 "="
+      R_ANGLE@57..58 ">"
+      WHITESPACE@58..59 " "
+      TOKEN_TREE@59..61
+        L_CURLY@59..60 "{"
+        R_CURLY@60..61 "}"
+      SEMICOLON@61..62 ";"
+      WHITESPACE@62..63 "\n"
+      R_CURLY@63..64 "}"
+  WHITESPACE@64..65 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rs b/crates/syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rs
new file mode 100644
index 00000000000..b59c23c56a9
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rs
@@ -0,0 +1,5 @@
+/// Some docs
+#[macro_export]
+macro_rules! foo {
+    () => {};
+}
diff --git a/crates/syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rast b/crates/syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rast
new file mode 100644
index 00000000000..f25c9ac36ff
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rast
@@ -0,0 +1,123 @@
+SOURCE_FILE@0..88
+  FN@0..26
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..4
+      IDENT@3..4 "a"
+    PARAM_LIST@4..6
+      L_PAREN@4..5 "("
+      R_PAREN@5..6 ")"
+    WHITESPACE@6..7 " "
+    RET_TYPE@7..23
+      THIN_ARROW@7..9 "->"
+      WHITESPACE@9..10 " "
+      PATH_TYPE@10..23
+        PATH@10..23
+          PATH_SEGMENT@10..23
+            NAME_REF@10..13
+              IDENT@10..13 "Foo"
+            GENERIC_ARG_LIST@13..23
+              L_ANGLE@13..14 "<"
+              TYPE_ARG@14..22
+                PATH_TYPE@14..22
+                  PATH@14..22
+                    PATH@14..17
+                      PATH_SEGMENT@14..17
+                        NAME_REF@14..17
+                          IDENT@14..17 "bar"
+                    COLON2@17..19 "::"
+                    PATH_SEGMENT@19..22
+                      NAME_REF@19..22
+                        IDENT@19..22 "Baz"
+              R_ANGLE@22..23 ">"
+    WHITESPACE@23..24 " "
+    BLOCK_EXPR@24..26
+      L_CURLY@24..25 "{"
+      R_CURLY@25..26 "}"
+  WHITESPACE@26..28 "\n\n"
+  FN@28..56
+    FN_KW@28..30 "fn"
+    WHITESPACE@30..31 " "
+    NAME@31..32
+      IDENT@31..32 "b"
+    PARAM_LIST@32..53
+      L_PAREN@32..33 "("
+      PARAM@33..52
+        WILDCARD_PAT@33..34
+          UNDERSCORE@33..34 "_"
+        COLON@34..35 ":"
+        WHITESPACE@35..36 " "
+        IMPL_TRAIT_TYPE@36..52
+          IMPL_KW@36..40 "impl"
+          WHITESPACE@40..41 " "
+          TYPE_BOUND_LIST@41..52
+            TYPE_BOUND@41..52
+              PATH_TYPE@41..52
+                PATH@41..52
+                  PATH_SEGMENT@41..52
+                    NAME_REF@41..46
+                      IDENT@41..46 "FnMut"
+                    PARAM_LIST@46..52
+                      L_PAREN@46..47 "("
+                      PARAM@47..51
+                        PATH_TYPE@47..51
+                          PATH@47..51
+                            PATH@47..48
+                              PATH_SEGMENT@47..48
+                                NAME_REF@47..48
+                                  IDENT@47..48 "x"
+                            COLON2@48..50 "::"
+                            PATH_SEGMENT@50..51
+                              NAME_REF@50..51
+                                IDENT@50..51 "Y"
+                      R_PAREN@51..52 ")"
+      R_PAREN@52..53 ")"
+    WHITESPACE@53..54 " "
+    BLOCK_EXPR@54..56
+      L_CURLY@54..55 "{"
+      R_CURLY@55..56 "}"
+  WHITESPACE@56..58 "\n\n"
+  FN@58..87
+    FN_KW@58..60 "fn"
+    WHITESPACE@60..61 " "
+    NAME@61..62
+      IDENT@61..62 "c"
+    PARAM_LIST@62..84
+      L_PAREN@62..63 "("
+      PARAM@63..83
+        WILDCARD_PAT@63..64
+          UNDERSCORE@63..64 "_"
+        COLON@64..65 ":"
+        WHITESPACE@65..66 " "
+        IMPL_TRAIT_TYPE@66..83
+          IMPL_KW@66..70 "impl"
+          WHITESPACE@70..71 " "
+          TYPE_BOUND_LIST@71..83
+            TYPE_BOUND@71..83
+              PATH_TYPE@71..83
+                PATH@71..83
+                  PATH_SEGMENT@71..83
+                    NAME_REF@71..76
+                      IDENT@71..76 "FnMut"
+                    PARAM_LIST@76..83
+                      L_PAREN@76..77 "("
+                      PARAM@77..82
+                        REF_TYPE@77..82
+                          AMP@77..78 "&"
+                          PATH_TYPE@78..82
+                            PATH@78..82
+                              PATH@78..79
+                                PATH_SEGMENT@78..79
+                                  NAME_REF@78..79
+                                    IDENT@78..79 "x"
+                              COLON2@79..81 "::"
+                              PATH_SEGMENT@81..82
+                                NAME_REF@81..82
+                                  IDENT@81..82 "Y"
+                      R_PAREN@82..83 ")"
+      R_PAREN@83..84 ")"
+    WHITESPACE@84..85 " "
+    BLOCK_EXPR@85..87
+      L_CURLY@85..86 "{"
+      R_CURLY@86..87 "}"
+  WHITESPACE@87..88 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rs b/crates/syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rs
new file mode 100644
index 00000000000..0d3f5722a5a
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rs
@@ -0,0 +1,5 @@
+fn a() -> Foo<bar::Baz> {}
+
+fn b(_: impl FnMut(x::Y)) {}
+
+fn c(_: impl FnMut(&x::Y)) {}
diff --git a/crates/syntax/test_data/parser/ok/0055_dot_dot_dot.rast b/crates/syntax/test_data/parser/ok/0055_dot_dot_dot.rast
new file mode 100644
index 00000000000..7447d516ed1
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0055_dot_dot_dot.rast
@@ -0,0 +1,49 @@
+SOURCE_FILE@0..49
+  TYPE_ALIAS@0..12
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "X"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    TUPLE_TYPE@9..11
+      L_PAREN@9..10 "("
+      R_PAREN@10..11 ")"
+    SEMICOLON@11..12 ";"
+  WHITESPACE@12..14 "\n\n"
+  FN@14..48
+    FN_KW@14..16 "fn"
+    WHITESPACE@16..17 " "
+    NAME@17..21
+      IDENT@17..21 "main"
+    PARAM_LIST@21..23
+      L_PAREN@21..22 "("
+      R_PAREN@22..23 ")"
+    WHITESPACE@23..24 " "
+    BLOCK_EXPR@24..48
+      L_CURLY@24..25 "{"
+      WHITESPACE@25..30 "\n    "
+      LET_STMT@30..46
+        LET_KW@30..33 "let"
+        WHITESPACE@33..34 " "
+        TUPLE_PAT@34..36
+          L_PAREN@34..35 "("
+          R_PAREN@35..36 ")"
+        COLON@36..37 ":"
+        PATH_TYPE@37..40
+          PATH@37..40
+            PATH_SEGMENT@37..40
+              COLON2@37..39 "::"
+              NAME_REF@39..40
+                IDENT@39..40 "X"
+        WHITESPACE@40..41 " "
+        EQ@41..42 "="
+        WHITESPACE@42..43 " "
+        TUPLE_EXPR@43..45
+          L_PAREN@43..44 "("
+          R_PAREN@44..45 ")"
+        SEMICOLON@45..46 ";"
+      WHITESPACE@46..47 "\n"
+      R_CURLY@47..48 "}"
+  WHITESPACE@48..49 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0055_dot_dot_dot.rs b/crates/syntax/test_data/parser/ok/0055_dot_dot_dot.rs
new file mode 100644
index 00000000000..cd204f65ed9
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0055_dot_dot_dot.rs
@@ -0,0 +1,5 @@
+type X = ();
+
+fn main() {
+    let ():::X = ();
+}
diff --git a/crates/syntax/test_data/parser/ok/0056_neq_in_type.rast b/crates/syntax/test_data/parser/ok/0056_neq_in_type.rast
new file mode 100644
index 00000000000..3ef916e5565
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0056_neq_in_type.rast
@@ -0,0 +1,64 @@
+SOURCE_FILE@0..71
+  FN@0..70
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..70
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      IF_EXPR@16..68
+        IF_KW@16..18 "if"
+        WHITESPACE@18..19 " "
+        CONDITION@19..65
+          BIN_EXPR@19..65
+            CAST_EXPR@19..40
+              METHOD_CALL_EXPR@19..33
+                LITERAL@19..25
+                  FLOAT_NUMBER@19..25 "1.0f32"
+                DOT@25..26 "."
+                NAME_REF@26..31
+                  IDENT@26..31 "floor"
+                ARG_LIST@31..33
+                  L_PAREN@31..32 "("
+                  R_PAREN@32..33 ")"
+              WHITESPACE@33..34 " "
+              AS_KW@34..36 "as"
+              WHITESPACE@36..37 " "
+              PATH_TYPE@37..40
+                PATH@37..40
+                  PATH_SEGMENT@37..40
+                    NAME_REF@37..40
+                      IDENT@37..40 "i64"
+            WHITESPACE@40..41 " "
+            NEQ@41..43 "!="
+            WHITESPACE@43..44 " "
+            CAST_EXPR@44..65
+              METHOD_CALL_EXPR@44..58
+                LITERAL@44..50
+                  FLOAT_NUMBER@44..50 "1.0f32"
+                DOT@50..51 "."
+                NAME_REF@51..56
+                  IDENT@51..56 "floor"
+                ARG_LIST@56..58
+                  L_PAREN@56..57 "("
+                  R_PAREN@57..58 ")"
+              WHITESPACE@58..59 " "
+              AS_KW@59..61 "as"
+              WHITESPACE@61..62 " "
+              PATH_TYPE@62..65
+                PATH@62..65
+                  PATH_SEGMENT@62..65
+                    NAME_REF@62..65
+                      IDENT@62..65 "i64"
+        WHITESPACE@65..66 " "
+        BLOCK_EXPR@66..68
+          L_CURLY@66..67 "{"
+          R_CURLY@67..68 "}"
+      WHITESPACE@68..69 "\n"
+      R_CURLY@69..70 "}"
+  WHITESPACE@70..71 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0056_neq_in_type.rs b/crates/syntax/test_data/parser/ok/0056_neq_in_type.rs
new file mode 100644
index 00000000000..6210683cea3
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0056_neq_in_type.rs
@@ -0,0 +1,3 @@
+fn main() {
+    if 1.0f32.floor() as i64 != 1.0f32.floor() as i64 {}
+}
diff --git a/crates/syntax/test_data/parser/ok/0057_loop_in_call.rast b/crates/syntax/test_data/parser/ok/0057_loop_in_call.rast
new file mode 100644
index 00000000000..76301004a5d
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0057_loop_in_call.rast
@@ -0,0 +1,56 @@
+SOURCE_FILE@0..50
+  FN@0..17
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..14
+      L_PAREN@6..7 "("
+      PARAM@7..13
+        IDENT_PAT@7..8
+          NAME@7..8
+            IDENT@7..8 "x"
+        COLON@8..9 ":"
+        WHITESPACE@9..10 " "
+        PATH_TYPE@10..13
+          PATH@10..13
+            PATH_SEGMENT@10..13
+              NAME_REF@10..13
+                IDENT@10..13 "i32"
+      R_PAREN@13..14 ")"
+    WHITESPACE@14..15 " "
+    BLOCK_EXPR@15..17
+      L_CURLY@15..16 "{"
+      R_CURLY@16..17 "}"
+  WHITESPACE@17..19 "\n\n"
+  FN@19..50
+    FN_KW@19..21 "fn"
+    WHITESPACE@21..22 " "
+    NAME@22..26
+      IDENT@22..26 "main"
+    PARAM_LIST@26..28
+      L_PAREN@26..27 "("
+      R_PAREN@27..28 ")"
+    WHITESPACE@28..29 " "
+    BLOCK_EXPR@29..50
+      L_CURLY@29..30 "{"
+      WHITESPACE@30..35 "\n    "
+      EXPR_STMT@35..48
+        CALL_EXPR@35..47
+          PATH_EXPR@35..38
+            PATH@35..38
+              PATH_SEGMENT@35..38
+                NAME_REF@35..38
+                  IDENT@35..38 "foo"
+          ARG_LIST@38..47
+            L_PAREN@38..39 "("
+            LOOP_EXPR@39..46
+              LOOP_KW@39..43 "loop"
+              WHITESPACE@43..44 " "
+              BLOCK_EXPR@44..46
+                L_CURLY@44..45 "{"
+                R_CURLY@45..46 "}"
+            R_PAREN@46..47 ")"
+        SEMICOLON@47..48 ";"
+      WHITESPACE@48..49 "\n"
+      R_CURLY@49..50 "}"
diff --git a/crates/syntax/test_data/parser/ok/0057_loop_in_call.rs b/crates/syntax/test_data/parser/ok/0057_loop_in_call.rs
new file mode 100644
index 00000000000..31c12522ffc
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0057_loop_in_call.rs
@@ -0,0 +1,5 @@
+fn foo(x: i32) {}
+
+fn main() {
+    foo(loop {});
+}
\ No newline at end of file
diff --git a/crates/syntax/test_data/parser/ok/0058_unary_expr_precedence.rast b/crates/syntax/test_data/parser/ok/0058_unary_expr_precedence.rast
new file mode 100644
index 00000000000..a1dfd58f26b
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0058_unary_expr_precedence.rast
@@ -0,0 +1,96 @@
+SOURCE_FILE@0..79
+  FN@0..78
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..6
+      IDENT@3..6 "foo"
+    PARAM_LIST@6..8
+      L_PAREN@6..7 "("
+      R_PAREN@7..8 ")"
+    WHITESPACE@8..9 " "
+    BLOCK_EXPR@9..78
+      L_CURLY@9..10 "{"
+      WHITESPACE@10..15 "\n    "
+      EXPR_STMT@15..27
+        BIN_EXPR@15..26
+          BIN_EXPR@15..22
+            LITERAL@15..16
+              INT_NUMBER@15..16 "1"
+            WHITESPACE@16..17 " "
+            PLUS@17..18 "+"
+            WHITESPACE@18..19 " "
+            PREFIX_EXPR@19..22
+              STAR@19..20 "*"
+              REF_EXPR@20..22
+                AMP@20..21 "&"
+                LITERAL@21..22
+                  INT_NUMBER@21..22 "2"
+          WHITESPACE@22..23 " "
+          PLUS@23..24 "+"
+          WHITESPACE@24..25 " "
+          LITERAL@25..26
+            INT_NUMBER@25..26 "3"
+        SEMICOLON@26..27 ";"
+      WHITESPACE@27..32 "\n    "
+      EXPR_STMT@32..43
+        CAST_EXPR@32..42
+          PREFIX_EXPR@32..35
+            STAR@32..33 "*"
+            REF_EXPR@33..35
+              AMP@33..34 "&"
+              LITERAL@34..35
+                INT_NUMBER@34..35 "1"
+          WHITESPACE@35..36 " "
+          AS_KW@36..38 "as"
+          WHITESPACE@38..39 " "
+          PATH_TYPE@39..42
+            PATH@39..42
+              PATH_SEGMENT@39..42
+                NAME_REF@39..42
+                  IDENT@39..42 "u64"
+        SEMICOLON@42..43 ";"
+      WHITESPACE@43..48 "\n    "
+      EXPR_STMT@48..54
+        PREFIX_EXPR@48..53
+          STAR@48..49 "*"
+          CALL_EXPR@49..53
+            PATH_EXPR@49..50
+              PATH@49..50
+                PATH_SEGMENT@49..50
+                  NAME_REF@49..50
+                    IDENT@49..50 "x"
+            ARG_LIST@50..53
+              L_PAREN@50..51 "("
+              LITERAL@51..52
+                INT_NUMBER@51..52 "1"
+              R_PAREN@52..53 ")"
+        SEMICOLON@53..54 ";"
+      WHITESPACE@54..59 "\n    "
+      EXPR_STMT@59..65
+        REF_EXPR@59..64
+          AMP@59..60 "&"
+          INDEX_EXPR@60..64
+            PATH_EXPR@60..61
+              PATH@60..61
+                PATH_SEGMENT@60..61
+                  NAME_REF@60..61
+                    IDENT@60..61 "x"
+            L_BRACK@61..62 "["
+            LITERAL@62..63
+              INT_NUMBER@62..63 "1"
+            R_BRACK@63..64 "]"
+        SEMICOLON@64..65 ";"
+      WHITESPACE@65..70 "\n    "
+      EXPR_STMT@70..76
+        RANGE_EXPR@70..75
+          PREFIX_EXPR@70..72
+            MINUS@70..71 "-"
+            LITERAL@71..72
+              INT_NUMBER@71..72 "1"
+          DOT2@72..74 ".."
+          LITERAL@74..75
+            INT_NUMBER@74..75 "2"
+        SEMICOLON@75..76 ";"
+      WHITESPACE@76..77 "\n"
+      R_CURLY@77..78 "}"
+  WHITESPACE@78..79 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0058_unary_expr_precedence.rs b/crates/syntax/test_data/parser/ok/0058_unary_expr_precedence.rs
new file mode 100644
index 00000000000..100fccc641c
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0058_unary_expr_precedence.rs
@@ -0,0 +1,7 @@
+fn foo() {
+    1 + *&2 + 3;
+    *&1 as u64;
+    *x(1);
+    &x[1];
+    -1..2;
+}
diff --git a/crates/syntax/test_data/parser/ok/0059_loops_in_parens.rast b/crates/syntax/test_data/parser/ok/0059_loops_in_parens.rast
new file mode 100644
index 00000000000..213f7b3815a
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0059_loops_in_parens.rast
@@ -0,0 +1,97 @@
+SOURCE_FILE@0..105
+  FN@0..104
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..104
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      EXPR_STMT@16..50
+        CALL_EXPR@16..49
+          PATH_EXPR@16..20
+            PATH@16..20
+              PATH_SEGMENT@16..20
+                NAME_REF@16..20
+                  IDENT@16..20 "Some"
+          ARG_LIST@20..49
+            L_PAREN@20..21 "("
+            FOR_EXPR@21..48
+              FOR_KW@21..24 "for"
+              WHITESPACE@24..25 " "
+              WILDCARD_PAT@25..26
+                UNDERSCORE@25..26 "_"
+              WHITESPACE@26..27 " "
+              IN_KW@27..29 "in"
+              WHITESPACE@29..30 " "
+              METHOD_CALL_EXPR@30..45
+                ARRAY_EXPR@30..33
+                  L_BRACK@30..31 "["
+                  LITERAL@31..32
+                    INT_NUMBER@31..32 "1"
+                  R_BRACK@32..33 "]"
+                DOT@33..34 "."
+                NAME_REF@34..43
+                  IDENT@34..43 "into_iter"
+                ARG_LIST@43..45
+                  L_PAREN@43..44 "("
+                  R_PAREN@44..45 ")"
+              WHITESPACE@45..46 " "
+              BLOCK_EXPR@46..48
+                L_CURLY@46..47 "{"
+                R_CURLY@47..48 "}"
+            R_PAREN@48..49 ")"
+        SEMICOLON@49..50 ";"
+      WHITESPACE@50..55 "\n    "
+      EXPR_STMT@55..77
+        CALL_EXPR@55..76
+          PATH_EXPR@55..59
+            PATH@55..59
+              PATH_SEGMENT@55..59
+                NAME_REF@55..59
+                  IDENT@55..59 "Some"
+          ARG_LIST@59..76
+            L_PAREN@59..60 "("
+            LOOP_EXPR@60..75
+              LOOP_KW@60..64 "loop"
+              WHITESPACE@64..65 " "
+              BLOCK_EXPR@65..75
+                L_CURLY@65..66 "{"
+                WHITESPACE@66..67 " "
+                EXPR_STMT@67..73
+                  BREAK_EXPR@67..72
+                    BREAK_KW@67..72 "break"
+                  SEMICOLON@72..73 ";"
+                WHITESPACE@73..74 " "
+                R_CURLY@74..75 "}"
+            R_PAREN@75..76 ")"
+        SEMICOLON@76..77 ";"
+      WHITESPACE@77..82 "\n    "
+      EXPR_STMT@82..102
+        CALL_EXPR@82..101
+          PATH_EXPR@82..86
+            PATH@82..86
+              PATH_SEGMENT@82..86
+                NAME_REF@82..86
+                  IDENT@82..86 "Some"
+          ARG_LIST@86..101
+            L_PAREN@86..87 "("
+            WHILE_EXPR@87..100
+              WHILE_KW@87..92 "while"
+              WHITESPACE@92..93 " "
+              CONDITION@93..97
+                LITERAL@93..97
+                  TRUE_KW@93..97 "true"
+              WHITESPACE@97..98 " "
+              BLOCK_EXPR@98..100
+                L_CURLY@98..99 "{"
+                R_CURLY@99..100 "}"
+            R_PAREN@100..101 ")"
+        SEMICOLON@101..102 ";"
+      WHITESPACE@102..103 "\n"
+      R_CURLY@103..104 "}"
+  WHITESPACE@104..105 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0059_loops_in_parens.rs b/crates/syntax/test_data/parser/ok/0059_loops_in_parens.rs
new file mode 100644
index 00000000000..6e8b718aaf9
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0059_loops_in_parens.rs
@@ -0,0 +1,5 @@
+fn main() {
+    Some(for _ in [1].into_iter() {});
+    Some(loop { break; });
+    Some(while true {});
+}
diff --git a/crates/syntax/test_data/parser/ok/0060_as_range.rast b/crates/syntax/test_data/parser/ok/0060_as_range.rast
new file mode 100644
index 00000000000..1fd1a288845
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0060_as_range.rast
@@ -0,0 +1,55 @@
+SOURCE_FILE@0..56
+  FN@0..55
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..55
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      EXPR_STMT@16..30
+        RANGE_EXPR@16..29
+          CAST_EXPR@16..26
+            LITERAL@16..17
+              INT_NUMBER@16..17 "0"
+            WHITESPACE@17..18 " "
+            AS_KW@18..20 "as"
+            WHITESPACE@20..21 " "
+            PATH_TYPE@21..26
+              PATH@21..26
+                PATH_SEGMENT@21..26
+                  NAME_REF@21..26
+                    IDENT@21..26 "usize"
+          WHITESPACE@26..27 " "
+          DOT2@27..29 ".."
+        SEMICOLON@29..30 ";"
+      WHITESPACE@30..35 "\n    "
+      EXPR_STMT@35..53
+        RANGE_EXPR@35..52
+          BIN_EXPR@35..49
+            LITERAL@35..36
+              INT_NUMBER@35..36 "1"
+            WHITESPACE@36..37 " "
+            PLUS@37..38 "+"
+            WHITESPACE@38..39 " "
+            CAST_EXPR@39..49
+              LITERAL@39..40
+                INT_NUMBER@39..40 "2"
+              WHITESPACE@40..41 " "
+              AS_KW@41..43 "as"
+              WHITESPACE@43..44 " "
+              PATH_TYPE@44..49
+                PATH@44..49
+                  PATH_SEGMENT@44..49
+                    NAME_REF@44..49
+                      IDENT@44..49 "usize"
+          WHITESPACE@49..50 " "
+          DOT2@50..52 ".."
+        SEMICOLON@52..53 ";"
+      WHITESPACE@53..54 "\n"
+      R_CURLY@54..55 "}"
+  WHITESPACE@55..56 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0060_as_range.rs b/crates/syntax/test_data/parser/ok/0060_as_range.rs
new file mode 100644
index 00000000000..f063ffadb3d
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0060_as_range.rs
@@ -0,0 +1,4 @@
+fn main() {
+    0 as usize ..;
+    1 + 2 as usize ..;
+}
diff --git a/crates/syntax/test_data/parser/ok/0061_match_full_range.rast b/crates/syntax/test_data/parser/ok/0061_match_full_range.rast
new file mode 100644
index 00000000000..ba49c115b5a
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0061_match_full_range.rast
@@ -0,0 +1,26 @@
+SOURCE_FILE@0..35
+  FN@0..34
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..7
+      IDENT@3..7 "main"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    BLOCK_EXPR@10..34
+      L_CURLY@10..11 "{"
+      WHITESPACE@11..16 "\n    "
+      MATCH_EXPR@16..32
+        MATCH_KW@16..21 "match"
+        WHITESPACE@21..22 " "
+        RANGE_EXPR@22..24
+          DOT2@22..24 ".."
+        WHITESPACE@24..25 " "
+        MATCH_ARM_LIST@25..32
+          L_CURLY@25..26 "{"
+          WHITESPACE@26..31 "\n    "
+          R_CURLY@31..32 "}"
+      WHITESPACE@32..33 "\n"
+      R_CURLY@33..34 "}"
+  WHITESPACE@34..35 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0061_match_full_range.rs b/crates/syntax/test_data/parser/ok/0061_match_full_range.rs
new file mode 100644
index 00000000000..2c4ed11e1e5
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0061_match_full_range.rs
@@ -0,0 +1,4 @@
+fn main() {
+    match .. {
+    }
+}
diff --git a/crates/syntax/test_data/parser/ok/0062_macro_2.0.rast b/crates/syntax/test_data/parser/ok/0062_macro_2.0.rast
new file mode 100644
index 00000000000..0c22c31a4f6
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0062_macro_2.0.rast
@@ -0,0 +1,175 @@
+SOURCE_FILE@0..349
+  MACRO_DEF@0..93
+    MACRO_KW@0..5 "macro"
+    WHITESPACE@5..6 " "
+    NAME@6..21
+      IDENT@6..21 "parse_use_trees"
+    TOKEN_TREE@21..93
+      TOKEN_TREE@21..41
+        L_PAREN@21..22 "("
+        DOLLAR@22..23 "$"
+        TOKEN_TREE@23..32
+          L_PAREN@23..24 "("
+          DOLLAR@24..25 "$"
+          IDENT@25..26 "s"
+          COLON@26..27 ":"
+          IDENT@27..31 "expr"
+          R_PAREN@31..32 ")"
+        COMMA@32..33 ","
+        STAR@33..34 "*"
+        WHITESPACE@34..35 " "
+        DOLLAR@35..36 "$"
+        TOKEN_TREE@36..39
+          L_PAREN@36..37 "("
+          COMMA@37..38 ","
+          R_PAREN@38..39 ")"
+        STAR@39..40 "*"
+        R_PAREN@40..41 ")"
+      WHITESPACE@41..42 " "
+      TOKEN_TREE@42..93
+        L_CURLY@42..43 "{"
+        WHITESPACE@43..48 "\n    "
+        IDENT@48..51 "vec"
+        BANG@51..52 "!"
+        TOKEN_TREE@52..91
+          L_BRACK@52..53 "["
+          WHITESPACE@53..62 "\n        "
+          DOLLAR@62..63 "$"
+          TOKEN_TREE@63..84
+            L_PAREN@63..64 "("
+            IDENT@64..78 "parse_use_tree"
+            TOKEN_TREE@78..82
+              L_PAREN@78..79 "("
+              DOLLAR@79..80 "$"
+              IDENT@80..81 "s"
+              R_PAREN@81..82 ")"
+            COMMA@82..83 ","
+            R_PAREN@83..84 ")"
+          STAR@84..85 "*"
+          WHITESPACE@85..90 "\n    "
+          R_BRACK@90..91 "]"
+        WHITESPACE@91..92 "\n"
+        R_CURLY@92..93 "}"
+  WHITESPACE@93..95 "\n\n"
+  FN@95..348
+    ATTR@95..102
+      POUND@95..96 "#"
+      L_BRACK@96..97 "["
+      PATH@97..101
+        PATH_SEGMENT@97..101
+          NAME_REF@97..101
+            IDENT@97..101 "test"
+      R_BRACK@101..102 "]"
+    WHITESPACE@102..103 "\n"
+    FN_KW@103..105 "fn"
+    WHITESPACE@105..106 " "
+    NAME@106..125
+      IDENT@106..125 "test_use_tree_merge"
+    PARAM_LIST@125..127
+      L_PAREN@125..126 "("
+      R_PAREN@126..127 ")"
+    WHITESPACE@127..128 " "
+    BLOCK_EXPR@128..348
+      L_CURLY@128..129 "{"
+      WHITESPACE@129..134 "\n    "
+      MACRO_DEF@134..346
+        MACRO_KW@134..139 "macro"
+        WHITESPACE@139..140 " "
+        NAME@140..150
+          IDENT@140..150 "test_merge"
+        TOKEN_TREE@150..346
+          TOKEN_TREE@150..203
+            L_PAREN@150..151 "("
+            TOKEN_TREE@151..175
+              L_BRACK@151..152 "["
+              DOLLAR@152..153 "$"
+              TOKEN_TREE@153..166
+                L_PAREN@153..154 "("
+                DOLLAR@154..155 "$"
+                IDENT@155..160 "input"
+                COLON@160..161 ":"
+                IDENT@161..165 "expr"
+                R_PAREN@165..166 ")"
+              COMMA@166..167 ","
+              STAR@167..168 "*"
+              WHITESPACE@168..169 " "
+              DOLLAR@169..170 "$"
+              TOKEN_TREE@170..173
+                L_PAREN@170..171 "("
+                COMMA@171..172 ","
+                R_PAREN@172..173 ")"
+              STAR@173..174 "*"
+              R_BRACK@174..175 "]"
+            COMMA@175..176 ","
+            WHITESPACE@176..177 " "
+            TOKEN_TREE@177..202
+              L_BRACK@177..178 "["
+              DOLLAR@178..179 "$"
+              TOKEN_TREE@179..193
+                L_PAREN@179..180 "("
+                DOLLAR@180..181 "$"
+                IDENT@181..187 "output"
+                COLON@187..188 ":"
+                IDENT@188..192 "expr"
+                R_PAREN@192..193 ")"
+              COMMA@193..194 ","
+              STAR@194..195 "*"
+              WHITESPACE@195..196 " "
+              DOLLAR@196..197 "$"
+              TOKEN_TREE@197..200
+                L_PAREN@197..198 "("
+                COMMA@198..199 ","
+                R_PAREN@199..200 ")"
+              STAR@200..201 "*"
+              R_BRACK@201..202 "]"
+            R_PAREN@202..203 ")"
+          WHITESPACE@203..204 " "
+          TOKEN_TREE@204..346
+            L_CURLY@204..205 "{"
+            WHITESPACE@205..214 "\n        "
+            IDENT@214..223 "assert_eq"
+            BANG@223..224 "!"
+            TOKEN_TREE@224..339
+              L_PAREN@224..225 "("
+              WHITESPACE@225..238 "\n            "
+              IDENT@238..253 "merge_use_trees"
+              TOKEN_TREE@253..284
+                L_PAREN@253..254 "("
+                IDENT@254..269 "parse_use_trees"
+                BANG@269..270 "!"
+                TOKEN_TREE@270..283
+                  L_PAREN@270..271 "("
+                  DOLLAR@271..272 "$"
+                  TOKEN_TREE@272..281
+                    L_PAREN@272..273 "("
+                    DOLLAR@273..274 "$"
+                    IDENT@274..279 "input"
+                    COMMA@279..280 ","
+                    R_PAREN@280..281 ")"
+                  STAR@281..282 "*"
+                  R_PAREN@282..283 ")"
+                R_PAREN@283..284 ")"
+              COMMA@284..285 ","
+              WHITESPACE@285..298 "\n            "
+              IDENT@298..313 "parse_use_trees"
+              BANG@313..314 "!"
+              TOKEN_TREE@314..328
+                L_PAREN@314..315 "("
+                DOLLAR@315..316 "$"
+                TOKEN_TREE@316..326
+                  L_PAREN@316..317 "("
+                  DOLLAR@317..318 "$"
+                  IDENT@318..324 "output"
+                  COMMA@324..325 ","
+                  R_PAREN@325..326 ")"
+                STAR@326..327 "*"
+                R_PAREN@327..328 ")"
+              COMMA@328..329 ","
+              WHITESPACE@329..338 "\n        "
+              R_PAREN@338..339 ")"
+            SEMICOLON@339..340 ";"
+            WHITESPACE@340..345 "\n    "
+            R_CURLY@345..346 "}"
+      WHITESPACE@346..347 "\n"
+      R_CURLY@347..348 "}"
+  WHITESPACE@348..349 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0062_macro_2.0.rs b/crates/syntax/test_data/parser/ok/0062_macro_2.0.rs
new file mode 100644
index 00000000000..781047ba19a
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0062_macro_2.0.rs
@@ -0,0 +1,15 @@
+macro parse_use_trees($($s:expr),* $(,)*) {
+    vec![
+        $(parse_use_tree($s),)*
+    ]
+}
+
+#[test]
+fn test_use_tree_merge() {
+    macro test_merge([$($input:expr),* $(,)*], [$($output:expr),* $(,)*]) {
+        assert_eq!(
+            merge_use_trees(parse_use_trees!($($input,)*)),
+            parse_use_trees!($($output,)*),
+        );
+    }
+}
diff --git a/crates/syntax/test_data/parser/ok/0063_trait_fn_patterns.rast b/crates/syntax/test_data/parser/ok/0063_trait_fn_patterns.rast
new file mode 100644
index 00000000000..8eda5997627
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0063_trait_fn_patterns.rast
@@ -0,0 +1,194 @@
+SOURCE_FILE@0..170
+  TRAIT@0..169
+    TRAIT_KW@0..5 "trait"
+    WHITESPACE@5..6 " "
+    NAME@6..7
+      IDENT@6..7 "T"
+    WHITESPACE@7..8 " "
+    ASSOC_ITEM_LIST@8..169
+      L_CURLY@8..9 "{"
+      WHITESPACE@9..14 "\n    "
+      FN@14..46
+        FN_KW@14..16 "fn"
+        WHITESPACE@16..17 " "
+        NAME@17..19
+          IDENT@17..19 "f1"
+        PARAM_LIST@19..43
+          L_PAREN@19..20 "("
+          PARAM@20..42
+            TUPLE_PAT@20..26
+              L_PAREN@20..21 "("
+              IDENT_PAT@21..22
+                NAME@21..22
+                  IDENT@21..22 "a"
+              COMMA@22..23 ","
+              WHITESPACE@23..24 " "
+              IDENT_PAT@24..25
+                NAME@24..25
+                  IDENT@24..25 "b"
+              R_PAREN@25..26 ")"
+            COLON@26..27 ":"
+            WHITESPACE@27..28 " "
+            TUPLE_TYPE@28..42
+              L_PAREN@28..29 "("
+              PATH_TYPE@29..34
+                PATH@29..34
+                  PATH_SEGMENT@29..34
+                    NAME_REF@29..34
+                      IDENT@29..34 "usize"
+              COMMA@34..35 ","
+              WHITESPACE@35..36 " "
+              PATH_TYPE@36..41
+                PATH@36..41
+                  PATH_SEGMENT@36..41
+                    NAME_REF@36..41
+                      IDENT@36..41 "usize"
+              R_PAREN@41..42 ")"
+          R_PAREN@42..43 ")"
+        WHITESPACE@43..44 " "
+        BLOCK_EXPR@44..46
+          L_CURLY@44..45 "{"
+          R_CURLY@45..46 "}"
+      WHITESPACE@46..51 "\n    "
+      FN@51..74
+        FN_KW@51..53 "fn"
+        WHITESPACE@53..54 " "
+        NAME@54..56
+          IDENT@54..56 "f2"
+        PARAM_LIST@56..71
+          L_PAREN@56..57 "("
+          PARAM@57..70
+            RECORD_PAT@57..67
+              PATH@57..58
+                PATH_SEGMENT@57..58
+                  NAME_REF@57..58
+                    IDENT@57..58 "S"
+              WHITESPACE@58..59 " "
+              RECORD_PAT_FIELD_LIST@59..67
+                L_CURLY@59..60 "{"
+                WHITESPACE@60..61 " "
+                RECORD_PAT_FIELD@61..62
+                  IDENT_PAT@61..62
+                    NAME@61..62
+                      IDENT@61..62 "a"
+                COMMA@62..63 ","
+                WHITESPACE@63..64 " "
+                RECORD_PAT_FIELD@64..65
+                  IDENT_PAT@64..65
+                    NAME@64..65
+                      IDENT@64..65 "b"
+                WHITESPACE@65..66 " "
+                R_CURLY@66..67 "}"
+            COLON@67..68 ":"
+            WHITESPACE@68..69 " "
+            PATH_TYPE@69..70
+              PATH@69..70
+                PATH_SEGMENT@69..70
+                  NAME_REF@69..70
+                    IDENT@69..70 "S"
+          R_PAREN@70..71 ")"
+        WHITESPACE@71..72 " "
+        BLOCK_EXPR@72..74
+          L_CURLY@72..73 "{"
+          R_CURLY@73..74 "}"
+      WHITESPACE@74..79 "\n    "
+      FN@79..108
+        FN_KW@79..81 "fn"
+        WHITESPACE@81..82 " "
+        NAME@82..84
+          IDENT@82..84 "f3"
+        PARAM_LIST@84..105
+          L_PAREN@84..85 "("
+          PARAM@85..104
+            TUPLE_STRUCT_PAT@85..95
+              PATH@85..92
+                PATH_SEGMENT@85..92
+                  NAME_REF@85..92
+                    IDENT@85..92 "NewType"
+              L_PAREN@92..93 "("
+              IDENT_PAT@93..94
+                NAME@93..94
+                  IDENT@93..94 "a"
+              R_PAREN@94..95 ")"
+            COLON@95..96 ":"
+            WHITESPACE@96..97 " "
+            PATH_TYPE@97..104
+              PATH@97..104
+                PATH_SEGMENT@97..104
+                  NAME_REF@97..104
+                    IDENT@97..104 "NewType"
+          R_PAREN@104..105 ")"
+        WHITESPACE@105..106 " "
+        BLOCK_EXPR@106..108
+          L_CURLY@106..107 "{"
+          R_CURLY@107..108 "}"
+      WHITESPACE@108..113 "\n    "
+      FN@113..135
+        FN_KW@113..115 "fn"
+        WHITESPACE@115..116 " "
+        NAME@116..118
+          IDENT@116..118 "f4"
+        PARAM_LIST@118..132
+          L_PAREN@118..119 "("
+          PARAM@119..131
+            REF_PAT@119..122
+              AMP@119..120 "&"
+              REF_PAT@120..122
+                AMP@120..121 "&"
+                IDENT_PAT@121..122
+                  NAME@121..122
+                    IDENT@121..122 "a"
+            COLON@122..123 ":"
+            WHITESPACE@123..124 " "
+            REF_TYPE@124..131
+              AMP@124..125 "&"
+              REF_TYPE@125..131
+                AMP@125..126 "&"
+                PATH_TYPE@126..131
+                  PATH@126..131
+                    PATH_SEGMENT@126..131
+                      NAME_REF@126..131
+                        IDENT@126..131 "usize"
+          R_PAREN@131..132 ")"
+        WHITESPACE@132..133 " "
+        BLOCK_EXPR@133..135
+          L_CURLY@133..134 "{"
+          R_CURLY@134..135 "}"
+      WHITESPACE@135..140 "\n    "
+      FN@140..167
+        FN_KW@140..142 "fn"
+        WHITESPACE@142..143 " "
+        NAME@143..146
+          IDENT@143..146 "bar"
+        PARAM_LIST@146..166
+          L_PAREN@146..147 "("
+          PARAM@147..153
+            WILDCARD_PAT@147..148
+              UNDERSCORE@147..148 "_"
+            COLON@148..149 ":"
+            WHITESPACE@149..150 " "
+            PATH_TYPE@150..153
+              PATH@150..153
+                PATH_SEGMENT@150..153
+                  NAME_REF@150..153
+                    IDENT@150..153 "u64"
+          COMMA@153..154 ","
+          WHITESPACE@154..155 " "
+          PARAM@155..165
+            IDENT_PAT@155..160
+              MUT_KW@155..158 "mut"
+              WHITESPACE@158..159 " "
+              NAME@159..160
+                IDENT@159..160 "x"
+            COLON@160..161 ":"
+            WHITESPACE@161..162 " "
+            PATH_TYPE@162..165
+              PATH@162..165
+                PATH_SEGMENT@162..165
+                  NAME_REF@162..165
+                    IDENT@162..165 "i32"
+          R_PAREN@165..166 ")"
+        SEMICOLON@166..167 ";"
+      WHITESPACE@167..168 "\n"
+      R_CURLY@168..169 "}"
+  WHITESPACE@169..170 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0063_trait_fn_patterns.rs b/crates/syntax/test_data/parser/ok/0063_trait_fn_patterns.rs
new file mode 100644
index 00000000000..3b666af8eed
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0063_trait_fn_patterns.rs
@@ -0,0 +1,7 @@
+trait T {
+    fn f1((a, b): (usize, usize)) {}
+    fn f2(S { a, b }: S) {}
+    fn f3(NewType(a): NewType) {}
+    fn f4(&&a: &&usize) {}
+    fn bar(_: u64, mut x: i32);
+}
diff --git a/crates/syntax/test_data/parser/ok/0063_variadic_fun.rast b/crates/syntax/test_data/parser/ok/0063_variadic_fun.rast
new file mode 100644
index 00000000000..4009b3ff8d2
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0063_variadic_fun.rast
@@ -0,0 +1,133 @@
+SOURCE_FILE@0..126
+  EXTERN_BLOCK@0..125
+    ABI@0..10
+      EXTERN_KW@0..6 "extern"
+      WHITESPACE@6..7 " "
+      STRING@7..10 "\"C\""
+    WHITESPACE@10..11 " "
+    EXTERN_ITEM_LIST@11..125
+      L_CURLY@11..12 "{"
+      WHITESPACE@12..17 "\n    "
+      FN@17..40
+        FN_KW@17..19 "fn"
+        WHITESPACE@19..20 " "
+        NAME@20..21
+          IDENT@20..21 "a"
+        PARAM_LIST@21..39
+          L_PAREN@21..22 "("
+          PARAM@22..32
+            WILDCARD_PAT@22..23
+              UNDERSCORE@22..23 "_"
+            COLON@23..24 ":"
+            WHITESPACE@24..25 " "
+            PTR_TYPE@25..32
+              STAR@25..26 "*"
+              MUT_KW@26..29 "mut"
+              WHITESPACE@29..30 " "
+              PATH_TYPE@30..32
+                PATH@30..32
+                  PATH_SEGMENT@30..32
+                    NAME_REF@30..32
+                      IDENT@30..32 "u8"
+          COMMA@32..33 ","
+          WHITESPACE@33..34 " "
+          PARAM@34..37
+            DOT3@34..37 "..."
+          COMMA@37..38 ","
+          R_PAREN@38..39 ")"
+        SEMICOLON@39..40 ";"
+      WHITESPACE@40..45 "\n    "
+      FN@45..70
+        FN_KW@45..47 "fn"
+        WHITESPACE@47..48 " "
+        NAME@48..49
+          IDENT@48..49 "b"
+        PARAM_LIST@49..69
+          L_PAREN@49..50 "("
+          PARAM@50..60
+            WILDCARD_PAT@50..51
+              UNDERSCORE@50..51 "_"
+            COLON@51..52 ":"
+            WHITESPACE@52..53 " "
+            PTR_TYPE@53..60
+              STAR@53..54 "*"
+              MUT_KW@54..57 "mut"
+              WHITESPACE@57..58 " "
+              PATH_TYPE@58..60
+                PATH@58..60
+                  PATH_SEGMENT@58..60
+                    NAME_REF@58..60
+                      IDENT@58..60 "u8"
+          COMMA@60..61 ","
+          WHITESPACE@61..62 " "
+          PARAM@62..68
+            WILDCARD_PAT@62..63
+              UNDERSCORE@62..63 "_"
+            COLON@63..64 ":"
+            WHITESPACE@64..65 " "
+            DOT3@65..68 "..."
+          R_PAREN@68..69 ")"
+        SEMICOLON@69..70 ";"
+      WHITESPACE@70..75 "\n    "
+      FN@75..123
+        FN_KW@75..77 "fn"
+        WHITESPACE@77..78 " "
+        NAME@78..79
+          IDENT@78..79 "c"
+        PARAM_LIST@79..122
+          L_PAREN@79..80 "("
+          PARAM@80..90
+            WILDCARD_PAT@80..81
+              UNDERSCORE@80..81 "_"
+            COLON@81..82 ":"
+            WHITESPACE@82..83 " "
+            PTR_TYPE@83..90
+              STAR@83..84 "*"
+              MUT_KW@84..87 "mut"
+              WHITESPACE@87..88 " "
+              PATH_TYPE@88..90
+                PATH@88..90
+                  PATH_SEGMENT@88..90
+                    NAME_REF@88..90
+                      IDENT@88..90 "u8"
+          COMMA@90..91 ","
+          WHITESPACE@91..92 " "
+          ATTR@92..105
+            POUND@92..93 "#"
+            L_BRACK@93..94 "["
+            PATH@94..97
+              PATH_SEGMENT@94..97
+                NAME_REF@94..97
+                  IDENT@94..97 "cfg"
+            TOKEN_TREE@97..104
+              L_PAREN@97..98 "("
+              IDENT@98..103 "never"
+              R_PAREN@103..104 ")"
+            R_BRACK@104..105 "]"
+          WHITESPACE@105..106 " "
+          PARAM@106..120
+            SLICE_PAT@106..115
+              L_BRACK@106..107 "["
+              IDENT_PAT@107..108
+                NAME@107..108
+                  IDENT@107..108 "w"
+              COMMA@108..109 ","
+              WHITESPACE@109..110 " "
+              IDENT_PAT@110..111
+                NAME@110..111
+                  IDENT@110..111 "t"
+              COMMA@111..112 ","
+              WHITESPACE@112..113 " "
+              IDENT_PAT@113..114
+                NAME@113..114
+                  IDENT@113..114 "f"
+              R_BRACK@114..115 "]"
+            COLON@115..116 ":"
+            WHITESPACE@116..117 " "
+            DOT3@117..120 "..."
+          COMMA@120..121 ","
+          R_PAREN@121..122 ")"
+        SEMICOLON@122..123 ";"
+      WHITESPACE@123..124 "\n"
+      R_CURLY@124..125 "}"
+  WHITESPACE@125..126 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0063_variadic_fun.rs b/crates/syntax/test_data/parser/ok/0063_variadic_fun.rs
new file mode 100644
index 00000000000..a16afbaf386
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0063_variadic_fun.rs
@@ -0,0 +1,5 @@
+extern "C" {
+    fn a(_: *mut u8, ...,);
+    fn b(_: *mut u8, _: ...);
+    fn c(_: *mut u8, #[cfg(never)] [w, t, f]: ...,);
+}
diff --git a/crates/syntax/test_data/parser/ok/0064_impl_fn_params.rast b/crates/syntax/test_data/parser/ok/0064_impl_fn_params.rast
new file mode 100644
index 00000000000..a3c6ed82e15
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0064_impl_fn_params.rast
@@ -0,0 +1,162 @@
+SOURCE_FILE@0..137
+  IMPL@0..136
+    IMPL_KW@0..4 "impl"
+    WHITESPACE@4..5 " "
+    PATH_TYPE@5..6
+      PATH@5..6
+        PATH_SEGMENT@5..6
+          NAME_REF@5..6
+            IDENT@5..6 "U"
+    WHITESPACE@6..7 " "
+    ASSOC_ITEM_LIST@7..136
+      L_CURLY@7..8 "{"
+      WHITESPACE@8..13 "\n    "
+      FN@13..45
+        FN_KW@13..15 "fn"
+        WHITESPACE@15..16 " "
+        NAME@16..18
+          IDENT@16..18 "f1"
+        PARAM_LIST@18..42
+          L_PAREN@18..19 "("
+          PARAM@19..41
+            TUPLE_PAT@19..25
+              L_PAREN@19..20 "("
+              IDENT_PAT@20..21
+                NAME@20..21
+                  IDENT@20..21 "a"
+              COMMA@21..22 ","
+              WHITESPACE@22..23 " "
+              IDENT_PAT@23..24
+                NAME@23..24
+                  IDENT@23..24 "b"
+              R_PAREN@24..25 ")"
+            COLON@25..26 ":"
+            WHITESPACE@26..27 " "
+            TUPLE_TYPE@27..41
+              L_PAREN@27..28 "("
+              PATH_TYPE@28..33
+                PATH@28..33
+                  PATH_SEGMENT@28..33
+                    NAME_REF@28..33
+                      IDENT@28..33 "usize"
+              COMMA@33..34 ","
+              WHITESPACE@34..35 " "
+              PATH_TYPE@35..40
+                PATH@35..40
+                  PATH_SEGMENT@35..40
+                    NAME_REF@35..40
+                      IDENT@35..40 "usize"
+              R_PAREN@40..41 ")"
+          R_PAREN@41..42 ")"
+        WHITESPACE@42..43 " "
+        BLOCK_EXPR@43..45
+          L_CURLY@43..44 "{"
+          R_CURLY@44..45 "}"
+      WHITESPACE@45..50 "\n    "
+      FN@50..73
+        FN_KW@50..52 "fn"
+        WHITESPACE@52..53 " "
+        NAME@53..55
+          IDENT@53..55 "f2"
+        PARAM_LIST@55..70
+          L_PAREN@55..56 "("
+          PARAM@56..69
+            RECORD_PAT@56..66
+              PATH@56..57
+                PATH_SEGMENT@56..57
+                  NAME_REF@56..57
+                    IDENT@56..57 "S"
+              WHITESPACE@57..58 " "
+              RECORD_PAT_FIELD_LIST@58..66
+                L_CURLY@58..59 "{"
+                WHITESPACE@59..60 " "
+                RECORD_PAT_FIELD@60..61
+                  IDENT_PAT@60..61
+                    NAME@60..61
+                      IDENT@60..61 "a"
+                COMMA@61..62 ","
+                WHITESPACE@62..63 " "
+                RECORD_PAT_FIELD@63..64
+                  IDENT_PAT@63..64
+                    NAME@63..64
+                      IDENT@63..64 "b"
+                WHITESPACE@64..65 " "
+                R_CURLY@65..66 "}"
+            COLON@66..67 ":"
+            WHITESPACE@67..68 " "
+            PATH_TYPE@68..69
+              PATH@68..69
+                PATH_SEGMENT@68..69
+                  NAME_REF@68..69
+                    IDENT@68..69 "S"
+          R_PAREN@69..70 ")"
+        WHITESPACE@70..71 " "
+        BLOCK_EXPR@71..73
+          L_CURLY@71..72 "{"
+          R_CURLY@72..73 "}"
+      WHITESPACE@73..78 "\n    "
+      FN@78..107
+        FN_KW@78..80 "fn"
+        WHITESPACE@80..81 " "
+        NAME@81..83
+          IDENT@81..83 "f3"
+        PARAM_LIST@83..104
+          L_PAREN@83..84 "("
+          PARAM@84..103
+            TUPLE_STRUCT_PAT@84..94
+              PATH@84..91
+                PATH_SEGMENT@84..91
+                  NAME_REF@84..91
+                    IDENT@84..91 "NewType"
+              L_PAREN@91..92 "("
+              IDENT_PAT@92..93
+                NAME@92..93
+                  IDENT@92..93 "a"
+              R_PAREN@93..94 ")"
+            COLON@94..95 ":"
+            WHITESPACE@95..96 " "
+            PATH_TYPE@96..103
+              PATH@96..103
+                PATH_SEGMENT@96..103
+                  NAME_REF@96..103
+                    IDENT@96..103 "NewType"
+          R_PAREN@103..104 ")"
+        WHITESPACE@104..105 " "
+        BLOCK_EXPR@105..107
+          L_CURLY@105..106 "{"
+          R_CURLY@106..107 "}"
+      WHITESPACE@107..112 "\n    "
+      FN@112..134
+        FN_KW@112..114 "fn"
+        WHITESPACE@114..115 " "
+        NAME@115..117
+          IDENT@115..117 "f4"
+        PARAM_LIST@117..131
+          L_PAREN@117..118 "("
+          PARAM@118..130
+            REF_PAT@118..121
+              AMP@118..119 "&"
+              REF_PAT@119..121
+                AMP@119..120 "&"
+                IDENT_PAT@120..121
+                  NAME@120..121
+                    IDENT@120..121 "a"
+            COLON@121..122 ":"
+            WHITESPACE@122..123 " "
+            REF_TYPE@123..130
+              AMP@123..124 "&"
+              REF_TYPE@124..130
+                AMP@124..125 "&"
+                PATH_TYPE@125..130
+                  PATH@125..130
+                    PATH_SEGMENT@125..130
+                      NAME_REF@125..130
+                        IDENT@125..130 "usize"
+          R_PAREN@130..131 ")"
+        WHITESPACE@131..132 " "
+        BLOCK_EXPR@132..134
+          L_CURLY@132..133 "{"
+          R_CURLY@133..134 "}"
+      WHITESPACE@134..135 "\n"
+      R_CURLY@135..136 "}"
+  WHITESPACE@136..137 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0064_impl_fn_params.rs b/crates/syntax/test_data/parser/ok/0064_impl_fn_params.rs
new file mode 100644
index 00000000000..b49e872d79d
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0064_impl_fn_params.rs
@@ -0,0 +1,6 @@
+impl U {
+    fn f1((a, b): (usize, usize)) {}
+    fn f2(S { a, b }: S) {}
+    fn f3(NewType(a): NewType) {}
+    fn f4(&&a: &&usize) {}
+}
diff --git a/crates/syntax/test_data/parser/ok/0065_comment_newline.rast b/crates/syntax/test_data/parser/ok/0065_comment_newline.rast
new file mode 100644
index 00000000000..29bd38c051f
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0065_comment_newline.rast
@@ -0,0 +1,16 @@
+SOURCE_FILE@0..26
+  FN@0..25
+    COMMENT@0..11 "/// Example"
+    WHITESPACE@11..13 "\n\n"
+    FN_KW@13..15 "fn"
+    WHITESPACE@15..16 " "
+    NAME@16..20
+      IDENT@16..20 "test"
+    PARAM_LIST@20..22
+      L_PAREN@20..21 "("
+      R_PAREN@21..22 ")"
+    WHITESPACE@22..23 " "
+    BLOCK_EXPR@23..25
+      L_CURLY@23..24 "{"
+      R_CURLY@24..25 "}"
+  WHITESPACE@25..26 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0065_comment_newline.rs b/crates/syntax/test_data/parser/ok/0065_comment_newline.rs
new file mode 100644
index 00000000000..1fafe216b6e
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0065_comment_newline.rs
@@ -0,0 +1,3 @@
+/// Example
+
+fn test() {}
diff --git a/crates/syntax/test_data/parser/ok/0065_plus_after_fn_trait_bound.rast b/crates/syntax/test_data/parser/ok/0065_plus_after_fn_trait_bound.rast
new file mode 100644
index 00000000000..2c699ffcb6f
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0065_plus_after_fn_trait_bound.rast
@@ -0,0 +1,60 @@
+SOURCE_FILE@0..40
+  FN@0..39
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..4
+      IDENT@3..4 "f"
+    GENERIC_PARAM_LIST@4..7
+      L_ANGLE@4..5 "<"
+      TYPE_PARAM@5..6
+        NAME@5..6
+          IDENT@5..6 "T"
+      R_ANGLE@6..7 ">"
+    PARAM_LIST@7..9
+      L_PAREN@7..8 "("
+      R_PAREN@8..9 ")"
+    WHITESPACE@9..10 " "
+    WHERE_CLAUSE@10..36
+      WHERE_KW@10..15 "where"
+      WHITESPACE@15..16 " "
+      WHERE_PRED@16..36
+        PATH_TYPE@16..17
+          PATH@16..17
+            PATH_SEGMENT@16..17
+              NAME_REF@16..17
+                IDENT@16..17 "T"
+        COLON@17..18 ":"
+        WHITESPACE@18..19 " "
+        TYPE_BOUND_LIST@19..36
+          TYPE_BOUND@19..29
+            PATH_TYPE@19..29
+              PATH@19..29
+                PATH_SEGMENT@19..29
+                  NAME_REF@19..21
+                    IDENT@19..21 "Fn"
+                  PARAM_LIST@21..23
+                    L_PAREN@21..22 "("
+                    R_PAREN@22..23 ")"
+                  WHITESPACE@23..24 " "
+                  RET_TYPE@24..29
+                    THIN_ARROW@24..26 "->"
+                    WHITESPACE@26..27 " "
+                    PATH_TYPE@27..29
+                      PATH@27..29
+                        PATH_SEGMENT@27..29
+                          NAME_REF@27..29
+                            IDENT@27..29 "u8"
+          WHITESPACE@29..30 " "
+          PLUS@30..31 "+"
+          WHITESPACE@31..32 " "
+          TYPE_BOUND@32..36
+            PATH_TYPE@32..36
+              PATH@32..36
+                PATH_SEGMENT@32..36
+                  NAME_REF@32..36
+                    IDENT@32..36 "Send"
+    WHITESPACE@36..37 " "
+    BLOCK_EXPR@37..39
+      L_CURLY@37..38 "{"
+      R_CURLY@38..39 "}"
+  WHITESPACE@39..40 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0065_plus_after_fn_trait_bound.rs b/crates/syntax/test_data/parser/ok/0065_plus_after_fn_trait_bound.rs
new file mode 100644
index 00000000000..29f3655e013
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0065_plus_after_fn_trait_bound.rs
@@ -0,0 +1 @@
+fn f<T>() where T: Fn() -> u8 + Send {}
diff --git a/crates/syntax/test_data/parser/ok/0066_default_modifier.rast b/crates/syntax/test_data/parser/ok/0066_default_modifier.rast
new file mode 100644
index 00000000000..e9b57ec3b3f
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0066_default_modifier.rast
@@ -0,0 +1,218 @@
+SOURCE_FILE@0..294
+  TRAIT@0..113
+    TRAIT_KW@0..5 "trait"
+    WHITESPACE@5..6 " "
+    NAME@6..7
+      IDENT@6..7 "T"
+    WHITESPACE@7..8 " "
+    ASSOC_ITEM_LIST@8..113
+      L_CURLY@8..9 "{"
+      WHITESPACE@9..12 "\n  "
+      TYPE_ALIAS@12..33
+        DEFAULT_KW@12..19 "default"
+        WHITESPACE@19..20 " "
+        TYPE_KW@20..24 "type"
+        WHITESPACE@24..25 " "
+        NAME@25..26
+          IDENT@25..26 "T"
+        WHITESPACE@26..27 " "
+        EQ@27..28 "="
+        WHITESPACE@28..29 " "
+        PATH_TYPE@29..32
+          PATH@29..32
+            PATH_SEGMENT@29..32
+              NAME_REF@29..32
+                IDENT@29..32 "Bar"
+        SEMICOLON@32..33 ";"
+      WHITESPACE@33..36 "\n  "
+      CONST@36..60
+        DEFAULT_KW@36..43 "default"
+        WHITESPACE@43..44 " "
+        CONST_KW@44..49 "const"
+        WHITESPACE@49..50 " "
+        NAME@50..51
+          IDENT@50..51 "f"
+        COLON@51..52 ":"
+        WHITESPACE@52..53 " "
+        PATH_TYPE@53..55
+          PATH@53..55
+            PATH_SEGMENT@53..55
+              NAME_REF@53..55
+                IDENT@53..55 "u8"
+        WHITESPACE@55..56 " "
+        EQ@56..57 "="
+        WHITESPACE@57..58 " "
+        LITERAL@58..59
+          INT_NUMBER@58..59 "0"
+        SEMICOLON@59..60 ";"
+      WHITESPACE@60..63 "\n  "
+      FN@63..82
+        DEFAULT_KW@63..70 "default"
+        WHITESPACE@70..71 " "
+        FN_KW@71..73 "fn"
+        WHITESPACE@73..74 " "
+        NAME@74..77
+          IDENT@74..77 "foo"
+        PARAM_LIST@77..79
+          L_PAREN@77..78 "("
+          R_PAREN@78..79 ")"
+        WHITESPACE@79..80 " "
+        BLOCK_EXPR@80..82
+          L_CURLY@80..81 "{"
+          R_CURLY@81..82 "}"
+      WHITESPACE@82..85 "\n  "
+      FN@85..111
+        DEFAULT_KW@85..92 "default"
+        WHITESPACE@92..93 " "
+        UNSAFE_KW@93..99 "unsafe"
+        WHITESPACE@99..100 " "
+        FN_KW@100..102 "fn"
+        WHITESPACE@102..103 " "
+        NAME@103..106
+          IDENT@103..106 "bar"
+        PARAM_LIST@106..108
+          L_PAREN@106..107 "("
+          R_PAREN@107..108 ")"
+        WHITESPACE@108..109 " "
+        BLOCK_EXPR@109..111
+          L_CURLY@109..110 "{"
+          R_CURLY@110..111 "}"
+      WHITESPACE@111..112 "\n"
+      R_CURLY@112..113 "}"
+  WHITESPACE@113..115 "\n\n"
+  IMPL@115..235
+    IMPL_KW@115..119 "impl"
+    WHITESPACE@119..120 " "
+    PATH_TYPE@120..121
+      PATH@120..121
+        PATH_SEGMENT@120..121
+          NAME_REF@120..121
+            IDENT@120..121 "T"
+    WHITESPACE@121..122 " "
+    FOR_KW@122..125 "for"
+    WHITESPACE@125..126 " "
+    PATH_TYPE@126..129
+      PATH@126..129
+        PATH_SEGMENT@126..129
+          NAME_REF@126..129
+            IDENT@126..129 "Foo"
+    WHITESPACE@129..130 " "
+    ASSOC_ITEM_LIST@130..235
+      L_CURLY@130..131 "{"
+      WHITESPACE@131..134 "\n  "
+      TYPE_ALIAS@134..155
+        DEFAULT_KW@134..141 "default"
+        WHITESPACE@141..142 " "
+        TYPE_KW@142..146 "type"
+        WHITESPACE@146..147 " "
+        NAME@147..148
+          IDENT@147..148 "T"
+        WHITESPACE@148..149 " "
+        EQ@149..150 "="
+        WHITESPACE@150..151 " "
+        PATH_TYPE@151..154
+          PATH@151..154
+            PATH_SEGMENT@151..154
+              NAME_REF@151..154
+                IDENT@151..154 "Bar"
+        SEMICOLON@154..155 ";"
+      WHITESPACE@155..158 "\n  "
+      CONST@158..182
+        DEFAULT_KW@158..165 "default"
+        WHITESPACE@165..166 " "
+        CONST_KW@166..171 "const"
+        WHITESPACE@171..172 " "
+        NAME@172..173
+          IDENT@172..173 "f"
+        COLON@173..174 ":"
+        WHITESPACE@174..175 " "
+        PATH_TYPE@175..177
+          PATH@175..177
+            PATH_SEGMENT@175..177
+              NAME_REF@175..177
+                IDENT@175..177 "u8"
+        WHITESPACE@177..178 " "
+        EQ@178..179 "="
+        WHITESPACE@179..180 " "
+        LITERAL@180..181
+          INT_NUMBER@180..181 "0"
+        SEMICOLON@181..182 ";"
+      WHITESPACE@182..185 "\n  "
+      FN@185..204
+        DEFAULT_KW@185..192 "default"
+        WHITESPACE@192..193 " "
+        FN_KW@193..195 "fn"
+        WHITESPACE@195..196 " "
+        NAME@196..199
+          IDENT@196..199 "foo"
+        PARAM_LIST@199..201
+          L_PAREN@199..200 "("
+          R_PAREN@200..201 ")"
+        WHITESPACE@201..202 " "
+        BLOCK_EXPR@202..204
+          L_CURLY@202..203 "{"
+          R_CURLY@203..204 "}"
+      WHITESPACE@204..207 "\n  "
+      FN@207..233
+        DEFAULT_KW@207..214 "default"
+        WHITESPACE@214..215 " "
+        UNSAFE_KW@215..221 "unsafe"
+        WHITESPACE@221..222 " "
+        FN_KW@222..224 "fn"
+        WHITESPACE@224..225 " "
+        NAME@225..228
+          IDENT@225..228 "bar"
+        PARAM_LIST@228..230
+          L_PAREN@228..229 "("
+          R_PAREN@229..230 ")"
+        WHITESPACE@230..231 " "
+        BLOCK_EXPR@231..233
+          L_CURLY@231..232 "{"
+          R_CURLY@232..233 "}"
+      WHITESPACE@233..234 "\n"
+      R_CURLY@234..235 "}"
+  WHITESPACE@235..237 "\n\n"
+  IMPL@237..261
+    DEFAULT_KW@237..244 "default"
+    WHITESPACE@244..245 " "
+    IMPL_KW@245..249 "impl"
+    WHITESPACE@249..250 " "
+    PATH_TYPE@250..251
+      PATH@250..251
+        PATH_SEGMENT@250..251
+          NAME_REF@250..251
+            IDENT@250..251 "T"
+    WHITESPACE@251..252 " "
+    FOR_KW@252..255 "for"
+    WHITESPACE@255..256 " "
+    TUPLE_TYPE@256..258
+      L_PAREN@256..257 "("
+      R_PAREN@257..258 ")"
+    WHITESPACE@258..259 " "
+    ASSOC_ITEM_LIST@259..261
+      L_CURLY@259..260 "{"
+      R_CURLY@260..261 "}"
+  WHITESPACE@261..262 "\n"
+  IMPL@262..293
+    DEFAULT_KW@262..269 "default"
+    WHITESPACE@269..270 " "
+    UNSAFE_KW@270..276 "unsafe"
+    WHITESPACE@276..277 " "
+    IMPL_KW@277..281 "impl"
+    WHITESPACE@281..282 " "
+    PATH_TYPE@282..283
+      PATH@282..283
+        PATH_SEGMENT@282..283
+          NAME_REF@282..283
+            IDENT@282..283 "T"
+    WHITESPACE@283..284 " "
+    FOR_KW@284..287 "for"
+    WHITESPACE@287..288 " "
+    TUPLE_TYPE@288..290
+      L_PAREN@288..289 "("
+      R_PAREN@289..290 ")"
+    WHITESPACE@290..291 " "
+    ASSOC_ITEM_LIST@291..293
+      L_CURLY@291..292 "{"
+      R_CURLY@292..293 "}"
+  WHITESPACE@293..294 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0066_default_modifier.rs b/crates/syntax/test_data/parser/ok/0066_default_modifier.rs
new file mode 100644
index 00000000000..e443e3495e3
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0066_default_modifier.rs
@@ -0,0 +1,16 @@
+trait T {
+  default type T = Bar;
+  default const f: u8 = 0;
+  default fn foo() {}
+  default unsafe fn bar() {}
+}
+
+impl T for Foo {
+  default type T = Bar;
+  default const f: u8 = 0;
+  default fn foo() {}
+  default unsafe fn bar() {}
+}
+
+default impl T for () {}
+default unsafe impl T for () {}
diff --git a/crates/syntax/test_data/parser/ok/0067_where_for_pred.rast b/crates/syntax/test_data/parser/ok/0067_where_for_pred.rast
new file mode 100644
index 00000000000..8f8639a375b
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0067_where_for_pred.rast
@@ -0,0 +1,392 @@
+SOURCE_FILE@0..374
+  FN@0..55
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..12
+      IDENT@3..12 "for_trait"
+    GENERIC_PARAM_LIST@12..15
+      L_ANGLE@12..13 "<"
+      TYPE_PARAM@13..14
+        NAME@13..14
+          IDENT@13..14 "F"
+      R_ANGLE@14..15 ">"
+    PARAM_LIST@15..17
+      L_PAREN@15..16 "("
+      R_PAREN@16..17 ")"
+    WHITESPACE@17..18 "\n"
+    WHERE_CLAUSE@18..51
+      WHERE_KW@18..23 "where"
+      WHITESPACE@23..28 "\n    "
+      WHERE_PRED@28..50
+        FOR_KW@28..31 "for"
+        GENERIC_PARAM_LIST@31..35
+          L_ANGLE@31..32 "<"
+          LIFETIME_PARAM@32..34
+            LIFETIME@32..34 "\'a"
+          R_ANGLE@34..35 ">"
+        WHITESPACE@35..36 " "
+        PATH_TYPE@36..37
+          PATH@36..37
+            PATH_SEGMENT@36..37
+              NAME_REF@36..37
+                IDENT@36..37 "F"
+        COLON@37..38 ":"
+        WHITESPACE@38..39 " "
+        TYPE_BOUND_LIST@39..50
+          TYPE_BOUND@39..50
+            PATH_TYPE@39..50
+              PATH@39..50
+                PATH_SEGMENT@39..50
+                  NAME_REF@39..41
+                    IDENT@39..41 "Fn"
+                  PARAM_LIST@41..50
+                    L_PAREN@41..42 "("
+                    PARAM@42..49
+                      REF_TYPE@42..49
+                        AMP@42..43 "&"
+                        LIFETIME@43..45 "\'a"
+                        WHITESPACE@45..46 " "
+                        PATH_TYPE@46..49
+                          PATH@46..49
+                            PATH_SEGMENT@46..49
+                              NAME_REF@46..49
+                                IDENT@46..49 "str"
+                    R_PAREN@49..50 ")"
+      COMMA@50..51 ","
+    WHITESPACE@51..52 "\n"
+    BLOCK_EXPR@52..55
+      L_CURLY@52..53 "{"
+      WHITESPACE@53..54 "\n"
+      R_CURLY@54..55 "}"
+  WHITESPACE@55..56 "\n"
+  FN@56..107
+    FN_KW@56..58 "fn"
+    WHITESPACE@58..59 " "
+    NAME@59..66
+      IDENT@59..66 "for_ref"
+    GENERIC_PARAM_LIST@66..69
+      L_ANGLE@66..67 "<"
+      TYPE_PARAM@67..68
+        NAME@67..68
+          IDENT@67..68 "F"
+      R_ANGLE@68..69 ">"
+    PARAM_LIST@69..71
+      L_PAREN@69..70 "("
+      R_PAREN@70..71 ")"
+    WHITESPACE@71..72 "\n"
+    WHERE_CLAUSE@72..103
+      WHERE_KW@72..77 "where"
+      WHITESPACE@77..82 "\n    "
+      WHERE_PRED@82..102
+        FOR_KW@82..85 "for"
+        GENERIC_PARAM_LIST@85..89
+          L_ANGLE@85..86 "<"
+          LIFETIME_PARAM@86..88
+            LIFETIME@86..88 "\'a"
+          R_ANGLE@88..89 ">"
+        WHITESPACE@89..90 " "
+        REF_TYPE@90..95
+          AMP@90..91 "&"
+          LIFETIME@91..93 "\'a"
+          WHITESPACE@93..94 " "
+          PATH_TYPE@94..95
+            PATH@94..95
+              PATH_SEGMENT@94..95
+                NAME_REF@94..95
+                  IDENT@94..95 "F"
+        COLON@95..96 ":"
+        WHITESPACE@96..97 " "
+        TYPE_BOUND_LIST@97..102
+          TYPE_BOUND@97..102
+            PATH_TYPE@97..102
+              PATH@97..102
+                PATH_SEGMENT@97..102
+                  NAME_REF@97..102
+                    IDENT@97..102 "Debug"
+      COMMA@102..103 ","
+    WHITESPACE@103..104 "\n"
+    BLOCK_EXPR@104..107
+      L_CURLY@104..105 "{"
+      WHITESPACE@105..106 "\n"
+      R_CURLY@106..107 "}"
+  WHITESPACE@107..108 "\n"
+  FN@108..170
+    FN_KW@108..110 "fn"
+    WHITESPACE@110..111 " "
+    NAME@111..121
+      IDENT@111..121 "for_parens"
+    GENERIC_PARAM_LIST@121..124
+      L_ANGLE@121..122 "<"
+      TYPE_PARAM@122..123
+        NAME@122..123
+          IDENT@122..123 "F"
+      R_ANGLE@123..124 ">"
+    PARAM_LIST@124..126
+      L_PAREN@124..125 "("
+      R_PAREN@125..126 ")"
+    WHITESPACE@126..127 "\n"
+    WHERE_CLAUSE@127..166
+      WHERE_KW@127..132 "where"
+      WHITESPACE@132..137 "\n    "
+      WHERE_PRED@137..165
+        FOR_KW@137..140 "for"
+        GENERIC_PARAM_LIST@140..144
+          L_ANGLE@140..141 "<"
+          LIFETIME_PARAM@141..143
+            LIFETIME@141..143 "\'a"
+          R_ANGLE@143..144 ">"
+        WHITESPACE@144..145 " "
+        PAREN_TYPE@145..152
+          L_PAREN@145..146 "("
+          REF_TYPE@146..151
+            AMP@146..147 "&"
+            LIFETIME@147..149 "\'a"
+            WHITESPACE@149..150 " "
+            PATH_TYPE@150..151
+              PATH@150..151
+                PATH_SEGMENT@150..151
+                  NAME_REF@150..151
+                    IDENT@150..151 "F"
+          R_PAREN@151..152 ")"
+        COLON@152..153 ":"
+        WHITESPACE@153..154 " "
+        TYPE_BOUND_LIST@154..165
+          TYPE_BOUND@154..165
+            PATH_TYPE@154..165
+              PATH@154..165
+                PATH_SEGMENT@154..165
+                  NAME_REF@154..156
+                    IDENT@154..156 "Fn"
+                  PARAM_LIST@156..165
+                    L_PAREN@156..157 "("
+                    PARAM@157..164
+                      REF_TYPE@157..164
+                        AMP@157..158 "&"
+                        LIFETIME@158..160 "\'a"
+                        WHITESPACE@160..161 " "
+                        PATH_TYPE@161..164
+                          PATH@161..164
+                            PATH_SEGMENT@161..164
+                              NAME_REF@161..164
+                                IDENT@161..164 "str"
+                    R_PAREN@164..165 ")"
+      COMMA@165..166 ","
+    WHITESPACE@166..167 "\n"
+    BLOCK_EXPR@167..170
+      L_CURLY@167..168 "{"
+      WHITESPACE@168..169 "\n"
+      R_CURLY@169..170 "}"
+  WHITESPACE@170..171 "\n"
+  FN@171..223
+    FN_KW@171..173 "fn"
+    WHITESPACE@173..174 " "
+    NAME@174..183
+      IDENT@174..183 "for_slice"
+    GENERIC_PARAM_LIST@183..186
+      L_ANGLE@183..184 "<"
+      TYPE_PARAM@184..185
+        NAME@184..185
+          IDENT@184..185 "F"
+      R_ANGLE@185..186 ">"
+    PARAM_LIST@186..188
+      L_PAREN@186..187 "("
+      R_PAREN@187..188 ")"
+    WHITESPACE@188..189 "\n"
+    WHERE_CLAUSE@189..219
+      WHERE_KW@189..194 "where"
+      WHITESPACE@194..199 "\n    "
+      WHERE_PRED@199..218
+        FOR_KW@199..202 "for"
+        GENERIC_PARAM_LIST@202..206
+          L_ANGLE@202..203 "<"
+          LIFETIME_PARAM@203..205
+            LIFETIME@203..205 "\'a"
+          R_ANGLE@205..206 ">"
+        WHITESPACE@206..207 " "
+        SLICE_TYPE@207..214
+          L_BRACK@207..208 "["
+          REF_TYPE@208..213
+            AMP@208..209 "&"
+            LIFETIME@209..211 "\'a"
+            WHITESPACE@211..212 " "
+            PATH_TYPE@212..213
+              PATH@212..213
+                PATH_SEGMENT@212..213
+                  NAME_REF@212..213
+                    IDENT@212..213 "F"
+          R_BRACK@213..214 "]"
+        COLON@214..215 ":"
+        WHITESPACE@215..216 " "
+        TYPE_BOUND_LIST@216..218
+          TYPE_BOUND@216..218
+            PATH_TYPE@216..218
+              PATH@216..218
+                PATH_SEGMENT@216..218
+                  NAME_REF@216..218
+                    IDENT@216..218 "Eq"
+      COMMA@218..219 ","
+    WHITESPACE@219..220 "\n"
+    BLOCK_EXPR@220..223
+      L_CURLY@220..221 "{"
+      WHITESPACE@221..222 "\n"
+      R_CURLY@222..223 "}"
+  WHITESPACE@223..224 "\n"
+  FN@224..300
+    FN_KW@224..226 "fn"
+    WHITESPACE@226..227 " "
+    NAME@227..236
+      IDENT@227..236 "for_qpath"
+    GENERIC_PARAM_LIST@236..239
+      L_ANGLE@236..237 "<"
+      TYPE_PARAM@237..238
+        NAME@237..238
+          IDENT@237..238 "T"
+      R_ANGLE@238..239 ">"
+    PARAM_LIST@239..247
+      L_PAREN@239..240 "("
+      PARAM@240..246
+        IDENT_PAT@240..242
+          NAME@240..242
+            IDENT@240..242 "_t"
+        COLON@242..243 ":"
+        WHITESPACE@243..244 " "
+        REF_TYPE@244..246
+          AMP@244..245 "&"
+          PATH_TYPE@245..246
+            PATH@245..246
+              PATH_SEGMENT@245..246
+                NAME_REF@245..246
+                  IDENT@245..246 "T"
+      R_PAREN@246..247 ")"
+    WHITESPACE@247..248 "\n"
+    WHERE_CLAUSE@248..296
+      WHERE_KW@248..253 "where"
+      WHITESPACE@253..258 "\n    "
+      WHERE_PRED@258..295
+        FOR_KW@258..261 "for"
+        GENERIC_PARAM_LIST@261..265
+          L_ANGLE@261..262 "<"
+          LIFETIME_PARAM@262..264
+            LIFETIME@262..264 "\'a"
+          R_ANGLE@264..265 ">"
+        WHITESPACE@265..266 " "
+        PATH_TYPE@266..285
+          PATH@266..285
+            PATH@266..280
+              PATH_SEGMENT@266..280
+                L_ANGLE@266..267 "<"
+                REF_TYPE@267..272
+                  AMP@267..268 "&"
+                  LIFETIME@268..270 "\'a"
+                  WHITESPACE@270..271 " "
+                  PATH_TYPE@271..272
+                    PATH@271..272
+                      PATH_SEGMENT@271..272
+                        NAME_REF@271..272
+                          IDENT@271..272 "T"
+                WHITESPACE@272..273 " "
+                AS_KW@273..275 "as"
+                WHITESPACE@275..276 " "
+                PATH_TYPE@276..279
+                  PATH@276..279
+                    PATH_SEGMENT@276..279
+                      NAME_REF@276..279
+                        IDENT@276..279 "Baz"
+                R_ANGLE@279..280 ">"
+            COLON2@280..282 "::"
+            PATH_SEGMENT@282..285
+              NAME_REF@282..285
+                IDENT@282..285 "Foo"
+        COLON@285..286 ":"
+        WHITESPACE@286..287 " "
+        TYPE_BOUND_LIST@287..295
+          TYPE_BOUND@287..295
+            PATH_TYPE@287..295
+              PATH@287..295
+                PATH_SEGMENT@287..295
+                  NAME_REF@287..295
+                    IDENT@287..295 "Iterator"
+      COMMA@295..296 ","
+    WHITESPACE@296..297 "\n"
+    BLOCK_EXPR@297..300
+      L_CURLY@297..298 "{"
+      WHITESPACE@298..299 "\n"
+      R_CURLY@299..300 "}"
+  WHITESPACE@300..301 "\n"
+  FN@301..373
+    FN_KW@301..303 "fn"
+    WHITESPACE@303..304 " "
+    NAME@304..314
+      IDENT@304..314 "for_for_fn"
+    GENERIC_PARAM_LIST@314..317
+      L_ANGLE@314..315 "<"
+      TYPE_PARAM@315..316
+        NAME@315..316
+          IDENT@315..316 "T"
+      R_ANGLE@316..317 ">"
+    PARAM_LIST@317..319
+      L_PAREN@317..318 "("
+      R_PAREN@318..319 ")"
+    WHITESPACE@319..320 "\n"
+    WHERE_CLAUSE@320..369
+      WHERE_KW@320..325 "where"
+      WHITESPACE@325..330 "\n    "
+      WHERE_PRED@330..368
+        FOR_KW@330..333 "for"
+        GENERIC_PARAM_LIST@333..337
+          L_ANGLE@333..334 "<"
+          LIFETIME_PARAM@334..336
+            LIFETIME@334..336 "\'a"
+          R_ANGLE@336..337 ">"
+        WHITESPACE@337..338 " "
+        FOR_TYPE@338..362
+          FOR_KW@338..341 "for"
+          GENERIC_PARAM_LIST@341..345
+            L_ANGLE@341..342 "<"
+            LIFETIME_PARAM@342..344
+              LIFETIME@342..344 "\'b"
+            R_ANGLE@344..345 ">"
+          WHITESPACE@345..346 " "
+          FN_PTR_TYPE@346..362
+            FN_KW@346..348 "fn"
+            PARAM_LIST@348..362
+              L_PAREN@348..349 "("
+              PARAM@349..354
+                REF_TYPE@349..354
+                  AMP@349..350 "&"
+                  LIFETIME@350..352 "\'a"
+                  WHITESPACE@352..353 " "
+                  PATH_TYPE@353..354
+                    PATH@353..354
+                      PATH_SEGMENT@353..354
+                        NAME_REF@353..354
+                          IDENT@353..354 "T"
+              COMMA@354..355 ","
+              WHITESPACE@355..356 " "
+              PARAM@356..361
+                REF_TYPE@356..361
+                  AMP@356..357 "&"
+                  LIFETIME@357..359 "\'b"
+                  WHITESPACE@359..360 " "
+                  PATH_TYPE@360..361
+                    PATH@360..361
+                      PATH_SEGMENT@360..361
+                        NAME_REF@360..361
+                          IDENT@360..361 "T"
+              R_PAREN@361..362 ")"
+        COLON@362..363 ":"
+        WHITESPACE@363..364 " "
+        TYPE_BOUND_LIST@364..368
+          TYPE_BOUND@364..368
+            PATH_TYPE@364..368
+              PATH@364..368
+                PATH_SEGMENT@364..368
+                  NAME_REF@364..368
+                    IDENT@364..368 "Copy"
+      COMMA@368..369 ","
+    WHITESPACE@369..370 "\n"
+    BLOCK_EXPR@370..373
+      L_CURLY@370..371 "{"
+      WHITESPACE@371..372 "\n"
+      R_CURLY@372..373 "}"
+  WHITESPACE@373..374 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0067_where_for_pred.rs b/crates/syntax/test_data/parser/ok/0067_where_for_pred.rs
new file mode 100644
index 00000000000..9058c46190c
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0067_where_for_pred.rs
@@ -0,0 +1,30 @@
+fn for_trait<F>()
+where
+    for<'a> F: Fn(&'a str),
+{
+}
+fn for_ref<F>()
+where
+    for<'a> &'a F: Debug,
+{
+}
+fn for_parens<F>()
+where
+    for<'a> (&'a F): Fn(&'a str),
+{
+}
+fn for_slice<F>()
+where
+    for<'a> [&'a F]: Eq,
+{
+}
+fn for_qpath<T>(_t: &T)
+where
+    for<'a> <&'a T as Baz>::Foo: Iterator,
+{
+}
+fn for_for_fn<T>()
+where
+    for<'a> for<'b> fn(&'a T, &'b T): Copy,
+{
+}
diff --git a/crates/syntax/test_data/parser/ok/0068_item_modifiers.rast b/crates/syntax/test_data/parser/ok/0068_item_modifiers.rast
new file mode 100644
index 00000000000..50a6d8ee9a6
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0068_item_modifiers.rast
@@ -0,0 +1,218 @@
+SOURCE_FILE@0..304
+  FN@0..17
+    ASYNC_KW@0..5 "async"
+    WHITESPACE@5..6 " "
+    FN_KW@6..8 "fn"
+    WHITESPACE@8..9 " "
+    NAME@9..12
+      IDENT@9..12 "foo"
+    PARAM_LIST@12..14
+      L_PAREN@12..13 "("
+      R_PAREN@13..14 ")"
+    WHITESPACE@14..15 " "
+    BLOCK_EXPR@15..17
+      L_CURLY@15..16 "{"
+      R_CURLY@16..17 "}"
+  WHITESPACE@17..18 "\n"
+  FN@18..36
+    ABI@18..24
+      EXTERN_KW@18..24 "extern"
+    WHITESPACE@24..25 " "
+    FN_KW@25..27 "fn"
+    WHITESPACE@27..28 " "
+    NAME@28..31
+      IDENT@28..31 "foo"
+    PARAM_LIST@31..33
+      L_PAREN@31..32 "("
+      R_PAREN@32..33 ")"
+    WHITESPACE@33..34 " "
+    BLOCK_EXPR@34..36
+      L_CURLY@34..35 "{"
+      R_CURLY@35..36 "}"
+  WHITESPACE@36..37 "\n"
+  FN@37..54
+    CONST_KW@37..42 "const"
+    WHITESPACE@42..43 " "
+    FN_KW@43..45 "fn"
+    WHITESPACE@45..46 " "
+    NAME@46..49
+      IDENT@46..49 "foo"
+    PARAM_LIST@49..51
+      L_PAREN@49..50 "("
+      R_PAREN@50..51 ")"
+    WHITESPACE@51..52 " "
+    BLOCK_EXPR@52..54
+      L_CURLY@52..53 "{"
+      R_CURLY@53..54 "}"
+  WHITESPACE@54..55 "\n"
+  FN@55..79
+    CONST_KW@55..60 "const"
+    WHITESPACE@60..61 " "
+    UNSAFE_KW@61..67 "unsafe"
+    WHITESPACE@67..68 " "
+    FN_KW@68..70 "fn"
+    WHITESPACE@70..71 " "
+    NAME@71..74
+      IDENT@71..74 "foo"
+    PARAM_LIST@74..76
+      L_PAREN@74..75 "("
+      R_PAREN@75..76 ")"
+    WHITESPACE@76..77 " "
+    BLOCK_EXPR@77..79
+      L_CURLY@77..78 "{"
+      R_CURLY@78..79 "}"
+  WHITESPACE@79..80 "\n"
+  FN@80..109
+    UNSAFE_KW@80..86 "unsafe"
+    WHITESPACE@86..87 " "
+    ABI@87..97
+      EXTERN_KW@87..93 "extern"
+      WHITESPACE@93..94 " "
+      STRING@94..97 "\"C\""
+    WHITESPACE@97..98 " "
+    FN_KW@98..100 "fn"
+    WHITESPACE@100..101 " "
+    NAME@101..104
+      IDENT@101..104 "foo"
+    PARAM_LIST@104..106
+      L_PAREN@104..105 "("
+      R_PAREN@105..106 ")"
+    WHITESPACE@106..107 " "
+    BLOCK_EXPR@107..109
+      L_CURLY@107..108 "{"
+      R_CURLY@108..109 "}"
+  WHITESPACE@109..110 "\n"
+  FN@110..128
+    UNSAFE_KW@110..116 "unsafe"
+    WHITESPACE@116..117 " "
+    FN_KW@117..119 "fn"
+    WHITESPACE@119..120 " "
+    NAME@120..123
+      IDENT@120..123 "foo"
+    PARAM_LIST@123..125
+      L_PAREN@123..124 "("
+      R_PAREN@124..125 ")"
+    WHITESPACE@125..126 " "
+    BLOCK_EXPR@126..128
+      L_CURLY@126..127 "{"
+      R_CURLY@127..128 "}"
+  WHITESPACE@128..129 "\n"
+  FN@129..153
+    ASYNC_KW@129..134 "async"
+    WHITESPACE@134..135 " "
+    UNSAFE_KW@135..141 "unsafe"
+    WHITESPACE@141..142 " "
+    FN_KW@142..144 "fn"
+    WHITESPACE@144..145 " "
+    NAME@145..148
+      IDENT@145..148 "foo"
+    PARAM_LIST@148..150
+      L_PAREN@148..149 "("
+      R_PAREN@149..150 ")"
+    WHITESPACE@150..151 " "
+    BLOCK_EXPR@151..153
+      L_CURLY@151..152 "{"
+      R_CURLY@152..153 "}"
+  WHITESPACE@153..154 "\n"
+  FN@154..178
+    CONST_KW@154..159 "const"
+    WHITESPACE@159..160 " "
+    UNSAFE_KW@160..166 "unsafe"
+    WHITESPACE@166..167 " "
+    FN_KW@167..169 "fn"
+    WHITESPACE@169..170 " "
+    NAME@170..173
+      IDENT@170..173 "bar"
+    PARAM_LIST@173..175
+      L_PAREN@173..174 "("
+      R_PAREN@174..175 ")"
+    WHITESPACE@175..176 " "
+    BLOCK_EXPR@176..178
+      L_CURLY@176..177 "{"
+      R_CURLY@177..178 "}"
+  WHITESPACE@178..180 "\n\n"
+  TRAIT@180..197
+    UNSAFE_KW@180..186 "unsafe"
+    WHITESPACE@186..187 " "
+    TRAIT_KW@187..192 "trait"
+    WHITESPACE@192..193 " "
+    NAME@193..194
+      IDENT@193..194 "T"
+    WHITESPACE@194..195 " "
+    ASSOC_ITEM_LIST@195..197
+      L_CURLY@195..196 "{"
+      R_CURLY@196..197 "}"
+  WHITESPACE@197..198 "\n"
+  TRAIT@198..213
+    AUTO_KW@198..202 "auto"
+    WHITESPACE@202..203 " "
+    TRAIT_KW@203..208 "trait"
+    WHITESPACE@208..209 " "
+    NAME@209..210
+      IDENT@209..210 "T"
+    WHITESPACE@210..211 " "
+    ASSOC_ITEM_LIST@211..213
+      L_CURLY@211..212 "{"
+      R_CURLY@212..213 "}"
+  WHITESPACE@213..214 "\n"
+  TRAIT@214..236
+    UNSAFE_KW@214..220 "unsafe"
+    WHITESPACE@220..221 " "
+    AUTO_KW@221..225 "auto"
+    WHITESPACE@225..226 " "
+    TRAIT_KW@226..231 "trait"
+    WHITESPACE@231..232 " "
+    NAME@232..233
+      IDENT@232..233 "T"
+    WHITESPACE@233..234 " "
+    ASSOC_ITEM_LIST@234..236
+      L_CURLY@234..235 "{"
+      R_CURLY@235..236 "}"
+  WHITESPACE@236..238 "\n\n"
+  IMPL@238..256
+    UNSAFE_KW@238..244 "unsafe"
+    WHITESPACE@244..245 " "
+    IMPL_KW@245..249 "impl"
+    WHITESPACE@249..250 " "
+    PATH_TYPE@250..253
+      PATH@250..253
+        PATH_SEGMENT@250..253
+          NAME_REF@250..253
+            IDENT@250..253 "Foo"
+    WHITESPACE@253..254 " "
+    ASSOC_ITEM_LIST@254..256
+      L_CURLY@254..255 "{"
+      R_CURLY@255..256 "}"
+  WHITESPACE@256..257 "\n"
+  IMPL@257..276
+    DEFAULT_KW@257..264 "default"
+    WHITESPACE@264..265 " "
+    IMPL_KW@265..269 "impl"
+    WHITESPACE@269..270 " "
+    PATH_TYPE@270..273
+      PATH@270..273
+        PATH_SEGMENT@270..273
+          NAME_REF@270..273
+            IDENT@270..273 "Foo"
+    WHITESPACE@273..274 " "
+    ASSOC_ITEM_LIST@274..276
+      L_CURLY@274..275 "{"
+      R_CURLY@275..276 "}"
+  WHITESPACE@276..277 "\n"
+  IMPL@277..303
+    UNSAFE_KW@277..283 "unsafe"
+    WHITESPACE@283..284 " "
+    DEFAULT_KW@284..291 "default"
+    WHITESPACE@291..292 " "
+    IMPL_KW@292..296 "impl"
+    WHITESPACE@296..297 " "
+    PATH_TYPE@297..300
+      PATH@297..300
+        PATH_SEGMENT@297..300
+          NAME_REF@297..300
+            IDENT@297..300 "Foo"
+    WHITESPACE@300..301 " "
+    ASSOC_ITEM_LIST@301..303
+      L_CURLY@301..302 "{"
+      R_CURLY@302..303 "}"
+  WHITESPACE@303..304 "\n"
diff --git a/crates/syntax/test_data/parser/ok/0068_item_modifiers.rs b/crates/syntax/test_data/parser/ok/0068_item_modifiers.rs
new file mode 100644
index 00000000000..8d697c04b95
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0068_item_modifiers.rs
@@ -0,0 +1,16 @@
+async fn foo() {}
+extern fn foo() {}
+const fn foo() {}
+const unsafe fn foo() {}
+unsafe extern "C" fn foo() {}
+unsafe fn foo() {}
+async unsafe fn foo() {}
+const unsafe fn bar() {}
+
+unsafe trait T {}
+auto trait T {}
+unsafe auto trait T {}
+
+unsafe impl Foo {}
+default impl Foo {}
+unsafe default impl Foo {}
diff --git a/crates/syntax/test_data/reparse/fuzz-failures/0000.rs b/crates/syntax/test_data/reparse/fuzz-failures/0000.rs
new file mode 100644
index 00000000000..388eb74eda1
--- /dev/null
+++ b/crates/syntax/test_data/reparse/fuzz-failures/0000.rs
@@ -0,0 +1,6 @@
+0
+1
+
+
+
+0
\ No newline at end of file
diff --git a/crates/syntax/test_data/reparse/fuzz-failures/0001.rs b/crates/syntax/test_data/reparse/fuzz-failures/0001.rs
new file mode 100644
index 00000000000..d2d42c6f941
--- /dev/null
+++ b/crates/syntax/test_data/reparse/fuzz-failures/0001.rs
@@ -0,0 +1,4 @@
+0
+1
+
+bb"
\ No newline at end of file
diff --git a/crates/syntax/test_data/reparse/fuzz-failures/0002.rs b/crates/syntax/test_data/reparse/fuzz-failures/0002.rs
new file mode 100644
index 00000000000..3fbee154810
--- /dev/null
+++ b/crates/syntax/test_data/reparse/fuzz-failures/0002.rs
@@ -0,0 +1,4 @@
+1
+1
+
+""!
\ No newline at end of file
diff --git a/crates/syntax/test_data/reparse/fuzz-failures/0003.rs b/crates/syntax/test_data/reparse/fuzz-failures/0003.rs
new file mode 100644
index 00000000000..d2757cd08df
--- /dev/null
+++ b/crates/syntax/test_data/reparse/fuzz-failures/0003.rs
Binary files differdiff --git a/crates/syntax/test_data/reparse/fuzz-failures/0004.rs b/crates/syntax/test_data/reparse/fuzz-failures/0004.rs
new file mode 100644
index 00000000000..481617a701d
--- /dev/null
+++ b/crates/syntax/test_data/reparse/fuzz-failures/0004.rs
@@ -0,0 +1,4 @@
+0
+0
+}
+{;
\ No newline at end of file
diff --git a/crates/syntax/test_data/reparse/fuzz-failures/0005.rs b/crates/syntax/test_data/reparse/fuzz-failures/0005.rs
new file mode 100644
index 00000000000..074d761c7b5
--- /dev/null
+++ b/crates/syntax/test_data/reparse/fuzz-failures/0005.rs
@@ -0,0 +1,7 @@
+05
+1
+
+
+
+b'
+		
\ No newline at end of file