Przeglądaj źródła

Removed builtin empty tuple type (#3021)

Co-authored-by: Farzana Ahmed Siddique <fasiddique@google.com>
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
Farzana Ahmed Siddique 2 lat temu
rodzic
commit
db5e269097
71 zmienionych plików z 350 dodań i 259 usunięć
  1. 10 12
      toolchain/lowering/lowering_context.cpp
  2. 11 3
      toolchain/lowering/lowering_handle.cpp
  3. 1 2
      toolchain/lowering/testdata/function/call/empty_struct.carbon
  4. 1 2
      toolchain/lowering/testdata/function/call/empty_tuple.carbon
  5. 1 3
      toolchain/lowering/testdata/function/call/i32.carbon
  6. 37 0
      toolchain/lowering/testdata/function/call/implicit_empty_tuple_as_arg.carbon
  7. 4 5
      toolchain/lowering/testdata/function/call/params_one.carbon
  8. 6 6
      toolchain/lowering/testdata/function/call/params_one_comma.carbon
  9. 4 5
      toolchain/lowering/testdata/function/call/params_two.carbon
  10. 6 6
      toolchain/lowering/testdata/function/call/params_two_comma.carbon
  11. 4 5
      toolchain/lowering/testdata/function/call/params_zero.carbon
  12. 31 0
      toolchain/lowering/testdata/function/call/return_implicit.carbon
  13. 4 5
      toolchain/lowering/testdata/function/call/var_param.carbon
  14. 4 5
      toolchain/lowering/testdata/function/declaration/simple.carbon
  15. 1 2
      toolchain/lowering/testdata/function/definition/empty_struct.carbon
  16. 1 3
      toolchain/lowering/testdata/function/definition/params_one.carbon
  17. 1 3
      toolchain/lowering/testdata/function/definition/params_two.carbon
  18. 1 3
      toolchain/lowering/testdata/function/definition/params_zero.carbon
  19. 10 9
      toolchain/lowering/testdata/if/else.carbon
  20. 7 7
      toolchain/lowering/testdata/if/no_else.carbon
  21. 5 6
      toolchain/lowering/testdata/namespace/function.carbon
  22. 4 5
      toolchain/lowering/testdata/namespace/nested.carbon
  23. 2 4
      toolchain/lowering/testdata/return/code_after_return.carbon
  24. 1 3
      toolchain/lowering/testdata/return/no_value.carbon
  25. 0 3
      toolchain/semantics/semantics_builtin_kind.def
  26. 8 1
      toolchain/semantics/semantics_handle_call_expression.cpp
  27. 0 3
      toolchain/semantics/semantics_handle_function.cpp
  28. 0 12
      toolchain/semantics/semantics_ir.h
  29. 0 1
      toolchain/semantics/testdata/basics/builtin_nodes.carbon
  30. 0 1
      toolchain/semantics/testdata/basics/fail_name_lookup.carbon
  31. 0 1
      toolchain/semantics/testdata/function/call/empty_struct.carbon
  32. 0 1
      toolchain/semantics/testdata/function/call/empty_tuple.carbon
  33. 18 19
      toolchain/semantics/testdata/function/call/fail_param_count.carbon
  34. 2 3
      toolchain/semantics/testdata/function/call/fail_param_type.carbon
  35. 2 3
      toolchain/semantics/testdata/function/call/fail_return_type_mismatch.carbon
  36. 0 1
      toolchain/semantics/testdata/function/call/i32.carbon
  37. 6 2
      toolchain/semantics/testdata/function/call/more_param_ir.carbon
  38. 6 2
      toolchain/semantics/testdata/function/call/params_one.carbon
  39. 9 5
      toolchain/semantics/testdata/function/call/params_one_comma.carbon
  40. 6 2
      toolchain/semantics/testdata/function/call/params_two.carbon
  41. 11 7
      toolchain/semantics/testdata/function/call/params_two_comma.carbon
  42. 6 2
      toolchain/semantics/testdata/function/call/params_zero.carbon
  43. 40 4
      toolchain/semantics/testdata/function/call/return_implicit.carbon
  44. 6 2
      toolchain/semantics/testdata/function/declaration/simple.carbon
  45. 0 1
      toolchain/semantics/testdata/function/definition/fail_param_name_conflict.carbon
  46. 0 1
      toolchain/semantics/testdata/function/definition/order.carbon
  47. 0 1
      toolchain/semantics/testdata/function/definition/params_one.carbon
  48. 0 1
      toolchain/semantics/testdata/function/definition/params_one_comma.carbon
  49. 0 1
      toolchain/semantics/testdata/function/definition/params_two.carbon
  50. 0 1
      toolchain/semantics/testdata/function/definition/params_two_comma.carbon
  51. 0 1
      toolchain/semantics/testdata/function/definition/params_zero.carbon
  52. 0 1
      toolchain/semantics/testdata/function/definition/same_param_name.carbon
  53. 13 9
      toolchain/semantics/testdata/if/else.carbon
  54. 10 6
      toolchain/semantics/testdata/if/no_else.carbon
  55. 1 2
      toolchain/semantics/testdata/namespace/fail_duplicate.carbon
  56. 0 1
      toolchain/semantics/testdata/namespace/fail_unresolved_scope.carbon
  57. 6 2
      toolchain/semantics/testdata/namespace/function.carbon
  58. 6 2
      toolchain/semantics/testdata/namespace/nested.carbon
  59. 6 7
      toolchain/semantics/testdata/return/code_after_return.carbon
  60. 2 3
      toolchain/semantics/testdata/return/fail_value_disallowed.carbon
  61. 0 1
      toolchain/semantics/testdata/return/missing_return_no_return_type.carbon
  62. 0 1
      toolchain/semantics/testdata/return/no_value.carbon
  63. 2 3
      toolchain/semantics/testdata/var/decl.carbon
  64. 4 5
      toolchain/semantics/testdata/var/decl_with_init.carbon
  65. 8 9
      toolchain/semantics/testdata/var/fail_duplicate_decl.carbon
  66. 3 4
      toolchain/semantics/testdata/var/fail_init_type_mismatch.carbon
  67. 2 3
      toolchain/semantics/testdata/var/fail_init_with_self.carbon
  68. 4 5
      toolchain/semantics/testdata/var/fail_lookup_outside_scope.carbon
  69. 2 3
      toolchain/semantics/testdata/var/fail_storage_is_literal.carbon
  70. 0 1
      toolchain/semantics/testdata/var/global_lookup_in_scope.carbon
  71. 4 5
      toolchain/semantics/testdata/var/lookup.carbon

+ 10 - 12
toolchain/lowering/lowering_context.cpp

@@ -7,6 +7,7 @@
 #include "common/vlog.h"
 #include "common/vlog.h"
 #include "toolchain/lowering/lowering_function_context.h"
 #include "toolchain/lowering/lowering_function_context.h"
 #include "toolchain/semantics/semantics_ir.h"
 #include "toolchain/semantics/semantics_ir.h"
+#include "toolchain/semantics/semantics_node.h"
 #include "toolchain/semantics/semantics_node_kind.h"
 #include "toolchain/semantics/semantics_node_kind.h"
 
 
 namespace Carbon {
 namespace Carbon {
@@ -64,9 +65,11 @@ auto LoweringContext::BuildFunctionDeclaration(SemanticsFunctionId function_id)
     args[i] = GetType(semantics_ir().GetNode(param_refs[i]).type_id());
     args[i] = GetType(semantics_ir().GetNode(param_refs[i]).type_id());
   }
   }
 
 
-  llvm::Type* return_type = GetType(function.return_type_id.is_valid()
-                                        ? function.return_type_id
-                                        : semantics_ir().empty_tuple_type_id());
+  // If return type is not valid, the function does not have a return type.
+  // Hence, set return type to void.
+  llvm::Type* return_type = function.return_type_id.is_valid()
+                                ? GetType(function.return_type_id)
+                                : llvm::Type::getVoidTy(llvm_context());
   llvm::FunctionType* function_type =
   llvm::FunctionType* function_type =
       llvm::FunctionType::get(return_type, args, /*isVarArg=*/false);
       llvm::FunctionType::get(return_type, args, /*isVarArg=*/false);
   auto* llvm_function = llvm::Function::Create(
   auto* llvm_function = llvm::Function::Create(
@@ -127,15 +130,6 @@ auto LoweringContext::BuildFunctionDefinition(SemanticsFunctionId function_id)
 
 
 auto LoweringContext::BuildType(SemanticsNodeId node_id) -> llvm::Type* {
 auto LoweringContext::BuildType(SemanticsNodeId node_id) -> llvm::Type* {
   switch (node_id.index) {
   switch (node_id.index) {
-    case SemanticsBuiltinKind::EmptyTupleType.AsInt():
-      // Represent empty types as empty structs.
-      // TODO: Investigate special-casing handling of these so that they can be
-      // collectively replaced with LLVM's void, particularly around function
-      // returns. LLVM doesn't allow declaring variables with a void type, so
-      // that may require significant special casing.
-      return llvm::StructType::create(
-          *llvm_context_, llvm::ArrayRef<llvm::Type*>(),
-          SemanticsBuiltinKind::FromInt(node_id.index).name());
     case SemanticsBuiltinKind::FloatingPointType.AsInt():
     case SemanticsBuiltinKind::FloatingPointType.AsInt():
       // TODO: Handle different sizes.
       // TODO: Handle different sizes.
       return llvm::Type::getDoubleTy(*llvm_context_);
       return llvm::Type::getDoubleTy(*llvm_context_);
@@ -166,6 +160,10 @@ auto LoweringContext::BuildType(SemanticsNodeId node_id) -> llvm::Type* {
                                       "StructLiteralType");
                                       "StructLiteralType");
     }
     }
     case SemanticsNodeKind::TupleType: {
     case SemanticsNodeKind::TupleType: {
+      // TODO: Investigate special-casing handling of empty tuples so that they
+      // can be collectively replaced with LLVM's void, particularly around
+      // function returns. LLVM doesn't allow declaring variables with a void
+      // type, so that may require significant special casing.
       auto refs = semantics_ir_->GetTypeBlock(node.GetAsTupleType());
       auto refs = semantics_ir_->GetTypeBlock(node.GetAsTupleType());
       llvm::SmallVector<llvm::Type*> subtypes;
       llvm::SmallVector<llvm::Type*> subtypes;
       subtypes.reserve(refs.size());
       subtypes.reserve(refs.size());

+ 11 - 3
toolchain/lowering/lowering_handle.cpp

@@ -123,9 +123,17 @@ auto LoweringHandleCall(LoweringFunctionContext& context,
   for (auto ref_id : context.semantics_ir().GetNodeBlock(refs_id)) {
   for (auto ref_id : context.semantics_ir().GetNodeBlock(refs_id)) {
     args.push_back(context.GetLocalLoaded(ref_id));
     args.push_back(context.GetLocalLoaded(ref_id));
   }
   }
-  auto* value =
-      context.builder().CreateCall(function, args, function->getName());
-  context.SetLocal(node_id, value);
+  if (function->getReturnType()->isVoidTy()) {
+    context.builder().CreateCall(function, args);
+    // TODO: use empty tuple type.
+    // TODO: don't create the empty tuple if the call does not get assigned.
+    context.SetLocal(node_id, context.builder().CreateAlloca(
+                                  llvm::StructType::get(context.llvm_context()),
+                                  /*ArraySize=*/nullptr, "TupleLiteralValue"));
+  } else {
+    context.SetLocal(node_id, context.builder().CreateCall(
+                                  function, args, function->getName()));
+  }
 }
 }
 
 
 auto LoweringHandleFunctionDeclaration(LoweringFunctionContext& /*context*/,
 auto LoweringHandleFunctionDeclaration(LoweringFunctionContext& /*context*/,

+ 1 - 2
toolchain/lowering/testdata/function/call/empty_struct.carbon

@@ -7,7 +7,6 @@
 // CHECK:STDOUT: source_filename = "empty_struct.carbon"
 // CHECK:STDOUT: source_filename = "empty_struct.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: %StructLiteralType = type {}
 // CHECK:STDOUT: %StructLiteralType = type {}
-// CHECK:STDOUT: %EmptyTupleType = type {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: define %StructLiteralType @Echo(%StructLiteralType %a) {
 // CHECK:STDOUT: define %StructLiteralType @Echo(%StructLiteralType %a) {
 // CHECK:STDOUT:   %StructLiteralValue = alloca %StructLiteralType, align 8
 // CHECK:STDOUT:   %StructLiteralValue = alloca %StructLiteralType, align 8
@@ -15,7 +14,7 @@
 // CHECK:STDOUT:   ret %StructLiteralType %1
 // CHECK:STDOUT:   ret %StructLiteralType %1
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Main() {
+// CHECK:STDOUT: define void @Main() {
 // CHECK:STDOUT:   %StructLiteralValue = alloca %StructLiteralType, align 8
 // CHECK:STDOUT:   %StructLiteralValue = alloca %StructLiteralType, align 8
 // CHECK:STDOUT:   %var = alloca %StructLiteralType, align 8
 // CHECK:STDOUT:   %var = alloca %StructLiteralType, align 8
 // CHECK:STDOUT:   %StructLiteralValue1 = alloca %StructLiteralType, align 8
 // CHECK:STDOUT:   %StructLiteralValue1 = alloca %StructLiteralType, align 8

+ 1 - 2
toolchain/lowering/testdata/function/call/empty_tuple.carbon

@@ -7,13 +7,12 @@
 // CHECK:STDOUT: source_filename = "empty_tuple.carbon"
 // CHECK:STDOUT: source_filename = "empty_tuple.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: %TupleLiteralType = type {}
 // CHECK:STDOUT: %TupleLiteralType = type {}
-// CHECK:STDOUT: %EmptyTupleType = type {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: define %TupleLiteralType @Echo(%TupleLiteralType %a) {
 // CHECK:STDOUT: define %TupleLiteralType @Echo(%TupleLiteralType %a) {
 // CHECK:STDOUT:   ret %TupleLiteralType %a
 // CHECK:STDOUT:   ret %TupleLiteralType %a
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Main() {
+// CHECK:STDOUT: define void @Main() {
 // CHECK:STDOUT:   %TupleLiteralValue = alloca %TupleLiteralType, align 8
 // CHECK:STDOUT:   %TupleLiteralValue = alloca %TupleLiteralType, align 8
 // CHECK:STDOUT:   %var = alloca %TupleLiteralType, align 8
 // CHECK:STDOUT:   %var = alloca %TupleLiteralType, align 8
 // CHECK:STDOUT:   %TupleLiteralValue1 = alloca %TupleLiteralType, align 8
 // CHECK:STDOUT:   %TupleLiteralValue1 = alloca %TupleLiteralType, align 8

+ 1 - 3
toolchain/lowering/testdata/function/call/i32.carbon

@@ -6,13 +6,11 @@
 // CHECK:STDOUT: ; ModuleID = 'i32.carbon'
 // CHECK:STDOUT: ; ModuleID = 'i32.carbon'
 // CHECK:STDOUT: source_filename = "i32.carbon"
 // CHECK:STDOUT: source_filename = "i32.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: %EmptyTupleType = type {}
-// CHECK:STDOUT:
 // CHECK:STDOUT: define i32 @Echo(i32 %a) {
 // CHECK:STDOUT: define i32 @Echo(i32 %a) {
 // CHECK:STDOUT:   ret i32 %a
 // CHECK:STDOUT:   ret i32 %a
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Main() {
+// CHECK:STDOUT: define void @Main() {
 // CHECK:STDOUT:   %var = alloca i32, align 4
 // CHECK:STDOUT:   %var = alloca i32, align 4
 // CHECK:STDOUT:   %Echo = call i32 @Echo(i32 1)
 // CHECK:STDOUT:   %Echo = call i32 @Echo(i32 1)
 // CHECK:STDOUT:   store i32 %Echo, ptr %var, align 4
 // CHECK:STDOUT:   store i32 %Echo, ptr %var, align 4

+ 37 - 0
toolchain/lowering/testdata/function/call/implicit_empty_tuple_as_arg.carbon

@@ -0,0 +1,37 @@
+// 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
+// CHECK:STDOUT: ; ModuleID = 'implicit_empty_tuple_as_arg.carbon'
+// CHECK:STDOUT: source_filename = "implicit_empty_tuple_as_arg.carbon"
+// CHECK:STDOUT:
+// CHECK:STDOUT: %TupleLiteralType = type {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: define void @Foo() {
+// CHECK:STDOUT:   ret void
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define %TupleLiteralType @Bar(%TupleLiteralType %a) {
+// CHECK:STDOUT:   ret %TupleLiteralType %a
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define void @Main() {
+// CHECK:STDOUT:   %TupleLiteralValue = alloca %TupleLiteralType, align 8
+// CHECK:STDOUT:   %var = alloca %TupleLiteralType, align 8
+// CHECK:STDOUT:   call void @Foo()
+// CHECK:STDOUT:   %TupleLiteralValue1 = alloca {}, align 8
+// CHECK:STDOUT:   %1 = load %TupleLiteralType, ptr %TupleLiteralValue1, align 1
+// CHECK:STDOUT:   %Bar = call %TupleLiteralType @Bar(%TupleLiteralType %1)
+// CHECK:STDOUT:   store %TupleLiteralType %Bar, ptr %var, align 1
+// CHECK:STDOUT:   ret void
+// CHECK:STDOUT: }
+
+
+fn Foo() {}
+
+fn Bar(a: ()) -> () { return a; }
+
+fn Main() {
+  var x: () = Bar(Foo());
+}

+ 4 - 5
toolchain/lowering/testdata/function/call/params_one.carbon

@@ -6,14 +6,13 @@
 // CHECK:STDOUT: ; ModuleID = 'params_one.carbon'
 // CHECK:STDOUT: ; ModuleID = 'params_one.carbon'
 // CHECK:STDOUT: source_filename = "params_one.carbon"
 // CHECK:STDOUT: source_filename = "params_one.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: %EmptyTupleType = type {}
-// CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Foo(i32 %a) {
+// CHECK:STDOUT: define void @Foo(i32 %a) {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Main() {
-// CHECK:STDOUT:   %Foo = call %EmptyTupleType @Foo(i32 1)
+// CHECK:STDOUT: define void @Main() {
+// CHECK:STDOUT:   call void @Foo(i32 1)
+// CHECK:STDOUT:   %TupleLiteralValue = alloca {}, align 8
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 
 

+ 6 - 6
toolchain/lowering/testdata/function/call/params_one_comma.carbon

@@ -6,15 +6,15 @@
 // CHECK:STDOUT: ; ModuleID = 'params_one_comma.carbon'
 // CHECK:STDOUT: ; ModuleID = 'params_one_comma.carbon'
 // CHECK:STDOUT: source_filename = "params_one_comma.carbon"
 // CHECK:STDOUT: source_filename = "params_one_comma.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: %EmptyTupleType = type {}
-// CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Foo(i32 %a) {
+// CHECK:STDOUT: define void @Foo(i32 %a) {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Main() {
-// CHECK:STDOUT:   %Foo = call %EmptyTupleType @Foo(i32 1)
-// CHECK:STDOUT:   %Foo1 = call %EmptyTupleType @Foo(i32 1)
+// CHECK:STDOUT: define void @Main() {
+// CHECK:STDOUT:   call void @Foo(i32 1)
+// CHECK:STDOUT:   %TupleLiteralValue = alloca {}, align 8
+// CHECK:STDOUT:   call void @Foo(i32 1)
+// CHECK:STDOUT:   %TupleLiteralValue1 = alloca {}, align 8
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 
 

+ 4 - 5
toolchain/lowering/testdata/function/call/params_two.carbon

@@ -6,14 +6,13 @@
 // CHECK:STDOUT: ; ModuleID = 'params_two.carbon'
 // CHECK:STDOUT: ; ModuleID = 'params_two.carbon'
 // CHECK:STDOUT: source_filename = "params_two.carbon"
 // CHECK:STDOUT: source_filename = "params_two.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: %EmptyTupleType = type {}
-// CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Foo(i32 %a, i32 %b) {
+// CHECK:STDOUT: define void @Foo(i32 %a, i32 %b) {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Main() {
-// CHECK:STDOUT:   %Foo = call %EmptyTupleType @Foo(i32 1, i32 2)
+// CHECK:STDOUT: define void @Main() {
+// CHECK:STDOUT:   call void @Foo(i32 1, i32 2)
+// CHECK:STDOUT:   %TupleLiteralValue = alloca {}, align 8
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 
 

+ 6 - 6
toolchain/lowering/testdata/function/call/params_two_comma.carbon

@@ -6,15 +6,15 @@
 // CHECK:STDOUT: ; ModuleID = 'params_two_comma.carbon'
 // CHECK:STDOUT: ; ModuleID = 'params_two_comma.carbon'
 // CHECK:STDOUT: source_filename = "params_two_comma.carbon"
 // CHECK:STDOUT: source_filename = "params_two_comma.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: %EmptyTupleType = type {}
-// CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Foo(i32 %a, i32 %b) {
+// CHECK:STDOUT: define void @Foo(i32 %a, i32 %b) {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Main() {
-// CHECK:STDOUT:   %Foo = call %EmptyTupleType @Foo(i32 1, i32 2)
-// CHECK:STDOUT:   %Foo1 = call %EmptyTupleType @Foo(i32 1, i32 2)
+// CHECK:STDOUT: define void @Main() {
+// CHECK:STDOUT:   call void @Foo(i32 1, i32 2)
+// CHECK:STDOUT:   %TupleLiteralValue = alloca {}, align 8
+// CHECK:STDOUT:   call void @Foo(i32 1, i32 2)
+// CHECK:STDOUT:   %TupleLiteralValue1 = alloca {}, align 8
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 
 

+ 4 - 5
toolchain/lowering/testdata/function/call/params_zero.carbon

@@ -6,14 +6,13 @@
 // CHECK:STDOUT: ; ModuleID = 'params_zero.carbon'
 // CHECK:STDOUT: ; ModuleID = 'params_zero.carbon'
 // CHECK:STDOUT: source_filename = "params_zero.carbon"
 // CHECK:STDOUT: source_filename = "params_zero.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: %EmptyTupleType = type {}
-// CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Foo() {
+// CHECK:STDOUT: define void @Foo() {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Main() {
-// CHECK:STDOUT:   %Foo = call %EmptyTupleType @Foo()
+// CHECK:STDOUT: define void @Main() {
+// CHECK:STDOUT:   call void @Foo()
+// CHECK:STDOUT:   %TupleLiteralValue = alloca {}, align 8
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 
 

+ 31 - 0
toolchain/lowering/testdata/function/call/return_implicit.carbon

@@ -0,0 +1,31 @@
+// 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
+// CHECK:STDOUT: ; ModuleID = 'return_implicit.carbon'
+// CHECK:STDOUT: source_filename = "return_implicit.carbon"
+// CHECK:STDOUT:
+// CHECK:STDOUT: %TupleLiteralType = type {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: define void @MakeImplicitEmptyTuple() {
+// CHECK:STDOUT:   ret void
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define void @Main() {
+// CHECK:STDOUT:   %TupleLiteralValue = alloca %TupleLiteralType, align 8
+// CHECK:STDOUT:   %var = alloca %TupleLiteralType, align 8
+// CHECK:STDOUT:   call void @MakeImplicitEmptyTuple()
+// CHECK:STDOUT:   %TupleLiteralValue1 = alloca {}, align 8
+// CHECK:STDOUT:   %1 = load %TupleLiteralType, ptr %TupleLiteralValue1, align 1
+// CHECK:STDOUT:   store %TupleLiteralType %1, ptr %var, align 1
+// CHECK:STDOUT:   ret void
+// CHECK:STDOUT: }
+
+
+fn MakeImplicitEmptyTuple() {
+}
+
+fn Main() {
+  var b: () = MakeImplicitEmptyTuple();
+}

+ 4 - 5
toolchain/lowering/testdata/function/call/var_param.carbon

@@ -6,17 +6,16 @@
 // CHECK:STDOUT: ; ModuleID = 'var_param.carbon'
 // CHECK:STDOUT: ; ModuleID = 'var_param.carbon'
 // CHECK:STDOUT: source_filename = "var_param.carbon"
 // CHECK:STDOUT: source_filename = "var_param.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: %EmptyTupleType = type {}
-// CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @DoNothing(i32 %a) {
+// CHECK:STDOUT: define void @DoNothing(i32 %a) {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Main() {
+// CHECK:STDOUT: define void @Main() {
 // CHECK:STDOUT:   %var = alloca i32, align 4
 // CHECK:STDOUT:   %var = alloca i32, align 4
 // CHECK:STDOUT:   store i32 0, ptr %var, align 4
 // CHECK:STDOUT:   store i32 0, ptr %var, align 4
 // CHECK:STDOUT:   %1 = load i32, ptr %var, align 4
 // CHECK:STDOUT:   %1 = load i32, ptr %var, align 4
-// CHECK:STDOUT:   %DoNothing = call %EmptyTupleType @DoNothing(i32 %1)
+// CHECK:STDOUT:   call void @DoNothing(i32 %1)
+// CHECK:STDOUT:   %TupleLiteralValue = alloca {}, align 8
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 
 

+ 4 - 5
toolchain/lowering/testdata/function/declaration/simple.carbon

@@ -6,12 +6,11 @@
 // CHECK:STDOUT: ; ModuleID = 'simple.carbon'
 // CHECK:STDOUT: ; ModuleID = 'simple.carbon'
 // CHECK:STDOUT: source_filename = "simple.carbon"
 // CHECK:STDOUT: source_filename = "simple.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: %EmptyTupleType = type {}
+// CHECK:STDOUT: declare void @F(i32)
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: declare %EmptyTupleType @F(i32)
-// CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @G(i32 %n) {
-// CHECK:STDOUT:   %F = call %EmptyTupleType @F(i32 %n)
+// CHECK:STDOUT: define void @G(i32 %n) {
+// CHECK:STDOUT:   call void @F(i32 %n)
+// CHECK:STDOUT:   %TupleLiteralValue = alloca {}, align 8
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 
 

+ 1 - 2
toolchain/lowering/testdata/function/definition/empty_struct.carbon

@@ -6,10 +6,9 @@
 // CHECK:STDOUT: ; ModuleID = 'empty_struct.carbon'
 // CHECK:STDOUT: ; ModuleID = 'empty_struct.carbon'
 // CHECK:STDOUT: source_filename = "empty_struct.carbon"
 // CHECK:STDOUT: source_filename = "empty_struct.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: %EmptyTupleType = type {}
 // CHECK:STDOUT: %StructLiteralType = type {}
 // CHECK:STDOUT: %StructLiteralType = type {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Echo(%StructLiteralType %a) {
+// CHECK:STDOUT: define void @Echo(%StructLiteralType %a) {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 
 

+ 1 - 3
toolchain/lowering/testdata/function/definition/params_one.carbon

@@ -6,9 +6,7 @@
 // CHECK:STDOUT: ; ModuleID = 'params_one.carbon'
 // CHECK:STDOUT: ; ModuleID = 'params_one.carbon'
 // CHECK:STDOUT: source_filename = "params_one.carbon"
 // CHECK:STDOUT: source_filename = "params_one.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: %EmptyTupleType = type {}
-// CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Foo(i32 %a) {
+// CHECK:STDOUT: define void @Foo(i32 %a) {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 
 

+ 1 - 3
toolchain/lowering/testdata/function/definition/params_two.carbon

@@ -6,9 +6,7 @@
 // CHECK:STDOUT: ; ModuleID = 'params_two.carbon'
 // CHECK:STDOUT: ; ModuleID = 'params_two.carbon'
 // CHECK:STDOUT: source_filename = "params_two.carbon"
 // CHECK:STDOUT: source_filename = "params_two.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: %EmptyTupleType = type {}
-// CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Foo(i32 %a, i32 %b) {
+// CHECK:STDOUT: define void @Foo(i32 %a, i32 %b) {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 
 

+ 1 - 3
toolchain/lowering/testdata/function/definition/params_zero.carbon

@@ -6,9 +6,7 @@
 // CHECK:STDOUT: ; ModuleID = 'params_zero.carbon'
 // CHECK:STDOUT: ; ModuleID = 'params_zero.carbon'
 // CHECK:STDOUT: source_filename = "params_zero.carbon"
 // CHECK:STDOUT: source_filename = "params_zero.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: %EmptyTupleType = type {}
-// CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Foo() {
+// CHECK:STDOUT: define void @Foo() {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 
 

+ 10 - 9
toolchain/lowering/testdata/if/else.carbon

@@ -6,33 +6,34 @@
 // CHECK:STDOUT: ; ModuleID = 'else.carbon'
 // CHECK:STDOUT: ; ModuleID = 'else.carbon'
 // CHECK:STDOUT: source_filename = "else.carbon"
 // CHECK:STDOUT: source_filename = "else.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: %EmptyTupleType = type {}
-// CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @F() {
+// CHECK:STDOUT: define void @F() {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @G() {
+// CHECK:STDOUT: define void @G() {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @H() {
+// CHECK:STDOUT: define void @H() {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @If(i1 %b) {
+// CHECK:STDOUT: define void @If(i1 %b) {
 // CHECK:STDOUT:   br i1 %b, label %1, label %2
 // CHECK:STDOUT:   br i1 %b, label %1, label %2
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: 1:                                                ; preds = %0
 // CHECK:STDOUT: 1:                                                ; preds = %0
-// CHECK:STDOUT:   %F = call %EmptyTupleType @F()
+// CHECK:STDOUT:   call void @F()
+// CHECK:STDOUT:   %TupleLiteralValue = alloca {}, align 8
 // CHECK:STDOUT:   br label %3
 // CHECK:STDOUT:   br label %3
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: 2:                                                ; preds = %0
 // CHECK:STDOUT: 2:                                                ; preds = %0
-// CHECK:STDOUT:   %G = call %EmptyTupleType @G()
+// CHECK:STDOUT:   call void @G()
+// CHECK:STDOUT:   %TupleLiteralValue1 = alloca {}, align 8
 // CHECK:STDOUT:   br label %3
 // CHECK:STDOUT:   br label %3
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: 3:                                                ; preds = %2, %1
 // CHECK:STDOUT: 3:                                                ; preds = %2, %1
-// CHECK:STDOUT:   %H = call %EmptyTupleType @H()
+// CHECK:STDOUT:   call void @H()
+// CHECK:STDOUT:   %TupleLiteralValue2 = alloca {}, align 8
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 
 

+ 7 - 7
toolchain/lowering/testdata/if/no_else.carbon

@@ -6,25 +6,25 @@
 // CHECK:STDOUT: ; ModuleID = 'no_else.carbon'
 // CHECK:STDOUT: ; ModuleID = 'no_else.carbon'
 // CHECK:STDOUT: source_filename = "no_else.carbon"
 // CHECK:STDOUT: source_filename = "no_else.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: %EmptyTupleType = type {}
-// CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @F() {
+// CHECK:STDOUT: define void @F() {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @G() {
+// CHECK:STDOUT: define void @G() {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @If(i1 %b) {
+// CHECK:STDOUT: define void @If(i1 %b) {
 // CHECK:STDOUT:   br i1 %b, label %1, label %2
 // CHECK:STDOUT:   br i1 %b, label %1, label %2
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: 1:                                                ; preds = %0
 // CHECK:STDOUT: 1:                                                ; preds = %0
-// CHECK:STDOUT:   %F = call %EmptyTupleType @F()
+// CHECK:STDOUT:   call void @F()
+// CHECK:STDOUT:   %TupleLiteralValue = alloca {}, align 8
 // CHECK:STDOUT:   br label %2
 // CHECK:STDOUT:   br label %2
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: 2:                                                ; preds = %1, %0
 // CHECK:STDOUT: 2:                                                ; preds = %1, %0
-// CHECK:STDOUT:   %G = call %EmptyTupleType @G()
+// CHECK:STDOUT:   call void @G()
+// CHECK:STDOUT:   %TupleLiteralValue1 = alloca {}, align 8
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 
 

+ 5 - 6
toolchain/lowering/testdata/namespace/function.carbon

@@ -6,18 +6,17 @@
 // CHECK:STDOUT: ; ModuleID = 'function.carbon'
 // CHECK:STDOUT: ; ModuleID = 'function.carbon'
 // CHECK:STDOUT: source_filename = "function.carbon"
 // CHECK:STDOUT: source_filename = "function.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: %EmptyTupleType = type {}
-// CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Baz() {
+// CHECK:STDOUT: define void @Baz() {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Baz.1() {
+// CHECK:STDOUT: define void @Baz.1() {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Bar() {
-// CHECK:STDOUT:   %Baz.1 = call %EmptyTupleType @Baz.1()
+// CHECK:STDOUT: define void @Bar() {
+// CHECK:STDOUT:   call void @Baz.1()
+// CHECK:STDOUT:   %TupleLiteralValue = alloca {}, align 8
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 
 

+ 4 - 5
toolchain/lowering/testdata/namespace/nested.carbon

@@ -6,14 +6,13 @@
 // CHECK:STDOUT: ; ModuleID = 'nested.carbon'
 // CHECK:STDOUT: ; ModuleID = 'nested.carbon'
 // CHECK:STDOUT: source_filename = "nested.carbon"
 // CHECK:STDOUT: source_filename = "nested.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: %EmptyTupleType = type {}
-// CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Wiz() {
+// CHECK:STDOUT: define void @Wiz() {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Baz() {
-// CHECK:STDOUT:   %Wiz = call %EmptyTupleType @Wiz()
+// CHECK:STDOUT: define void @Baz() {
+// CHECK:STDOUT:   call void @Wiz()
+// CHECK:STDOUT:   %TupleLiteralValue = alloca {}, align 8
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 
 

+ 2 - 4
toolchain/lowering/testdata/return/code_after_return.carbon

@@ -6,13 +6,11 @@
 // CHECK:STDOUT: ; ModuleID = 'code_after_return.carbon'
 // CHECK:STDOUT: ; ModuleID = 'code_after_return.carbon'
 // CHECK:STDOUT: source_filename = "code_after_return.carbon"
 // CHECK:STDOUT: source_filename = "code_after_return.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: %EmptyTupleType = type {}
-// CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @F() {
+// CHECK:STDOUT: define void @F() {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Main() {
+// CHECK:STDOUT: define void @Main() {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 
 

+ 1 - 3
toolchain/lowering/testdata/return/no_value.carbon

@@ -6,9 +6,7 @@
 // CHECK:STDOUT: ; ModuleID = 'no_value.carbon'
 // CHECK:STDOUT: ; ModuleID = 'no_value.carbon'
 // CHECK:STDOUT: source_filename = "no_value.carbon"
 // CHECK:STDOUT: source_filename = "no_value.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: %EmptyTupleType = type {}
-// CHECK:STDOUT:
-// CHECK:STDOUT: define %EmptyTupleType @Main() {
+// CHECK:STDOUT: define void @Main() {
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 
 

+ 0 - 3
toolchain/semantics/semantics_builtin_kind.def

@@ -64,9 +64,6 @@ CARBON_SEMANTICS_BUILTIN_KIND(FloatingPointType, "f64")
 // The type of string values and String literals.
 // The type of string values and String literals.
 CARBON_SEMANTICS_BUILTIN_KIND(StringType, "String")
 CARBON_SEMANTICS_BUILTIN_KIND(StringType, "String")
 
 
-// The canonical empty tuple type.
-CARBON_SEMANTICS_BUILTIN_KIND(EmptyTupleType, "() as type")
-
 // Keep invalid last, so that we can use values as array indices without needing
 // Keep invalid last, so that we can use values as array indices without needing
 // an invalid entry.
 // an invalid entry.
 CARBON_SEMANTICS_BUILTIN_KIND_NAME(Invalid)
 CARBON_SEMANTICS_BUILTIN_KIND_NAME(Invalid)

+ 8 - 1
toolchain/semantics/semantics_handle_call_expression.cpp

@@ -3,6 +3,7 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
 
 #include "toolchain/semantics/semantics_context.h"
 #include "toolchain/semantics/semantics_context.h"
+#include "toolchain/semantics/semantics_node.h"
 
 
 namespace Carbon {
 namespace Carbon {
 
 
@@ -41,8 +42,14 @@ auto SemanticsHandleCallExpression(SemanticsContext& context,
                                          /*diagnostic=*/nullptr));
                                          /*diagnostic=*/nullptr));
 
 
   // TODO: Propagate return types from callable.
   // TODO: Propagate return types from callable.
+  SemanticsTypeId type_id = callable.return_type_id;
+  // For functions with an implicit return type, set the return type to empty
+  // tuple type.
+  if (type_id == SemanticsTypeId::Invalid) {
+    type_id = context.CanonicalizeTupleType(call_expr_parse_node, {});
+  }
   auto call_node_id = context.AddNode(SemanticsNode::Call::Make(
   auto call_node_id = context.AddNode(SemanticsNode::Call::Make(
-      call_expr_parse_node, callable.return_type_id, refs_id, function_id));
+      call_expr_parse_node, type_id, refs_id, function_id));
 
 
   context.node_stack().Push(parse_node, call_node_id);
   context.node_stack().Push(parse_node, call_node_id);
   return true;
   return true;

+ 0 - 3
toolchain/semantics/semantics_handle_function.cpp

@@ -15,9 +15,6 @@ static auto BuildFunctionDeclaration(SemanticsContext& context)
   if (context.parse_tree().node_kind(context.node_stack().PeekParseNode()) ==
   if (context.parse_tree().node_kind(context.node_stack().PeekParseNode()) ==
       ParseNodeKind::ReturnType) {
       ParseNodeKind::ReturnType) {
     return_type_id = context.node_stack().Pop<ParseNodeKind::ReturnType>();
     return_type_id = context.node_stack().Pop<ParseNodeKind::ReturnType>();
-  } else {
-    // Canonicalize the empty tuple for the implicit return.
-    context.CanonicalizeType(SemanticsNodeId::BuiltinEmptyTupleType);
   }
   }
   SemanticsNodeBlockId param_refs_id =
   SemanticsNodeBlockId param_refs_id =
       context.node_stack().Pop<ParseNodeKind::ParameterList>();
       context.node_stack().Pop<ParseNodeKind::ParameterList>();

+ 0 - 12
toolchain/semantics/semantics_ir.h

@@ -217,10 +217,6 @@ class SemanticsIR {
   auto AddType(SemanticsNodeId node_id) -> SemanticsTypeId {
   auto AddType(SemanticsNodeId node_id) -> SemanticsTypeId {
     SemanticsTypeId type_id(types_.size());
     SemanticsTypeId type_id(types_.size());
     types_.push_back(node_id);
     types_.push_back(node_id);
-    if (node_id == SemanticsNodeId::BuiltinEmptyTupleType) {
-      CARBON_CHECK(!empty_tuple_type_id_.is_valid());
-      empty_tuple_type_id_ = type_id;
-    }
     return type_id;
     return type_id;
   }
   }
 
 
@@ -274,10 +270,6 @@ class SemanticsIR {
     return types_;
     return types_;
   }
   }
 
 
-  auto empty_tuple_type_id() const -> SemanticsTypeId {
-    return empty_tuple_type_id_;
-  }
-
   // The node blocks, for direct mutation.
   // The node blocks, for direct mutation.
   auto node_blocks() -> llvm::SmallVector<llvm::SmallVector<SemanticsNodeId>>& {
   auto node_blocks() -> llvm::SmallVector<llvm::SmallVector<SemanticsNodeId>>& {
     return node_blocks_;
     return node_blocks_;
@@ -329,10 +321,6 @@ class SemanticsIR {
   // Storage for blocks within the IR. These reference entries in types_.
   // Storage for blocks within the IR. These reference entries in types_.
   llvm::SmallVector<llvm::SmallVector<SemanticsTypeId>> type_blocks_;
   llvm::SmallVector<llvm::SmallVector<SemanticsTypeId>> type_blocks_;
 
 
-  // The type of the empty tuple. This is special-cased due to its use in
-  // implicit function returns.
-  SemanticsTypeId empty_tuple_type_id_ = SemanticsTypeId::Invalid;
-
   // All nodes. The first entries will always be cross-references to builtins,
   // All nodes. The first entries will always be cross-references to builtins,
   // at indices matching SemanticsBuiltinKind ordering.
   // at indices matching SemanticsBuiltinKind ordering.
   llvm::SmallVector<SemanticsNode> nodes_;
   llvm::SmallVector<SemanticsNode> nodes_;

+ 0 - 1
toolchain/semantics/testdata/basics/builtin_nodes.carbon

@@ -26,7 +26,6 @@
 // CHECK:STDOUT:   {kind: CrossReference, arg0: ir0, arg1: nodeIntegerType, type: typeTypeType},
 // CHECK:STDOUT:   {kind: CrossReference, arg0: ir0, arg1: nodeIntegerType, type: typeTypeType},
 // CHECK:STDOUT:   {kind: CrossReference, arg0: ir0, arg1: nodeFloatingPointType, type: typeTypeType},
 // CHECK:STDOUT:   {kind: CrossReference, arg0: ir0, arg1: nodeFloatingPointType, type: typeTypeType},
 // CHECK:STDOUT:   {kind: CrossReference, arg0: ir0, arg1: nodeStringType, type: typeTypeType},
 // CHECK:STDOUT:   {kind: CrossReference, arg0: ir0, arg1: nodeStringType, type: typeTypeType},
-// CHECK:STDOUT:   {kind: CrossReference, arg0: ir0, arg1: nodeEmptyTupleType, type: typeTypeType},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [

+ 0 - 1
toolchain/semantics/testdata/basics/fail_name_lookup.carbon

@@ -16,7 +16,6 @@
 // CHECK:STDOUT:   x,
 // CHECK:STDOUT:   x,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]

+ 0 - 1
toolchain/semantics/testdata/function/call/empty_struct.carbon

@@ -19,7 +19,6 @@
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT:   node+0,
 // CHECK:STDOUT:   node+0,
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]

+ 0 - 1
toolchain/semantics/testdata/function/call/empty_tuple.carbon

@@ -19,7 +19,6 @@
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT:   node+0,
 // CHECK:STDOUT:   node+0,
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [

+ 18 - 19
toolchain/semantics/testdata/function/call/fail_param_count.carbon

@@ -29,7 +29,6 @@
 // CHECK:STDOUT:   Main,
 // CHECK:STDOUT:   Main,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
@@ -37,29 +36,29 @@
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
-// CHECK:STDOUT:   {kind: VarStorage, type: type1},
-// CHECK:STDOUT:   {kind: BindName, arg0: str2, arg1: node+2, type: type1},
+// CHECK:STDOUT:   {kind: VarStorage, type: type0},
+// CHECK:STDOUT:   {kind: BindName, arg0: str2, arg1: node+2, type: type0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
-// CHECK:STDOUT:   {kind: VarStorage, type: type1},
-// CHECK:STDOUT:   {kind: BindName, arg0: str2, arg1: node+6, type: type1},
-// CHECK:STDOUT:   {kind: VarStorage, type: type1},
-// CHECK:STDOUT:   {kind: BindName, arg0: str4, arg1: node+8, type: type1},
+// CHECK:STDOUT:   {kind: VarStorage, type: type0},
+// CHECK:STDOUT:   {kind: BindName, arg0: str2, arg1: node+6, type: type0},
+// CHECK:STDOUT:   {kind: VarStorage, type: type0},
+// CHECK:STDOUT:   {kind: BindName, arg0: str4, arg1: node+8, type: type0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function2},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function2},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function3},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function3},
-// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type1},
-// CHECK:STDOUT:   {kind: StubReference, arg0: node+13, type: type1},
-// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int1, type: type1},
-// CHECK:STDOUT:   {kind: StubReference, arg0: node+15, type: type1},
-// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int2, type: type1},
-// CHECK:STDOUT:   {kind: StubReference, arg0: node+17, type: type1},
-// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int3, type: type1},
-// CHECK:STDOUT:   {kind: StubReference, arg0: node+19, type: type1},
-// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int4, type: type1},
-// CHECK:STDOUT:   {kind: StubReference, arg0: node+21, type: type1},
-// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int5, type: type1},
-// CHECK:STDOUT:   {kind: StubReference, arg0: node+23, type: type1},
+// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type0},
+// CHECK:STDOUT:   {kind: StubReference, arg0: node+13, type: type0},
+// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int1, type: type0},
+// CHECK:STDOUT:   {kind: StubReference, arg0: node+15, type: type0},
+// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int2, type: type0},
+// CHECK:STDOUT:   {kind: StubReference, arg0: node+17, type: type0},
+// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int3, type: type0},
+// CHECK:STDOUT:   {kind: StubReference, arg0: node+19, type: type0},
+// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int4, type: type0},
+// CHECK:STDOUT:   {kind: StubReference, arg0: node+21, type: type0},
+// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int5, type: type0},
+// CHECK:STDOUT:   {kind: StubReference, arg0: node+23, type: type0},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [

+ 2 - 3
toolchain/semantics/testdata/function/call/fail_param_type.carbon

@@ -20,7 +20,6 @@
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT:   nodeFloatingPointType,
 // CHECK:STDOUT:   nodeFloatingPointType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
@@ -31,8 +30,8 @@
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
-// CHECK:STDOUT:   {kind: RealLiteral, arg0: real0, type: type2},
-// CHECK:STDOUT:   {kind: StubReference, arg0: node+5, type: type2},
+// CHECK:STDOUT:   {kind: RealLiteral, arg0: real0, type: type1},
+// CHECK:STDOUT:   {kind: StubReference, arg0: node+5, type: type1},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [

+ 2 - 3
toolchain/semantics/testdata/function/call/fail_return_type_mismatch.carbon

@@ -20,7 +20,6 @@
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT:   nodeFloatingPointType,
 // CHECK:STDOUT:   nodeFloatingPointType,
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
@@ -30,8 +29,8 @@
 // CHECK:STDOUT:   {kind: RealLiteral, arg0: real0, type: type0},
 // CHECK:STDOUT:   {kind: RealLiteral, arg0: real0, type: type0},
 // CHECK:STDOUT:   {kind: ReturnExpression, arg0: node+1, type: type0},
 // CHECK:STDOUT:   {kind: ReturnExpression, arg0: node+1, type: type0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
-// CHECK:STDOUT:   {kind: VarStorage, type: type2},
-// CHECK:STDOUT:   {kind: BindName, arg0: str2, arg1: node+4, type: type2},
+// CHECK:STDOUT:   {kind: VarStorage, type: type1},
+// CHECK:STDOUT:   {kind: BindName, arg0: str2, arg1: node+4, type: type1},
 // CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function0, type: type0},
 // CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function0, type: type0},
 // CHECK:STDOUT:   {kind: Assign, arg0: node+4, arg1: nodeError, type: typeError},
 // CHECK:STDOUT:   {kind: Assign, arg0: node+4, arg1: nodeError, type: typeError},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},

+ 0 - 1
toolchain/semantics/testdata/function/call/i32.carbon

@@ -21,7 +21,6 @@
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]

+ 6 - 2
toolchain/semantics/testdata/function/call/more_param_ir.carbon

@@ -27,9 +27,11 @@
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
-// CHECK:STDOUT:   nodeEmptyTupleType,
+// CHECK:STDOUT:   node+21,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: VarStorage, type: type0},
 // CHECK:STDOUT:   {kind: VarStorage, type: type0},
@@ -53,7 +55,8 @@
 // CHECK:STDOUT:   {kind: StubReference, arg0: node+17, type: type0},
 // CHECK:STDOUT:   {kind: StubReference, arg0: node+17, type: type0},
 // CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int5, type: type0},
 // CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int5, type: type0},
 // CHECK:STDOUT:   {kind: StubReference, arg0: node+19, type: type0},
 // CHECK:STDOUT:   {kind: StubReference, arg0: node+19, type: type0},
-// CHECK:STDOUT:   {kind: Call, arg0: block6, arg1: function0},
+// CHECK:STDOUT:   {kind: TupleType, arg0: typeBlock0, type: typeTypeType},
+// CHECK:STDOUT:   {kind: Call, arg0: block6, arg1: function0, type: type1},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [
@@ -94,6 +97,7 @@
 // CHECK:STDOUT:     node+20,
 // CHECK:STDOUT:     node+20,
 // CHECK:STDOUT:     node+21,
 // CHECK:STDOUT:     node+21,
 // CHECK:STDOUT:     node+22,
 // CHECK:STDOUT:     node+22,
+// CHECK:STDOUT:     node+23,
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:     node+14,
 // CHECK:STDOUT:     node+14,

+ 6 - 2
toolchain/semantics/testdata/function/call/params_one.carbon

@@ -20,9 +20,11 @@
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
-// CHECK:STDOUT:   nodeEmptyTupleType,
+// CHECK:STDOUT:   node+7,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: VarStorage, type: type0},
 // CHECK:STDOUT:   {kind: VarStorage, type: type0},
@@ -32,7 +34,8 @@
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
 // CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type0},
 // CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type0},
 // CHECK:STDOUT:   {kind: StubReference, arg0: node+5, type: type0},
 // CHECK:STDOUT:   {kind: StubReference, arg0: node+5, type: type0},
-// CHECK:STDOUT:   {kind: Call, arg0: block6, arg1: function0},
+// CHECK:STDOUT:   {kind: TupleType, arg0: typeBlock0, type: typeTypeType},
+// CHECK:STDOUT:   {kind: Call, arg0: block6, arg1: function0, type: type1},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [
@@ -57,6 +60,7 @@
 // CHECK:STDOUT:     node+6,
 // CHECK:STDOUT:     node+6,
 // CHECK:STDOUT:     node+7,
 // CHECK:STDOUT:     node+7,
 // CHECK:STDOUT:     node+8,
 // CHECK:STDOUT:     node+8,
+// CHECK:STDOUT:     node+9,
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:     node+6,
 // CHECK:STDOUT:     node+6,

+ 9 - 5
toolchain/semantics/testdata/function/call/params_one_comma.carbon

@@ -21,9 +21,11 @@
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
-// CHECK:STDOUT:   nodeEmptyTupleType,
+// CHECK:STDOUT:   node+7,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: VarStorage, type: type0},
 // CHECK:STDOUT:   {kind: VarStorage, type: type0},
@@ -33,10 +35,11 @@
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
 // CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type0},
 // CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type0},
 // CHECK:STDOUT:   {kind: StubReference, arg0: node+5, type: type0},
 // CHECK:STDOUT:   {kind: StubReference, arg0: node+5, type: type0},
-// CHECK:STDOUT:   {kind: Call, arg0: block6, arg1: function0},
+// CHECK:STDOUT:   {kind: TupleType, arg0: typeBlock0, type: typeTypeType},
+// CHECK:STDOUT:   {kind: Call, arg0: block6, arg1: function0, type: type1},
 // CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int1, type: type0},
 // CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int1, type: type0},
-// CHECK:STDOUT:   {kind: StubReference, arg0: node+8, type: type0},
-// CHECK:STDOUT:   {kind: Call, arg0: block7, arg1: function0},
+// CHECK:STDOUT:   {kind: StubReference, arg0: node+9, type: type0},
+// CHECK:STDOUT:   {kind: Call, arg0: block7, arg1: function0, type: type1},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [
@@ -64,12 +67,13 @@
 // CHECK:STDOUT:     node+9,
 // CHECK:STDOUT:     node+9,
 // CHECK:STDOUT:     node+10,
 // CHECK:STDOUT:     node+10,
 // CHECK:STDOUT:     node+11,
 // CHECK:STDOUT:     node+11,
+// CHECK:STDOUT:     node+12,
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:     node+6,
 // CHECK:STDOUT:     node+6,
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [
-// CHECK:STDOUT:     node+9,
+// CHECK:STDOUT:     node+10,
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 
 

+ 6 - 2
toolchain/semantics/testdata/function/call/params_two.carbon

@@ -22,9 +22,11 @@
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
-// CHECK:STDOUT:   nodeEmptyTupleType,
+// CHECK:STDOUT:   node+11,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: VarStorage, type: type0},
 // CHECK:STDOUT:   {kind: VarStorage, type: type0},
@@ -38,7 +40,8 @@
 // CHECK:STDOUT:   {kind: StubReference, arg0: node+7, type: type0},
 // CHECK:STDOUT:   {kind: StubReference, arg0: node+7, type: type0},
 // CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int1, type: type0},
 // CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int1, type: type0},
 // CHECK:STDOUT:   {kind: StubReference, arg0: node+9, type: type0},
 // CHECK:STDOUT:   {kind: StubReference, arg0: node+9, type: type0},
-// CHECK:STDOUT:   {kind: Call, arg0: block6, arg1: function0},
+// CHECK:STDOUT:   {kind: TupleType, arg0: typeBlock0, type: typeTypeType},
+// CHECK:STDOUT:   {kind: Call, arg0: block6, arg1: function0, type: type1},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [
@@ -68,6 +71,7 @@
 // CHECK:STDOUT:     node+10,
 // CHECK:STDOUT:     node+10,
 // CHECK:STDOUT:     node+11,
 // CHECK:STDOUT:     node+11,
 // CHECK:STDOUT:     node+12,
 // CHECK:STDOUT:     node+12,
+// CHECK:STDOUT:     node+13,
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:     node+8,
 // CHECK:STDOUT:     node+8,

+ 11 - 7
toolchain/semantics/testdata/function/call/params_two_comma.carbon

@@ -24,9 +24,11 @@
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
-// CHECK:STDOUT:   nodeEmptyTupleType,
+// CHECK:STDOUT:   node+11,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: VarStorage, type: type0},
 // CHECK:STDOUT:   {kind: VarStorage, type: type0},
@@ -40,12 +42,13 @@
 // CHECK:STDOUT:   {kind: StubReference, arg0: node+7, type: type0},
 // CHECK:STDOUT:   {kind: StubReference, arg0: node+7, type: type0},
 // CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int1, type: type0},
 // CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int1, type: type0},
 // CHECK:STDOUT:   {kind: StubReference, arg0: node+9, type: type0},
 // CHECK:STDOUT:   {kind: StubReference, arg0: node+9, type: type0},
-// CHECK:STDOUT:   {kind: Call, arg0: block6, arg1: function0},
+// CHECK:STDOUT:   {kind: TupleType, arg0: typeBlock0, type: typeTypeType},
+// CHECK:STDOUT:   {kind: Call, arg0: block6, arg1: function0, type: type1},
 // CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int2, type: type0},
 // CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int2, type: type0},
-// CHECK:STDOUT:   {kind: StubReference, arg0: node+12, type: type0},
+// CHECK:STDOUT:   {kind: StubReference, arg0: node+13, type: type0},
 // CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int3, type: type0},
 // CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int3, type: type0},
-// CHECK:STDOUT:   {kind: StubReference, arg0: node+14, type: type0},
-// CHECK:STDOUT:   {kind: Call, arg0: block7, arg1: function0},
+// CHECK:STDOUT:   {kind: StubReference, arg0: node+15, type: type0},
+// CHECK:STDOUT:   {kind: Call, arg0: block7, arg1: function0, type: type1},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [
@@ -80,14 +83,15 @@
 // CHECK:STDOUT:     node+15,
 // CHECK:STDOUT:     node+15,
 // CHECK:STDOUT:     node+16,
 // CHECK:STDOUT:     node+16,
 // CHECK:STDOUT:     node+17,
 // CHECK:STDOUT:     node+17,
+// CHECK:STDOUT:     node+18,
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:     node+8,
 // CHECK:STDOUT:     node+8,
 // CHECK:STDOUT:     node+10,
 // CHECK:STDOUT:     node+10,
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [
-// CHECK:STDOUT:     node+13,
-// CHECK:STDOUT:     node+15,
+// CHECK:STDOUT:     node+14,
+// CHECK:STDOUT:     node+16,
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 
 

+ 6 - 2
toolchain/semantics/testdata/function/call/params_zero.carbon

@@ -17,15 +17,18 @@
 // CHECK:STDOUT:   Main,
 // CHECK:STDOUT:   Main,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
+// CHECK:STDOUT:   node+3,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
-// CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function0},
+// CHECK:STDOUT:   {kind: TupleType, arg0: typeBlock0, type: typeTypeType},
+// CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function0, type: type0},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [
@@ -41,6 +44,7 @@
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:     node+3,
 // CHECK:STDOUT:     node+3,
 // CHECK:STDOUT:     node+4,
 // CHECK:STDOUT:     node+4,
+// CHECK:STDOUT:     node+5,
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 
 

+ 40 - 4
toolchain/semantics/testdata/function/call/return_implicit.carbon

@@ -5,25 +5,61 @@
 // AUTOUPDATE
 // AUTOUPDATE
 // CHECK:STDOUT: cross_reference_irs_size: 1
 // CHECK:STDOUT: cross_reference_irs_size: 1
 // CHECK:STDOUT: functions: [
 // CHECK:STDOUT: functions: [
+// CHECK:STDOUT:   {name: str0, param_refs: block0, body: {block2}}},
+// CHECK:STDOUT:   {name: str1, param_refs: block0, body: {block3}}},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: integer_literals: [
 // CHECK:STDOUT: integer_literals: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: real_literals: [
 // CHECK:STDOUT: real_literals: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: strings: [
 // CHECK:STDOUT: strings: [
+// CHECK:STDOUT:   MakeImplicitEmptyTuple,
+// CHECK:STDOUT:   Main,
+// CHECK:STDOUT:   b,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
+// CHECK:STDOUT:   node+3,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
+// CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
+// CHECK:STDOUT:   {kind: Return},
+// CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
+// CHECK:STDOUT:   {kind: TupleType, arg0: typeBlock0, type: typeTypeType},
+// CHECK:STDOUT:   {kind: TupleValue, arg0: block0, type: type0},
+// CHECK:STDOUT:   {kind: VarStorage, type: type0},
+// CHECK:STDOUT:   {kind: BindName, arg0: str2, arg1: node+5, type: type0},
+// CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function0, type: type0},
+// CHECK:STDOUT:   {kind: Assign, arg0: node+5, arg1: node+7, type: type0},
+// CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   ],
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:     node+0,
+// CHECK:STDOUT:     node+2,
+// CHECK:STDOUT:   ],
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:     node+1,
+// CHECK:STDOUT:   ],
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:     node+3,
+// CHECK:STDOUT:     node+4,
+// CHECK:STDOUT:     node+5,
+// CHECK:STDOUT:     node+6,
+// CHECK:STDOUT:     node+7,
+// CHECK:STDOUT:     node+8,
+// CHECK:STDOUT:     node+9,
+// CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 
 
-// TODO test if builtin implicit empty tuple type is treated as being the same type as an explicitly-created empty tuple type.
-// Currently crashes due to call expression.
-// fn MakeImplicitEmptyTuple() {}
-// var v: () = MakeImplicitEmptyTuple();
+fn MakeImplicitEmptyTuple() {
+}
+
+fn Main() {
+  var b: () = MakeImplicitEmptyTuple();
+}

+ 6 - 2
toolchain/semantics/testdata/function/declaration/simple.carbon

@@ -17,14 +17,17 @@
 // CHECK:STDOUT:   G,
 // CHECK:STDOUT:   G,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
+// CHECK:STDOUT:   node+2,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
-// CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function0},
+// CHECK:STDOUT:   {kind: TupleType, arg0: typeBlock0, type: typeTypeType},
+// CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function0, type: type0},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [
@@ -37,6 +40,7 @@
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:     node+2,
 // CHECK:STDOUT:     node+2,
 // CHECK:STDOUT:     node+3,
 // CHECK:STDOUT:     node+3,
+// CHECK:STDOUT:     node+4,
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 
 

+ 0 - 1
toolchain/semantics/testdata/function/definition/fail_param_name_conflict.carbon

@@ -17,7 +17,6 @@
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]

+ 0 - 1
toolchain/semantics/testdata/function/definition/order.carbon

@@ -19,7 +19,6 @@
 // CHECK:STDOUT:   Baz,
 // CHECK:STDOUT:   Baz,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]

+ 0 - 1
toolchain/semantics/testdata/function/definition/params_one.carbon

@@ -17,7 +17,6 @@
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]

+ 0 - 1
toolchain/semantics/testdata/function/definition/params_one_comma.carbon

@@ -17,7 +17,6 @@
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]

+ 0 - 1
toolchain/semantics/testdata/function/definition/params_two.carbon

@@ -18,7 +18,6 @@
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]

+ 0 - 1
toolchain/semantics/testdata/function/definition/params_two_comma.carbon

@@ -18,7 +18,6 @@
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]

+ 0 - 1
toolchain/semantics/testdata/function/definition/params_zero.carbon

@@ -15,7 +15,6 @@
 // CHECK:STDOUT:   Foo,
 // CHECK:STDOUT:   Foo,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]

+ 0 - 1
toolchain/semantics/testdata/function/definition/same_param_name.carbon

@@ -19,7 +19,6 @@
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]

+ 13 - 9
toolchain/semantics/testdata/if/else.carbon

@@ -22,10 +22,12 @@
 // CHECK:STDOUT:   b,
 // CHECK:STDOUT:   b,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT:   nodeBoolType,
 // CHECK:STDOUT:   nodeBoolType,
+// CHECK:STDOUT:   node+11,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
@@ -34,16 +36,17 @@
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function2},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function2},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
-// CHECK:STDOUT:   {kind: VarStorage, type: type1},
-// CHECK:STDOUT:   {kind: BindName, arg0: str4, arg1: node+6, type: type1},
+// CHECK:STDOUT:   {kind: VarStorage, type: type0},
+// CHECK:STDOUT:   {kind: BindName, arg0: str4, arg1: node+6, type: type0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function3},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function3},
 // CHECK:STDOUT:   {kind: BranchIf, arg0: block8, arg1: node+6},
 // CHECK:STDOUT:   {kind: BranchIf, arg0: block8, arg1: node+6},
 // CHECK:STDOUT:   {kind: Branch, arg0: block9},
 // CHECK:STDOUT:   {kind: Branch, arg0: block9},
-// CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function0},
-// CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function1},
+// CHECK:STDOUT:   {kind: TupleType, arg0: typeBlock0, type: typeTypeType},
+// CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function0, type: type1},
+// CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function1, type: type1},
 // CHECK:STDOUT:   {kind: Branch, arg0: block10},
 // CHECK:STDOUT:   {kind: Branch, arg0: block10},
 // CHECK:STDOUT:   {kind: Branch, arg0: block10},
 // CHECK:STDOUT:   {kind: Branch, arg0: block10},
-// CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function2},
+// CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function2, type: type1},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [
@@ -77,15 +80,16 @@
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:     node+11,
 // CHECK:STDOUT:     node+11,
-// CHECK:STDOUT:     node+13,
-// CHECK:STDOUT:   ],
-// CHECK:STDOUT:   [
 // CHECK:STDOUT:     node+12,
 // CHECK:STDOUT:     node+12,
 // CHECK:STDOUT:     node+14,
 // CHECK:STDOUT:     node+14,
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [
+// CHECK:STDOUT:     node+13,
 // CHECK:STDOUT:     node+15,
 // CHECK:STDOUT:     node+15,
+// CHECK:STDOUT:   ],
+// CHECK:STDOUT:   [
 // CHECK:STDOUT:     node+16,
 // CHECK:STDOUT:     node+16,
+// CHECK:STDOUT:     node+17,
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 
 

+ 10 - 6
toolchain/semantics/testdata/if/no_else.carbon

@@ -20,24 +20,27 @@
 // CHECK:STDOUT:   b,
 // CHECK:STDOUT:   b,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT:   nodeBoolType,
 // CHECK:STDOUT:   nodeBoolType,
+// CHECK:STDOUT:   node+9,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
-// CHECK:STDOUT:   {kind: VarStorage, type: type1},
-// CHECK:STDOUT:   {kind: BindName, arg0: str3, arg1: node+4, type: type1},
+// CHECK:STDOUT:   {kind: VarStorage, type: type0},
+// CHECK:STDOUT:   {kind: BindName, arg0: str3, arg1: node+4, type: type0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function2},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function2},
 // CHECK:STDOUT:   {kind: BranchIf, arg0: block7, arg1: node+4},
 // CHECK:STDOUT:   {kind: BranchIf, arg0: block7, arg1: node+4},
 // CHECK:STDOUT:   {kind: Branch, arg0: block8},
 // CHECK:STDOUT:   {kind: Branch, arg0: block8},
-// CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function0},
+// CHECK:STDOUT:   {kind: TupleType, arg0: typeBlock0, type: typeTypeType},
+// CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function0, type: type1},
 // CHECK:STDOUT:   {kind: Branch, arg0: block8},
 // CHECK:STDOUT:   {kind: Branch, arg0: block8},
-// CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function1},
+// CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function1, type: type1},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [
@@ -68,10 +71,11 @@
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:     node+9,
 // CHECK:STDOUT:     node+9,
 // CHECK:STDOUT:     node+10,
 // CHECK:STDOUT:     node+10,
+// CHECK:STDOUT:     node+11,
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [
-// CHECK:STDOUT:     node+11,
 // CHECK:STDOUT:     node+12,
 // CHECK:STDOUT:     node+12,
+// CHECK:STDOUT:     node+13,
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 
 

+ 1 - 2
toolchain/semantics/testdata/namespace/fail_duplicate.carbon

@@ -6,7 +6,7 @@
 // CHECK:STDOUT: cross_reference_irs_size: 1
 // CHECK:STDOUT: cross_reference_irs_size: 1
 // CHECK:STDOUT: functions: [
 // CHECK:STDOUT: functions: [
 // CHECK:STDOUT:   {name: str1, param_refs: block0, body: {block2}}},
 // CHECK:STDOUT:   {name: str1, param_refs: block0, body: {block2}}},
-// CHECK:STDOUT:   {name: str8, param_refs: block0, body: {block3}}},
+// CHECK:STDOUT:   {name: str7, param_refs: block0, body: {block3}}},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: integer_literals: [
 // CHECK:STDOUT: integer_literals: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
@@ -17,7 +17,6 @@
 // CHECK:STDOUT:   Baz,
 // CHECK:STDOUT:   Baz,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]

+ 0 - 1
toolchain/semantics/testdata/namespace/fail_unresolved_scope.carbon

@@ -16,7 +16,6 @@
 // CHECK:STDOUT:   Baz,
 // CHECK:STDOUT:   Baz,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]

+ 6 - 2
toolchain/semantics/testdata/namespace/function.carbon

@@ -19,9 +19,11 @@
 // CHECK:STDOUT:   Bar,
 // CHECK:STDOUT:   Bar,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
+// CHECK:STDOUT:   node+6,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: Namespace, arg0: name_scope0},
 // CHECK:STDOUT:   {kind: Namespace, arg0: name_scope0},
@@ -30,7 +32,8 @@
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function2},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function2},
-// CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function1},
+// CHECK:STDOUT:   {kind: TupleType, arg0: typeBlock0, type: typeTypeType},
+// CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function1, type: type0},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [
@@ -51,6 +54,7 @@
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:     node+6,
 // CHECK:STDOUT:     node+6,
 // CHECK:STDOUT:     node+7,
 // CHECK:STDOUT:     node+7,
+// CHECK:STDOUT:     node+8,
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 
 

+ 6 - 2
toolchain/semantics/testdata/namespace/nested.carbon

@@ -19,9 +19,11 @@
 // CHECK:STDOUT:   Baz,
 // CHECK:STDOUT:   Baz,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
+// CHECK:STDOUT:   node+5,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
+// CHECK:STDOUT:   [
+// CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: Namespace, arg0: name_scope0},
 // CHECK:STDOUT:   {kind: Namespace, arg0: name_scope0},
@@ -29,7 +31,8 @@
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function1},
-// CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function0},
+// CHECK:STDOUT:   {kind: TupleType, arg0: typeBlock0, type: typeTypeType},
+// CHECK:STDOUT:   {kind: Call, arg0: block0, arg1: function0, type: type0},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [
@@ -47,6 +50,7 @@
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:     node+5,
 // CHECK:STDOUT:     node+5,
 // CHECK:STDOUT:     node+6,
 // CHECK:STDOUT:     node+6,
+// CHECK:STDOUT:     node+7,
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 
 

+ 6 - 7
toolchain/semantics/testdata/return/code_after_return.carbon

@@ -18,7 +18,6 @@
 // CHECK:STDOUT:   n,
 // CHECK:STDOUT:   n,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
@@ -26,12 +25,12 @@
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
-// CHECK:STDOUT:   {kind: VarStorage, type: type1},
-// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+2, type: type1},
-// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type1},
-// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int1, type: type1},
-// CHECK:STDOUT:   {kind: BinaryOperatorAdd, arg0: node+4, arg1: node+5, type: type1},
-// CHECK:STDOUT:   {kind: Assign, arg0: node+2, arg1: node+6, type: type1},
+// CHECK:STDOUT:   {kind: VarStorage, type: type0},
+// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+2, type: type0},
+// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type0},
+// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int1, type: type0},
+// CHECK:STDOUT:   {kind: BinaryOperatorAdd, arg0: node+4, arg1: node+5, type: type0},
+// CHECK:STDOUT:   {kind: Assign, arg0: node+2, arg1: node+6, type: type0},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [

+ 2 - 3
toolchain/semantics/testdata/return/fail_value_disallowed.carbon

@@ -16,15 +16,14 @@
 // CHECK:STDOUT:   Main,
 // CHECK:STDOUT:   Main,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
-// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type1},
-// CHECK:STDOUT:   {kind: ReturnExpression, arg0: node+1, type: type1},
+// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type0},
+// CHECK:STDOUT:   {kind: ReturnExpression, arg0: node+1, type: type0},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT:   [
 // CHECK:STDOUT:   [

+ 0 - 1
toolchain/semantics/testdata/return/missing_return_no_return_type.carbon

@@ -15,7 +15,6 @@
 // CHECK:STDOUT:   F,
 // CHECK:STDOUT:   F,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]

+ 0 - 1
toolchain/semantics/testdata/return/no_value.carbon

@@ -15,7 +15,6 @@
 // CHECK:STDOUT:   Main,
 // CHECK:STDOUT:   Main,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]

+ 2 - 3
toolchain/semantics/testdata/var/decl.carbon

@@ -16,15 +16,14 @@
 // CHECK:STDOUT:   x,
 // CHECK:STDOUT:   x,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
-// CHECK:STDOUT:   {kind: VarStorage, type: type1},
-// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+1, type: type1},
+// CHECK:STDOUT:   {kind: VarStorage, type: type0},
+// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+1, type: type0},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [

+ 4 - 5
toolchain/semantics/testdata/var/decl_with_init.carbon

@@ -17,17 +17,16 @@
 // CHECK:STDOUT:   x,
 // CHECK:STDOUT:   x,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
-// CHECK:STDOUT:   {kind: VarStorage, type: type1},
-// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+1, type: type1},
-// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type1},
-// CHECK:STDOUT:   {kind: Assign, arg0: node+1, arg1: node+3, type: type1},
+// CHECK:STDOUT:   {kind: VarStorage, type: type0},
+// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+1, type: type0},
+// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type0},
+// CHECK:STDOUT:   {kind: Assign, arg0: node+1, arg1: node+3, type: type0},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [

+ 8 - 9
toolchain/semantics/testdata/var/fail_duplicate_decl.carbon

@@ -18,21 +18,20 @@
 // CHECK:STDOUT:   x,
 // CHECK:STDOUT:   x,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
-// CHECK:STDOUT:   {kind: VarStorage, type: type1},
-// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+1, type: type1},
-// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type1},
-// CHECK:STDOUT:   {kind: Assign, arg0: node+1, arg1: node+3, type: type1},
-// CHECK:STDOUT:   {kind: VarStorage, type: type1},
-// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+5, type: type1},
-// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int1, type: type1},
-// CHECK:STDOUT:   {kind: Assign, arg0: node+5, arg1: node+7, type: type1},
+// CHECK:STDOUT:   {kind: VarStorage, type: type0},
+// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+1, type: type0},
+// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type0},
+// CHECK:STDOUT:   {kind: Assign, arg0: node+1, arg1: node+3, type: type0},
+// CHECK:STDOUT:   {kind: VarStorage, type: type0},
+// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+5, type: type0},
+// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int1, type: type0},
+// CHECK:STDOUT:   {kind: Assign, arg0: node+5, arg1: node+7, type: type0},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [

+ 3 - 4
toolchain/semantics/testdata/var/fail_init_type_mismatch.carbon

@@ -17,7 +17,6 @@
 // CHECK:STDOUT:   x,
 // CHECK:STDOUT:   x,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeFloatingPointType,
 // CHECK:STDOUT:   nodeFloatingPointType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
@@ -25,9 +24,9 @@
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
-// CHECK:STDOUT:   {kind: VarStorage, type: type1},
-// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+1, type: type1},
-// CHECK:STDOUT:   {kind: RealLiteral, arg0: real0, type: type2},
+// CHECK:STDOUT:   {kind: VarStorage, type: type0},
+// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+1, type: type0},
+// CHECK:STDOUT:   {kind: RealLiteral, arg0: real0, type: type1},
 // CHECK:STDOUT:   {kind: Assign, arg0: node+1, arg1: nodeError, type: typeError},
 // CHECK:STDOUT:   {kind: Assign, arg0: node+1, arg1: nodeError, type: typeError},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]

+ 2 - 3
toolchain/semantics/testdata/var/fail_init_with_self.carbon

@@ -16,15 +16,14 @@
 // CHECK:STDOUT:   x,
 // CHECK:STDOUT:   x,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
-// CHECK:STDOUT:   {kind: VarStorage, type: type1},
-// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+1, type: type1},
+// CHECK:STDOUT:   {kind: VarStorage, type: type0},
+// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+1, type: type0},
 // CHECK:STDOUT:   {kind: Assign, arg0: node+1, arg1: nodeError, type: typeError},
 // CHECK:STDOUT:   {kind: Assign, arg0: node+1, arg1: nodeError, type: typeError},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]

+ 4 - 5
toolchain/semantics/testdata/var/fail_lookup_outside_scope.carbon

@@ -17,18 +17,17 @@
 // CHECK:STDOUT:   y,
 // CHECK:STDOUT:   y,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
-// CHECK:STDOUT:   {kind: VarStorage, type: type1},
-// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+1, type: type1},
+// CHECK:STDOUT:   {kind: VarStorage, type: type0},
+// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+1, type: type0},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
-// CHECK:STDOUT:   {kind: VarStorage, type: type1},
-// CHECK:STDOUT:   {kind: BindName, arg0: str2, arg1: node+4, type: type1},
+// CHECK:STDOUT:   {kind: VarStorage, type: type0},
+// CHECK:STDOUT:   {kind: BindName, arg0: str2, arg1: node+4, type: type0},
 // CHECK:STDOUT:   {kind: Assign, arg0: node+4, arg1: nodeError, type: typeError},
 // CHECK:STDOUT:   {kind: Assign, arg0: node+4, arg1: nodeError, type: typeError},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [

+ 2 - 3
toolchain/semantics/testdata/var/fail_storage_is_literal.carbon

@@ -18,17 +18,16 @@
 // CHECK:STDOUT:   x,
 // CHECK:STDOUT:   x,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
-// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type1},
+// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type0},
 // CHECK:STDOUT:   {kind: VarStorage, type: typeError},
 // CHECK:STDOUT:   {kind: VarStorage, type: typeError},
 // CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+2, type: typeError},
 // CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+2, type: typeError},
-// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int1, type: type1},
+// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int1, type: type0},
 // CHECK:STDOUT:   {kind: Assign, arg0: node+2, arg1: nodeError, type: typeError},
 // CHECK:STDOUT:   {kind: Assign, arg0: node+2, arg1: nodeError, type: typeError},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]

+ 0 - 1
toolchain/semantics/testdata/var/global_lookup_in_scope.carbon

@@ -19,7 +19,6 @@
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]

+ 4 - 5
toolchain/semantics/testdata/var/lookup.carbon

@@ -17,17 +17,16 @@
 // CHECK:STDOUT:   x,
 // CHECK:STDOUT:   x,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: types: [
 // CHECK:STDOUT: types: [
-// CHECK:STDOUT:   nodeEmptyTupleType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT:   nodeIntegerType,
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: type_blocks: [
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT: nodes: [
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
 // CHECK:STDOUT:   {kind: FunctionDeclaration, arg0: function0},
-// CHECK:STDOUT:   {kind: VarStorage, type: type1},
-// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+1, type: type1},
-// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type1},
-// CHECK:STDOUT:   {kind: Assign, arg0: node+1, arg1: node+3, type: type1},
+// CHECK:STDOUT:   {kind: VarStorage, type: type0},
+// CHECK:STDOUT:   {kind: BindName, arg0: str1, arg1: node+1, type: type0},
+// CHECK:STDOUT:   {kind: IntegerLiteral, arg0: int0, type: type0},
+// CHECK:STDOUT:   {kind: Assign, arg0: node+1, arg1: node+3, type: type0},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT:   {kind: Return},
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: ]
 // CHECK:STDOUT: node_blocks: [
 // CHECK:STDOUT: node_blocks: [