Parse -> ref T as a primitive return form (#7911)

Previously `-> ref T` was parsed as a type expression whose outermost
node is a `ref` prefix operator (the same one used for `F(ref x)`
arguments), and `ReturnExprAsForm` recognized the resulting `RefTagExpr`
and turned it into a `RefForm`.

Per p5434, a return form that begins with `val`, `ref`, or `var` is not
a type expression. Parse a leading `ref` after `->` as a
`RefPrimitiveForm` node wrapping the type expression, reusing the node
produced by `form(ref T)`, and check it as a form. This prepares for
supporting `-> val T` and `-> var T` in the same way.

The only SemIR change is that the `ref_tag` instruction is no longer
emitted, and the return slot pattern refers to a `type_component_of` the
form, matching `->? form(ref T)`.

---------

Co-authored-by: Nicholas Bishop <nbishop@nbishop.net>
This commit is contained in:
David BlaikieandNicholas Bishop authored and GitHub committed 2026-10-07 23:05:55 +00:00
1 parent 72068410c2
commit 059ee7b9ed
7 files changed
+143 -50

No files matched your search

+65
View File
@@ -183,6 +183,20 @@ fn FormInVar(var x:? Form);
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 => 0;
// --- fail_ref_return_missing_type.carbon
// CHECK:STDERR: fail_ref_return_missing_type.carbon:[[@LINE+4]]:22: error: expected expression [ExpectedExpr]
// CHECK:STDERR: fn RefReturn() -> ref;
// CHECK:STDERR: ^
// CHECK:STDERR:
fn RefReturn() -> ref;
// CHECK:STDOUT: - filename: basic.carbon
// CHECK:STDOUT: ╭─FileStart ''
// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn'
@@ -505,3 +519,54 @@ fn ComplexReturnForm() ->? X.Y(Z);
// 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: │ │ │ ╭─PrefixOperatorRef 'ref'
// CHECK:STDOUT: │ │ ├─ReturnType '->'
// CHECK:STDOUT: │ │ ╭─LambdaDefinitionStart '=>'
// CHECK:STDOUT: │ │ ├─IntLiteral '0'
// CHECK:STDOUT: │ ├─Lambda 'fn'
// 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)