Kaynağa Gözat

Add evaluation for `conversion` instructions. (#3594)

Also some finessing of evaluation for other instruction kinds and some
additional testing.
Richard Smith 2 yıl önce
ebeveyn
işleme
a2012d4777
58 değiştirilmiş dosya ile 232 ekleme ve 171 silme
  1. 10 10
      toolchain/check/eval.cpp
  2. 1 1
      toolchain/check/testdata/array/array_in_place.carbon
  3. 1 1
      toolchain/check/testdata/array/assign_return_value.carbon
  4. 1 1
      toolchain/check/testdata/array/assign_var.carbon
  5. 1 1
      toolchain/check/testdata/array/base.carbon
  6. 2 2
      toolchain/check/testdata/array/fail_type_mismatch.carbon
  7. 1 1
      toolchain/check/testdata/as/as_type.carbon
  8. 2 2
      toolchain/check/testdata/as/fail_no_conversion.carbon
  9. 4 4
      toolchain/check/testdata/as/tuple.carbon
  10. 1 0
      toolchain/check/testdata/basics/raw_and_textual_ir.carbon
  11. 1 0
      toolchain/check/testdata/basics/raw_ir.carbon
  12. 1 1
      toolchain/check/testdata/class/fail_base_bad_type.carbon
  13. 62 37
      toolchain/check/testdata/class/method.carbon
  14. 1 1
      toolchain/check/testdata/expr_category/in_place_tuple_init.carbon
  15. 1 1
      toolchain/check/testdata/function/call/empty_struct.carbon
  16. 1 1
      toolchain/check/testdata/function/call/empty_tuple.carbon
  17. 1 1
      toolchain/check/testdata/function/call/more_param_ir.carbon
  18. 1 1
      toolchain/check/testdata/function/call/return_implicit.carbon
  19. 1 1
      toolchain/check/testdata/index/fail_invalid_base.carbon
  20. 1 1
      toolchain/check/testdata/index/fail_non_deterministic_type.carbon
  21. 1 1
      toolchain/check/testdata/index/fail_tuple_index_error.carbon
  22. 2 2
      toolchain/check/testdata/index/fail_tuple_large_index.carbon
  23. 1 1
      toolchain/check/testdata/index/fail_tuple_non_int_indexing.carbon
  24. 1 1
      toolchain/check/testdata/index/fail_tuple_out_of_bound_access.carbon
  25. 2 2
      toolchain/check/testdata/index/tuple_element_access.carbon
  26. 1 1
      toolchain/check/testdata/index/tuple_return_value_access.carbon
  27. 2 2
      toolchain/check/testdata/let/convert.carbon
  28. 4 4
      toolchain/check/testdata/namespace/imported.carbon
  29. 1 1
      toolchain/check/testdata/namespace/imported_indirect.carbon
  30. 1 1
      toolchain/check/testdata/operators/assignment.carbon
  31. 2 2
      toolchain/check/testdata/operators/fail_assignment_to_non_assignable.carbon
  32. 1 1
      toolchain/check/testdata/packages/fail_name_with_import_failure.carbon
  33. 1 1
      toolchain/check/testdata/packages/fail_todo_lazy_import_ref.carbon
  34. 4 4
      toolchain/check/testdata/packages/loaded_global.carbon
  35. 1 1
      toolchain/check/testdata/pointer/address_of_lvalue.carbon
  36. 1 1
      toolchain/check/testdata/pointer/fail_address_of_value.carbon
  37. 2 2
      toolchain/check/testdata/pointer/fail_deref_not_pointer.carbon
  38. 1 1
      toolchain/check/testdata/return/fail_returned_var_no_return_type.carbon
  39. 1 1
      toolchain/check/testdata/return/struct.carbon
  40. 2 2
      toolchain/check/testdata/struct/empty.carbon
  41. 1 1
      toolchain/check/testdata/struct/fail_assign_nested.carbon
  42. 1 1
      toolchain/check/testdata/struct/fail_assign_to_empty.carbon
  43. 2 2
      toolchain/check/testdata/struct/nested_struct_in_place.carbon
  44. 2 2
      toolchain/check/testdata/struct/tuple_as_element.carbon
  45. 37 21
      toolchain/check/testdata/struct/two_entries.carbon
  46. 2 2
      toolchain/check/testdata/tuples/empty.carbon
  47. 1 1
      toolchain/check/testdata/tuples/fail_assign_empty.carbon
  48. 3 3
      toolchain/check/testdata/tuples/fail_assign_nested.carbon
  49. 1 1
      toolchain/check/testdata/tuples/fail_assign_to_empty.carbon
  50. 1 1
      toolchain/check/testdata/tuples/fail_element_type_mismatch.carbon
  51. 1 1
      toolchain/check/testdata/tuples/fail_nested_incomplete.carbon
  52. 1 1
      toolchain/check/testdata/tuples/fail_too_few_element.carbon
  53. 1 1
      toolchain/check/testdata/tuples/fail_type_assign.carbon
  54. 1 1
      toolchain/check/testdata/tuples/fail_value_as_type.carbon
  55. 2 2
      toolchain/check/testdata/tuples/nested_tuple.carbon
  56. 5 5
      toolchain/check/testdata/tuples/nested_tuple_in_place.carbon
  57. 2 2
      toolchain/check/testdata/tuples/one_element.carbon
  58. 41 23
      toolchain/check/testdata/tuples/two_elements.carbon

+ 10 - 10
toolchain/check/eval.cpp

@@ -77,6 +77,9 @@ static auto RebuildIfFieldsAreConstant(Context& context, SemIR::Inst inst,
 
 auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
     -> SemIR::InstId {
+  // TODO: Ensure we have test coverage for each of these cases that can result
+  // in a constant, once those situations are all reachable.
+
   // clang warns on unhandled enum values; clang-tidy is incorrect here.
   // NOLINTNEXTLINE(bugprone-switch-missing-default-case)
   switch (inst.kind()) {
@@ -84,10 +87,6 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
     case SemIR::AddrOf::Kind:
       return RebuildIfFieldsAreConstant(context, inst,
                                         &SemIR::AddrOf::lvalue_id);
-    case SemIR::ArrayIndex::Kind:
-      return RebuildIfFieldsAreConstant(context, inst,
-                                        &SemIR::ArrayIndex::array_id,
-                                        &SemIR::ArrayIndex::index_id);
     case SemIR::ArrayType::Kind:
       return RebuildIfFieldsAreConstant(context, inst,
                                         &SemIR::ArrayType::bound_id);
@@ -129,18 +128,18 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
       return context.AddConstantInst(inst);
 
     // TODO: These need special handling.
-    case SemIR::StructInit::Kind:
+    case SemIR::ArrayIndex::Kind:
     case SemIR::ArrayInit::Kind:
     case SemIR::BindValue::Kind:
     case SemIR::Call::Kind:
     case SemIR::ClassElementAccess::Kind:
     case SemIR::ClassInit::Kind:
-    case SemIR::Converted::Kind:
     case SemIR::CrossRef::Kind:
     case SemIR::Deref::Kind:
     case SemIR::InitializeFrom::Kind:
     case SemIR::SpliceBlock::Kind:
     case SemIR::StructAccess::Kind:
+    case SemIR::StructInit::Kind:
     case SemIR::TemporaryStorage::Kind:
     case SemIR::TupleAccess::Kind:
     case SemIR::TupleIndex::Kind:
@@ -150,15 +149,16 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
       break;
 
     case SemIR::BindName::Kind:
-    case SemIR::BindSymbolicName::Kind: {
+    case SemIR::BindSymbolicName::Kind:
       // TODO: Should we really be looking through runtime and symbolic `let`
       // bindings?
       return GetConstantValue(context, inst.As<SemIR::AnyBindName>().value_id);
-    }
 
-    case SemIR::NameRef::Kind: {
+    case SemIR::NameRef::Kind:
       return GetConstantValue(context, inst.As<SemIR::NameRef>().value_id);
-    }
+
+    case SemIR::Converted::Kind:
+      return GetConstantValue(context, inst.As<SemIR::Converted>().result_id);
 
     case SemIR::UnaryOperatorNot::Kind: {
       auto const_id = GetConstantValue(

+ 1 - 1
toolchain/check/testdata/array/array_in_place.carbon

@@ -34,7 +34,7 @@ fn G() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc10_25: (type, type, type) = tuple_literal (i32, i32, i32)
 // CHECK:STDOUT:   %.loc10_28: i32 = int_literal 2, const = constants.%.loc10_28
-// CHECK:STDOUT:   %.loc7: type = converted %.loc10_25, constants.%.loc7_25.2
+// CHECK:STDOUT:   %.loc7: type = converted %.loc10_25, constants.%.loc7_25.2, const = constants.%.loc7_25.2
 // CHECK:STDOUT:   %.loc10_29: type = array_type %.loc10_28, (i32, i32, i32), const = constants.%.loc10_29.1
 // CHECK:STDOUT:   %v.var: ref [(i32, i32, i32); 2] = var v
 // CHECK:STDOUT:   %v: ref [(i32, i32, i32); 2] = bind_name v, %v.var

+ 1 - 1
toolchain/check/testdata/array/assign_return_value.carbon

@@ -33,7 +33,7 @@ fn Run() {
 // CHECK:STDOUT:   %.loc7_28: i32 = int_literal 0, const = constants.%.loc7_28
 // CHECK:STDOUT:   %.loc7_30.1: (i32,) = tuple_literal (%.loc7_28)
 // CHECK:STDOUT:   %.loc7_30.2: (i32,) = tuple_value (%.loc7_28), const = constants.%.loc7_30
-// CHECK:STDOUT:   %.loc7_30.3: (i32,) = converted %.loc7_30.1, %.loc7_30.2
+// CHECK:STDOUT:   %.loc7_30.3: (i32,) = converted %.loc7_30.1, %.loc7_30.2, const = constants.%.loc7_30
 // CHECK:STDOUT:   return %.loc7_30.3
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 1 - 1
toolchain/check/testdata/array/assign_var.carbon

@@ -24,7 +24,7 @@ var b: [i32; 3] = a;
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.a = %a, .b = %b}
 // CHECK:STDOUT:   %.loc7_22.1: (type, type, type) = tuple_literal (i32, i32, i32)
-// CHECK:STDOUT:   %.loc7_22.2: type = converted %.loc7_22.1, constants.%.loc7_22.2
+// CHECK:STDOUT:   %.loc7_22.2: type = converted %.loc7_22.1, constants.%.loc7_22.2, const = constants.%.loc7_22.2
 // CHECK:STDOUT:   %a.var: ref (i32, i32, i32) = var a
 // CHECK:STDOUT:   %a: ref (i32, i32, i32) = bind_name a, %a.var
 // CHECK:STDOUT:   %.loc7_27: i32 = int_literal 1, const = constants.%.loc7_27

+ 1 - 1
toolchain/check/testdata/array/base.carbon

@@ -61,7 +61,7 @@ var c: [(); 5] = ((), (), (), (), (),);
 // CHECK:STDOUT:   assign %b.var, %.loc8_30.9
 // CHECK:STDOUT:   %.loc9_10.1: () = tuple_literal ()
 // CHECK:STDOUT:   %.loc9_13: i32 = int_literal 5, const = constants.%.loc9_13
-// CHECK:STDOUT:   %.loc9_10.2: type = converted %.loc9_10.1, constants.%.loc9_10
+// CHECK:STDOUT:   %.loc9_10.2: type = converted %.loc9_10.1, constants.%.loc9_10, const = constants.%.loc9_10
 // CHECK:STDOUT:   %.loc9_14: type = array_type %.loc9_13, (), const = constants.%.loc9_14.1
 // CHECK:STDOUT:   %c.var: ref [(); 5] = var c
 // CHECK:STDOUT:   %c: ref [(); 5] = bind_name c, %c.var

+ 2 - 2
toolchain/check/testdata/array/fail_type_mismatch.carbon

@@ -68,7 +68,7 @@ var d: [i32; 3] = t2;
 // CHECK:STDOUT:   %.loc10_39.4: init i32 = initialize_from %.loc10_20 to %.loc10_39.3
 // CHECK:STDOUT:   assign %a.var, <error>
 // CHECK:STDOUT:   %.loc12: (type, type, type) = tuple_literal (i32, String, String)
-// CHECK:STDOUT:   %.loc10_39.5: type = converted %.loc12, constants.%.loc10_39.1
+// CHECK:STDOUT:   %.loc10_39.5: type = converted %.loc12, constants.%.loc10_39.1, const = constants.%.loc10_39.1
 // CHECK:STDOUT:   %t1.var: ref (i32, String, String) = var t1
 // CHECK:STDOUT:   %t1: ref (i32, String, String) = bind_name t1, %t1.var
 // CHECK:STDOUT:   %.loc16_14: i32 = int_literal 3, const = constants.%.loc16_14
@@ -92,7 +92,7 @@ var d: [i32; 3] = t2;
 // CHECK:STDOUT:   %.loc21_24.1: (i32, i32) = tuple_literal (%.loc21_20, %.loc21_23)
 // CHECK:STDOUT:   assign %c.var, <error>
 // CHECK:STDOUT:   %.loc23: (type, type) = tuple_literal (i32, i32)
-// CHECK:STDOUT:   %.loc21_24.2: type = converted %.loc23, constants.%.loc21_24.1
+// CHECK:STDOUT:   %.loc21_24.2: type = converted %.loc23, constants.%.loc21_24.1, const = constants.%.loc21_24.1
 // CHECK:STDOUT:   %t2.var: ref (i32, i32) = var t2
 // CHECK:STDOUT:   %t2: ref (i32, i32) = bind_name t2, %t2.var
 // CHECK:STDOUT:   %.loc27_14: i32 = int_literal 3, const = constants.%.loc27_14

+ 1 - 1
toolchain/check/testdata/as/as_type.carbon

@@ -16,7 +16,7 @@ let t: type = (i32, i32) as type;
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {}
 // CHECK:STDOUT:   %.loc7_24: (type, type) = tuple_literal (i32, i32)
-// CHECK:STDOUT:   %.loc7_26: type = converted %.loc7_24, constants.%.loc7_26
+// CHECK:STDOUT:   %.loc7_26: type = converted %.loc7_24, constants.%.loc7_26, const = constants.%.loc7_26
 // CHECK:STDOUT:   %t: type = bind_name t, %.loc7_26
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 2 - 2
toolchain/check/testdata/as/fail_no_conversion.carbon

@@ -21,10 +21,10 @@ let n: (i32, i32) = 1 as (i32, i32);
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {}
 // CHECK:STDOUT:   %.loc10_17.1: (type, type) = tuple_literal (i32, i32)
-// CHECK:STDOUT:   %.loc10_17.2: type = converted %.loc10_17.1, constants.%.loc10_17.2
+// CHECK:STDOUT:   %.loc10_17.2: type = converted %.loc10_17.1, constants.%.loc10_17.2, const = constants.%.loc10_17.2
 // CHECK:STDOUT:   %.loc10_21: i32 = int_literal 1, const = constants.%.loc10_21
 // CHECK:STDOUT:   %.loc10_35: (type, type) = tuple_literal (i32, i32)
-// CHECK:STDOUT:   %.loc10_17.3: type = converted %.loc10_35, constants.%.loc10_17.2
+// CHECK:STDOUT:   %.loc10_17.3: type = converted %.loc10_35, constants.%.loc10_17.2, const = constants.%.loc10_17.2
 // CHECK:STDOUT:   %n: (i32, i32) = bind_name n, <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 4 - 4
toolchain/check/testdata/as/tuple.carbon

@@ -53,7 +53,7 @@ fn Var() {
 // CHECK:STDOUT:   %X.ref.loc15_11: type = name_ref X, file.%X, const = file.%X
 // CHECK:STDOUT:   %X.ref.loc15_14: type = name_ref X, file.%X, const = file.%X
 // CHECK:STDOUT:   %.loc15_15.1: (type, type) = tuple_literal (%X.ref.loc15_11, %X.ref.loc15_14)
-// CHECK:STDOUT:   %.loc15_15.2: type = converted %.loc15_15.1, constants.%.loc15_15.2
+// CHECK:STDOUT:   %.loc15_15.2: type = converted %.loc15_15.1, constants.%.loc15_15.2, const = constants.%.loc15_15.2
 // CHECK:STDOUT:   %Make.ref.loc15_20: <function> = name_ref Make, file.%Make, const = file.%Make
 // CHECK:STDOUT:   %.loc15_24.1: ref X = temporary_storage
 // CHECK:STDOUT:   %.loc15_24.2: init X = call %Make.ref.loc15_20() to %.loc15_24.1
@@ -64,7 +64,7 @@ fn Var() {
 // CHECK:STDOUT:   %X.ref.loc15_40: type = name_ref X, file.%X, const = file.%X
 // CHECK:STDOUT:   %X.ref.loc15_43: type = name_ref X, file.%X, const = file.%X
 // CHECK:STDOUT:   %.loc15_44: (type, type) = tuple_literal (%X.ref.loc15_40, %X.ref.loc15_43)
-// CHECK:STDOUT:   %.loc15_15.3: type = converted %.loc15_44, constants.%.loc15_15.2
+// CHECK:STDOUT:   %.loc15_15.3: type = converted %.loc15_44, constants.%.loc15_15.2, const = constants.%.loc15_15.2
 // CHECK:STDOUT:   %.loc15_24.3: ref X = temporary %.loc15_24.1, %.loc15_24.2
 // CHECK:STDOUT:   %.loc15_24.4: X = bind_value %.loc15_24.3
 // CHECK:STDOUT:   %.loc15_32.3: ref X = temporary %.loc15_32.1, %.loc15_32.2
@@ -80,7 +80,7 @@ fn Var() {
 // CHECK:STDOUT:   %X.ref.loc20_11: type = name_ref X, file.%X, const = file.%X
 // CHECK:STDOUT:   %X.ref.loc20_14: type = name_ref X, file.%X, const = file.%X
 // CHECK:STDOUT:   %.loc20_15: (type, type) = tuple_literal (%X.ref.loc20_11, %X.ref.loc20_14)
-// CHECK:STDOUT:   %.loc15_15.1: type = converted %.loc20_15, constants.%.loc15_15.2
+// CHECK:STDOUT:   %.loc15_15.1: type = converted %.loc20_15, constants.%.loc15_15.2, const = constants.%.loc15_15.2
 // CHECK:STDOUT:   %b.var: ref (X, X) = var b
 // CHECK:STDOUT:   %b: ref (X, X) = bind_name b, %b.var
 // CHECK:STDOUT:   %Make.ref.loc20_20: <function> = name_ref Make, file.%Make, const = file.%Make
@@ -93,7 +93,7 @@ fn Var() {
 // CHECK:STDOUT:   %X.ref.loc20_40: type = name_ref X, file.%X, const = file.%X
 // CHECK:STDOUT:   %X.ref.loc20_43: type = name_ref X, file.%X, const = file.%X
 // CHECK:STDOUT:   %.loc20_44: (type, type) = tuple_literal (%X.ref.loc20_40, %X.ref.loc20_43)
-// CHECK:STDOUT:   %.loc15_15.2: type = converted %.loc20_44, constants.%.loc15_15.2
+// CHECK:STDOUT:   %.loc15_15.2: type = converted %.loc20_44, constants.%.loc15_15.2, const = constants.%.loc15_15.2
 // CHECK:STDOUT:   %.loc20_34.4: init (X, X) = tuple_init (%.loc20_24, %.loc20_32) to %b.var
 // CHECK:STDOUT:   %.loc20_34.5: init (X, X) = converted %.loc20_34.3, %.loc20_34.4
 // CHECK:STDOUT:   assign %b.var, %.loc20_34.5

+ 1 - 0
toolchain/check/testdata/basics/raw_and_textual_ir.carbon

@@ -69,6 +69,7 @@ fn Foo(n: i32) -> (i32, i32, f64) {
 // CHECK:STDOUT:   constant_values:
 // CHECK:STDOUT:     inst+3:          inst+3
 // CHECK:STDOUT:     inst+5:          inst+5
+// CHECK:STDOUT:     inst+6:          inst+5
 // CHECK:STDOUT:     inst+8:          inst+8
 // CHECK:STDOUT:     inst+9:          inst+9
 // CHECK:STDOUT:     inst+11:         inst+12

+ 1 - 0
toolchain/check/testdata/basics/raw_ir.carbon

@@ -69,6 +69,7 @@ fn Foo(n: i32) -> (i32, i32, f64) {
 // CHECK:STDOUT:   constant_values:
 // CHECK:STDOUT:     inst+3:          inst+3
 // CHECK:STDOUT:     inst+5:          inst+5
+// CHECK:STDOUT:     inst+6:          inst+5
 // CHECK:STDOUT:     inst+8:          inst+8
 // CHECK:STDOUT:     inst+9:          inst+9
 // CHECK:STDOUT:     inst+11:         inst+12

+ 1 - 1
toolchain/check/testdata/class/fail_base_bad_type.carbon

@@ -220,7 +220,7 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT: class @DeriveFromTuple {
 // CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base, const = file.%Base
 // CHECK:STDOUT:   %.loc51_22: (type,) = tuple_literal (%Base.ref)
-// CHECK:STDOUT:   %.loc51_23.1: type = converted %.loc51_22, constants.%.loc51_23.1
+// CHECK:STDOUT:   %.loc51_23.1: type = converted %.loc51_22, constants.%.loc51_23.1, const = constants.%.loc51_23.1
 // CHECK:STDOUT:   %.loc51_23.2: type = unbound_element_type DeriveFromTuple, <error>, const
 // CHECK:STDOUT:   %.loc51_23.3: <unbound element of class DeriveFromTuple> = base_decl <error>, element0, const
 // CHECK:STDOUT:

+ 62 - 37
toolchain/check/testdata/class/method.carbon

@@ -21,6 +21,10 @@ fn Call(c: Class) -> i32 {
   return c.F();
 }
 
+fn CallOnConstBoundMethod() -> i32 {
+  return ({.k = 1} as Class).F();
+}
+
 fn CallWithAddr() -> i32 {
   var c: Class;
   return c.G();
@@ -49,14 +53,16 @@ fn CallGOnInitializingExpr() -> i32 {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %.loc12: type = struct_type {.k: i32}, const
 // CHECK:STDOUT:   %.loc7: type = ptr_type {.k: i32}, const
+// CHECK:STDOUT:   %.loc25: i32 = int_literal 1, const
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
-// CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .Call = %Call, .CallWithAddr = %CallWithAddr, .CallFThroughPointer = %CallFThroughPointer, .CallGThroughPointer = %CallGThroughPointer, .Make = %Make, .CallFOnInitializingExpr = %CallFOnInitializingExpr, .CallGOnInitializingExpr = %CallGOnInitializingExpr}
+// CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .Call = %Call, .CallOnConstBoundMethod = %CallOnConstBoundMethod, .CallWithAddr = %CallWithAddr, .CallFThroughPointer = %CallFThroughPointer, .CallGThroughPointer = %CallGThroughPointer, .Make = %Make, .CallFOnInitializingExpr = %CallFOnInitializingExpr, .CallGOnInitializingExpr = %CallGOnInitializingExpr}
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
 // CHECK:STDOUT:   %Class: type = class_type @Class, const
 // CHECK:STDOUT:   %F: <function> = fn_decl @F, const
 // CHECK:STDOUT:   %Call: <function> = fn_decl @Call, const
+// CHECK:STDOUT:   %CallOnConstBoundMethod: <function> = fn_decl @CallOnConstBoundMethod, const
 // CHECK:STDOUT:   %CallWithAddr: <function> = fn_decl @CallWithAddr, const
 // CHECK:STDOUT:   %CallFThroughPointer: <function> = fn_decl @CallFThroughPointer, const
 // CHECK:STDOUT:   %CallGThroughPointer: <function> = fn_decl @CallGThroughPointer, const
@@ -98,71 +104,90 @@ fn CallGOnInitializingExpr() -> i32 {
 // CHECK:STDOUT:   return %.loc21_15.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: fn @CallOnConstBoundMethod() -> i32 {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %.loc25_17: i32 = int_literal 1, const = constants.%.loc25
+// CHECK:STDOUT:   %.loc25_18.1: {.k: i32} = struct_literal (%.loc25_17)
+// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class, const = file.%Class
+// CHECK:STDOUT:   %.loc25_18.2: ref Class = temporary_storage
+// CHECK:STDOUT:   %.loc25_18.3: ref i32 = class_element_access %.loc25_18.2, element0
+// CHECK:STDOUT:   %.loc25_18.4: init i32 = initialize_from %.loc25_17 to %.loc25_18.3
+// CHECK:STDOUT:   %.loc25_18.5: init Class = class_init (%.loc25_18.4), %.loc25_18.2
+// CHECK:STDOUT:   %.loc25_18.6: ref Class = temporary %.loc25_18.2, %.loc25_18.5
+// CHECK:STDOUT:   %.loc25_18.7: ref Class = converted %.loc25_18.1, %.loc25_18.6
+// CHECK:STDOUT:   %.loc25_29: <bound method> = bound_method %.loc25_18.7, @Class.%F
+// CHECK:STDOUT:   %.loc25_18.8: Class = bind_value %.loc25_18.7
+// CHECK:STDOUT:   %.loc25_31: init i32 = call %.loc25_29(%.loc25_18.8)
+// CHECK:STDOUT:   %.loc25_33.1: i32 = value_of_initializer %.loc25_31
+// CHECK:STDOUT:   %.loc25_33.2: i32 = converted %.loc25_31, %.loc25_33.1
+// CHECK:STDOUT:   return %.loc25_33.2
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
 // CHECK:STDOUT: fn @CallWithAddr() -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class, const = file.%Class
 // CHECK:STDOUT:   %c.var: ref Class = var c
 // CHECK:STDOUT:   %c: ref Class = bind_name c, %c.var
 // CHECK:STDOUT:   %c.ref: ref Class = name_ref c, %c
-// CHECK:STDOUT:   %.loc26_11: <bound method> = bound_method %c.ref, @Class.%G
-// CHECK:STDOUT:   %.loc26_10: Class* = addr_of %c.ref
-// CHECK:STDOUT:   %.loc26_13: init i32 = call %.loc26_11(%.loc26_10)
-// CHECK:STDOUT:   %.loc26_15.1: i32 = value_of_initializer %.loc26_13
-// CHECK:STDOUT:   %.loc26_15.2: i32 = converted %.loc26_13, %.loc26_15.1
-// CHECK:STDOUT:   return %.loc26_15.2
+// CHECK:STDOUT:   %.loc30_11: <bound method> = bound_method %c.ref, @Class.%G
+// CHECK:STDOUT:   %.loc30_10: Class* = addr_of %c.ref
+// CHECK:STDOUT:   %.loc30_13: init i32 = call %.loc30_11(%.loc30_10)
+// CHECK:STDOUT:   %.loc30_15.1: i32 = value_of_initializer %.loc30_13
+// CHECK:STDOUT:   %.loc30_15.2: i32 = converted %.loc30_13, %.loc30_15.1
+// CHECK:STDOUT:   return %.loc30_15.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @CallFThroughPointer(%p: Class*) -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %p.ref: Class* = name_ref p, %p
-// CHECK:STDOUT:   %.loc30_11.1: ref Class = deref %p.ref
-// CHECK:STDOUT:   %.loc30_14: <bound method> = bound_method %.loc30_11.1, @Class.%F
-// CHECK:STDOUT:   %.loc30_11.2: Class = bind_value %.loc30_11.1
-// CHECK:STDOUT:   %.loc30_16: init i32 = call %.loc30_14(%.loc30_11.2)
-// CHECK:STDOUT:   %.loc30_18.1: i32 = value_of_initializer %.loc30_16
-// CHECK:STDOUT:   %.loc30_18.2: i32 = converted %.loc30_16, %.loc30_18.1
-// CHECK:STDOUT:   return %.loc30_18.2
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: fn @CallGThroughPointer(%p: Class*) -> i32 {
-// CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %p.ref: Class* = name_ref p, %p
 // CHECK:STDOUT:   %.loc34_11.1: ref Class = deref %p.ref
-// CHECK:STDOUT:   %.loc34_14: <bound method> = bound_method %.loc34_11.1, @Class.%G
-// CHECK:STDOUT:   %.loc34_11.2: Class* = addr_of %.loc34_11.1
+// CHECK:STDOUT:   %.loc34_14: <bound method> = bound_method %.loc34_11.1, @Class.%F
+// CHECK:STDOUT:   %.loc34_11.2: Class = bind_value %.loc34_11.1
 // CHECK:STDOUT:   %.loc34_16: init i32 = call %.loc34_14(%.loc34_11.2)
 // CHECK:STDOUT:   %.loc34_18.1: i32 = value_of_initializer %.loc34_16
 // CHECK:STDOUT:   %.loc34_18.2: i32 = converted %.loc34_16, %.loc34_18.1
 // CHECK:STDOUT:   return %.loc34_18.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @Make() -> %return: Class;
-// CHECK:STDOUT:
-// CHECK:STDOUT: fn @CallFOnInitializingExpr() -> i32 {
+// CHECK:STDOUT: fn @CallGThroughPointer(%p: Class*) -> i32 {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %Make.ref: <function> = name_ref Make, file.%Make, const = file.%Make
-// CHECK:STDOUT:   %.loc40_14.1: ref Class = temporary_storage
-// CHECK:STDOUT:   %.loc40_14.2: init Class = call %Make.ref() to %.loc40_14.1
-// CHECK:STDOUT:   %.loc40_14.3: ref Class = temporary %.loc40_14.1, %.loc40_14.2
-// CHECK:STDOUT:   %.loc40_16: <bound method> = bound_method %.loc40_14.3, @Class.%F
-// CHECK:STDOUT:   %.loc40_14.4: Class = bind_value %.loc40_14.3
-// CHECK:STDOUT:   %.loc40_18: init i32 = call %.loc40_16(%.loc40_14.4)
-// CHECK:STDOUT:   %.loc40_20.1: i32 = value_of_initializer %.loc40_18
-// CHECK:STDOUT:   %.loc40_20.2: i32 = converted %.loc40_18, %.loc40_20.1
-// CHECK:STDOUT:   return %.loc40_20.2
+// CHECK:STDOUT:   %p.ref: Class* = name_ref p, %p
+// CHECK:STDOUT:   %.loc38_11.1: ref Class = deref %p.ref
+// CHECK:STDOUT:   %.loc38_14: <bound method> = bound_method %.loc38_11.1, @Class.%G
+// CHECK:STDOUT:   %.loc38_11.2: Class* = addr_of %.loc38_11.1
+// CHECK:STDOUT:   %.loc38_16: init i32 = call %.loc38_14(%.loc38_11.2)
+// CHECK:STDOUT:   %.loc38_18.1: i32 = value_of_initializer %.loc38_16
+// CHECK:STDOUT:   %.loc38_18.2: i32 = converted %.loc38_16, %.loc38_18.1
+// CHECK:STDOUT:   return %.loc38_18.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @CallGOnInitializingExpr() -> i32 {
+// CHECK:STDOUT: fn @Make() -> %return: Class;
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @CallFOnInitializingExpr() -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Make.ref: <function> = name_ref Make, file.%Make, const = file.%Make
 // CHECK:STDOUT:   %.loc44_14.1: ref Class = temporary_storage
 // CHECK:STDOUT:   %.loc44_14.2: init Class = call %Make.ref() to %.loc44_14.1
 // CHECK:STDOUT:   %.loc44_14.3: ref Class = temporary %.loc44_14.1, %.loc44_14.2
-// CHECK:STDOUT:   %.loc44_16: <bound method> = bound_method %.loc44_14.3, @Class.%G
-// CHECK:STDOUT:   %.loc44_14.4: Class* = addr_of %.loc44_14.3
+// CHECK:STDOUT:   %.loc44_16: <bound method> = bound_method %.loc44_14.3, @Class.%F
+// CHECK:STDOUT:   %.loc44_14.4: Class = bind_value %.loc44_14.3
 // CHECK:STDOUT:   %.loc44_18: init i32 = call %.loc44_16(%.loc44_14.4)
 // CHECK:STDOUT:   %.loc44_20.1: i32 = value_of_initializer %.loc44_18
 // CHECK:STDOUT:   %.loc44_20.2: i32 = converted %.loc44_18, %.loc44_20.1
 // CHECK:STDOUT:   return %.loc44_20.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: fn @CallGOnInitializingExpr() -> i32 {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %Make.ref: <function> = name_ref Make, file.%Make, const = file.%Make
+// CHECK:STDOUT:   %.loc48_14.1: ref Class = temporary_storage
+// CHECK:STDOUT:   %.loc48_14.2: init Class = call %Make.ref() to %.loc48_14.1
+// CHECK:STDOUT:   %.loc48_14.3: ref Class = temporary %.loc48_14.1, %.loc48_14.2
+// CHECK:STDOUT:   %.loc48_16: <bound method> = bound_method %.loc48_14.3, @Class.%G
+// CHECK:STDOUT:   %.loc48_14.4: Class* = addr_of %.loc48_14.3
+// CHECK:STDOUT:   %.loc48_18: init i32 = call %.loc48_16(%.loc48_14.4)
+// CHECK:STDOUT:   %.loc48_20.1: i32 = value_of_initializer %.loc48_18
+// CHECK:STDOUT:   %.loc48_20.2: i32 = converted %.loc48_18, %.loc48_20.1
+// CHECK:STDOUT:   return %.loc48_20.2
+// CHECK:STDOUT: }
+// CHECK:STDOUT:

+ 1 - 1
toolchain/check/testdata/expr_category/in_place_tuple_init.carbon

@@ -37,7 +37,7 @@ fn H() -> i32 {
 // CHECK:STDOUT: fn @G() -> %return: (i32, i32) {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc10_19: (type, type) = tuple_literal (i32, i32)
-// CHECK:STDOUT:   %.loc7: type = converted %.loc10_19, constants.%.loc7_20.2
+// CHECK:STDOUT:   %.loc7: type = converted %.loc10_19, constants.%.loc7_20.2, const = constants.%.loc7_20.2
 // CHECK:STDOUT:   %v.var: ref (i32, i32) = var v
 // CHECK:STDOUT:   %v: ref (i32, i32) = bind_name v, %v.var
 // CHECK:STDOUT:   %F.ref.loc10: <function> = name_ref F, file.%F, const = file.%F

+ 1 - 1
toolchain/check/testdata/function/call/empty_struct.carbon

@@ -37,7 +37,7 @@ fn Main() {
 // CHECK:STDOUT:   %Echo.ref: <function> = name_ref Echo, file.%Echo, const = file.%Echo
 // CHECK:STDOUT:   %.loc12_9.1: {} = struct_literal ()
 // CHECK:STDOUT:   %.loc12_9.2: {} = struct_value (), const = constants.%.loc12
-// CHECK:STDOUT:   %.loc12_9.3: {} = converted %.loc12_9.1, %.loc12_9.2
+// CHECK:STDOUT:   %.loc12_9.3: {} = converted %.loc12_9.1, %.loc12_9.2, const = constants.%.loc12
 // CHECK:STDOUT:   %.loc12_7: init {} = call %Echo.ref(%.loc12_9.3)
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 1 - 1
toolchain/check/testdata/function/call/empty_tuple.carbon

@@ -36,7 +36,7 @@ fn Main() {
 // CHECK:STDOUT:   %Echo.ref: <function> = name_ref Echo, file.%Echo, const = file.%Echo
 // CHECK:STDOUT:   %.loc12_9.1: () = tuple_literal ()
 // CHECK:STDOUT:   %.loc12_9.2: () = tuple_value (), const = constants.%.loc12
-// CHECK:STDOUT:   %.loc12_9.3: () = converted %.loc12_9.1, %.loc12_9.2
+// CHECK:STDOUT:   %.loc12_9.3: () = converted %.loc12_9.1, %.loc12_9.2, const = constants.%.loc12
 // CHECK:STDOUT:   %.loc12_7: init () = call %Echo.ref(%.loc12_9.3)
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 1 - 1
toolchain/check/testdata/function/call/more_param_ir.carbon

@@ -37,7 +37,7 @@ fn Main() {
 // CHECK:STDOUT: fn @Main() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc10_15.1: (type,) = tuple_literal (i32)
-// CHECK:STDOUT:   %.loc10_15.2: type = converted %.loc10_15.1, constants.%.loc10_15.2
+// CHECK:STDOUT:   %.loc10_15.2: type = converted %.loc10_15.1, constants.%.loc10_15.2, const = constants.%.loc10_15.2
 // CHECK:STDOUT:   %x.var: ref (i32,) = var x
 // CHECK:STDOUT:   %x: ref (i32,) = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc10_20: i32 = int_literal 1, const = constants.%.loc10_20

+ 1 - 1
toolchain/check/testdata/function/call/return_implicit.carbon

@@ -31,7 +31,7 @@ fn Main() {
 // CHECK:STDOUT: fn @Main() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc11_11.1: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc11_11.2: type = converted %.loc11_11.1, constants.%.loc11
+// CHECK:STDOUT:   %.loc11_11.2: type = converted %.loc11_11.1, constants.%.loc11, const = constants.%.loc11
 // CHECK:STDOUT:   %b.var: ref () = var b
 // CHECK:STDOUT:   %b: ref () = bind_name b, %b.var
 // CHECK:STDOUT:   %MakeImplicitEmptyTuple.ref: <function> = name_ref MakeImplicitEmptyTuple, file.%MakeImplicitEmptyTuple, const = file.%MakeImplicitEmptyTuple

+ 1 - 1
toolchain/check/testdata/index/fail_invalid_base.carbon

@@ -65,7 +65,7 @@ var d: i32 = {.a: i32, .b: i32}[0];
 // CHECK:STDOUT:   %.loc26_29.1: {.a: i32, .b: i32} = struct_literal (%.loc26_20, %.loc26_28)
 // CHECK:STDOUT:   %.loc26_31: i32 = int_literal 0, const = constants.%.loc26_31
 // CHECK:STDOUT:   %.loc26_29.2: {.a: i32, .b: i32} = struct_value (%.loc26_20, %.loc26_28), const = constants.%.loc26_29.3
-// CHECK:STDOUT:   %.loc26_29.3: {.a: i32, .b: i32} = converted %.loc26_29.1, %.loc26_29.2
+// CHECK:STDOUT:   %.loc26_29.3: {.a: i32, .b: i32} = converted %.loc26_29.1, %.loc26_29.2, const = constants.%.loc26_29.3
 // CHECK:STDOUT:   assign %c.var, <error>
 // CHECK:STDOUT:   %d.var: ref i32 = var d
 // CHECK:STDOUT:   %d: ref i32 = bind_name d, %d.var

+ 1 - 1
toolchain/check/testdata/index/fail_non_deterministic_type.carbon

@@ -25,7 +25,7 @@ var c: i32 = a[b];
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.a = %a, .b = %b, .c = %c}
 // CHECK:STDOUT:   %.loc7_17.1: (type, type) = tuple_literal (i32, i32)
-// CHECK:STDOUT:   %.loc7_17.2: type = converted %.loc7_17.1, constants.%.loc7_17.2
+// CHECK:STDOUT:   %.loc7_17.2: type = converted %.loc7_17.1, constants.%.loc7_17.2, const = constants.%.loc7_17.2
 // CHECK:STDOUT:   %a.var: ref (i32, i32) = var a
 // CHECK:STDOUT:   %a: ref (i32, i32) = bind_name a, %a.var
 // CHECK:STDOUT:   %.loc7_22: i32 = int_literal 2, const = constants.%.loc7_22

+ 1 - 1
toolchain/check/testdata/index/fail_tuple_index_error.carbon

@@ -23,7 +23,7 @@ var b: i32 = a[oops];
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.a = %a, .b = %b}
 // CHECK:STDOUT:   %.loc7_17.1: (type, type) = tuple_literal (i32, i32)
-// CHECK:STDOUT:   %.loc7_17.2: type = converted %.loc7_17.1, constants.%.loc7_17.2
+// CHECK:STDOUT:   %.loc7_17.2: type = converted %.loc7_17.1, constants.%.loc7_17.2, const = constants.%.loc7_17.2
 // CHECK:STDOUT:   %a.var: ref (i32, i32) = var a
 // CHECK:STDOUT:   %a: ref (i32, i32) = bind_name a, %a.var
 // CHECK:STDOUT:   %.loc7_22: i32 = int_literal 12, const = constants.%.loc7_22

+ 2 - 2
toolchain/check/testdata/index/fail_tuple_large_index.carbon

@@ -23,7 +23,7 @@ var c: i32 = b[0xFFFFFFFFFFFFFFFFF];
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.a = %a, .b = %b, .c = %c}
 // CHECK:STDOUT:   %.loc7_13.1: (type,) = tuple_literal (i32)
-// CHECK:STDOUT:   %.loc7_13.2: type = converted %.loc7_13.1, constants.%.loc7_13.2
+// CHECK:STDOUT:   %.loc7_13.2: type = converted %.loc7_13.1, constants.%.loc7_13.2, const = constants.%.loc7_13.2
 // CHECK:STDOUT:   %a.var: ref (i32,) = var a
 // CHECK:STDOUT:   %a: ref (i32,) = bind_name a, %a.var
 // CHECK:STDOUT:   %.loc7_18: i32 = int_literal 12, const = constants.%.loc7_18
@@ -32,7 +32,7 @@ var c: i32 = b[0xFFFFFFFFFFFFFFFFF];
 // CHECK:STDOUT:   %.loc7_21.3: init (i32,) = converted %.loc7_21.1, %.loc7_21.2
 // CHECK:STDOUT:   assign %a.var, %.loc7_21.3
 // CHECK:STDOUT:   %.loc8_13: (type,) = tuple_literal (i32)
-// CHECK:STDOUT:   %.loc7_13.3: type = converted %.loc8_13, constants.%.loc7_13.2
+// CHECK:STDOUT:   %.loc7_13.3: type = converted %.loc8_13, constants.%.loc7_13.2, const = constants.%.loc7_13.2
 // CHECK:STDOUT:   %b.var: ref (i32,) = var b
 // CHECK:STDOUT:   %b: ref (i32,) = bind_name b, %b.var
 // CHECK:STDOUT:   %a.ref: ref (i32,) = name_ref a, %a

+ 1 - 1
toolchain/check/testdata/index/fail_tuple_non_int_indexing.carbon

@@ -24,7 +24,7 @@ var b: i32 = a[2.6];
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.a = %a, .b = %b}
 // CHECK:STDOUT:   %.loc7_17.1: (type, type) = tuple_literal (i32, i32)
-// CHECK:STDOUT:   %.loc7_17.2: type = converted %.loc7_17.1, constants.%.loc7_17.2
+// CHECK:STDOUT:   %.loc7_17.2: type = converted %.loc7_17.1, constants.%.loc7_17.2, const = constants.%.loc7_17.2
 // CHECK:STDOUT:   %a.var: ref (i32, i32) = var a
 // CHECK:STDOUT:   %a: ref (i32, i32) = bind_name a, %a.var
 // CHECK:STDOUT:   %.loc7_22: i32 = int_literal 12, const = constants.%.loc7_22

+ 1 - 1
toolchain/check/testdata/index/fail_tuple_out_of_bound_access.carbon

@@ -24,7 +24,7 @@ var b: i32 = a[2];
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.a = %a, .b = %b}
 // CHECK:STDOUT:   %.loc7_17.1: (type, type) = tuple_literal (i32, i32)
-// CHECK:STDOUT:   %.loc7_17.2: type = converted %.loc7_17.1, constants.%.loc7_17.2
+// CHECK:STDOUT:   %.loc7_17.2: type = converted %.loc7_17.1, constants.%.loc7_17.2, const = constants.%.loc7_17.2
 // CHECK:STDOUT:   %a.var: ref (i32, i32) = var a
 // CHECK:STDOUT:   %a: ref (i32, i32) = bind_name a, %a.var
 // CHECK:STDOUT:   %.loc7_22: i32 = int_literal 12, const = constants.%.loc7_22

+ 2 - 2
toolchain/check/testdata/index/tuple_element_access.carbon

@@ -20,7 +20,7 @@ var c: i32 = b[0];
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.a = %a, .b = %b, .c = %c}
 // CHECK:STDOUT:   %.loc7_13.1: (type,) = tuple_literal (i32)
-// CHECK:STDOUT:   %.loc7_13.2: type = converted %.loc7_13.1, constants.%.loc7_13.2
+// CHECK:STDOUT:   %.loc7_13.2: type = converted %.loc7_13.1, constants.%.loc7_13.2, const = constants.%.loc7_13.2
 // CHECK:STDOUT:   %a.var: ref (i32,) = var a
 // CHECK:STDOUT:   %a: ref (i32,) = bind_name a, %a.var
 // CHECK:STDOUT:   %.loc7_18: i32 = int_literal 12, const = constants.%.loc7_18
@@ -29,7 +29,7 @@ var c: i32 = b[0];
 // CHECK:STDOUT:   %.loc7_21.3: init (i32,) = converted %.loc7_21.1, %.loc7_21.2
 // CHECK:STDOUT:   assign %a.var, %.loc7_21.3
 // CHECK:STDOUT:   %.loc8_13: (type,) = tuple_literal (i32)
-// CHECK:STDOUT:   %.loc7_13.3: type = converted %.loc8_13, constants.%.loc7_13.2
+// CHECK:STDOUT:   %.loc7_13.3: type = converted %.loc8_13, constants.%.loc7_13.2, const = constants.%.loc7_13.2
 // CHECK:STDOUT:   %b.var: ref (i32,) = var b
 // CHECK:STDOUT:   %b: ref (i32,) = bind_name b, %b.var
 // CHECK:STDOUT:   %a.ref: ref (i32,) = name_ref a, %a

+ 1 - 1
toolchain/check/testdata/index/tuple_return_value_access.carbon

@@ -31,7 +31,7 @@ fn Run() -> i32 {
 // CHECK:STDOUT:   %.loc7_28: i32 = int_literal 0, const = constants.%.loc7_28
 // CHECK:STDOUT:   %.loc7_30.1: (i32,) = tuple_literal (%.loc7_28)
 // CHECK:STDOUT:   %.loc7_30.2: (i32,) = tuple_value (%.loc7_28), const = constants.%.loc7_30
-// CHECK:STDOUT:   %.loc7_30.3: (i32,) = converted %.loc7_30.1, %.loc7_30.2
+// CHECK:STDOUT:   %.loc7_30.3: (i32,) = converted %.loc7_30.1, %.loc7_30.2, const = constants.%.loc7_30
 // CHECK:STDOUT:   return %.loc7_30.3
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 2 - 2
toolchain/check/testdata/let/convert.carbon

@@ -31,7 +31,7 @@ fn F() -> i32 {
 // CHECK:STDOUT: fn @F() -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc8_24.1: (type, type, type) = tuple_literal (i32, i32, i32)
-// CHECK:STDOUT:   %.loc8_24.2: type = converted %.loc8_24.1, constants.%.loc8_24.2
+// CHECK:STDOUT:   %.loc8_24.2: type = converted %.loc8_24.1, constants.%.loc8_24.2, const = constants.%.loc8_24.2
 // CHECK:STDOUT:   %v.var: ref (i32, i32, i32) = var v
 // CHECK:STDOUT:   %v: ref (i32, i32, i32) = bind_name v, %v.var
 // CHECK:STDOUT:   %.loc8_29: i32 = int_literal 1, const = constants.%.loc8_29
@@ -48,7 +48,7 @@ fn F() -> i32 {
 // CHECK:STDOUT:   %.loc8_36.9: init (i32, i32, i32) = converted %.loc8_36.1, %.loc8_36.8
 // CHECK:STDOUT:   assign %v.var, %.loc8_36.9
 // CHECK:STDOUT:   %.loc10_24: (type, type, type) = tuple_literal (i32, i32, i32)
-// CHECK:STDOUT:   %.loc8_24.3: type = converted %.loc10_24, constants.%.loc8_24.2
+// CHECK:STDOUT:   %.loc8_24.3: type = converted %.loc10_24, constants.%.loc8_24.2, const = constants.%.loc8_24.2
 // CHECK:STDOUT:   %v.ref: ref (i32, i32, i32) = name_ref v, %v
 // CHECK:STDOUT:   %.loc10_28.1: ref i32 = tuple_access %v.ref, element0
 // CHECK:STDOUT:   %.loc10_28.2: i32 = bind_value %.loc10_28.1

+ 4 - 4
toolchain/check/testdata/namespace/imported.carbon

@@ -51,7 +51,7 @@ var package_b: () = package.NS.ChildNS.B();
 // CHECK:STDOUT:   %.4: <function> = fn_decl @.1, const
 // CHECK:STDOUT:   %.5: <function> = fn_decl @.2, const
 // CHECK:STDOUT:   %.loc4_9.1: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc4_9.2: type = converted %.loc4_9.1, constants.%.loc4
+// CHECK:STDOUT:   %.loc4_9.2: type = converted %.loc4_9.1, constants.%.loc4, const = constants.%.loc4
 // CHECK:STDOUT:   %a.var: ref () = var a
 // CHECK:STDOUT:   %a: ref () = bind_name a, %a.var
 // CHECK:STDOUT:   %NS.ref.loc4: <namespace> = name_ref NS, %.2
@@ -59,7 +59,7 @@ var package_b: () = package.NS.ChildNS.B();
 // CHECK:STDOUT:   %.loc4_17: init () = call %A.ref.loc4()
 // CHECK:STDOUT:   assign %a.var, %.loc4_17
 // CHECK:STDOUT:   %.loc5_9: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc4_9.3: type = converted %.loc5_9, constants.%.loc4
+// CHECK:STDOUT:   %.loc4_9.3: type = converted %.loc5_9, constants.%.loc4, const = constants.%.loc4
 // CHECK:STDOUT:   %b.var: ref () = var b
 // CHECK:STDOUT:   %b: ref () = bind_name b, %b.var
 // CHECK:STDOUT:   %NS.ref.loc5: <namespace> = name_ref NS, %.2
@@ -68,7 +68,7 @@ var package_b: () = package.NS.ChildNS.B();
 // CHECK:STDOUT:   %.loc5_25: init () = call %B.ref.loc5()
 // CHECK:STDOUT:   assign %b.var, %.loc5_25
 // CHECK:STDOUT:   %.loc7_17: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc4_9.4: type = converted %.loc7_17, constants.%.loc4
+// CHECK:STDOUT:   %.loc4_9.4: type = converted %.loc7_17, constants.%.loc4, const = constants.%.loc4
 // CHECK:STDOUT:   %package_a.var: ref () = var package_a
 // CHECK:STDOUT:   %package_a: ref () = bind_name package_a, %package_a.var
 // CHECK:STDOUT:   %package.ref.loc7: <namespace> = name_ref package, package
@@ -77,7 +77,7 @@ var package_b: () = package.NS.ChildNS.B();
 // CHECK:STDOUT:   %.loc7_33: init () = call %A.ref.loc7()
 // CHECK:STDOUT:   assign %package_a.var, %.loc7_33
 // CHECK:STDOUT:   %.loc8_17: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc4_9.5: type = converted %.loc8_17, constants.%.loc4
+// CHECK:STDOUT:   %.loc4_9.5: type = converted %.loc8_17, constants.%.loc4, const = constants.%.loc4
 // CHECK:STDOUT:   %package_b.var: ref () = var package_b
 // CHECK:STDOUT:   %package_b: ref () = bind_name package_b, %package_b.var
 // CHECK:STDOUT:   %package.ref.loc8: <namespace> = name_ref package, package

+ 1 - 1
toolchain/check/testdata/namespace/imported_indirect.carbon

@@ -90,7 +90,7 @@ var e: () = A.B.C.D();
 // CHECK:STDOUT:   %.4: <namespace> = namespace C, {.D = %.5}
 // CHECK:STDOUT:   %.5: <function> = fn_decl @.1, const
 // CHECK:STDOUT:   %.loc5_9.1: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc5_9.2: type = converted %.loc5_9.1, constants.%.loc5
+// CHECK:STDOUT:   %.loc5_9.2: type = converted %.loc5_9.1, constants.%.loc5, const = constants.%.loc5
 // CHECK:STDOUT:   %e.var: ref () = var e
 // CHECK:STDOUT:   %e: ref () = bind_name e, %e.var
 // CHECK:STDOUT:   %A.ref: <namespace> = name_ref A, %.2

+ 1 - 1
toolchain/check/testdata/operators/assignment.carbon

@@ -61,7 +61,7 @@ fn Main() {
 // CHECK:STDOUT:   %.loc9: i32 = int_literal 9, const = constants.%.loc9
 // CHECK:STDOUT:   assign %a.ref.loc9, %.loc9
 // CHECK:STDOUT:   %.loc11_19.1: (type, type) = tuple_literal (i32, i32)
-// CHECK:STDOUT:   %.loc11_19.2: type = converted %.loc11_19.1, constants.%.loc11_19.2
+// CHECK:STDOUT:   %.loc11_19.2: type = converted %.loc11_19.1, constants.%.loc11_19.2, const = constants.%.loc11_19.2
 // CHECK:STDOUT:   %b.var: ref (i32, i32) = var b
 // CHECK:STDOUT:   %b: ref (i32, i32) = bind_name b, %b.var
 // CHECK:STDOUT:   %.loc11_24: i32 = int_literal 1, const = constants.%.loc11_24

+ 2 - 2
toolchain/check/testdata/operators/fail_assignment_to_non_assignable.carbon

@@ -107,7 +107,7 @@ fn Main() {
 // CHECK:STDOUT:   %.loc21_17.7: init (i32, i32) = converted %.loc21_17.1, %.loc21_17.6
 // CHECK:STDOUT:   assign %.loc21_8.1, %.loc21_17.7
 // CHECK:STDOUT:   %.loc21_8.2: (i32, i32) = tuple_value (%.loc21_4, %.loc21_7), const = constants.%.loc21_8.3
-// CHECK:STDOUT:   %.loc21_8.3: (i32, i32) = converted %.loc21_8.1, %.loc21_8.2
+// CHECK:STDOUT:   %.loc21_8.3: (i32, i32) = converted %.loc21_8.1, %.loc21_8.2, const = constants.%.loc21_8.3
 // CHECK:STDOUT:   %n.var: ref i32 = var n
 // CHECK:STDOUT:   %n: ref i32 = bind_name n, %n.var
 // CHECK:STDOUT:   %.loc22: i32 = int_literal 0, const = constants.%.loc22
@@ -145,7 +145,7 @@ fn Main() {
 // CHECK:STDOUT:   %.loc34_37.7: init {.x: i32, .y: i32} = converted %.loc34_37.1, %.loc34_37.6
 // CHECK:STDOUT:   assign %.loc34_18.1, %.loc34_37.7
 // CHECK:STDOUT:   %.loc34_18.2: {.x: i32, .y: i32} = struct_value (%.loc34_9, %.loc34_17), const = constants.%.loc34_18.3
-// CHECK:STDOUT:   %.loc34_18.3: {.x: i32, .y: i32} = converted %.loc34_18.1, %.loc34_18.2
+// CHECK:STDOUT:   %.loc34_18.3: {.x: i32, .y: i32} = converted %.loc34_18.1, %.loc34_18.2, const = constants.%.loc34_18.3
 // CHECK:STDOUT:   %.loc38_7: bool = bool_literal true, const = constants.%.loc38_7
 // CHECK:STDOUT:   if %.loc38_7 br !if.expr.then.loc38 else br !if.expr.else.loc38
 // CHECK:STDOUT:

+ 1 - 1
toolchain/check/testdata/packages/fail_name_with_import_failure.carbon

@@ -22,7 +22,7 @@ var a: () = A();
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.a = %a, has_error}
 // CHECK:STDOUT:   %.loc7_9.1: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc7_9.2: type = converted %.loc7_9.1, constants.%.loc7
+// CHECK:STDOUT:   %.loc7_9.2: type = converted %.loc7_9.1, constants.%.loc7, const = constants.%.loc7
 // CHECK:STDOUT:   %a.var: ref () = var a
 // CHECK:STDOUT:   %a: ref () = bind_name a, %a.var
 // CHECK:STDOUT:   %A.ref: <error> = name_ref A, <error>

+ 1 - 1
toolchain/check/testdata/packages/fail_todo_lazy_import_ref.carbon

@@ -44,7 +44,7 @@ var a: () = a_ref;
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.a_ref = %package.var, .a = %a}
 // CHECK:STDOUT:   %package.var: ref <error> = var package
 // CHECK:STDOUT:   %.loc4_9.1: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc4_9.2: type = converted %.loc4_9.1, constants.%.loc4
+// CHECK:STDOUT:   %.loc4_9.2: type = converted %.loc4_9.1, constants.%.loc4, const = constants.%.loc4
 // CHECK:STDOUT:   %a.var: ref () = var a
 // CHECK:STDOUT:   %a: ref () = bind_name a, %a.var
 // CHECK:STDOUT:   %a_ref.ref: ref <error> = name_ref a_ref, %package.var

+ 4 - 4
toolchain/check/testdata/packages/loaded_global.carbon

@@ -53,14 +53,14 @@ var package_b: () = package.B();
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.A = %.2, .a = %a, .package_a = %package_a}
 // CHECK:STDOUT:   %.2: <function> = fn_decl @.1, const
 // CHECK:STDOUT:   %.loc4_9.1: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc4_9.2: type = converted %.loc4_9.1, constants.%.loc4
+// CHECK:STDOUT:   %.loc4_9.2: type = converted %.loc4_9.1, constants.%.loc4, const = constants.%.loc4
 // CHECK:STDOUT:   %a.var: ref () = var a
 // CHECK:STDOUT:   %a: ref () = bind_name a, %a.var
 // CHECK:STDOUT:   %A.ref.loc4: <function> = name_ref A, %.2, const = %.2
 // CHECK:STDOUT:   %.loc4_14: init () = call %A.ref.loc4()
 // CHECK:STDOUT:   assign %a.var, %.loc4_14
 // CHECK:STDOUT:   %.loc6_17: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc4_9.3: type = converted %.loc6_17, constants.%.loc4
+// CHECK:STDOUT:   %.loc4_9.3: type = converted %.loc6_17, constants.%.loc4, const = constants.%.loc4
 // CHECK:STDOUT:   %package_a.var: ref () = var package_a
 // CHECK:STDOUT:   %package_a: ref () = bind_name package_a, %package_a.var
 // CHECK:STDOUT:   %package.ref: <namespace> = name_ref package, package
@@ -90,14 +90,14 @@ var package_b: () = package.B();
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.B = %.2, .b = %b, .package_b = %package_b}
 // CHECK:STDOUT:   %.2: <function> = fn_decl @.1, const
 // CHECK:STDOUT:   %.loc6_9.1: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc6_9.2: type = converted %.loc6_9.1, constants.%.loc6
+// CHECK:STDOUT:   %.loc6_9.2: type = converted %.loc6_9.1, constants.%.loc6, const = constants.%.loc6
 // CHECK:STDOUT:   %b.var: ref () = var b
 // CHECK:STDOUT:   %b: ref () = bind_name b, %b.var
 // CHECK:STDOUT:   %B.ref.loc6: <function> = name_ref B, %.2, const = %.2
 // CHECK:STDOUT:   %.loc6_14: init () = call %B.ref.loc6()
 // CHECK:STDOUT:   assign %b.var, %.loc6_14
 // CHECK:STDOUT:   %.loc8_17: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc6_9.3: type = converted %.loc8_17, constants.%.loc6
+// CHECK:STDOUT:   %.loc6_9.3: type = converted %.loc8_17, constants.%.loc6, const = constants.%.loc6
 // CHECK:STDOUT:   %package_b.var: ref () = var package_b
 // CHECK:STDOUT:   %package_b: ref () = bind_name package_b, %package_b.var
 // CHECK:STDOUT:   %package.ref: <namespace> = name_ref package, package

+ 1 - 1
toolchain/check/testdata/pointer/address_of_lvalue.carbon

@@ -73,7 +73,7 @@ fn F() {
 // CHECK:STDOUT:   %.loc12_17: i32* = addr_of %.loc12_19
 // CHECK:STDOUT:   assign %r.var, %.loc12_17
 // CHECK:STDOUT:   %.loc14_19.1: (type, type) = tuple_literal (i32, i32)
-// CHECK:STDOUT:   %.loc14_19.2: type = converted %.loc14_19.1, constants.%.loc14_19.2
+// CHECK:STDOUT:   %.loc14_19.2: type = converted %.loc14_19.1, constants.%.loc14_19.2, const = constants.%.loc14_19.2
 // CHECK:STDOUT:   %t.var: ref (i32, i32) = var t
 // CHECK:STDOUT:   %t: ref (i32, i32) = bind_name t, %t.var
 // CHECK:STDOUT:   %.loc14_24: i32 = int_literal 1, const = constants.%.loc14_24

+ 1 - 1
toolchain/check/testdata/pointer/fail_address_of_value.carbon

@@ -202,7 +202,7 @@ fn AddressOfParam(param: i32) {
 // CHECK:STDOUT:   %.loc75_10.1: (i32, i32) = tuple_literal (%.loc75_6, %.loc75_9)
 // CHECK:STDOUT:   %.loc75_12: i32 = int_literal 0, const = constants.%.loc75_12
 // CHECK:STDOUT:   %.loc75_10.2: (i32, i32) = tuple_value (%.loc75_6, %.loc75_9), const = constants.%.loc75_10
-// CHECK:STDOUT:   %.loc75_10.3: (i32, i32) = converted %.loc75_10.1, %.loc75_10.2
+// CHECK:STDOUT:   %.loc75_10.3: (i32, i32) = converted %.loc75_10.1, %.loc75_10.2, const = constants.%.loc75_10
 // CHECK:STDOUT:   %.loc75_13: i32 = tuple_index %.loc75_10.3, %.loc75_12
 // CHECK:STDOUT:   %.loc75_3: i32* = addr_of %.loc75_13
 // CHECK:STDOUT:   return

+ 2 - 2
toolchain/check/testdata/pointer/fail_deref_not_pointer.carbon

@@ -39,11 +39,11 @@ fn Deref(n: i32) {
 // CHECK:STDOUT:   %.loc11: ref <error> = deref %n.ref
 // CHECK:STDOUT:   %.loc15_5.1: () = tuple_literal ()
 // CHECK:STDOUT:   %.loc15_5.2: () = tuple_value (), const = constants.%.loc15_5.2
-// CHECK:STDOUT:   %.loc15_5.3: () = converted %.loc15_5.1, %.loc15_5.2
+// CHECK:STDOUT:   %.loc15_5.3: () = converted %.loc15_5.1, %.loc15_5.2, const = constants.%.loc15_5.2
 // CHECK:STDOUT:   %.loc15_3: ref <error> = deref %.loc15_5.3
 // CHECK:STDOUT:   %.loc19_5.1: {} = struct_literal ()
 // CHECK:STDOUT:   %.loc19_5.2: {} = struct_value (), const = constants.%.loc19_5.2
-// CHECK:STDOUT:   %.loc19_5.3: {} = converted %.loc19_5.1, %.loc19_5.2
+// CHECK:STDOUT:   %.loc19_5.3: {} = converted %.loc19_5.1, %.loc19_5.2, const = constants.%.loc19_5.2
 // CHECK:STDOUT:   %.loc19_3: ref <error> = deref %.loc19_5.3
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 1 - 1
toolchain/check/testdata/return/fail_returned_var_no_return_type.carbon

@@ -29,7 +29,7 @@ fn Procedure() {
 // CHECK:STDOUT: fn @Procedure() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc14_20.1: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc14_20.2: type = converted %.loc14_20.1, constants.%.loc14
+// CHECK:STDOUT:   %.loc14_20.2: type = converted %.loc14_20.1, constants.%.loc14, const = constants.%.loc14
 // CHECK:STDOUT:   %v: () = bind_name v, <error>
 // CHECK:STDOUT:   %.loc14_25: () = tuple_literal ()
 // CHECK:STDOUT:   assign <error>, <error>

+ 1 - 1
toolchain/check/testdata/return/struct.carbon

@@ -25,7 +25,7 @@ fn Main() -> {.a: i32} {
 // CHECK:STDOUT:   %.loc8_16: i32 = int_literal 3, const = constants.%.loc8_16
 // CHECK:STDOUT:   %.loc8_17.1: {.a: i32} = struct_literal (%.loc8_16)
 // CHECK:STDOUT:   %.loc8_17.2: {.a: i32} = struct_value (%.loc8_16), const = constants.%.loc8_17
-// CHECK:STDOUT:   %.loc8_17.3: {.a: i32} = converted %.loc8_17.1, %.loc8_17.2
+// CHECK:STDOUT:   %.loc8_17.3: {.a: i32} = converted %.loc8_17.1, %.loc8_17.2, const = constants.%.loc8_17
 // CHECK:STDOUT:   return %.loc8_17.3
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 2 - 2
toolchain/check/testdata/struct/empty.carbon

@@ -17,7 +17,7 @@ var y: {} = x;
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.x = %x, .y = %y}
 // CHECK:STDOUT:   %.loc7_9.1: {} = struct_literal ()
-// CHECK:STDOUT:   %.loc7_9.2: type = converted %.loc7_9.1, constants.%.loc7_9.1
+// CHECK:STDOUT:   %.loc7_9.2: type = converted %.loc7_9.1, constants.%.loc7_9.1, const = constants.%.loc7_9.1
 // CHECK:STDOUT:   %x.var: ref {} = var x
 // CHECK:STDOUT:   %x: ref {} = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc7_14.1: {} = struct_literal ()
@@ -25,7 +25,7 @@ var y: {} = x;
 // CHECK:STDOUT:   %.loc7_14.3: init {} = converted %.loc7_14.1, %.loc7_14.2
 // CHECK:STDOUT:   assign %x.var, %.loc7_14.3
 // CHECK:STDOUT:   %.loc8_9: {} = struct_literal ()
-// CHECK:STDOUT:   %.loc7_9.3: type = converted %.loc8_9, constants.%.loc7_9.1
+// CHECK:STDOUT:   %.loc7_9.3: type = converted %.loc8_9, constants.%.loc7_9.1, const = constants.%.loc7_9.1
 // CHECK:STDOUT:   %y.var: ref {} = var y
 // CHECK:STDOUT:   %y: ref {} = bind_name y, %y.var
 // CHECK:STDOUT:   %x.ref: ref {} = name_ref x, %x

+ 1 - 1
toolchain/check/testdata/struct/fail_assign_nested.carbon

@@ -21,7 +21,7 @@ var x: {.a: {}} = {.b = {}};
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.x = %x}
 // CHECK:STDOUT:   %.loc10_14.1: {} = struct_literal ()
-// CHECK:STDOUT:   %.loc10_14.2: type = converted %.loc10_14.1, constants.%.loc10_14.1
+// CHECK:STDOUT:   %.loc10_14.2: type = converted %.loc10_14.1, constants.%.loc10_14.1, const = constants.%.loc10_14.1
 // CHECK:STDOUT:   %.loc10_15: type = struct_type {.a: {}}, const
 // CHECK:STDOUT:   %x.var: ref {.a: {}} = var x
 // CHECK:STDOUT:   %x: ref {.a: {}} = bind_name x, %x.var

+ 1 - 1
toolchain/check/testdata/struct/fail_assign_to_empty.carbon

@@ -21,7 +21,7 @@ var x: {} = {.a = 1};
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.x = %x}
 // CHECK:STDOUT:   %.loc10_9.1: {} = struct_literal ()
-// CHECK:STDOUT:   %.loc10_9.2: type = converted %.loc10_9.1, constants.%.loc10_9.1
+// CHECK:STDOUT:   %.loc10_9.2: type = converted %.loc10_9.1, constants.%.loc10_9.1, const = constants.%.loc10_9.1
 // CHECK:STDOUT:   %x.var: ref {} = var x
 // CHECK:STDOUT:   %x: ref {} = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc10_19: i32 = int_literal 1, const = constants.%.loc10_19

+ 2 - 2
toolchain/check/testdata/struct/nested_struct_in_place.carbon

@@ -31,9 +31,9 @@ fn G() {
 // CHECK:STDOUT: fn @G() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc10_29: (type, type, type) = tuple_literal (i32, i32, i32)
-// CHECK:STDOUT:   %.loc7_25.1: type = converted %.loc10_29, constants.%.loc7_25.2
+// CHECK:STDOUT:   %.loc7_25.1: type = converted %.loc10_29, constants.%.loc7_25.2, const = constants.%.loc7_25.2
 // CHECK:STDOUT:   %.loc10_50: (type, type, type) = tuple_literal (i32, i32, i32)
-// CHECK:STDOUT:   %.loc7_25.2: type = converted %.loc10_50, constants.%.loc7_25.2
+// CHECK:STDOUT:   %.loc7_25.2: type = converted %.loc10_50, constants.%.loc7_25.2, const = constants.%.loc7_25.2
 // CHECK:STDOUT:   %.loc10_51: type = struct_type {.a: (i32, i32, i32), .b: (i32, i32, i32)}, const
 // CHECK:STDOUT:   %v.var: ref {.a: (i32, i32, i32), .b: (i32, i32, i32)} = var v
 // CHECK:STDOUT:   %v: ref {.a: (i32, i32, i32), .b: (i32, i32, i32)} = bind_name v, %v.var

+ 2 - 2
toolchain/check/testdata/struct/tuple_as_element.carbon

@@ -20,7 +20,7 @@ var y: {.a: i32, .b: (i32,)} = x;
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.x = %x, .y = %y}
 // CHECK:STDOUT:   %.loc7_27.1: (type,) = tuple_literal (i32)
-// CHECK:STDOUT:   %.loc7_27.2: type = converted %.loc7_27.1, constants.%.loc7_27.2
+// CHECK:STDOUT:   %.loc7_27.2: type = converted %.loc7_27.1, constants.%.loc7_27.2, const = constants.%.loc7_27.2
 // CHECK:STDOUT:   %.loc7_28: type = struct_type {.a: i32, .b: (i32,)}, const
 // CHECK:STDOUT:   %x.var: ref {.a: i32, .b: (i32,)} = var x
 // CHECK:STDOUT:   %x: ref {.a: i32, .b: (i32,)} = bind_name x, %x.var
@@ -38,7 +38,7 @@ var y: {.a: i32, .b: (i32,)} = x;
 // CHECK:STDOUT:   %.loc7_50.7: init {.a: i32, .b: (i32,)} = converted %.loc7_50.1, %.loc7_50.6
 // CHECK:STDOUT:   assign %x.var, %.loc7_50.7
 // CHECK:STDOUT:   %.loc8_27: (type,) = tuple_literal (i32)
-// CHECK:STDOUT:   %.loc7_27.3: type = converted %.loc8_27, constants.%.loc7_27.2
+// CHECK:STDOUT:   %.loc7_27.3: type = converted %.loc8_27, constants.%.loc7_27.2, const = constants.%.loc7_27.2
 // CHECK:STDOUT:   %.loc8_28: type = struct_type {.a: i32, .b: (i32,)}, const
 // CHECK:STDOUT:   %y.var: ref {.a: i32, .b: (i32,)} = var y
 // CHECK:STDOUT:   %y: ref {.a: i32, .b: (i32,)} = bind_name y, %y.var

+ 37 - 21
toolchain/check/testdata/struct/two_entries.carbon

@@ -4,6 +4,9 @@
 //
 // AUTOUPDATE
 
+let v: {.a: i32, .b: i32} = {.a = 1, .b = 2};
+let w: {.a: i32, .b: i32} = v;
+
 var x: {.a: i32, .b: i32} = {.a = 1, .b = 2};
 var y: {.a: i32, .b: i32} = x;
 
@@ -13,37 +16,50 @@ var y: {.a: i32, .b: i32} = x;
 // CHECK:STDOUT:   %.loc7_25: type = ptr_type {.a: i32, .b: i32}, const
 // CHECK:STDOUT:   %.loc7_35: i32 = int_literal 1, const
 // CHECK:STDOUT:   %.loc7_43: i32 = int_literal 2, const
+// CHECK:STDOUT:   %.loc7_44: {.a: i32, .b: i32} = struct_value (%.loc7_35, %.loc7_43), const
+// CHECK:STDOUT:   %.loc10_35: i32 = int_literal 1, const
+// CHECK:STDOUT:   %.loc10_43: i32 = int_literal 2, const
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.x = %x, .y = %y}
 // CHECK:STDOUT:   %.loc7_25: type = struct_type {.a: i32, .b: i32}, const
-// CHECK:STDOUT:   %x.var: ref {.a: i32, .b: i32} = var x
-// CHECK:STDOUT:   %x: ref {.a: i32, .b: i32} = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc7_35: i32 = int_literal 1, const = constants.%.loc7_35
 // CHECK:STDOUT:   %.loc7_43: i32 = int_literal 2, const = constants.%.loc7_43
 // CHECK:STDOUT:   %.loc7_44.1: {.a: i32, .b: i32} = struct_literal (%.loc7_35, %.loc7_43)
-// CHECK:STDOUT:   %.loc7_44.2: ref i32 = struct_access %x.var, element0
-// CHECK:STDOUT:   %.loc7_44.3: init i32 = initialize_from %.loc7_35 to %.loc7_44.2
-// CHECK:STDOUT:   %.loc7_44.4: ref i32 = struct_access %x.var, element1
-// CHECK:STDOUT:   %.loc7_44.5: init i32 = initialize_from %.loc7_43 to %.loc7_44.4
-// CHECK:STDOUT:   %.loc7_44.6: init {.a: i32, .b: i32} = struct_init (%.loc7_44.3, %.loc7_44.5) to %x.var
-// CHECK:STDOUT:   %.loc7_44.7: init {.a: i32, .b: i32} = converted %.loc7_44.1, %.loc7_44.6
-// CHECK:STDOUT:   assign %x.var, %.loc7_44.7
-// CHECK:STDOUT:   %.loc8_25: type = struct_type {.a: i32, .b: i32}, const
+// CHECK:STDOUT:   %.loc7_44.2: {.a: i32, .b: i32} = struct_value (%.loc7_35, %.loc7_43), const = constants.%.loc7_44
+// CHECK:STDOUT:   %.loc7_44.3: {.a: i32, .b: i32} = converted %.loc7_44.1, %.loc7_44.2, const = constants.%.loc7_44
+// CHECK:STDOUT:   %v: {.a: i32, .b: i32} = bind_name v, %.loc7_44.3
+// CHECK:STDOUT:   %.loc8: type = struct_type {.a: i32, .b: i32}, const
+// CHECK:STDOUT:   %v.ref: {.a: i32, .b: i32} = name_ref v, %v
+// CHECK:STDOUT:   %w: {.a: i32, .b: i32} = bind_name w, %v.ref
+// CHECK:STDOUT:   %.loc10_25: type = struct_type {.a: i32, .b: i32}, const
+// CHECK:STDOUT:   %x.var: ref {.a: i32, .b: i32} = var x
+// CHECK:STDOUT:   %x: ref {.a: i32, .b: i32} = bind_name x, %x.var
+// CHECK:STDOUT:   %.loc10_35: i32 = int_literal 1, const = constants.%.loc10_35
+// CHECK:STDOUT:   %.loc10_43: i32 = int_literal 2, const = constants.%.loc10_43
+// CHECK:STDOUT:   %.loc10_44.1: {.a: i32, .b: i32} = struct_literal (%.loc10_35, %.loc10_43)
+// CHECK:STDOUT:   %.loc10_44.2: ref i32 = struct_access %x.var, element0
+// CHECK:STDOUT:   %.loc10_44.3: init i32 = initialize_from %.loc10_35 to %.loc10_44.2
+// CHECK:STDOUT:   %.loc10_44.4: ref i32 = struct_access %x.var, element1
+// CHECK:STDOUT:   %.loc10_44.5: init i32 = initialize_from %.loc10_43 to %.loc10_44.4
+// CHECK:STDOUT:   %.loc10_44.6: init {.a: i32, .b: i32} = struct_init (%.loc10_44.3, %.loc10_44.5) to %x.var
+// CHECK:STDOUT:   %.loc10_44.7: init {.a: i32, .b: i32} = converted %.loc10_44.1, %.loc10_44.6
+// CHECK:STDOUT:   assign %x.var, %.loc10_44.7
+// CHECK:STDOUT:   %.loc11_25: type = struct_type {.a: i32, .b: i32}, const
 // CHECK:STDOUT:   %y.var: ref {.a: i32, .b: i32} = var y
 // CHECK:STDOUT:   %y: ref {.a: i32, .b: i32} = bind_name y, %y.var
 // CHECK:STDOUT:   %x.ref: ref {.a: i32, .b: i32} = name_ref x, %x
-// CHECK:STDOUT:   %.loc8_29.1: ref i32 = struct_access %x.ref, element0
-// CHECK:STDOUT:   %.loc8_29.2: i32 = bind_value %.loc8_29.1
-// CHECK:STDOUT:   %.loc8_29.3: ref i32 = struct_access %y.var, element0
-// CHECK:STDOUT:   %.loc8_29.4: init i32 = initialize_from %.loc8_29.2 to %.loc8_29.3
-// CHECK:STDOUT:   %.loc8_29.5: ref i32 = struct_access %x.ref, element1
-// CHECK:STDOUT:   %.loc8_29.6: i32 = bind_value %.loc8_29.5
-// CHECK:STDOUT:   %.loc8_29.7: ref i32 = struct_access %y.var, element1
-// CHECK:STDOUT:   %.loc8_29.8: init i32 = initialize_from %.loc8_29.6 to %.loc8_29.7
-// CHECK:STDOUT:   %.loc8_29.9: init {.a: i32, .b: i32} = struct_init (%.loc8_29.4, %.loc8_29.8) to %y.var
-// CHECK:STDOUT:   %.loc8_29.10: init {.a: i32, .b: i32} = converted %x.ref, %.loc8_29.9
-// CHECK:STDOUT:   assign %y.var, %.loc8_29.10
+// CHECK:STDOUT:   %.loc11_29.1: ref i32 = struct_access %x.ref, element0
+// CHECK:STDOUT:   %.loc11_29.2: i32 = bind_value %.loc11_29.1
+// CHECK:STDOUT:   %.loc11_29.3: ref i32 = struct_access %y.var, element0
+// CHECK:STDOUT:   %.loc11_29.4: init i32 = initialize_from %.loc11_29.2 to %.loc11_29.3
+// CHECK:STDOUT:   %.loc11_29.5: ref i32 = struct_access %x.ref, element1
+// CHECK:STDOUT:   %.loc11_29.6: i32 = bind_value %.loc11_29.5
+// CHECK:STDOUT:   %.loc11_29.7: ref i32 = struct_access %y.var, element1
+// CHECK:STDOUT:   %.loc11_29.8: init i32 = initialize_from %.loc11_29.6 to %.loc11_29.7
+// CHECK:STDOUT:   %.loc11_29.9: init {.a: i32, .b: i32} = struct_init (%.loc11_29.4, %.loc11_29.8) to %y.var
+// CHECK:STDOUT:   %.loc11_29.10: init {.a: i32, .b: i32} = converted %x.ref, %.loc11_29.9
+// CHECK:STDOUT:   assign %y.var, %.loc11_29.10
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 2 - 2
toolchain/check/testdata/tuples/empty.carbon

@@ -16,7 +16,7 @@ var y: () = x;
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.x = %x, .y = %y}
 // CHECK:STDOUT:   %.loc7_9.1: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc7_9.2: type = converted %.loc7_9.1, constants.%.loc7
+// CHECK:STDOUT:   %.loc7_9.2: type = converted %.loc7_9.1, constants.%.loc7, const = constants.%.loc7
 // CHECK:STDOUT:   %x.var: ref () = var x
 // CHECK:STDOUT:   %x: ref () = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc7_14.1: () = tuple_literal ()
@@ -24,7 +24,7 @@ var y: () = x;
 // CHECK:STDOUT:   %.loc7_14.3: init () = converted %.loc7_14.1, %.loc7_14.2
 // CHECK:STDOUT:   assign %x.var, %.loc7_14.3
 // CHECK:STDOUT:   %.loc8_9: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc7_9.3: type = converted %.loc8_9, constants.%.loc7
+// CHECK:STDOUT:   %.loc7_9.3: type = converted %.loc8_9, constants.%.loc7, const = constants.%.loc7
 // CHECK:STDOUT:   %y.var: ref () = var y
 // CHECK:STDOUT:   %y: ref () = bind_name y, %y.var
 // CHECK:STDOUT:   %x.ref: ref () = name_ref x, %x

+ 1 - 1
toolchain/check/testdata/tuples/fail_assign_empty.carbon

@@ -20,7 +20,7 @@ var x: (i32,) = ();
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.x = %x}
 // CHECK:STDOUT:   %.loc10_13.1: (type,) = tuple_literal (i32)
-// CHECK:STDOUT:   %.loc10_13.2: type = converted %.loc10_13.1, constants.%.loc10_13.2
+// CHECK:STDOUT:   %.loc10_13.2: type = converted %.loc10_13.1, constants.%.loc10_13.2, const = constants.%.loc10_13.2
 // CHECK:STDOUT:   %x.var: ref (i32,) = var x
 // CHECK:STDOUT:   %x: ref (i32,) = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc10_18: () = tuple_literal ()

+ 3 - 3
toolchain/check/testdata/tuples/fail_assign_nested.carbon

@@ -34,9 +34,9 @@ var x: ((i32, i32), (i32, i32)) = ((1, 2, 3), (4, 5, 6));
 // CHECK:STDOUT:   %.loc10_18: (type, type) = tuple_literal (i32, i32)
 // CHECK:STDOUT:   %.loc10_30: (type, type) = tuple_literal (i32, i32)
 // CHECK:STDOUT:   %.loc10_31.1: ((type, type), (type, type)) = tuple_literal (%.loc10_18, %.loc10_30)
-// CHECK:STDOUT:   %.loc10_31.2: type = converted %.loc10_18, constants.%.loc10_31.2
-// CHECK:STDOUT:   %.loc10_31.3: type = converted %.loc10_30, constants.%.loc10_31.2
-// CHECK:STDOUT:   %.loc10_31.4: type = converted %.loc10_31.1, constants.%.loc10_31.3
+// CHECK:STDOUT:   %.loc10_31.2: type = converted %.loc10_18, constants.%.loc10_31.2, const = constants.%.loc10_31.2
+// CHECK:STDOUT:   %.loc10_31.3: type = converted %.loc10_30, constants.%.loc10_31.2, const = constants.%.loc10_31.2
+// CHECK:STDOUT:   %.loc10_31.4: type = converted %.loc10_31.1, constants.%.loc10_31.3, const = constants.%.loc10_31.3
 // CHECK:STDOUT:   %x.var: ref ((i32, i32), (i32, i32)) = var x
 // CHECK:STDOUT:   %x: ref ((i32, i32), (i32, i32)) = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc10_37: i32 = int_literal 1, const = constants.%.loc10_37

+ 1 - 1
toolchain/check/testdata/tuples/fail_assign_to_empty.carbon

@@ -19,7 +19,7 @@ var x: () = (66);
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.x = %x}
 // CHECK:STDOUT:   %.loc10_9.1: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc10_9.2: type = converted %.loc10_9.1, constants.%.loc10_9
+// CHECK:STDOUT:   %.loc10_9.2: type = converted %.loc10_9.1, constants.%.loc10_9, const = constants.%.loc10_9
 // CHECK:STDOUT:   %x.var: ref () = var x
 // CHECK:STDOUT:   %x: ref () = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc10_14: i32 = int_literal 66, const = constants.%.loc10_14

+ 1 - 1
toolchain/check/testdata/tuples/fail_element_type_mismatch.carbon

@@ -23,7 +23,7 @@ var x: (i32, i32) = (2, 65.89);
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.x = %x}
 // CHECK:STDOUT:   %.loc10_17.1: (type, type) = tuple_literal (i32, i32)
-// CHECK:STDOUT:   %.loc10_17.2: type = converted %.loc10_17.1, constants.%.loc10_17.2
+// CHECK:STDOUT:   %.loc10_17.2: type = converted %.loc10_17.1, constants.%.loc10_17.2, const = constants.%.loc10_17.2
 // CHECK:STDOUT:   %x.var: ref (i32, i32) = var x
 // CHECK:STDOUT:   %x: ref (i32, i32) = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc10_22: i32 = int_literal 2, const = constants.%.loc10_22

+ 1 - 1
toolchain/check/testdata/tuples/fail_nested_incomplete.carbon

@@ -34,7 +34,7 @@ var p: Incomplete* = &t[1];
 // CHECK:STDOUT:   %Incomplete: type = class_type @Incomplete, const
 // CHECK:STDOUT:   %Incomplete.ref.loc15: type = name_ref Incomplete, %Incomplete, const = %Incomplete
 // CHECK:STDOUT:   %.loc15_24.1: (type, type) = tuple_literal (i32, %Incomplete.ref.loc15)
-// CHECK:STDOUT:   %.loc15_24.2: type = converted %.loc15_24.1, constants.%.loc15_24.2
+// CHECK:STDOUT:   %.loc15_24.2: type = converted %.loc15_24.1, constants.%.loc15_24.2, const = constants.%.loc15_24.2
 // CHECK:STDOUT:   %t.var: ref <error> = var t
 // CHECK:STDOUT:   %t: ref <error> = bind_name t, %t.var
 // CHECK:STDOUT:   %Incomplete.ref.loc20: type = name_ref Incomplete, %Incomplete, const = %Incomplete

+ 1 - 1
toolchain/check/testdata/tuples/fail_too_few_element.carbon

@@ -22,7 +22,7 @@ var x: (i32, i32) = (2, );
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.x = %x}
 // CHECK:STDOUT:   %.loc10_17.1: (type, type) = tuple_literal (i32, i32)
-// CHECK:STDOUT:   %.loc10_17.2: type = converted %.loc10_17.1, constants.%.loc10_17.2
+// CHECK:STDOUT:   %.loc10_17.2: type = converted %.loc10_17.1, constants.%.loc10_17.2, const = constants.%.loc10_17.2
 // CHECK:STDOUT:   %x.var: ref (i32, i32) = var x
 // CHECK:STDOUT:   %x: ref (i32, i32) = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc10_22: i32 = int_literal 2, const = constants.%.loc10_22

+ 1 - 1
toolchain/check/testdata/tuples/fail_type_assign.carbon

@@ -19,7 +19,7 @@ var x: (i32, ) = (i32, );
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.x = %x}
 // CHECK:STDOUT:   %.loc10_14.1: (type,) = tuple_literal (i32)
-// CHECK:STDOUT:   %.loc10_14.2: type = converted %.loc10_14.1, constants.%.loc10_14.2
+// CHECK:STDOUT:   %.loc10_14.2: type = converted %.loc10_14.1, constants.%.loc10_14.2, const = constants.%.loc10_14.2
 // CHECK:STDOUT:   %x.var: ref (i32,) = var x
 // CHECK:STDOUT:   %x: ref (i32,) = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc10_24: (type,) = tuple_literal (i32)

+ 1 - 1
toolchain/check/testdata/tuples/fail_value_as_type.carbon

@@ -21,7 +21,7 @@ var x: (1, );
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.x = %x}
 // CHECK:STDOUT:   %.loc10_9: i32 = int_literal 1, const = constants.%.loc10_9
 // CHECK:STDOUT:   %.loc10_12.1: (i32,) = tuple_literal (%.loc10_9)
-// CHECK:STDOUT:   %.loc10_12.2: type = converted %.loc10_12.1, constants.%.loc10_12.2
+// CHECK:STDOUT:   %.loc10_12.2: type = converted %.loc10_12.1, constants.%.loc10_12.2, const = constants.%.loc10_12.2
 // CHECK:STDOUT:   %x.var: ref (<error>,) = var x
 // CHECK:STDOUT:   %x: ref (<error>,) = bind_name x, %x.var
 // CHECK:STDOUT: }

+ 2 - 2
toolchain/check/testdata/tuples/nested_tuple.carbon

@@ -25,8 +25,8 @@ var x: ((i32, i32), i32) = ((12, 76), 6);
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.x = %x}
 // CHECK:STDOUT:   %.loc7_18: (type, type) = tuple_literal (i32, i32)
 // CHECK:STDOUT:   %.loc7_24.1: ((type, type), type) = tuple_literal (%.loc7_18, i32)
-// CHECK:STDOUT:   %.loc7_24.2: type = converted %.loc7_18, constants.%.loc7_24.2
-// CHECK:STDOUT:   %.loc7_24.3: type = converted %.loc7_24.1, constants.%.loc7_24.3
+// CHECK:STDOUT:   %.loc7_24.2: type = converted %.loc7_18, constants.%.loc7_24.2, const = constants.%.loc7_24.2
+// CHECK:STDOUT:   %.loc7_24.3: type = converted %.loc7_24.1, constants.%.loc7_24.3, const = constants.%.loc7_24.3
 // CHECK:STDOUT:   %x.var: ref ((i32, i32), i32) = var x
 // CHECK:STDOUT:   %x: ref ((i32, i32), i32) = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc7_30: i32 = int_literal 12, const = constants.%.loc7_30

+ 5 - 5
toolchain/check/testdata/tuples/nested_tuple_in_place.carbon

@@ -46,9 +46,9 @@ fn H() {
 // CHECK:STDOUT:   %.loc10_25: (type, type, type) = tuple_literal (i32, i32, i32)
 // CHECK:STDOUT:   %.loc10_42: (type, type, type) = tuple_literal (i32, i32, i32)
 // CHECK:STDOUT:   %.loc10_43.1: ((type, type, type), (type, type, type)) = tuple_literal (%.loc10_25, %.loc10_42)
-// CHECK:STDOUT:   %.loc7_25.1: type = converted %.loc10_25, constants.%.loc7_25.2
-// CHECK:STDOUT:   %.loc7_25.2: type = converted %.loc10_42, constants.%.loc7_25.2
-// CHECK:STDOUT:   %.loc10_43.2: type = converted %.loc10_43.1, constants.%.loc10_43.2
+// CHECK:STDOUT:   %.loc7_25.1: type = converted %.loc10_25, constants.%.loc7_25.2, const = constants.%.loc7_25.2
+// CHECK:STDOUT:   %.loc7_25.2: type = converted %.loc10_42, constants.%.loc7_25.2, const = constants.%.loc7_25.2
+// CHECK:STDOUT:   %.loc10_43.2: type = converted %.loc10_43.1, constants.%.loc10_43.2, const = constants.%.loc10_43.2
 // CHECK:STDOUT:   %v.var: ref ((i32, i32, i32), (i32, i32, i32)) = var v
 // CHECK:STDOUT:   %v: ref ((i32, i32, i32), (i32, i32, i32)) = bind_name v, %v.var
 // CHECK:STDOUT:   %F.ref.loc10_48: <function> = name_ref F, file.%F, const = file.%F
@@ -68,8 +68,8 @@ fn H() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc14_30: (type, type, type) = tuple_literal (i32, i32, i32)
 // CHECK:STDOUT:   %.loc14_36.1: (type, (type, type, type), type) = tuple_literal (i32, %.loc14_30, i32)
-// CHECK:STDOUT:   %.loc7: type = converted %.loc14_30, constants.%.loc7_25.2
-// CHECK:STDOUT:   %.loc14_36.2: type = converted %.loc14_36.1, constants.%.loc14_36.2
+// CHECK:STDOUT:   %.loc7: type = converted %.loc14_30, constants.%.loc7_25.2, const = constants.%.loc7_25.2
+// CHECK:STDOUT:   %.loc14_36.2: type = converted %.loc14_36.1, constants.%.loc14_36.2, const = constants.%.loc14_36.2
 // CHECK:STDOUT:   %v.var: ref (i32, (i32, i32, i32), i32) = var v
 // CHECK:STDOUT:   %v: ref (i32, (i32, i32, i32), i32) = bind_name v, %v.var
 // CHECK:STDOUT:   %.loc14_41: i32 = int_literal 1, const = constants.%.loc14_41

+ 2 - 2
toolchain/check/testdata/tuples/one_element.carbon

@@ -18,7 +18,7 @@ var y: (i32,) = x;
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.x = %x, .y = %y}
 // CHECK:STDOUT:   %.loc7_13.1: (type,) = tuple_literal (i32)
-// CHECK:STDOUT:   %.loc7_13.2: type = converted %.loc7_13.1, constants.%.loc7_13.2
+// CHECK:STDOUT:   %.loc7_13.2: type = converted %.loc7_13.1, constants.%.loc7_13.2, const = constants.%.loc7_13.2
 // CHECK:STDOUT:   %x.var: ref (i32,) = var x
 // CHECK:STDOUT:   %x: ref (i32,) = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc7_18: i32 = int_literal 4, const = constants.%.loc7_18
@@ -27,7 +27,7 @@ var y: (i32,) = x;
 // CHECK:STDOUT:   %.loc7_20.3: init (i32,) = converted %.loc7_20.1, %.loc7_20.2
 // CHECK:STDOUT:   assign %x.var, %.loc7_20.3
 // CHECK:STDOUT:   %.loc8_13: (type,) = tuple_literal (i32)
-// CHECK:STDOUT:   %.loc7_13.3: type = converted %.loc8_13, constants.%.loc7_13.2
+// CHECK:STDOUT:   %.loc7_13.3: type = converted %.loc8_13, constants.%.loc7_13.2, const = constants.%.loc7_13.2
 // CHECK:STDOUT:   %y.var: ref (i32,) = var y
 // CHECK:STDOUT:   %y: ref (i32,) = bind_name y, %y.var
 // CHECK:STDOUT:   %x.ref: ref (i32,) = name_ref x, %x

+ 41 - 23
toolchain/check/testdata/tuples/two_elements.carbon

@@ -4,6 +4,9 @@
 //
 // AUTOUPDATE
 
+let v: (i32, i32) = (4, 102);
+let w: (i32, i32) = v;
+
 var x: (i32, i32) = (4, 102);
 var y: (i32, i32) = x;
 
@@ -15,39 +18,54 @@ var y: (i32, i32) = x;
 // CHECK:STDOUT:   %.loc7_17.3: type = ptr_type (i32, i32), const
 // CHECK:STDOUT:   %.loc7_22: i32 = int_literal 4, const
 // CHECK:STDOUT:   %.loc7_25: i32 = int_literal 102, const
+// CHECK:STDOUT:   %.loc7_28: (i32, i32) = tuple_value (%.loc7_22, %.loc7_25), const
+// CHECK:STDOUT:   %.loc10_22: i32 = int_literal 4, const
+// CHECK:STDOUT:   %.loc10_25: i32 = int_literal 102, const
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.x = %x, .y = %y}
 // CHECK:STDOUT:   %.loc7_17.1: (type, type) = tuple_literal (i32, i32)
-// CHECK:STDOUT:   %.loc7_17.2: type = converted %.loc7_17.1, constants.%.loc7_17.2
-// CHECK:STDOUT:   %x.var: ref (i32, i32) = var x
-// CHECK:STDOUT:   %x: ref (i32, i32) = bind_name x, %x.var
+// CHECK:STDOUT:   %.loc7_17.2: type = converted %.loc7_17.1, constants.%.loc7_17.2, const = constants.%.loc7_17.2
 // CHECK:STDOUT:   %.loc7_22: i32 = int_literal 4, const = constants.%.loc7_22
 // CHECK:STDOUT:   %.loc7_25: i32 = int_literal 102, const = constants.%.loc7_25
 // CHECK:STDOUT:   %.loc7_28.1: (i32, i32) = tuple_literal (%.loc7_22, %.loc7_25)
-// CHECK:STDOUT:   %.loc7_28.2: ref i32 = tuple_access %x.var, element0
-// CHECK:STDOUT:   %.loc7_28.3: init i32 = initialize_from %.loc7_22 to %.loc7_28.2
-// CHECK:STDOUT:   %.loc7_28.4: ref i32 = tuple_access %x.var, element1
-// CHECK:STDOUT:   %.loc7_28.5: init i32 = initialize_from %.loc7_25 to %.loc7_28.4
-// CHECK:STDOUT:   %.loc7_28.6: init (i32, i32) = tuple_init (%.loc7_28.3, %.loc7_28.5) to %x.var
-// CHECK:STDOUT:   %.loc7_28.7: init (i32, i32) = converted %.loc7_28.1, %.loc7_28.6
-// CHECK:STDOUT:   assign %x.var, %.loc7_28.7
-// CHECK:STDOUT:   %.loc8_17: (type, type) = tuple_literal (i32, i32)
-// CHECK:STDOUT:   %.loc7_17.3: type = converted %.loc8_17, constants.%.loc7_17.2
+// CHECK:STDOUT:   %.loc7_28.2: (i32, i32) = tuple_value (%.loc7_22, %.loc7_25), const = constants.%.loc7_28
+// CHECK:STDOUT:   %.loc7_28.3: (i32, i32) = converted %.loc7_28.1, %.loc7_28.2, const = constants.%.loc7_28
+// CHECK:STDOUT:   %v: (i32, i32) = bind_name v, %.loc7_28.3
+// CHECK:STDOUT:   %.loc8: (type, type) = tuple_literal (i32, i32)
+// CHECK:STDOUT:   %.loc7_17.3: type = converted %.loc8, constants.%.loc7_17.2, const = constants.%.loc7_17.2
+// CHECK:STDOUT:   %v.ref: (i32, i32) = name_ref v, %v
+// CHECK:STDOUT:   %w: (i32, i32) = bind_name w, %v.ref
+// CHECK:STDOUT:   %.loc10_17: (type, type) = tuple_literal (i32, i32)
+// CHECK:STDOUT:   %.loc7_17.4: type = converted %.loc10_17, constants.%.loc7_17.2, const = constants.%.loc7_17.2
+// CHECK:STDOUT:   %x.var: ref (i32, i32) = var x
+// CHECK:STDOUT:   %x: ref (i32, i32) = bind_name x, %x.var
+// CHECK:STDOUT:   %.loc10_22: i32 = int_literal 4, const = constants.%.loc10_22
+// CHECK:STDOUT:   %.loc10_25: i32 = int_literal 102, const = constants.%.loc10_25
+// CHECK:STDOUT:   %.loc10_28.1: (i32, i32) = tuple_literal (%.loc10_22, %.loc10_25)
+// CHECK:STDOUT:   %.loc10_28.2: ref i32 = tuple_access %x.var, element0
+// CHECK:STDOUT:   %.loc10_28.3: init i32 = initialize_from %.loc10_22 to %.loc10_28.2
+// CHECK:STDOUT:   %.loc10_28.4: ref i32 = tuple_access %x.var, element1
+// CHECK:STDOUT:   %.loc10_28.5: init i32 = initialize_from %.loc10_25 to %.loc10_28.4
+// CHECK:STDOUT:   %.loc10_28.6: init (i32, i32) = tuple_init (%.loc10_28.3, %.loc10_28.5) to %x.var
+// CHECK:STDOUT:   %.loc10_28.7: init (i32, i32) = converted %.loc10_28.1, %.loc10_28.6
+// CHECK:STDOUT:   assign %x.var, %.loc10_28.7
+// CHECK:STDOUT:   %.loc11_17: (type, type) = tuple_literal (i32, i32)
+// CHECK:STDOUT:   %.loc7_17.5: type = converted %.loc11_17, constants.%.loc7_17.2, const = constants.%.loc7_17.2
 // CHECK:STDOUT:   %y.var: ref (i32, i32) = var y
 // CHECK:STDOUT:   %y: ref (i32, i32) = bind_name y, %y.var
 // CHECK:STDOUT:   %x.ref: ref (i32, i32) = name_ref x, %x
-// CHECK:STDOUT:   %.loc8_21.1: ref i32 = tuple_access %x.ref, element0
-// CHECK:STDOUT:   %.loc8_21.2: i32 = bind_value %.loc8_21.1
-// CHECK:STDOUT:   %.loc8_21.3: ref i32 = tuple_access %y.var, element0
-// CHECK:STDOUT:   %.loc8_21.4: init i32 = initialize_from %.loc8_21.2 to %.loc8_21.3
-// CHECK:STDOUT:   %.loc8_21.5: ref i32 = tuple_access %x.ref, element1
-// CHECK:STDOUT:   %.loc8_21.6: i32 = bind_value %.loc8_21.5
-// CHECK:STDOUT:   %.loc8_21.7: ref i32 = tuple_access %y.var, element1
-// CHECK:STDOUT:   %.loc8_21.8: init i32 = initialize_from %.loc8_21.6 to %.loc8_21.7
-// CHECK:STDOUT:   %.loc8_21.9: init (i32, i32) = tuple_init (%.loc8_21.4, %.loc8_21.8) to %y.var
-// CHECK:STDOUT:   %.loc8_21.10: init (i32, i32) = converted %x.ref, %.loc8_21.9
-// CHECK:STDOUT:   assign %y.var, %.loc8_21.10
+// CHECK:STDOUT:   %.loc11_21.1: ref i32 = tuple_access %x.ref, element0
+// CHECK:STDOUT:   %.loc11_21.2: i32 = bind_value %.loc11_21.1
+// CHECK:STDOUT:   %.loc11_21.3: ref i32 = tuple_access %y.var, element0
+// CHECK:STDOUT:   %.loc11_21.4: init i32 = initialize_from %.loc11_21.2 to %.loc11_21.3
+// CHECK:STDOUT:   %.loc11_21.5: ref i32 = tuple_access %x.ref, element1
+// CHECK:STDOUT:   %.loc11_21.6: i32 = bind_value %.loc11_21.5
+// CHECK:STDOUT:   %.loc11_21.7: ref i32 = tuple_access %y.var, element1
+// CHECK:STDOUT:   %.loc11_21.8: init i32 = initialize_from %.loc11_21.6 to %.loc11_21.7
+// CHECK:STDOUT:   %.loc11_21.9: init (i32, i32) = tuple_init (%.loc11_21.4, %.loc11_21.8) to %y.var
+// CHECK:STDOUT:   %.loc11_21.10: init (i32, i32) = converted %x.ref, %.loc11_21.9
+// CHECK:STDOUT:   assign %y.var, %.loc11_21.10
 // CHECK:STDOUT: }
 // CHECK:STDOUT: