Form-aware textual format for return parameters and arguments (#6588)

The key changes are:
- Function output parameters are now prefixed with `out`, and more
consistently formatted as named parameters.
- Function and inst output arguments are now written as part of the inst
form, rather than as one of the inst arguments.

As a drive-by fix, this also changes `Temporary::storage_id` from
`DestInstId` to `InstId`, because it doesn't represent an output
parameter of the `Temporary` inst itself.

See the review of
[#6532](https://github.com/carbon-language/carbon-lang/pull/6532) and
[this Discord
discussion](https://discord.com/channels/655572317891461132/999638000126394370/1458268977020141589)
for additional background.
This commit is contained in:
Geoff Romer
2026-01-14 23:27:21 +00:00
committed by GitHub
parent 9861c31476
commit 4329a83e4c
353 changed files with 1779 additions and 1721 deletions
@@ -182,20 +182,20 @@ fn CallFAndGIncomplete() {
// CHECK:STDOUT: .Self = constants.%D
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @ReturnCUnused() -> %C;
// CHECK:STDOUT: fn @ReturnCUnused() -> out %return.param: %C;
// CHECK:STDOUT:
// CHECK:STDOUT: fn @ReturnCUsed() -> %C;
// CHECK:STDOUT: fn @ReturnCUsed() -> out %return.param: %C;
// CHECK:STDOUT:
// CHECK:STDOUT: fn @ReturnDUnused() -> %D;
// CHECK:STDOUT: fn @ReturnDUnused() -> out %return.param: %D;
// CHECK:STDOUT:
// CHECK:STDOUT: fn @ReturnDUsed() -> %D;
// CHECK:STDOUT: fn @ReturnDUsed() -> out %return.param: %D;
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Call() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %ReturnCUsed.ref: %ReturnCUsed.type = name_ref ReturnCUsed, file.%ReturnCUsed.decl [concrete = constants.%ReturnCUsed]
// CHECK:STDOUT: %ReturnCUsed.call: init <error> = call %ReturnCUsed.ref(<invalid return info>)
// CHECK:STDOUT: %ReturnCUsed.call: init <error> = call %ReturnCUsed.ref()
// CHECK:STDOUT: %ReturnDUsed.ref: %ReturnDUsed.type = name_ref ReturnDUsed, file.%ReturnDUsed.decl [concrete = constants.%ReturnDUsed]
// CHECK:STDOUT: %ReturnDUsed.call: init <error> = call %ReturnDUsed.ref(<invalid return info>)
// CHECK:STDOUT: %ReturnDUsed.call: init <error> = call %ReturnDUsed.ref()
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -268,16 +268,16 @@ fn CallFAndGIncomplete() {
// CHECK:STDOUT: fn @CallFAndGIncomplete() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %ReturnCUnused.ref: %ReturnCUnused.type = name_ref ReturnCUnused, imports.%Main.ReturnCUnused [concrete = constants.%ReturnCUnused]
// CHECK:STDOUT: %ReturnCUnused.call: init <error> = call %ReturnCUnused.ref(<invalid return info>)
// CHECK:STDOUT: %ReturnCUnused.call: init <error> = call %ReturnCUnused.ref()
// CHECK:STDOUT: %ReturnCUsed.ref: %ReturnCUsed.type = name_ref ReturnCUsed, imports.%Main.ReturnCUsed [concrete = constants.%ReturnCUsed]
// CHECK:STDOUT: %ReturnCUsed.call: init <error> = call %ReturnCUsed.ref(<invalid return info>)
// CHECK:STDOUT: %ReturnCUsed.call: init <error> = call %ReturnCUsed.ref()
// CHECK:STDOUT: %ReturnDUnused.ref: %ReturnDUnused.type = name_ref ReturnDUnused, imports.%Main.ReturnDUnused [concrete = constants.%ReturnDUnused]
// CHECK:STDOUT: %.loc33_17.1: ref %D = temporary_storage
// CHECK:STDOUT: %ReturnDUnused.call: init %D = call %ReturnDUnused.ref() to %.loc33_17.1
// CHECK:STDOUT: %ReturnDUnused.call: init %D to %.loc33_17.1 = call %ReturnDUnused.ref()
// CHECK:STDOUT: %.loc33_17.2: ref %D = temporary %.loc33_17.1, %ReturnDUnused.call
// CHECK:STDOUT: %ReturnDUsed.ref: %ReturnDUsed.type = name_ref ReturnDUsed, imports.%Main.ReturnDUsed [concrete = constants.%ReturnDUsed]
// CHECK:STDOUT: %.loc34_15.1: ref %D = temporary_storage
// CHECK:STDOUT: %ReturnDUsed.call: init %D = call %ReturnDUsed.ref() to %.loc34_15.1
// CHECK:STDOUT: %ReturnDUsed.call: init %D to %.loc34_15.1 = call %ReturnDUsed.ref()
// CHECK:STDOUT: %.loc34_15.2: ref %D = temporary %.loc34_15.1, %ReturnDUsed.call
// CHECK:STDOUT: %DestroyOp.bound.loc34: <bound method> = bound_method %.loc34_15.2, constants.%DestroyOp
// CHECK:STDOUT: %DestroyOp.call.loc34: init %empty_tuple.type = call %DestroyOp.bound.loc34(%.loc34_15.2)
@@ -143,7 +143,7 @@ fn A {
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @A() -> %empty_tuple.type;
// CHECK:STDOUT: fn @A() -> out %return.param: %empty_tuple.type;
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_implicit_only.carbon
// CHECK:STDOUT:
@@ -172,7 +172,7 @@ fn A {
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @A() -> %empty_tuple.type;
// CHECK:STDOUT: fn @A() -> out %return.param: %empty_tuple.type;
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_arrow_body.carbon
// CHECK:STDOUT:
@@ -356,9 +356,9 @@ import library "extern_api";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @A();
// CHECK:STDOUT:
// CHECK:STDOUT: fn @B(%b.param: %i32) -> %i32;
// CHECK:STDOUT: fn @B(%b.param: %i32) -> out %return.param: %i32;
// CHECK:STDOUT:
// CHECK:STDOUT: fn @C(%c.param: %tuple.type.a1c) -> %struct_type.c;
// CHECK:STDOUT: fn @C(%c.param: %tuple.type.a1c) -> out %return.param: %struct_type.c;
// CHECK:STDOUT:
// CHECK:STDOUT: extern fn @D();
// CHECK:STDOUT:
@@ -460,9 +460,9 @@ import library "extern_api";
// CHECK:STDOUT:
// CHECK:STDOUT: extern fn @A();
// CHECK:STDOUT:
// CHECK:STDOUT: extern fn @B(%b.param: %i32) -> %i32;
// CHECK:STDOUT: extern fn @B(%b.param: %i32) -> out %return.param: %i32;
// CHECK:STDOUT:
// CHECK:STDOUT: extern fn @C(%c.param: %tuple.type.a1c) -> %struct_type.c;
// CHECK:STDOUT: extern fn @C(%c.param: %tuple.type.a1c) -> out %return.param: %struct_type.c;
// CHECK:STDOUT:
// CHECK:STDOUT: extern fn @D();
// CHECK:STDOUT:
+1 -1
View File
@@ -61,7 +61,7 @@ fn G() {
// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F();
// CHECK:STDOUT: fn @F() -> ref %i32;
// CHECK:STDOUT:
// CHECK:STDOUT: fn @G() {
// CHECK:STDOUT: !entry: