Files
carbon-lang/toolchain/parse/testdata/function/declaration.carbon
T
Chandler CarruthandRichard Smith 68569d234d Improve lexer and parser diagnostic locations (#7990)
Lexer diagnostics used a single `const char*` as their source location,
which only allowed pointing at a single character rather than a run of
characters. This limited the underlining of unrecognized tokens, and
also made escape sequence diagnostics particularly strange by stopping
at whatever point the lexer discovered the error and pointing only at
that location. For example: `"\w"` was reported at the `w`, and `"\x"`
at the closing `"`.

This change tries to always keep the primary location of a diagnostic
the point at which typing (inserting or deleting) might fix the error.
So for `"\x"`, `\x` is underlined, but the position is at the `"` as
that's where you would type a hex code.

The lexer's emitter now takes a special lexing source location that
represents either a single position _between_ two characters, a single
character, or a range of the source buffer. The lexer diagnostics are
updated to construct these for the character range as appropriate.

Parser diagnostics for a missing token were located at the _next_ token,
which is particularly confusing for terminators like missing `;`s. Now
they are located at a position after the previous token, with or without
a space depending on the token, but typically on the same line.
Diagnostics still sort by how far the parser has read.

The parser diagnostics for unclosed groups also now attaches a label to
the opening token when it is on a separate line. And the diagnostics for
mismatched indent in a multi-line string attaches a label to the closing
`'''` that establishes that indent.

There are likely more location improvements we should do here, but this
seemed like a reasonable incremental improvement and is what Claude
found when doing an initial audit. One example where I think we should
make further improvements is around suggesting raw identifiers when we
find an unexpected `Cpp` or `Core` or `base`. We do this consistently
now, but raw identifiers should be rare. A TODO is added for these
cases.

Assisted-by: Claude Code

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-11-01 06:22:00 +00:00

634 lines
28 KiB
Plaintext

// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// TIP: To test this file alone, run:
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/parse/testdata/function/declaration.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/function/declaration.carbon
// --- basic.carbon
fn F();
// --- ref.carbon
fn foo(ref a: i32);
// --- implicit_empty.carbon
fn foo[]();
// --- implicit_params.carbon
fn foo[a: i32, b: i32]();
// --- no_params.carbon
fn foo {}
// --- params.carbon
fn foo(a: i32, b: i32);
// --- with_return_type.carbon
fn foo() -> u32;
// --- impl_fn.carbon
override fn F();
abstract override fn G();
override abstract fn H();
private override default fn I();
// --- fail_identifier_instead_of_sig.carbon
// CHECK:STDERR: fail_identifier_instead_of_sig.carbon:[[@LINE+2]]:7: error: `fn` declarations must either end with a `;` or have a `{ ... }` block for a definition [ExpectedDeclSemiOrDefinition]
// CHECK:STDERR:
fn foo bar;
// --- fail_missing_implicit_close.carbon
// CHECK:STDERR: fail_missing_implicit_close.carbon:[[@LINE+3]]:7: error: opening symbol without a corresponding closing symbol [UnmatchedOpening]
// CHECK:STDERR: fail_missing_implicit_close.carbon:[[@LINE+2]]:10: note: possibly missing `]` here [PossiblyMissingBracketHere]
// CHECK:STDERR:
fn Div[();
// --- fail_missing_name.carbon
// CHECK:STDERR: fail_missing_name.carbon:[[@LINE+2]]:3: error: `fn` introducer should be followed by a name [ExpectedDeclName]
// CHECK:STDERR:
fn ();
// --- fail_no_sig_or_semi.carbon
// CHECK:STDERR: fail_no_sig_or_semi.carbon:[[@LINE+2]]:7: error: `fn` declarations must either end with a `;` or have a `{ ... }` block for a definition [ExpectedDeclSemiOrDefinition]
// CHECK:STDERR:
fn foo
// --- fail_only_fn_and_semi.carbon
// CHECK:STDERR: fail_only_fn_and_semi.carbon:[[@LINE+2]]:3: error: `fn` introducer should be followed by a name [ExpectedDeclName]
// CHECK:STDERR:
fn;
// --- fail_repeated_fn_and_semi.carbon
// CHECK:STDERR: fail_repeated_fn_and_semi.carbon:[[@LINE+2]]:4-5: error: `fn` introducer should be followed by a name; prefix reserved word with `r#` to form a valid identifier [ExpectedDeclName]
// CHECK:STDERR:
fn fn;
// --- fail_skip_indented_newline_until_outdent.carbon
// CHECK:STDERR: fail_skip_indented_newline_until_outdent.carbon:[[@LINE+2]]:5: error: `fn` introducer should be followed by a name [ExpectedDeclName]
// CHECK:STDERR:
fn (x,
y,
z)
fn F();
// --- fail_skip_indented_newline_with_semi.carbon
// CHECK:STDERR: fail_skip_indented_newline_with_semi.carbon:[[@LINE+2]]:3: error: `fn` introducer should be followed by a name [ExpectedDeclName]
// CHECK:STDERR:
fn (x,
y,
z);
fn F();
// --- fail_skip_indented_newline_without_semi.carbon
// CHECK:STDERR: fail_skip_indented_newline_without_semi.carbon:[[@LINE+2]]:3: error: `fn` introducer should be followed by a name [ExpectedDeclName]
// CHECK:STDERR:
fn (x,
y,
z)
fn F();
// --- fail_skip_to_newline_without_semi.carbon
// CHECK:STDERR: fail_skip_to_newline_without_semi.carbon:[[@LINE+2]]:3: error: `fn` introducer should be followed by a name [ExpectedDeclName]
// CHECK:STDERR:
fn ()
fn F();
// --- fail_skip_without_semi_to_curly.carbon
// CHECK:STDERR: fail_skip_without_semi_to_curly.carbon:[[@LINE+2]]:1-6: error: unrecognized declaration introducer [UnrecognizedDecl]
// CHECK:STDERR:
struct X { fn () }
fn F();
// --- with_identifier_as_param.carbon
fn foo(bar);
// --- fail_without_name_and_many_tokens_in_params.carbon
// CHECK:STDERR: fail_without_name_and_many_tokens_in_params.carbon:[[@LINE+2]]:3: error: `fn` introducer should be followed by a name [ExpectedDeclName]
// CHECK:STDERR:
fn (a tokens c d e f g h i j k l m n o p q r s t u v w x y z);
// --- form_parameter.carbon
fn FormParam(x:? Form);
fn ComplexFormParam(x:? X.Y(Z));
// --- fail_ref_on_form_parameter.carbon
// CHECK:STDERR: fail_ref_on_form_parameter.carbon:[[@LINE+2]]:6-8: error: `ref` is only allowed on a runtime binding [ExpectedRuntimeBindingPatternAfterRef]
// CHECK:STDERR:
fn F(ref x:? Form);
// --- fail_form_within_var.carbon
// CHECK:STDERR: fail_form_within_var.carbon:[[@LINE+2]]:26: error: found `:?` binding inside `var` pattern [NonRegularBindingInVarDecl]
// CHECK:STDERR:
fn FormInVar(var x:? Form);
// --- return_form.carbon
fn SimpleReturnForm() ->? Form;
fn ComplexReturnForm() ->? X.Y(Z);
// --- ref_return.carbon
fn RefReturn() -> ref u32;
fn ComplexRefReturn() -> ref X.Y(Z);
let a: auto = fn -> ref u32 { return 0; };
// --- fail_ref_return_missing_type.carbon
// CHECK:STDERR: fail_ref_return_missing_type.carbon:[[@LINE+2]]:22: error: expected expression [ExpectedExpr]
// CHECK:STDERR:
fn RefReturn() -> ref;
// --- val_var_return.carbon
fn ValReturn() -> val u32;
fn VarReturn() -> var u32;
fn ComplexValReturn() -> val X.Y(Z);
let a: auto = fn -> val u32 { return 0; };
let b: auto = fn -> var u32 { return 0; };
// --- fail_val_return_missing_type.carbon
// CHECK:STDERR: fail_val_return_missing_type.carbon:[[@LINE+2]]:22: error: expected expression [ExpectedExpr]
// CHECK:STDERR:
fn ValReturn() -> val;
// CHECK:STDOUT: - filename: basic.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'F'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: ref.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'foo'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'a'
// CHECK:STDOUT: │ │ │ ╭─RefBindingName 'ref'
// CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':'
// CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32'
// CHECK:STDOUT: │ │ ├─LetBindingPattern ':'
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: implicit_empty.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'foo'
// CHECK:STDOUT: │ │ ╭─ImplicitParamListStart '['
// CHECK:STDOUT: │ ├─ImplicitParamList ']'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: implicit_params.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'foo'
// CHECK:STDOUT: │ │ ╭─ImplicitParamListStart '['
// CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'a'
// CHECK:STDOUT: │ │ │ ├─CompileTimeBindingPatternTypeStart ':'
// CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32'
// CHECK:STDOUT: │ │ ├─CompileTimeBindingPattern ':'
// CHECK:STDOUT: │ │ ├─PatternListComma ','
// CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'b'
// CHECK:STDOUT: │ │ │ ├─CompileTimeBindingPatternTypeStart ':'
// CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32'
// CHECK:STDOUT: │ │ ├─CompileTimeBindingPattern ':'
// CHECK:STDOUT: │ ├─ImplicitParamList ']'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: no_params.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameNotBeforeSignature 'foo'
// CHECK:STDOUT: │ ╭─FunctionDefinitionStart '{'
// CHECK:STDOUT: ├─FunctionDefinition '}'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: params.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'foo'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'a'
// CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':'
// CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32'
// CHECK:STDOUT: │ │ ├─LetBindingPattern ':'
// CHECK:STDOUT: │ │ ├─PatternListComma ','
// CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'b'
// CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':'
// CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32'
// CHECK:STDOUT: │ │ ├─LetBindingPattern ':'
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: with_return_type.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'foo'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: │ │ ╭─UnsignedIntTypeLiteral 'u32'
// CHECK:STDOUT: │ ├─ReturnType '->'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: impl_fn.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─OverrideModifier 'override'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'F'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─AbstractModifier 'abstract'
// CHECK:STDOUT: │ ├─OverrideModifier 'override'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'G'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─OverrideModifier 'override'
// CHECK:STDOUT: │ ├─AbstractModifier 'abstract'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'H'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─PrivateModifier 'private'
// CHECK:STDOUT: │ ├─OverrideModifier 'override'
// CHECK:STDOUT: │ ├─DefaultModifier 'default'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'I'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: fail_identifier_instead_of_sig.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameNotBeforeSignature 'foo'
// CHECK:STDOUT: ├─FunctionDecl ';' has_error
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: fail_missing_implicit_close.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'Div'
// CHECK:STDOUT: │ │ ╭─ImplicitParamListStart '['
// CHECK:STDOUT: │ │ │ ╭─TuplePatternStart '('
// CHECK:STDOUT: │ │ ├─TuplePattern ')'
// CHECK:STDOUT: │ ├─ImplicitParamList ']'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: fail_missing_name.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─InvalidParse '(' has_error
// CHECK:STDOUT: ├─FunctionDecl ';' has_error
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: fail_no_sig_or_semi.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameNotBeforeSignature 'foo'
// CHECK:STDOUT: ├─FunctionDecl 'fn' has_error
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: fail_only_fn_and_semi.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─InvalidParse ';' has_error
// CHECK:STDOUT: ├─FunctionDecl ';' has_error
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: fail_repeated_fn_and_semi.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameNotBeforeSignature 'fn'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: fail_skip_indented_newline_until_outdent.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─InvalidParse '(' has_error
// CHECK:STDOUT: ├─FunctionDecl ')' has_error
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'F'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: fail_skip_indented_newline_with_semi.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─InvalidParse '(' has_error
// CHECK:STDOUT: ├─FunctionDecl ';' has_error
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'F'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: fail_skip_indented_newline_without_semi.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─InvalidParse '(' has_error
// CHECK:STDOUT: ├─FunctionDecl ')' has_error
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'F'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: fail_skip_to_newline_without_semi.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─InvalidParse '(' has_error
// CHECK:STDOUT: ├─FunctionDecl ')' has_error
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'F'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: fail_skip_without_semi_to_curly.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─InvalidParseStart 'struct' has_error
// CHECK:STDOUT: ├─InvalidParseSubtree '}' has_error
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'F'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: with_identifier_as_param.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'foo'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ │ ├─IdentifierNameExpr 'bar'
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: fail_without_name_and_many_tokens_in_params.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─InvalidParse '(' has_error
// CHECK:STDOUT: ├─FunctionDecl ';' has_error
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: form_parameter.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'FormParam'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'x'
// CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':?'
// CHECK:STDOUT: │ │ │ ├─IdentifierNameExpr 'Form'
// CHECK:STDOUT: │ │ ├─FormBindingPattern ':?'
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'ComplexFormParam'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'x'
// CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':?'
// CHECK:STDOUT: │ │ │ │ ╭─IdentifierNameExpr 'X'
// CHECK:STDOUT: │ │ │ │ ├─IdentifierNameNotBeforeSignature 'Y'
// CHECK:STDOUT: │ │ │ │ ╭─MemberAccessExpr '.'
// CHECK:STDOUT: │ │ │ │ ╭─CallExprStart '('
// CHECK:STDOUT: │ │ │ │ ├─IdentifierNameExpr 'Z'
// CHECK:STDOUT: │ │ │ ├─CallExpr ')'
// CHECK:STDOUT: │ │ ├─FormBindingPattern ':?'
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: fail_ref_on_form_parameter.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'F'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'x'
// CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':?' has_error
// CHECK:STDOUT: │ │ │ ├─IdentifierNameExpr 'Form'
// CHECK:STDOUT: │ │ ├─FormBindingPattern ':?' has_error
// CHECK:STDOUT: │ ├─ExplicitParamList ')' has_error
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: fail_form_within_var.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'FormInVar'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ │ │ ╭─IdentifierNameNotBeforeSignature 'x'
// CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':?'
// CHECK:STDOUT: │ │ │ ├─IdentifierNameExpr 'Form'
// CHECK:STDOUT: │ │ │ ╭─VarBindingPattern ':?' has_error
// CHECK:STDOUT: │ │ ├─VariablePattern 'var' has_error
// CHECK:STDOUT: │ ├─ExplicitParamList ')' has_error
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: return_form.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'SimpleReturnForm'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: │ │ ╭─IdentifierNameExpr 'Form'
// CHECK:STDOUT: │ ├─ReturnForm '->?'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'ComplexReturnForm'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: │ │ ╭─IdentifierNameExpr 'X'
// CHECK:STDOUT: │ │ ├─IdentifierNameNotBeforeSignature 'Y'
// CHECK:STDOUT: │ │ ╭─MemberAccessExpr '.'
// CHECK:STDOUT: │ │ ╭─CallExprStart '('
// CHECK:STDOUT: │ │ ├─IdentifierNameExpr 'Z'
// CHECK:STDOUT: │ │ ╭─CallExpr ')'
// CHECK:STDOUT: │ ├─ReturnForm '->?'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: ref_return.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'RefReturn'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: │ │ ╭─UnsignedIntTypeLiteral 'u32'
// CHECK:STDOUT: │ │ ╭─RefPrimitiveForm 'ref'
// CHECK:STDOUT: │ ├─ReturnType '->'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'ComplexRefReturn'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: │ │ ╭─IdentifierNameExpr 'X'
// CHECK:STDOUT: │ │ ├─IdentifierNameNotBeforeSignature 'Y'
// CHECK:STDOUT: │ │ ╭─MemberAccessExpr '.'
// CHECK:STDOUT: │ │ ╭─CallExprStart '('
// CHECK:STDOUT: │ │ ├─IdentifierNameExpr 'Z'
// CHECK:STDOUT: │ │ ╭─CallExpr ')'
// CHECK:STDOUT: │ │ ╭─RefPrimitiveForm 'ref'
// CHECK:STDOUT: │ ├─ReturnType '->'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: │ ╭─LetIntroducer 'let'
// CHECK:STDOUT: │ │ ╭─IdentifierNameNotBeforeSignature 'a'
// CHECK:STDOUT: │ │ ├─BindingPatternTypeStart ':'
// CHECK:STDOUT: │ │ ├─AutoTypeLiteral 'auto'
// CHECK:STDOUT: │ ├─LetBindingPattern ':'
// CHECK:STDOUT: │ ├─LetInitializer '='
// CHECK:STDOUT: │ │ ╭─LambdaIntroducer 'fn'
// CHECK:STDOUT: │ │ │ ╭─UnsignedIntTypeLiteral 'u32'
// CHECK:STDOUT: │ │ │ ╭─RefPrimitiveForm 'ref'
// CHECK:STDOUT: │ │ ├─ReturnType '->'
// CHECK:STDOUT: │ │ ╭─LambdaDefinitionStart '{'
// CHECK:STDOUT: │ │ │ ╭─ReturnStatementStart 'return'
// CHECK:STDOUT: │ │ │ ├─IntLiteral '0'
// CHECK:STDOUT: │ │ ├─ReturnStatement ';'
// CHECK:STDOUT: │ ├─Lambda '}'
// CHECK:STDOUT: ├─LetDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: fail_ref_return_missing_type.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'RefReturn'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: │ │ ╭─InvalidParse ';' has_error
// CHECK:STDOUT: │ │ ╭─RefPrimitiveForm 'ref' has_error
// CHECK:STDOUT: │ ├─ReturnType '->'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: val_var_return.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'ValReturn'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: │ │ ╭─UnsignedIntTypeLiteral 'u32'
// CHECK:STDOUT: │ │ ╭─ValPrimitiveForm 'val'
// CHECK:STDOUT: │ ├─ReturnType '->'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'VarReturn'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: │ │ ╭─UnsignedIntTypeLiteral 'u32'
// CHECK:STDOUT: │ │ ╭─VarPrimitiveForm 'var'
// CHECK:STDOUT: │ ├─ReturnType '->'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'ComplexValReturn'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: │ │ ╭─IdentifierNameExpr 'X'
// CHECK:STDOUT: │ │ ├─IdentifierNameNotBeforeSignature 'Y'
// CHECK:STDOUT: │ │ ╭─MemberAccessExpr '.'
// CHECK:STDOUT: │ │ ╭─CallExprStart '('
// CHECK:STDOUT: │ │ ├─IdentifierNameExpr 'Z'
// CHECK:STDOUT: │ │ ╭─CallExpr ')'
// CHECK:STDOUT: │ │ ╭─ValPrimitiveForm 'val'
// CHECK:STDOUT: │ ├─ReturnType '->'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: │ ╭─LetIntroducer 'let'
// CHECK:STDOUT: │ │ ╭─IdentifierNameNotBeforeSignature 'a'
// CHECK:STDOUT: │ │ ├─BindingPatternTypeStart ':'
// CHECK:STDOUT: │ │ ├─AutoTypeLiteral 'auto'
// CHECK:STDOUT: │ ├─LetBindingPattern ':'
// CHECK:STDOUT: │ ├─LetInitializer '='
// CHECK:STDOUT: │ │ ╭─LambdaIntroducer 'fn'
// CHECK:STDOUT: │ │ │ ╭─UnsignedIntTypeLiteral 'u32'
// CHECK:STDOUT: │ │ │ ╭─ValPrimitiveForm 'val'
// CHECK:STDOUT: │ │ ├─ReturnType '->'
// CHECK:STDOUT: │ │ ╭─LambdaDefinitionStart '{'
// CHECK:STDOUT: │ │ │ ╭─ReturnStatementStart 'return'
// CHECK:STDOUT: │ │ │ ├─IntLiteral '0'
// CHECK:STDOUT: │ │ ├─ReturnStatement ';'
// CHECK:STDOUT: │ ├─Lambda '}'
// CHECK:STDOUT: ├─LetDecl ';'
// CHECK:STDOUT: │ ╭─LetIntroducer 'let'
// CHECK:STDOUT: │ │ ╭─IdentifierNameNotBeforeSignature 'b'
// CHECK:STDOUT: │ │ ├─BindingPatternTypeStart ':'
// CHECK:STDOUT: │ │ ├─AutoTypeLiteral 'auto'
// CHECK:STDOUT: │ ├─LetBindingPattern ':'
// CHECK:STDOUT: │ ├─LetInitializer '='
// CHECK:STDOUT: │ │ ╭─LambdaIntroducer 'fn'
// CHECK:STDOUT: │ │ │ ╭─UnsignedIntTypeLiteral 'u32'
// CHECK:STDOUT: │ │ │ ╭─VarPrimitiveForm 'var'
// CHECK:STDOUT: │ │ ├─ReturnType '->'
// CHECK:STDOUT: │ │ ╭─LambdaDefinitionStart '{'
// CHECK:STDOUT: │ │ │ ╭─ReturnStatementStart 'return'
// CHECK:STDOUT: │ │ │ ├─IntLiteral '0'
// CHECK:STDOUT: │ │ ├─ReturnStatement ';'
// CHECK:STDOUT: │ ├─Lambda '}'
// CHECK:STDOUT: ├─LetDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)
// CHECK:STDOUT: - filename: fail_val_return_missing_type.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'ValReturn'
// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '('
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
// CHECK:STDOUT: │ │ ╭─InvalidParse ';' has_error
// CHECK:STDOUT: │ │ ╭─ValPrimitiveForm 'val' has_error
// CHECK:STDOUT: │ ├─ReturnType '->'
// CHECK:STDOUT: ├─FunctionDecl ';'
// CHECK:STDOUT: ├─FileEnd ''
// CHECK:STDOUT: (root)