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

+11 -1
View File
@@ -24,7 +24,7 @@ auto HandleFunctionAfterParams(Context& context) -> void {
if (context.PositionIs(Lex::TokenKind::MinusGreater)) {
context.PushState(StateKind::FunctionReturnTypeFinish);
context.ConsumeAndDiscard();
context.PushStateForExpr(PrecedenceGroup::ForType());
context.PushState(StateKind::ReturnTypeOrFormExpr);
} else if (context.PositionIs(Lex::TokenKind::MinusGreaterQuestion)) {
context.PushState(StateKind::FunctionReturnFormFinish);
context.ConsumeAndDiscard();
@@ -32,6 +32,16 @@ auto HandleFunctionAfterParams(Context& context) -> void {
}
}
auto HandleReturnTypeOrFormExpr(Context& context) -> void {
context.PopAndDiscardState();
// `-> ref T` specifies a primitive return form.
if (context.PositionIs(Lex::TokenKind::Ref)) {
context.PushState(StateKind::PrimitiveFormFinish, context.Consume());
}
context.PushStateForExpr(PrecedenceGroup::ForType());
}
auto HandleFunctionReturnTypeFinish(Context& context) -> void {
auto state = context.PopState();