mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Allow incomplete return types in function declarations. (#3875)
Move completeness check to the point where the function is defined or first called. This means we also defer deciding whether the function has a return slot until that point. Instead of storing a return slot per function, store the location of the return storage, which may or may not be used, and compute and store a separate flag saying whether to use it at the point of first use or definition. This is the final piece in supporting simple `Make` functions in classes as a replacement for constructors.
This commit is contained in:
+6
-6
@@ -15,9 +15,9 @@ fn G() {
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %.1: type = tuple_type (type, type, type) [template]
|
||||
// CHECK:STDOUT: %.2: type = tuple_type (i32, i32, i32) [template]
|
||||
// CHECK:STDOUT: %.3: type = ptr_type (i32, i32, i32) [template]
|
||||
// CHECK:STDOUT: %.4: i32 = int_literal 2 [template]
|
||||
// CHECK:STDOUT: %.5: type = array_type %.4, (i32, i32, i32) [template]
|
||||
// CHECK:STDOUT: %.3: i32 = int_literal 2 [template]
|
||||
// CHECK:STDOUT: %.4: type = array_type %.3, (i32, i32, i32) [template]
|
||||
// CHECK:STDOUT: %.5: type = ptr_type (i32, i32, i32) [template]
|
||||
// CHECK:STDOUT: %.6: type = ptr_type [(i32, i32, i32); 2] [template]
|
||||
// CHECK:STDOUT: %.7: type = tuple_type ((i32, i32, i32), (i32, i32, i32)) [template]
|
||||
// CHECK:STDOUT: %.8: i32 = int_literal 0 [template]
|
||||
@@ -39,14 +39,14 @@ fn G() {
|
||||
// CHECK:STDOUT: %G: <function> = fn_decl @G [template] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F() -> %return: (i32, i32, i32);
|
||||
// CHECK:STDOUT: fn @F() -> (i32, i32, i32);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @G() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %.loc10_25.1: (type, type, type) = tuple_literal (i32, i32, i32)
|
||||
// CHECK:STDOUT: %.loc10_28: i32 = int_literal 2 [template = constants.%.4]
|
||||
// CHECK:STDOUT: %.loc10_28: i32 = int_literal 2 [template = constants.%.3]
|
||||
// CHECK:STDOUT: %.loc10_25.2: type = converted %.loc10_25.1, constants.%.2 [template = constants.%.2]
|
||||
// CHECK:STDOUT: %.loc10_29: type = array_type %.loc10_28, (i32, i32, i32) [template = constants.%.5]
|
||||
// CHECK:STDOUT: %.loc10_29: type = array_type %.loc10_28, (i32, i32, i32) [template = constants.%.4]
|
||||
// CHECK:STDOUT: %v.var: ref [(i32, i32, i32); 2] = var v
|
||||
// CHECK:STDOUT: %v: ref [(i32, i32, i32); 2] = bind_name v, %v.var
|
||||
// CHECK:STDOUT: %F.ref.loc10_34: <function> = name_ref F, file.%F [template = file.%F]
|
||||
|
||||
@@ -32,7 +32,7 @@ fn Run() {
|
||||
// CHECK:STDOUT: %F: <function> = fn_decl @F [template] {
|
||||
// CHECK:STDOUT: %.loc7_16.1: (type,) = tuple_literal (i32)
|
||||
// CHECK:STDOUT: %.loc7_16.2: type = converted %.loc7_16.1, constants.%.2 [template = constants.%.2]
|
||||
// CHECK:STDOUT: %return.var: ref (i32,) = var <return slot>
|
||||
// CHECK:STDOUT: @F.%return: ref (i32,) = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Run: <function> = fn_decl @Run [template] {}
|
||||
// CHECK:STDOUT: }
|
||||
|
||||
@@ -34,7 +34,7 @@ let b: [i32; 3]* = &a;
|
||||
// CHECK:STDOUT: @Add.%a: i32 = bind_name a, %a.loc7_8.1
|
||||
// CHECK:STDOUT: %b.loc7_16.1: i32 = param b
|
||||
// CHECK:STDOUT: @Add.%b: i32 = bind_name b, %b.loc7_16.1
|
||||
// CHECK:STDOUT: %return.var: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: @Add.%return: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Add.ref: <function> = name_ref Add, %Add [template = %Add]
|
||||
// CHECK:STDOUT: %.loc9_18: i32 = int_literal 1 [template = constants.%.1]
|
||||
|
||||
@@ -28,7 +28,7 @@ var a: [i32; Negate(1)];
|
||||
// CHECK:STDOUT: %Negate: <function> = fn_decl @Negate [template] {
|
||||
// CHECK:STDOUT: %n.loc7_11.1: i32 = param n
|
||||
// CHECK:STDOUT: @Negate.%n: i32 = bind_name n, %n.loc7_11.1
|
||||
// CHECK:STDOUT: %return.var: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: @Negate.%return: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Negate.ref: <function> = name_ref Negate, %Negate [template = %Negate]
|
||||
// CHECK:STDOUT: %.loc12_21: i32 = int_literal 1 [template = constants.%.1]
|
||||
|
||||
+2
-2
@@ -39,10 +39,10 @@ fn G() -> i32 {
|
||||
// CHECK:STDOUT: @F.%arr: [i32; 3] = bind_name arr, %arr.loc7_6.1
|
||||
// CHECK:STDOUT: %i.loc7_21.1: i32 = param i
|
||||
// CHECK:STDOUT: @F.%i: i32 = bind_name i, %i.loc7_21.1
|
||||
// CHECK:STDOUT: %return.var.loc7: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: @F.%return: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %G: <function> = fn_decl @G [template] {
|
||||
// CHECK:STDOUT: %return.var.loc11: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: @G.%return: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
Reference in New Issue
Block a user