Pārlūkot izejas kodu

Convert array bounds to `IntLiteral`. (#4526)

Instead of leaving array bounds as whatever integer type they arrive as,
convert them to the `IntLiteral` type as part of forming an `ArrayType`.
This ensures that array types canonicalize properly even when the bounds
are specified with different types.

Create an empty generic definition for a generic builtin function to
avoid this causing "use of undefined generic function" errors.
Richard Smith 1 gadu atpakaļ
vecāks
revīzija
980ce6b25a
62 mainītis faili ar 2867 papildinājumiem un 1430 dzēšanām
  1. 12 6
      toolchain/check/handle_array.cpp
  2. 3 0
      toolchain/check/handle_function.cpp
  3. 24 12
      toolchain/check/testdata/array/array_in_place.carbon
  4. 36 24
      toolchain/check/testdata/array/array_vs_tuple.carbon
  5. 20 8
      toolchain/check/testdata/array/assign_return_value.carbon
  6. 22 10
      toolchain/check/testdata/array/assign_var.carbon
  7. 70 44
      toolchain/check/testdata/array/base.carbon
  8. 115 40
      toolchain/check/testdata/array/canonicalize_index.carbon
  9. 16 2
      toolchain/check/testdata/array/fail_bound_negative.carbon
  10. 21 9
      toolchain/check/testdata/array/fail_incomplete_element.carbon
  11. 13 2
      toolchain/check/testdata/array/fail_invalid_type.carbon
  12. 22 10
      toolchain/check/testdata/array/fail_out_of_bound.carbon
  13. 37 25
      toolchain/check/testdata/array/fail_out_of_bound_non_literal.carbon
  14. 56 30
      toolchain/check/testdata/array/fail_type_mismatch.carbon
  15. 40 28
      toolchain/check/testdata/array/function_param.carbon
  16. 22 10
      toolchain/check/testdata/array/generic_empty.carbon
  17. 39 27
      toolchain/check/testdata/array/index_not_literal.carbon
  18. 55 43
      toolchain/check/testdata/array/nine_elements.carbon
  19. 87 70
      toolchain/check/testdata/basics/numeric_literals.carbon
  20. 31 12
      toolchain/check/testdata/builtins/int/and.carbon
  21. 31 12
      toolchain/check/testdata/builtins/int/complement.carbon
  22. 31 12
      toolchain/check/testdata/builtins/int/left_shift.carbon
  23. 31 12
      toolchain/check/testdata/builtins/int/or.carbon
  24. 101 49
      toolchain/check/testdata/builtins/int/right_shift.carbon
  25. 39 14
      toolchain/check/testdata/builtins/int/sadd.carbon
  26. 31 12
      toolchain/check/testdata/builtins/int/sdiv.carbon
  27. 31 12
      toolchain/check/testdata/builtins/int/smod.carbon
  28. 31 12
      toolchain/check/testdata/builtins/int/smul.carbon
  29. 45 20
      toolchain/check/testdata/builtins/int/snegate.carbon
  30. 31 12
      toolchain/check/testdata/builtins/int/ssub.carbon
  31. 39 14
      toolchain/check/testdata/builtins/int/uadd.carbon
  32. 31 12
      toolchain/check/testdata/builtins/int/udiv.carbon
  33. 31 12
      toolchain/check/testdata/builtins/int/umod.carbon
  34. 31 12
      toolchain/check/testdata/builtins/int/umul.carbon
  35. 45 20
      toolchain/check/testdata/builtins/int/unegate.carbon
  36. 31 12
      toolchain/check/testdata/builtins/int/usub.carbon
  37. 31 12
      toolchain/check/testdata/builtins/int/xor.carbon
  38. 257 153
      toolchain/check/testdata/deduce/array.carbon
  39. 67 40
      toolchain/check/testdata/eval/aggregate.carbon
  40. 53 32
      toolchain/check/testdata/eval/fail_aggregate.carbon
  41. 27 13
      toolchain/check/testdata/eval/fail_symbolic.carbon
  42. 18 6
      toolchain/check/testdata/eval/symbolic.carbon
  43. 19 5
      toolchain/check/testdata/function/builtin/call.carbon
  44. 48 34
      toolchain/check/testdata/function/builtin/method.carbon
  45. 408 125
      toolchain/check/testdata/function/builtin/no_prelude/call_from_operator.carbon
  46. 82 30
      toolchain/check/testdata/function/builtin/no_prelude/import.carbon
  47. 2 0
      toolchain/check/testdata/function/declaration/fail_param_in_type.carbon
  48. 29 13
      toolchain/check/testdata/function/generic/fail_todo_param_in_type.carbon
  49. 30 18
      toolchain/check/testdata/function/generic/return_slot.carbon
  50. 26 14
      toolchain/check/testdata/if_expr/basic.carbon
  51. 73 51
      toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon
  52. 35 23
      toolchain/check/testdata/index/array_element_access.carbon
  53. 105 73
      toolchain/check/testdata/index/expr_category.carbon
  54. 30 18
      toolchain/check/testdata/index/fail_array_large_index.carbon
  55. 27 16
      toolchain/check/testdata/index/fail_array_non_int_indexing.carbon
  56. 27 15
      toolchain/check/testdata/index/fail_array_out_of_bound_access.carbon
  57. 60 43
      toolchain/check/testdata/index/fail_expr_category.carbon
  58. 33 21
      toolchain/check/testdata/index/fail_negative_indexing.carbon
  59. 1 0
      toolchain/check/testdata/interface/fail_todo_define_default_fn_inline.carbon
  60. 1 0
      toolchain/check/testdata/interface/fail_todo_define_default_fn_out_of_line.carbon
  61. 1 0
      toolchain/check/testdata/interface/todo_define_not_default.carbon
  62. 26 14
      toolchain/check/testdata/tuple/access/fail_non_tuple_access.carbon

+ 12 - 6
toolchain/check/handle_array.cpp

@@ -6,6 +6,7 @@
 #include "toolchain/check/convert.h"
 #include "toolchain/check/handle.h"
 #include "toolchain/parse/node_kind.h"
+#include "toolchain/sem_ir/builtin_inst_kind.h"
 
 namespace Carbon::Check {
 
@@ -33,24 +34,29 @@ auto HandleParseNode(Context& context, Parse::ArrayExprId node_id) -> bool {
   auto [element_type_node_id, element_type_inst_id] =
       context.node_stack().PopExprWithNodeId();
 
-  // The array bound must be a constant.
+  auto element_type_id =
+      ExprAsType(context, element_type_node_id, element_type_inst_id).type_id;
+
+  // The array bound must be a constant. Diagnose this prior to conversion
+  // because conversion to `IntLiteral` will produce a generic "non-constant
+  // call to compile-time-only function" error.
   //
   // TODO: Should we support runtime-phase bounds in cases such as:
   //   comptime fn F(n: i32) -> type { return [i32; n]; }
-  auto bound_inst = context.constant_values().Get(bound_inst_id);
-  if (!bound_inst.is_constant()) {
+  if (!context.constant_values().Get(bound_inst_id).is_constant()) {
     CARBON_DIAGNOSTIC(InvalidArrayExpr, Error, "array bound is not a constant");
     context.emitter().Emit(bound_inst_id, InvalidArrayExpr);
     context.node_stack().Push(node_id, SemIR::InstId::BuiltinError);
     return true;
   }
 
+  bound_inst_id = ConvertToValueOfType(
+      context, context.insts().GetLocId(bound_inst_id), bound_inst_id,
+      context.GetBuiltinType(SemIR::BuiltinInstKind::IntLiteralType));
   context.AddInstAndPush<SemIR::ArrayType>(
       node_id, {.type_id = SemIR::TypeId::TypeType,
                 .bound_id = bound_inst_id,
-                .element_type_id = ExprAsType(context, element_type_node_id,
-                                              element_type_inst_id)
-                                       .type_id});
+                .element_type_id = element_type_id});
   return true;
 }
 

+ 3 - 0
toolchain/check/handle_function.cpp

@@ -502,6 +502,9 @@ auto HandleParseNode(Context& context,
     auto& function = context.functions().Get(function_id);
     if (IsValidBuiltinDeclaration(context, function, builtin_kind)) {
       function.builtin_function_kind = builtin_kind;
+      // Build an empty generic definition if this is a generic builtin.
+      StartGenericDefinition(context);
+      FinishGenericDefinition(context, function.generic_id);
     } else {
       CARBON_DIAGNOSTIC(InvalidBuiltinSignature, Error,
                         "invalid signature for builtin function \"{0}\"",

+ 24 - 12
toolchain/check/testdata/array/array_in_place.carbon

@@ -26,15 +26,22 @@ fn G() {
 // CHECK:STDOUT:   %G.type: type = fn_type @G [template]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 2 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, %tuple.type.2 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 2 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, %tuple.type.2 [template]
 // CHECK:STDOUT:   %tuple.type.3: type = tuple_type (%tuple.type.2, %tuple.type.2) [template]
-// CHECK:STDOUT:   %.5: i32 = int_value 0 [template]
-// CHECK:STDOUT:   %.6: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %.31: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %.32: i32 = int_value 1 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -76,7 +83,7 @@ fn G() {
 // CHECK:STDOUT:   %int.make_type_32.loc14_17: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %int.make_type_32.loc14_22: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc14_25.1: %tuple.type.1 = tuple_literal (%int.make_type_32.loc14_12, %int.make_type_32.loc14_17, %int.make_type_32.loc14_22)
-// CHECK:STDOUT:   %.loc14_28: i32 = int_value 2 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc14_28.1: i32 = int_value 2 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc14_25.2: type = value_of_initializer %int.make_type_32.loc14_12 [template = i32]
 // CHECK:STDOUT:   %.loc14_25.3: type = converted %int.make_type_32.loc14_12, %.loc14_25.2 [template = i32]
 // CHECK:STDOUT:   %.loc14_25.4: type = value_of_initializer %int.make_type_32.loc14_17 [template = i32]
@@ -84,24 +91,29 @@ fn G() {
 // CHECK:STDOUT:   %.loc14_25.6: type = value_of_initializer %int.make_type_32.loc14_22 [template = i32]
 // CHECK:STDOUT:   %.loc14_25.7: type = converted %int.make_type_32.loc14_22, %.loc14_25.6 [template = i32]
 // CHECK:STDOUT:   %.loc14_25.8: type = converted %.loc14_25.1, constants.%tuple.type.2 [template = constants.%tuple.type.2]
-// CHECK:STDOUT:   %.loc14_29: type = array_type %.loc14_28, %tuple.type.2 [template = constants.%.2]
-// CHECK:STDOUT:   %v.var: ref %.2 = var v
-// CHECK:STDOUT:   %v: ref %.2 = bind_name v, %v.var
+// CHECK:STDOUT:   %.loc14_28.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc14_28.3: <bound method> = bound_method %.loc14_28.1, %.loc14_28.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc14_28.3(%.loc14_28.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc14_28.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:   %.loc14_28.5: Core.IntLiteral = converted %.loc14_28.1, %.loc14_28.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc14_29: type = array_type %.loc14_28.5, %tuple.type.2 [template = constants.%.28]
+// CHECK:STDOUT:   %v.var: ref %.28 = var v
+// CHECK:STDOUT:   %v: ref %.28 = bind_name v, %v.var
 // CHECK:STDOUT:   %F.ref.loc14_34: %F.type = name_ref F, file.%F.decl [template = constants.%F]
 // CHECK:STDOUT:   %.loc14_42.3: ref %tuple.type.2 = splice_block %.loc14_42.2 {
-// CHECK:STDOUT:     %.loc14_42.1: i32 = int_value 0 [template = constants.%.5]
+// CHECK:STDOUT:     %.loc14_42.1: i32 = int_value 0 [template = constants.%.31]
 // CHECK:STDOUT:     %.loc14_42.2: ref %tuple.type.2 = array_index %v.var, %.loc14_42.1
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %F.call.loc14_35: init %tuple.type.2 = call %F.ref.loc14_34() to %.loc14_42.3
 // CHECK:STDOUT:   %F.ref.loc14_39: %F.type = name_ref F, file.%F.decl [template = constants.%F]
 // CHECK:STDOUT:   %.loc14_42.6: ref %tuple.type.2 = splice_block %.loc14_42.5 {
-// CHECK:STDOUT:     %.loc14_42.4: i32 = int_value 1 [template = constants.%.6]
+// CHECK:STDOUT:     %.loc14_42.4: i32 = int_value 1 [template = constants.%.32]
 // CHECK:STDOUT:     %.loc14_42.5: ref %tuple.type.2 = array_index %v.var, %.loc14_42.4
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %F.call.loc14_40: init %tuple.type.2 = call %F.ref.loc14_39() to %.loc14_42.6
 // CHECK:STDOUT:   %.loc14_42.7: %tuple.type.3 = tuple_literal (%F.call.loc14_35, %F.call.loc14_40)
-// CHECK:STDOUT:   %.loc14_42.8: init %.2 = array_init (%F.call.loc14_35, %F.call.loc14_40) to %v.var
-// CHECK:STDOUT:   %.loc14_43: init %.2 = converted %.loc14_42.7, %.loc14_42.8
+// CHECK:STDOUT:   %.loc14_42.8: init %.28 = array_init (%F.call.loc14_35, %F.call.loc14_40) to %v.var
+// CHECK:STDOUT:   %.loc14_43: init %.28 = converted %.loc14_42.7, %.loc14_42.8
 // CHECK:STDOUT:   assign %v.var, %.loc14_43
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 36 - 24
toolchain/check/testdata/array/array_vs_tuple.carbon

@@ -22,19 +22,26 @@ fn G() {
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.5: i32 = int_value 2 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, i32 [template]
+// CHECK:STDOUT:   %.30: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %.31: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %tuple.type.1: type = tuple_type (i32, i32, i32) [template]
-// CHECK:STDOUT:   %.6: i32 = int_value 0 [template]
-// CHECK:STDOUT:   %array: %.2 = tuple_value (%.4, %.5, %.1) [template]
+// CHECK:STDOUT:   %.32: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %array: %.28 = tuple_value (%.30, %.31, %.1) [template]
 // CHECK:STDOUT:   %tuple.type.2: type = tuple_type (type, type, type) [template]
-// CHECK:STDOUT:   %tuple: %tuple.type.1 = tuple_value (%.4, %.5, %.1) [template]
+// CHECK:STDOUT:   %tuple: %tuple.type.1 = tuple_value (%.30, %.31, %.1) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -52,27 +59,32 @@ fn G() {
 // CHECK:STDOUT: fn @G() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %int.make_type_32.loc13: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc13_16: i32 = int_value 3 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc13_16.1: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc13_11.1: type = value_of_initializer %int.make_type_32.loc13 [template = i32]
 // CHECK:STDOUT:   %.loc13_11.2: type = converted %int.make_type_32.loc13, %.loc13_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc13_17: type = array_type %.loc13_16, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %a.var: ref %.2 = var a
-// CHECK:STDOUT:   %a: ref %.2 = bind_name a, %a.var
-// CHECK:STDOUT:   %.loc13_22: i32 = int_value 1 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc13_25: i32 = int_value 2 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc13_16.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc13_16.3: <bound method> = bound_method %.loc13_16.1, %.loc13_16.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc13_16.3(%.loc13_16.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc13_16.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:   %.loc13_16.5: Core.IntLiteral = converted %.loc13_16.1, %.loc13_16.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc13_17: type = array_type %.loc13_16.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %a.var: ref %.28 = var a
+// CHECK:STDOUT:   %a: ref %.28 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc13_22: i32 = int_value 1 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc13_25: i32 = int_value 2 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc13_28: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc13_29.1: %tuple.type.1 = tuple_literal (%.loc13_22, %.loc13_25, %.loc13_28)
-// CHECK:STDOUT:   %.loc13_29.2: i32 = int_value 0 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc13_29.2: i32 = int_value 0 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc13_29.3: ref i32 = array_index %a.var, %.loc13_29.2
-// CHECK:STDOUT:   %.loc13_29.4: init i32 = initialize_from %.loc13_22 to %.loc13_29.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc13_29.5: i32 = int_value 1 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc13_29.4: init i32 = initialize_from %.loc13_22 to %.loc13_29.3 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc13_29.5: i32 = int_value 1 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc13_29.6: ref i32 = array_index %a.var, %.loc13_29.5
-// CHECK:STDOUT:   %.loc13_29.7: init i32 = initialize_from %.loc13_25 to %.loc13_29.6 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc13_29.8: i32 = int_value 2 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc13_29.7: init i32 = initialize_from %.loc13_25 to %.loc13_29.6 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc13_29.8: i32 = int_value 2 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc13_29.9: ref i32 = array_index %a.var, %.loc13_29.8
 // CHECK:STDOUT:   %.loc13_29.10: init i32 = initialize_from %.loc13_28 to %.loc13_29.9 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc13_29.11: init %.2 = array_init (%.loc13_29.4, %.loc13_29.7, %.loc13_29.10) to %a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc13_30: init %.2 = converted %.loc13_29.1, %.loc13_29.11 [template = constants.%array]
+// CHECK:STDOUT:   %.loc13_29.11: init %.28 = array_init (%.loc13_29.4, %.loc13_29.7, %.loc13_29.10) to %a.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc13_30: init %.28 = converted %.loc13_29.1, %.loc13_29.11 [template = constants.%array]
 // CHECK:STDOUT:   assign %a.var, %.loc13_30
 // CHECK:STDOUT:   %int.make_type_32.loc14_11: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %int.make_type_32.loc14_16: init type = call constants.%Int32() [template = i32]
@@ -87,14 +99,14 @@ fn G() {
 // CHECK:STDOUT:   %.loc14_24.8: type = converted %.loc14_24.1, constants.%tuple.type.1 [template = constants.%tuple.type.1]
 // CHECK:STDOUT:   %b.var: ref %tuple.type.1 = var b
 // CHECK:STDOUT:   %b: ref %tuple.type.1 = bind_name b, %b.var
-// CHECK:STDOUT:   %.loc14_29: i32 = int_value 1 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc14_32: i32 = int_value 2 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc14_29: i32 = int_value 1 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc14_32: i32 = int_value 2 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc14_35: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc14_36.1: %tuple.type.1 = tuple_literal (%.loc14_29, %.loc14_32, %.loc14_35)
 // CHECK:STDOUT:   %.loc14_36.2: ref i32 = tuple_access %b.var, element0
-// CHECK:STDOUT:   %.loc14_36.3: init i32 = initialize_from %.loc14_29 to %.loc14_36.2 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc14_36.3: init i32 = initialize_from %.loc14_29 to %.loc14_36.2 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc14_36.4: ref i32 = tuple_access %b.var, element1
-// CHECK:STDOUT:   %.loc14_36.5: init i32 = initialize_from %.loc14_32 to %.loc14_36.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc14_36.5: init i32 = initialize_from %.loc14_32 to %.loc14_36.4 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc14_36.6: ref i32 = tuple_access %b.var, element2
 // CHECK:STDOUT:   %.loc14_36.7: init i32 = initialize_from %.loc14_35 to %.loc14_36.6 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc14_36.8: init %tuple.type.1 = tuple_init (%.loc14_36.3, %.loc14_36.5, %.loc14_36.7) to %b.var [template = constants.%tuple]

+ 20 - 8
toolchain/check/testdata/array/assign_return_value.carbon

@@ -28,12 +28,19 @@ fn Run() {
 // CHECK:STDOUT:   %Run.type: type = fn_type @Run [template]
 // CHECK:STDOUT:   %Run: %Run.type = struct_value () [template]
 // CHECK:STDOUT:   %.2: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.3: type = array_type %.2, i32 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.26: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.27: <bound method> = bound_method %.2, %Convert.15 [template]
+// CHECK:STDOUT:   %.28: Core.IntLiteral = int_value 1 [template]
+// CHECK:STDOUT:   %.29: type = array_type %.28, i32 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -73,12 +80,17 @@ fn Run() {
 // CHECK:STDOUT: fn @Run() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %int.make_type_32: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc14_16: i32 = int_value 1 [template = constants.%.2]
+// CHECK:STDOUT:   %.loc14_16.1: i32 = int_value 1 [template = constants.%.2]
 // CHECK:STDOUT:   %.loc14_11.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:   %.loc14_11.2: type = converted %int.make_type_32, %.loc14_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc14_17: type = array_type %.loc14_16, i32 [template = constants.%.3]
-// CHECK:STDOUT:   %t.var: ref %.3 = var t
-// CHECK:STDOUT:   %t: ref %.3 = bind_name t, %t.var
+// CHECK:STDOUT:   %.loc14_16.2: %Convert.type.2 = interface_witness_access constants.%.26, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc14_16.3: <bound method> = bound_method %.loc14_16.1, %.loc14_16.2 [template = constants.%.27]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc14_16.3(%.loc14_16.1) [template = constants.%.28]
+// CHECK:STDOUT:   %.loc14_16.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.28]
+// CHECK:STDOUT:   %.loc14_16.5: Core.IntLiteral = converted %.loc14_16.1, %.loc14_16.4 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc14_17: type = array_type %.loc14_16.5, i32 [template = constants.%.29]
+// CHECK:STDOUT:   %t.var: ref %.29 = var t
+// CHECK:STDOUT:   %t: ref %.29 = bind_name t, %t.var
 // CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F]
 // CHECK:STDOUT:   %F.call: init %tuple.type.2 = call %F.ref()
 // CHECK:STDOUT:   %.loc14_22.1: ref %tuple.type.2 = temporary_storage
@@ -88,8 +100,8 @@ fn Run() {
 // CHECK:STDOUT:   %.loc14_22.5: i32 = int_value 0 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc14_22.6: ref i32 = array_index %t.var, %.loc14_22.5
 // CHECK:STDOUT:   %.loc14_22.7: init i32 = initialize_from %.loc14_22.4 to %.loc14_22.6
-// CHECK:STDOUT:   %.loc14_22.8: init %.3 = array_init (%.loc14_22.7) to %t.var
-// CHECK:STDOUT:   %.loc14_24: init %.3 = converted %F.call, %.loc14_22.8
+// CHECK:STDOUT:   %.loc14_22.8: init %.29 = array_init (%.loc14_22.7) to %t.var
+// CHECK:STDOUT:   %.loc14_24: init %.29 = converted %F.call, %.loc14_22.8
 // CHECK:STDOUT:   assign %t.var, %.loc14_24
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 22 - 10
toolchain/check/testdata/array/assign_var.carbon

@@ -22,13 +22,20 @@ var b: [i32; 3] = a;
 // CHECK:STDOUT:   %.3: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %.4: i32 = int_value 3 [template]
 // CHECK:STDOUT:   %tuple: %tuple.type.2 = tuple_value (%.2, %.3, %.4) [template]
-// CHECK:STDOUT:   %.5: type = array_type %.4, i32 [template]
-// CHECK:STDOUT:   %.7: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.28: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.29: <bound method> = bound_method %.4, %Convert.15 [template]
+// CHECK:STDOUT:   %.30: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.31: type = array_type %.30, i32 [template]
+// CHECK:STDOUT:   %.33: i32 = int_value 0 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -55,12 +62,17 @@ var b: [i32; 3] = a;
 // CHECK:STDOUT:   %a.var: ref %tuple.type.2 = var a
 // CHECK:STDOUT:   %a: ref %tuple.type.2 = bind_name a, %a.var
 // CHECK:STDOUT:   %int.make_type_32.loc12: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc12_14: i32 = int_value 3 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc12_14.1: i32 = int_value 3 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc12_9.1: type = value_of_initializer %int.make_type_32.loc12 [template = i32]
 // CHECK:STDOUT:   %.loc12_9.2: type = converted %int.make_type_32.loc12, %.loc12_9.1 [template = i32]
-// CHECK:STDOUT:   %.loc12_15: type = array_type %.loc12_14, i32 [template = constants.%.5]
-// CHECK:STDOUT:   %b.var: ref %.5 = var b
-// CHECK:STDOUT:   %b: ref %.5 = bind_name b, %b.var
+// CHECK:STDOUT:   %.loc12_14.2: %Convert.type.2 = interface_witness_access constants.%.28, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc12_14.3: <bound method> = bound_method %.loc12_14.1, %.loc12_14.2 [template = constants.%.29]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc12_14.3(%.loc12_14.1) [template = constants.%.30]
+// CHECK:STDOUT:   %.loc12_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.30]
+// CHECK:STDOUT:   %.loc12_14.5: Core.IntLiteral = converted %.loc12_14.1, %.loc12_14.4 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc12_15: type = array_type %.loc12_14.5, i32 [template = constants.%.31]
+// CHECK:STDOUT:   %b.var: ref %.31 = var b
+// CHECK:STDOUT:   %b: ref %.31 = bind_name b, %b.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
@@ -81,7 +93,7 @@ var b: [i32; 3] = a;
 // CHECK:STDOUT:   %a.ref: ref %tuple.type.2 = name_ref a, file.%a
 // CHECK:STDOUT:   %.loc12_19.1: ref i32 = tuple_access %a.ref, element0
 // CHECK:STDOUT:   %.loc12_19.2: i32 = bind_value %.loc12_19.1
-// CHECK:STDOUT:   %.loc12_19.3: i32 = int_value 0 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc12_19.3: i32 = int_value 0 [template = constants.%.33]
 // CHECK:STDOUT:   %.loc12_19.4: ref i32 = array_index file.%b.var, %.loc12_19.3
 // CHECK:STDOUT:   %.loc12_19.5: init i32 = initialize_from %.loc12_19.2 to %.loc12_19.4
 // CHECK:STDOUT:   %.loc12_19.6: ref i32 = tuple_access %a.ref, element1
@@ -94,8 +106,8 @@ var b: [i32; 3] = a;
 // CHECK:STDOUT:   %.loc12_19.13: i32 = int_value 2 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc12_19.14: ref i32 = array_index file.%b.var, %.loc12_19.13
 // CHECK:STDOUT:   %.loc12_19.15: init i32 = initialize_from %.loc12_19.12 to %.loc12_19.14
-// CHECK:STDOUT:   %.loc12_19.16: init %.5 = array_init (%.loc12_19.5, %.loc12_19.10, %.loc12_19.15) to file.%b.var
-// CHECK:STDOUT:   %.loc12_20: init %.5 = converted %a.ref, %.loc12_19.16
+// CHECK:STDOUT:   %.loc12_19.16: init %.31 = array_init (%.loc12_19.5, %.loc12_19.10, %.loc12_19.15) to file.%b.var
+// CHECK:STDOUT:   %.loc12_20: init %.31 = converted %a.ref, %.loc12_19.16
 // CHECK:STDOUT:   assign file.%b.var, %.loc12_20
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 70 - 44
toolchain/check/testdata/array/base.carbon

@@ -19,32 +19,43 @@ var c: [(); 5] = ((), (), (), (), (),);
 // CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 1 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, i32 [template]
 // CHECK:STDOUT:   %tuple.type.1: type = tuple_type (i32) [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 0 [template]
-// CHECK:STDOUT:   %array.1: %.2 = tuple_value (%.1) [template]
-// CHECK:STDOUT:   %.5: Core.IntLiteral = int_value 64 [template]
+// CHECK:STDOUT:   %.30: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %array.1: %.28 = tuple_value (%.1) [template]
+// CHECK:STDOUT:   %.31: Core.IntLiteral = int_value 64 [template]
 // CHECK:STDOUT:   %Float.type: type = fn_type @Float [template]
 // CHECK:STDOUT:   %Float: %Float.type = struct_value () [template]
-// CHECK:STDOUT:   %.6: i32 = int_value 2 [template]
-// CHECK:STDOUT:   %.7: type = array_type %.6, f64 [template]
-// CHECK:STDOUT:   %.9: f64 = float_literal 11.100000000000001 [template]
-// CHECK:STDOUT:   %.10: f64 = float_literal 2.2000000000000002 [template]
+// CHECK:STDOUT:   %.32: i32 = int_value 2 [template]
+// CHECK:STDOUT:   %.33: <bound method> = bound_method %.32, %Convert.15 [template]
+// CHECK:STDOUT:   %.34: Core.IntLiteral = int_value 2 [template]
+// CHECK:STDOUT:   %.35: type = array_type %.34, f64 [template]
+// CHECK:STDOUT:   %.37: f64 = float_literal 11.100000000000001 [template]
+// CHECK:STDOUT:   %.38: f64 = float_literal 2.2000000000000002 [template]
 // CHECK:STDOUT:   %tuple.type.2: type = tuple_type (f64, f64) [template]
-// CHECK:STDOUT:   %array.2: %.7 = tuple_value (%.9, %.10) [template]
-// CHECK:STDOUT:   %.11: i32 = int_value 5 [template]
-// CHECK:STDOUT:   %.12: type = array_type %.11, %empty_tuple.type [template]
+// CHECK:STDOUT:   %array.2: %.35 = tuple_value (%.37, %.38) [template]
+// CHECK:STDOUT:   %.39: i32 = int_value 5 [template]
+// CHECK:STDOUT:   %.40: <bound method> = bound_method %.39, %Convert.15 [template]
+// CHECK:STDOUT:   %.41: Core.IntLiteral = int_value 5 [template]
+// CHECK:STDOUT:   %.42: type = array_type %.41, %empty_tuple.type [template]
 // CHECK:STDOUT:   %tuple.type.3: type = tuple_type (%empty_tuple.type, %empty_tuple.type, %empty_tuple.type, %empty_tuple.type, %empty_tuple.type) [template]
 // CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [template]
-// CHECK:STDOUT:   %.14: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.15: i32 = int_value 4 [template]
-// CHECK:STDOUT:   %array.3: %.12 = tuple_value (%empty_tuple, %empty_tuple, %empty_tuple, %empty_tuple, %empty_tuple) [template]
+// CHECK:STDOUT:   %.44: i32 = int_value 3 [template]
+// CHECK:STDOUT:   %.45: i32 = int_value 4 [template]
+// CHECK:STDOUT:   %array.3: %.42 = tuple_value (%empty_tuple, %empty_tuple, %empty_tuple, %empty_tuple, %empty_tuple) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
 // CHECK:STDOUT:     .Int32 = %import_ref.1
-// CHECK:STDOUT:     .Float = %import_ref.2
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
+// CHECK:STDOUT:     .Float = %import_ref.51
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -59,49 +70,64 @@ var c: [(); 5] = ((), (), (), (), (),);
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %int.make_type_32: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc11_14: i32 = int_value 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc11_14.1: i32 = int_value 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc11_9.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:   %.loc11_9.2: type = converted %int.make_type_32, %.loc11_9.1 [template = i32]
-// CHECK:STDOUT:   %.loc11_15: type = array_type %.loc11_14, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %a.var: ref %.2 = var a
-// CHECK:STDOUT:   %a: ref %.2 = bind_name a, %a.var
-// CHECK:STDOUT:   %.loc12_9.1: Core.IntLiteral = int_value 64 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc11_14.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc11_14.3: <bound method> = bound_method %.loc11_14.1, %.loc11_14.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked.loc11: init Core.IntLiteral = call %.loc11_14.3(%.loc11_14.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc11 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_14.5: Core.IntLiteral = converted %.loc11_14.1, %.loc11_14.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_15: type = array_type %.loc11_14.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %a.var: ref %.28 = var a
+// CHECK:STDOUT:   %a: ref %.28 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc12_9.1: Core.IntLiteral = int_value 64 [template = constants.%.31]
 // CHECK:STDOUT:   %float.make_type: init type = call constants.%Float(%.loc12_9.1) [template = f64]
-// CHECK:STDOUT:   %.loc12_14: i32 = int_value 2 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc12_14.1: i32 = int_value 2 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc12_9.2: type = value_of_initializer %float.make_type [template = f64]
 // CHECK:STDOUT:   %.loc12_9.3: type = converted %float.make_type, %.loc12_9.2 [template = f64]
-// CHECK:STDOUT:   %.loc12_15: type = array_type %.loc12_14, f64 [template = constants.%.7]
-// CHECK:STDOUT:   %b.var: ref %.7 = var b
-// CHECK:STDOUT:   %b: ref %.7 = bind_name b, %b.var
+// CHECK:STDOUT:   %.loc12_14.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc12_14.3: <bound method> = bound_method %.loc12_14.1, %.loc12_14.2 [template = constants.%.33]
+// CHECK:STDOUT:   %int.convert_checked.loc12: init Core.IntLiteral = call %.loc12_14.3(%.loc12_14.1) [template = constants.%.34]
+// CHECK:STDOUT:   %.loc12_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc12 [template = constants.%.34]
+// CHECK:STDOUT:   %.loc12_14.5: Core.IntLiteral = converted %.loc12_14.1, %.loc12_14.4 [template = constants.%.34]
+// CHECK:STDOUT:   %.loc12_15: type = array_type %.loc12_14.5, f64 [template = constants.%.35]
+// CHECK:STDOUT:   %b.var: ref %.35 = var b
+// CHECK:STDOUT:   %b: ref %.35 = bind_name b, %b.var
 // CHECK:STDOUT:   %.loc13_10.1: %empty_tuple.type = tuple_literal ()
-// CHECK:STDOUT:   %.loc13_13: i32 = int_value 5 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc13_13.1: i32 = int_value 5 [template = constants.%.39]
 // CHECK:STDOUT:   %.loc13_10.2: type = converted %.loc13_10.1, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
-// CHECK:STDOUT:   %.loc13_14: type = array_type %.loc13_13, %empty_tuple.type [template = constants.%.12]
-// CHECK:STDOUT:   %c.var: ref %.12 = var c
-// CHECK:STDOUT:   %c: ref %.12 = bind_name c, %c.var
+// CHECK:STDOUT:   %.loc13_13.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc13_13.3: <bound method> = bound_method %.loc13_13.1, %.loc13_13.2 [template = constants.%.40]
+// CHECK:STDOUT:   %int.convert_checked.loc13: init Core.IntLiteral = call %.loc13_13.3(%.loc13_13.1) [template = constants.%.41]
+// CHECK:STDOUT:   %.loc13_13.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc13 [template = constants.%.41]
+// CHECK:STDOUT:   %.loc13_13.5: Core.IntLiteral = converted %.loc13_13.1, %.loc13_13.4 [template = constants.%.41]
+// CHECK:STDOUT:   %.loc13_14: type = array_type %.loc13_13.5, %empty_tuple.type [template = constants.%.42]
+// CHECK:STDOUT:   %c.var: ref %.42 = var c
+// CHECK:STDOUT:   %c: ref %.42 = bind_name c, %c.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc11_20: i32 = int_value 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc11_22.1: %tuple.type.1 = tuple_literal (%.loc11_20)
-// CHECK:STDOUT:   %.loc11_22.2: i32 = int_value 0 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc11_22.2: i32 = int_value 0 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc11_22.3: ref i32 = array_index file.%a.var, %.loc11_22.2
 // CHECK:STDOUT:   %.loc11_22.4: init i32 = initialize_from %.loc11_20 to %.loc11_22.3 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc11_22.5: init %.2 = array_init (%.loc11_22.4) to file.%a.var [template = constants.%array.1]
-// CHECK:STDOUT:   %.loc11_23: init %.2 = converted %.loc11_22.1, %.loc11_22.5 [template = constants.%array.1]
+// CHECK:STDOUT:   %.loc11_22.5: init %.28 = array_init (%.loc11_22.4) to file.%a.var [template = constants.%array.1]
+// CHECK:STDOUT:   %.loc11_23: init %.28 = converted %.loc11_22.1, %.loc11_22.5 [template = constants.%array.1]
 // CHECK:STDOUT:   assign file.%a.var, %.loc11_23
-// CHECK:STDOUT:   %.loc12_20: f64 = float_literal 11.100000000000001 [template = constants.%.9]
-// CHECK:STDOUT:   %.loc12_26: f64 = float_literal 2.2000000000000002 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc12_20: f64 = float_literal 11.100000000000001 [template = constants.%.37]
+// CHECK:STDOUT:   %.loc12_26: f64 = float_literal 2.2000000000000002 [template = constants.%.38]
 // CHECK:STDOUT:   %.loc12_30.1: %tuple.type.2 = tuple_literal (%.loc12_20, %.loc12_26)
-// CHECK:STDOUT:   %.loc12_30.2: i32 = int_value 0 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc12_30.2: i32 = int_value 0 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc12_30.3: ref f64 = array_index file.%b.var, %.loc12_30.2
-// CHECK:STDOUT:   %.loc12_30.4: init f64 = initialize_from %.loc12_20 to %.loc12_30.3 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc12_30.4: init f64 = initialize_from %.loc12_20 to %.loc12_30.3 [template = constants.%.37]
 // CHECK:STDOUT:   %.loc12_30.5: i32 = int_value 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc12_30.6: ref f64 = array_index file.%b.var, %.loc12_30.5
-// CHECK:STDOUT:   %.loc12_30.7: init f64 = initialize_from %.loc12_26 to %.loc12_30.6 [template = constants.%.10]
-// CHECK:STDOUT:   %.loc12_30.8: init %.7 = array_init (%.loc12_30.4, %.loc12_30.7) to file.%b.var [template = constants.%array.2]
-// CHECK:STDOUT:   %.loc12_31: init %.7 = converted %.loc12_30.1, %.loc12_30.8 [template = constants.%array.2]
+// CHECK:STDOUT:   %.loc12_30.7: init f64 = initialize_from %.loc12_26 to %.loc12_30.6 [template = constants.%.38]
+// CHECK:STDOUT:   %.loc12_30.8: init %.35 = array_init (%.loc12_30.4, %.loc12_30.7) to file.%b.var [template = constants.%array.2]
+// CHECK:STDOUT:   %.loc12_31: init %.35 = converted %.loc12_30.1, %.loc12_30.8 [template = constants.%array.2]
 // CHECK:STDOUT:   assign file.%b.var, %.loc12_31
 // CHECK:STDOUT:   %.loc13_20.1: %empty_tuple.type = tuple_literal ()
 // CHECK:STDOUT:   %.loc13_24.1: %empty_tuple.type = tuple_literal ()
@@ -109,7 +135,7 @@ var c: [(); 5] = ((), (), (), (), (),);
 // CHECK:STDOUT:   %.loc13_32.1: %empty_tuple.type = tuple_literal ()
 // CHECK:STDOUT:   %.loc13_36.1: %empty_tuple.type = tuple_literal ()
 // CHECK:STDOUT:   %.loc13_38.1: %tuple.type.3 = tuple_literal (%.loc13_20.1, %.loc13_24.1, %.loc13_28.1, %.loc13_32.1, %.loc13_36.1)
-// CHECK:STDOUT:   %.loc13_38.2: i32 = int_value 0 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc13_38.2: i32 = int_value 0 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc13_38.3: ref %empty_tuple.type = array_index file.%c.var, %.loc13_38.2
 // CHECK:STDOUT:   %.loc13_20.2: init %empty_tuple.type = tuple_init () to %.loc13_38.3 [template = constants.%empty_tuple]
 // CHECK:STDOUT:   %.loc13_38.4: init %empty_tuple.type = converted %.loc13_20.1, %.loc13_20.2 [template = constants.%empty_tuple]
@@ -117,20 +143,20 @@ var c: [(); 5] = ((), (), (), (), (),);
 // CHECK:STDOUT:   %.loc13_38.6: ref %empty_tuple.type = array_index file.%c.var, %.loc13_38.5
 // CHECK:STDOUT:   %.loc13_24.2: init %empty_tuple.type = tuple_init () to %.loc13_38.6 [template = constants.%empty_tuple]
 // CHECK:STDOUT:   %.loc13_38.7: init %empty_tuple.type = converted %.loc13_24.1, %.loc13_24.2 [template = constants.%empty_tuple]
-// CHECK:STDOUT:   %.loc13_38.8: i32 = int_value 2 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc13_38.8: i32 = int_value 2 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc13_38.9: ref %empty_tuple.type = array_index file.%c.var, %.loc13_38.8
 // CHECK:STDOUT:   %.loc13_28.2: init %empty_tuple.type = tuple_init () to %.loc13_38.9 [template = constants.%empty_tuple]
 // CHECK:STDOUT:   %.loc13_38.10: init %empty_tuple.type = converted %.loc13_28.1, %.loc13_28.2 [template = constants.%empty_tuple]
-// CHECK:STDOUT:   %.loc13_38.11: i32 = int_value 3 [template = constants.%.14]
+// CHECK:STDOUT:   %.loc13_38.11: i32 = int_value 3 [template = constants.%.44]
 // CHECK:STDOUT:   %.loc13_38.12: ref %empty_tuple.type = array_index file.%c.var, %.loc13_38.11
 // CHECK:STDOUT:   %.loc13_32.2: init %empty_tuple.type = tuple_init () to %.loc13_38.12 [template = constants.%empty_tuple]
 // CHECK:STDOUT:   %.loc13_38.13: init %empty_tuple.type = converted %.loc13_32.1, %.loc13_32.2 [template = constants.%empty_tuple]
-// CHECK:STDOUT:   %.loc13_38.14: i32 = int_value 4 [template = constants.%.15]
+// CHECK:STDOUT:   %.loc13_38.14: i32 = int_value 4 [template = constants.%.45]
 // CHECK:STDOUT:   %.loc13_38.15: ref %empty_tuple.type = array_index file.%c.var, %.loc13_38.14
 // CHECK:STDOUT:   %.loc13_36.2: init %empty_tuple.type = tuple_init () to %.loc13_38.15 [template = constants.%empty_tuple]
 // CHECK:STDOUT:   %.loc13_38.16: init %empty_tuple.type = converted %.loc13_36.1, %.loc13_36.2 [template = constants.%empty_tuple]
-// CHECK:STDOUT:   %.loc13_38.17: init %.12 = array_init (%.loc13_38.4, %.loc13_38.7, %.loc13_38.10, %.loc13_38.13, %.loc13_38.16) to file.%c.var [template = constants.%array.3]
-// CHECK:STDOUT:   %.loc13_39: init %.12 = converted %.loc13_38.1, %.loc13_38.17 [template = constants.%array.3]
+// CHECK:STDOUT:   %.loc13_38.17: init %.42 = array_init (%.loc13_38.4, %.loc13_38.7, %.loc13_38.10, %.loc13_38.13, %.loc13_38.16) to file.%c.var [template = constants.%array.3]
+// CHECK:STDOUT:   %.loc13_39: init %.42 = converted %.loc13_38.1, %.loc13_38.17 [template = constants.%array.3]
 // CHECK:STDOUT:   assign file.%c.var, %.loc13_39
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 115 - 40
toolchain/check/testdata/array/canonicalize_index.carbon

@@ -9,9 +9,11 @@
 // TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/array/canonicalize_index.carbon
 
 fn Add(a: i32, b: i32) -> i32 = "int.sadd";
+fn ConvertToU32(a: i32) -> u32 = "int.convert_checked";
 
 var a: [i32; Add(1, 2)] = (1, 2, 3);
 let b: [i32; 3]* = &a;
+let c: [i32; ConvertToU32(3)]* = &a;
 
 // CHECK:STDOUT: --- canonicalize_index.carbon
 // CHECK:STDOUT:
@@ -20,19 +22,39 @@ let b: [i32; 3]* = &a;
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %Add.type: type = fn_type @Add [template]
 // CHECK:STDOUT:   %Add: %Add.type = struct_value () [template]
-// CHECK:STDOUT:   %.1: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.2: i32 = int_value 2 [template]
-// CHECK:STDOUT:   %.3: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
-// CHECK:STDOUT:   %.5: type = ptr_type %.4 [template]
+// CHECK:STDOUT:   %.1: Core.IntLiteral = int_value 32 [template]
+// CHECK:STDOUT:   %UInt.type: type = fn_type @UInt [template]
+// CHECK:STDOUT:   %UInt: %UInt.type = struct_value () [template]
+// CHECK:STDOUT:   %.2: type = int_type unsigned, %.1 [template]
+// CHECK:STDOUT:   %ConvertToU32.type: type = fn_type @ConvertToU32 [template]
+// CHECK:STDOUT:   %ConvertToU32: %ConvertToU32.type = struct_value () [template]
+// CHECK:STDOUT:   %.3: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %.4: i32 = int_value 2 [template]
+// CHECK:STDOUT:   %.5: i32 = int_value 3 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.29: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.30: <bound method> = bound_method %.5, %Convert.15 [template]
+// CHECK:STDOUT:   %.31: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.32: type = array_type %.31, i32 [template]
+// CHECK:STDOUT:   %.33: type = ptr_type %.32 [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (i32, i32, i32) [template]
-// CHECK:STDOUT:   %.6: i32 = int_value 0 [template]
-// CHECK:STDOUT:   %array: %.4 = tuple_value (%.1, %.2, %.3) [template]
+// CHECK:STDOUT:   %.34: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %array: %.32 = tuple_value (%.3, %.4, %.5) [template]
+// CHECK:STDOUT:   %.35: %.2 = int_value 3 [template]
+// CHECK:STDOUT:   %Convert.type.16: type = fn_type @Convert.5, @impl.6(%.1) [template]
+// CHECK:STDOUT:   %Convert.16: %Convert.type.16 = struct_value () [template]
+// CHECK:STDOUT:   %.37: <witness> = interface_witness (%Convert.16) [template]
+// CHECK:STDOUT:   %.38: <bound method> = bound_method %.35, %Convert.16 [template]
+// CHECK:STDOUT:   %.39: <specific function> = specific_function %.38, @Convert.5(%.1) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .UInt = %import_ref.2
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.3
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -42,8 +64,10 @@ let b: [i32; 3]* = &a;
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Core = imports.%Core
 // CHECK:STDOUT:     .Add = %Add.decl
+// CHECK:STDOUT:     .ConvertToU32 = %ConvertToU32.decl
 // CHECK:STDOUT:     .a = %a
 // CHECK:STDOUT:     .b = @__global_init.%b
+// CHECK:STDOUT:     .c = @__global_init.%c
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %Add.decl: %Add.type = fn_decl @Add [template = constants.%Add] {
@@ -70,47 +94,98 @@ let b: [i32; 3]* = &a;
 // CHECK:STDOUT:     %return.param: ref i32 = out_param runtime_param2
 // CHECK:STDOUT:     %return: ref i32 = return_slot %return.param
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %int.make_type_32.loc13: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %Add.ref: %Add.type = name_ref Add, %Add.decl [template = constants.%Add]
-// CHECK:STDOUT:   %.loc13_18: i32 = int_value 1 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc13_21: i32 = int_value 2 [template = constants.%.2]
-// CHECK:STDOUT:   %int.sadd: init i32 = call %Add.ref(%.loc13_18, %.loc13_21) [template = constants.%.3]
-// CHECK:STDOUT:   %.loc13_9.1: type = value_of_initializer %int.make_type_32.loc13 [template = i32]
-// CHECK:STDOUT:   %.loc13_9.2: type = converted %int.make_type_32.loc13, %.loc13_9.1 [template = i32]
-// CHECK:STDOUT:   %.loc13_23: type = array_type %int.sadd, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %a.var: ref %.4 = var a
-// CHECK:STDOUT:   %a: ref %.4 = bind_name a, %a.var
+// CHECK:STDOUT:   %ConvertToU32.decl: %ConvertToU32.type = fn_decl @ConvertToU32 [template = constants.%ConvertToU32] {
+// CHECK:STDOUT:     %a.patt: i32 = binding_pattern a
+// CHECK:STDOUT:     %a.param_patt: i32 = value_param_pattern %a.patt, runtime_param0
+// CHECK:STDOUT:     %return.patt: %.2 = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: %.2 = out_param_pattern %return.patt, runtime_param1
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %int.make_type_32: init type = call constants.%Int32() [template = i32]
+// CHECK:STDOUT:     %.loc12_20.1: type = value_of_initializer %int.make_type_32 [template = i32]
+// CHECK:STDOUT:     %.loc12_20.2: type = converted %int.make_type_32, %.loc12_20.1 [template = i32]
+// CHECK:STDOUT:     %.loc12_28.1: Core.IntLiteral = int_value 32 [template = constants.%.1]
+// CHECK:STDOUT:     %int.make_type_unsigned: init type = call constants.%UInt(%.loc12_28.1) [template = constants.%.2]
+// CHECK:STDOUT:     %.loc12_28.2: type = value_of_initializer %int.make_type_unsigned [template = constants.%.2]
+// CHECK:STDOUT:     %.loc12_28.3: type = converted %int.make_type_unsigned, %.loc12_28.2 [template = constants.%.2]
+// CHECK:STDOUT:     %a.param: i32 = value_param runtime_param0
+// CHECK:STDOUT:     %a: i32 = bind_name a, %a.param
+// CHECK:STDOUT:     %return.param: ref %.2 = out_param runtime_param1
+// CHECK:STDOUT:     %return: ref %.2 = return_slot %return.param
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %int.make_type_32.loc14: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc14_14: i32 = int_value 3 [template = constants.%.3]
+// CHECK:STDOUT:   %Add.ref: %Add.type = name_ref Add, %Add.decl [template = constants.%Add]
+// CHECK:STDOUT:   %.loc14_18: i32 = int_value 1 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc14_21: i32 = int_value 2 [template = constants.%.4]
+// CHECK:STDOUT:   %int.sadd: init i32 = call %Add.ref(%.loc14_18, %.loc14_21) [template = constants.%.5]
 // CHECK:STDOUT:   %.loc14_9.1: type = value_of_initializer %int.make_type_32.loc14 [template = i32]
 // CHECK:STDOUT:   %.loc14_9.2: type = converted %int.make_type_32.loc14, %.loc14_9.1 [template = i32]
-// CHECK:STDOUT:   %.loc14_15: type = array_type %.loc14_14, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc14_16: type = ptr_type %.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc14_17.1: %Convert.type.2 = interface_witness_access constants.%.29, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc14_17.2: <bound method> = bound_method %int.sadd, %.loc14_17.1 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc14_17.3: i32 = value_of_initializer %int.sadd [template = constants.%.5]
+// CHECK:STDOUT:   %.loc14_17.4: i32 = converted %int.sadd, %.loc14_17.3 [template = constants.%.5]
+// CHECK:STDOUT:   %int.convert_checked.loc14: init Core.IntLiteral = call %.loc14_17.2(%.loc14_17.4) [template = constants.%.31]
+// CHECK:STDOUT:   %.loc14_17.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc14 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc14_17.6: Core.IntLiteral = converted %int.sadd, %.loc14_17.5 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc14_23: type = array_type %.loc14_17.6, i32 [template = constants.%.32]
+// CHECK:STDOUT:   %a.var: ref %.32 = var a
+// CHECK:STDOUT:   %a: ref %.32 = bind_name a, %a.var
+// CHECK:STDOUT:   %int.make_type_32.loc15: init type = call constants.%Int32() [template = i32]
+// CHECK:STDOUT:   %.loc15_14.1: i32 = int_value 3 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc15_9.1: type = value_of_initializer %int.make_type_32.loc15 [template = i32]
+// CHECK:STDOUT:   %.loc15_9.2: type = converted %int.make_type_32.loc15, %.loc15_9.1 [template = i32]
+// CHECK:STDOUT:   %.loc15_14.2: %Convert.type.2 = interface_witness_access constants.%.29, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc15_14.3: <bound method> = bound_method %.loc15_14.1, %.loc15_14.2 [template = constants.%.30]
+// CHECK:STDOUT:   %int.convert_checked.loc15: init Core.IntLiteral = call %.loc15_14.3(%.loc15_14.1) [template = constants.%.31]
+// CHECK:STDOUT:   %.loc15_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc15 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc15_14.5: Core.IntLiteral = converted %.loc15_14.1, %.loc15_14.4 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc15_15: type = array_type %.loc15_14.5, i32 [template = constants.%.32]
+// CHECK:STDOUT:   %.loc15_16: type = ptr_type %.32 [template = constants.%.33]
+// CHECK:STDOUT:   %int.make_type_32.loc16: init type = call constants.%Int32() [template = i32]
+// CHECK:STDOUT:   %ConvertToU32.ref: %ConvertToU32.type = name_ref ConvertToU32, %ConvertToU32.decl [template = constants.%ConvertToU32]
+// CHECK:STDOUT:   %.loc16_27: i32 = int_value 3 [template = constants.%.5]
+// CHECK:STDOUT:   %int.convert_checked.loc16_26.1: init %.2 = call %ConvertToU32.ref(%.loc16_27) [template = constants.%.35]
+// CHECK:STDOUT:   %.loc16_9.1: type = value_of_initializer %int.make_type_32.loc16 [template = i32]
+// CHECK:STDOUT:   %.loc16_9.2: type = converted %int.make_type_32.loc16, %.loc16_9.1 [template = i32]
+// CHECK:STDOUT:   %.loc16_26.1: %Convert.type.2 = interface_witness_access constants.%.37, element0 [template = constants.%Convert.16]
+// CHECK:STDOUT:   %.loc16_26.2: <bound method> = bound_method %int.convert_checked.loc16_26.1, %.loc16_26.1 [template = constants.%.38]
+// CHECK:STDOUT:   %.loc16_26.3: <specific function> = specific_function %.loc16_26.2, @Convert.5(constants.%.1) [template = constants.%.39]
+// CHECK:STDOUT:   %.loc16_26.4: %.2 = value_of_initializer %int.convert_checked.loc16_26.1 [template = constants.%.35]
+// CHECK:STDOUT:   %.loc16_26.5: %.2 = converted %int.convert_checked.loc16_26.1, %.loc16_26.4 [template = constants.%.35]
+// CHECK:STDOUT:   %int.convert_checked.loc16_26.2: init Core.IntLiteral = call %.loc16_26.3(%.loc16_26.5) [template = constants.%.31]
+// CHECK:STDOUT:   %.loc16_26.6: Core.IntLiteral = value_of_initializer %int.convert_checked.loc16_26.2 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc16_26.7: Core.IntLiteral = converted %int.convert_checked.loc16_26.1, %.loc16_26.6 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc16_29: type = array_type %.loc16_26.7, i32 [template = constants.%.32]
+// CHECK:STDOUT:   %.loc16_30: type = ptr_type %.32 [template = constants.%.33]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Add(%a.param_patt: i32, %b.param_patt: i32) -> i32 = "int.sadd";
 // CHECK:STDOUT:
+// CHECK:STDOUT: fn @ConvertToU32(%a.param_patt: i32) -> %.2 = "int.convert_checked";
+// CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc13_28: i32 = int_value 1 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc13_31: i32 = int_value 2 [template = constants.%.2]
-// CHECK:STDOUT:   %.loc13_34: i32 = int_value 3 [template = constants.%.3]
-// CHECK:STDOUT:   %.loc13_35.1: %tuple.type = tuple_literal (%.loc13_28, %.loc13_31, %.loc13_34)
-// CHECK:STDOUT:   %.loc13_35.2: i32 = int_value 0 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc13_35.3: ref i32 = array_index file.%a.var, %.loc13_35.2
-// CHECK:STDOUT:   %.loc13_35.4: init i32 = initialize_from %.loc13_28 to %.loc13_35.3 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc13_35.5: i32 = int_value 1 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc13_35.6: ref i32 = array_index file.%a.var, %.loc13_35.5
-// CHECK:STDOUT:   %.loc13_35.7: init i32 = initialize_from %.loc13_31 to %.loc13_35.6 [template = constants.%.2]
-// CHECK:STDOUT:   %.loc13_35.8: i32 = int_value 2 [template = constants.%.2]
-// CHECK:STDOUT:   %.loc13_35.9: ref i32 = array_index file.%a.var, %.loc13_35.8
-// CHECK:STDOUT:   %.loc13_35.10: init i32 = initialize_from %.loc13_34 to %.loc13_35.9 [template = constants.%.3]
-// CHECK:STDOUT:   %.loc13_35.11: init %.4 = array_init (%.loc13_35.4, %.loc13_35.7, %.loc13_35.10) to file.%a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc13_36: init %.4 = converted %.loc13_35.1, %.loc13_35.11 [template = constants.%array]
-// CHECK:STDOUT:   assign file.%a.var, %.loc13_36
-// CHECK:STDOUT:   %a.ref: ref %.4 = name_ref a, file.%a
-// CHECK:STDOUT:   %.loc14: %.5 = addr_of %a.ref
-// CHECK:STDOUT:   %b: %.5 = bind_name b, %.loc14
+// CHECK:STDOUT:   %.loc14_28: i32 = int_value 1 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc14_31: i32 = int_value 2 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc14_34: i32 = int_value 3 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc14_35.1: %tuple.type = tuple_literal (%.loc14_28, %.loc14_31, %.loc14_34)
+// CHECK:STDOUT:   %.loc14_35.2: i32 = int_value 0 [template = constants.%.34]
+// CHECK:STDOUT:   %.loc14_35.3: ref i32 = array_index file.%a.var, %.loc14_35.2
+// CHECK:STDOUT:   %.loc14_35.4: init i32 = initialize_from %.loc14_28 to %.loc14_35.3 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc14_35.5: i32 = int_value 1 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc14_35.6: ref i32 = array_index file.%a.var, %.loc14_35.5
+// CHECK:STDOUT:   %.loc14_35.7: init i32 = initialize_from %.loc14_31 to %.loc14_35.6 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc14_35.8: i32 = int_value 2 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc14_35.9: ref i32 = array_index file.%a.var, %.loc14_35.8
+// CHECK:STDOUT:   %.loc14_35.10: init i32 = initialize_from %.loc14_34 to %.loc14_35.9 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc14_35.11: init %.32 = array_init (%.loc14_35.4, %.loc14_35.7, %.loc14_35.10) to file.%a.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc14_36: init %.32 = converted %.loc14_35.1, %.loc14_35.11 [template = constants.%array]
+// CHECK:STDOUT:   assign file.%a.var, %.loc14_36
+// CHECK:STDOUT:   %a.ref.loc15: ref %.32 = name_ref a, file.%a
+// CHECK:STDOUT:   %.loc15: %.33 = addr_of %a.ref.loc15
+// CHECK:STDOUT:   %b: %.33 = bind_name b, %.loc15
+// CHECK:STDOUT:   %a.ref.loc16: ref %.32 = name_ref a, file.%a
+// CHECK:STDOUT:   %.loc16: %.33 = addr_of %a.ref.loc16
+// CHECK:STDOUT:   %c: %.33 = bind_name c, %.loc16
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 16 - 2
toolchain/check/testdata/array/fail_bound_negative.carbon

@@ -24,11 +24,18 @@ var a: [i32; Negate(1)];
 // CHECK:STDOUT:   %Negate: %Negate.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 1 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value -1 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.26: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.27: <bound method> = bound_method %.2, %Convert.15 [template]
+// CHECK:STDOUT:   %.28: Core.IntLiteral = int_value -1 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -64,7 +71,14 @@ var a: [i32; Negate(1)];
 // CHECK:STDOUT:   %int.snegate: init i32 = call %Negate.ref(%.loc16_21) [template = constants.%.2]
 // CHECK:STDOUT:   %.loc16_9.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:   %.loc16_9.2: type = converted %int.make_type_32, %.loc16_9.1 [template = i32]
-// CHECK:STDOUT:   %.loc16_23: type = array_type %int.snegate, i32 [template = <error>]
+// CHECK:STDOUT:   %.loc16_20.1: %Convert.type.2 = interface_witness_access constants.%.26, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc16_20.2: <bound method> = bound_method %int.snegate, %.loc16_20.1 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc16_20.3: i32 = value_of_initializer %int.snegate [template = constants.%.2]
+// CHECK:STDOUT:   %.loc16_20.4: i32 = converted %int.snegate, %.loc16_20.3 [template = constants.%.2]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc16_20.2(%.loc16_20.4) [template = constants.%.28]
+// CHECK:STDOUT:   %.loc16_20.5: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.28]
+// CHECK:STDOUT:   %.loc16_20.6: Core.IntLiteral = converted %int.snegate, %.loc16_20.5 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc16_23: type = array_type %.loc16_20.6, i32 [template = <error>]
 // CHECK:STDOUT:   %a.var: ref <error> = var a
 // CHECK:STDOUT:   %a: ref <error> = bind_name a, %a.var
 // CHECK:STDOUT: }

+ 21 - 9
toolchain/check/testdata/array/fail_incomplete_element.carbon

@@ -25,13 +25,20 @@ var p: Incomplete* = &a[0];
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %Incomplete: type = class_type @Incomplete [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, %Incomplete [template]
-// CHECK:STDOUT:   %.3: type = ptr_type %Incomplete [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 1 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, %Incomplete [template]
+// CHECK:STDOUT:   %.29: type = ptr_type %Incomplete [template]
+// CHECK:STDOUT:   %.30: i32 = int_value 0 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.1
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -47,14 +54,19 @@ var p: Incomplete* = &a[0];
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %Incomplete.decl: type = class_decl @Incomplete [template = constants.%Incomplete] {} {}
 // CHECK:STDOUT:   %Incomplete.ref.loc19: type = name_ref Incomplete, %Incomplete.decl [template = constants.%Incomplete]
-// CHECK:STDOUT:   %.loc19_21: i32 = int_value 1 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc19_22: type = array_type %.loc19_21, %Incomplete [template = constants.%.2]
+// CHECK:STDOUT:   %.loc19_21.1: i32 = int_value 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc19_21.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc19_21.3: <bound method> = bound_method %.loc19_21.1, %.loc19_21.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc19_21.3(%.loc19_21.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc19_21.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:   %.loc19_21.5: Core.IntLiteral = converted %.loc19_21.1, %.loc19_21.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc19_22: type = array_type %.loc19_21.5, %Incomplete [template = constants.%.28]
 // CHECK:STDOUT:   %a.var: ref <error> = var a
 // CHECK:STDOUT:   %a: ref <error> = bind_name a, %a.var
 // CHECK:STDOUT:   %Incomplete.ref.loc21: type = name_ref Incomplete, %Incomplete.decl [template = constants.%Incomplete]
-// CHECK:STDOUT:   %.loc21: type = ptr_type %Incomplete [template = constants.%.3]
-// CHECK:STDOUT:   %p.var: ref %.3 = var p
-// CHECK:STDOUT:   %p: ref %.3 = bind_name p, %p.var
+// CHECK:STDOUT:   %.loc21: type = ptr_type %Incomplete [template = constants.%.29]
+// CHECK:STDOUT:   %p.var: ref %.29 = var p
+// CHECK:STDOUT:   %p: ref %.29 = bind_name p, %p.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Incomplete;
@@ -62,7 +74,7 @@ var p: Incomplete* = &a[0];
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %a.ref: ref <error> = name_ref a, file.%a
-// CHECK:STDOUT:   %.loc21_25: i32 = int_value 0 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc21_25: i32 = int_value 0 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc21_22: <error> = addr_of <error> [template = <error>]
 // CHECK:STDOUT:   assign file.%p.var, <error>
 // CHECK:STDOUT:   return

+ 13 - 2
toolchain/check/testdata/array/fail_invalid_type.carbon

@@ -20,6 +20,12 @@ var a: [1; 1];
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %.1: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %Convert.type.6: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.16: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.16: %Convert.type.16 = struct_value () [template]
+// CHECK:STDOUT:   %.27: <witness> = interface_witness (%Convert.16) [template]
+// CHECK:STDOUT:   %.28: <bound method> = bound_method %.1, %Convert.16 [template]
+// CHECK:STDOUT:   %.29: Core.IntLiteral = int_value 1 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -37,9 +43,14 @@ var a: [1; 1];
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %.loc17_9.1: i32 = int_value 1 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc17_12: i32 = int_value 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc17_12.1: i32 = int_value 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc17_9.2: type = converted %.loc17_9.1, <error> [template = <error>]
-// CHECK:STDOUT:   %.loc17_13: type = array_type %.loc17_12, <error> [template = <error>]
+// CHECK:STDOUT:   %.loc17_12.2: %Convert.type.6 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.16]
+// CHECK:STDOUT:   %.loc17_12.3: <bound method> = bound_method %.loc17_12.1, %.loc17_12.2 [template = constants.%.28]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc17_12.3(%.loc17_12.1) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc17_12.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.29]
+// CHECK:STDOUT:   %.loc17_12.5: Core.IntLiteral = converted %.loc17_12.1, %.loc17_12.4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc17_13: type = array_type %.loc17_12.5, <error> [template = <error>]
 // CHECK:STDOUT:   %a.var: ref <error> = var a
 // CHECK:STDOUT:   %a: ref <error> = bind_name a, %a.var
 // CHECK:STDOUT: }

+ 22 - 10
toolchain/check/testdata/array/fail_out_of_bound.carbon

@@ -19,15 +19,22 @@ var a: [i32; 1] = (1, 2, 3);
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 2 [template]
-// CHECK:STDOUT:   %.5: i32 = int_value 3 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 1 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, i32 [template]
+// CHECK:STDOUT:   %.30: i32 = int_value 2 [template]
+// CHECK:STDOUT:   %.31: i32 = int_value 3 [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (i32, i32, i32) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -40,19 +47,24 @@ var a: [i32; 1] = (1, 2, 3);
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %int.make_type_32: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc14_14: i32 = int_value 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc14_14.1: i32 = int_value 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc14_9.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:   %.loc14_9.2: type = converted %int.make_type_32, %.loc14_9.1 [template = i32]
-// CHECK:STDOUT:   %.loc14_15: type = array_type %.loc14_14, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %a.var: ref %.2 = var a
-// CHECK:STDOUT:   %a: ref %.2 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc14_14.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc14_14.3: <bound method> = bound_method %.loc14_14.1, %.loc14_14.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc14_14.3(%.loc14_14.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc14_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:   %.loc14_14.5: Core.IntLiteral = converted %.loc14_14.1, %.loc14_14.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc14_15: type = array_type %.loc14_14.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %a.var: ref %.28 = var a
+// CHECK:STDOUT:   %a: ref %.28 = bind_name a, %a.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc14_20: i32 = int_value 1 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc14_23: i32 = int_value 2 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc14_26: i32 = int_value 3 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc14_23: i32 = int_value 2 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc14_26: i32 = int_value 3 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc14_27: %tuple.type = tuple_literal (%.loc14_20, %.loc14_23, %.loc14_26)
 // CHECK:STDOUT:   assign file.%a.var, <error>
 // CHECK:STDOUT:   return

+ 37 - 25
toolchain/check/testdata/array/fail_out_of_bound_non_literal.carbon

@@ -20,19 +20,26 @@ var b: i32 = a[{.index = 3}.index];
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.5: i32 = int_value 2 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, i32 [template]
+// CHECK:STDOUT:   %.30: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %.31: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (i32, i32, i32) [template]
-// CHECK:STDOUT:   %.6: i32 = int_value 0 [template]
-// CHECK:STDOUT:   %array: %.2 = tuple_value (%.4, %.5, %.1) [template]
-// CHECK:STDOUT:   %.7: type = struct_type {.index: i32} [template]
-// CHECK:STDOUT:   %struct: %.7 = struct_value (%.1) [template]
+// CHECK:STDOUT:   %.32: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %array: %.28 = tuple_value (%.30, %.31, %.1) [template]
+// CHECK:STDOUT:   %.33: type = struct_type {.index: i32} [template]
+// CHECK:STDOUT:   %struct: %.33 = struct_value (%.1) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -46,12 +53,17 @@ var b: i32 = a[{.index = 3}.index];
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %int.make_type_32.loc11: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc11_14: i32 = int_value 3 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc11_14.1: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc11_9.1: type = value_of_initializer %int.make_type_32.loc11 [template = i32]
 // CHECK:STDOUT:   %.loc11_9.2: type = converted %int.make_type_32.loc11, %.loc11_9.1 [template = i32]
-// CHECK:STDOUT:   %.loc11_15: type = array_type %.loc11_14, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %a.var: ref %.2 = var a
-// CHECK:STDOUT:   %a: ref %.2 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc11_14.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc11_14.3: <bound method> = bound_method %.loc11_14.1, %.loc11_14.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc11_14.3(%.loc11_14.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_14.5: Core.IntLiteral = converted %.loc11_14.1, %.loc11_14.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_15: type = array_type %.loc11_14.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %a.var: ref %.28 = var a
+// CHECK:STDOUT:   %a: ref %.28 = bind_name a, %a.var
 // CHECK:STDOUT:   %int.make_type_32.loc15: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc15_8.1: type = value_of_initializer %int.make_type_32.loc15 [template = i32]
 // CHECK:STDOUT:   %.loc15_8.2: type = converted %int.make_type_32.loc15, %.loc15_8.1 [template = i32]
@@ -61,27 +73,27 @@ var b: i32 = a[{.index = 3}.index];
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc11_20: i32 = int_value 1 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc11_23: i32 = int_value 2 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc11_20: i32 = int_value 1 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc11_23: i32 = int_value 2 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc11_26: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc11_27.1: %tuple.type = tuple_literal (%.loc11_20, %.loc11_23, %.loc11_26)
-// CHECK:STDOUT:   %.loc11_27.2: i32 = int_value 0 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc11_27.2: i32 = int_value 0 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc11_27.3: ref i32 = array_index file.%a.var, %.loc11_27.2
-// CHECK:STDOUT:   %.loc11_27.4: init i32 = initialize_from %.loc11_20 to %.loc11_27.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc11_27.5: i32 = int_value 1 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc11_27.4: init i32 = initialize_from %.loc11_20 to %.loc11_27.3 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc11_27.5: i32 = int_value 1 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc11_27.6: ref i32 = array_index file.%a.var, %.loc11_27.5
-// CHECK:STDOUT:   %.loc11_27.7: init i32 = initialize_from %.loc11_23 to %.loc11_27.6 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc11_27.8: i32 = int_value 2 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc11_27.7: init i32 = initialize_from %.loc11_23 to %.loc11_27.6 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc11_27.8: i32 = int_value 2 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc11_27.9: ref i32 = array_index file.%a.var, %.loc11_27.8
 // CHECK:STDOUT:   %.loc11_27.10: init i32 = initialize_from %.loc11_26 to %.loc11_27.9 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc11_27.11: init %.2 = array_init (%.loc11_27.4, %.loc11_27.7, %.loc11_27.10) to file.%a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc11_28: init %.2 = converted %.loc11_27.1, %.loc11_27.11 [template = constants.%array]
+// CHECK:STDOUT:   %.loc11_27.11: init %.28 = array_init (%.loc11_27.4, %.loc11_27.7, %.loc11_27.10) to file.%a.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc11_28: init %.28 = converted %.loc11_27.1, %.loc11_27.11 [template = constants.%array]
 // CHECK:STDOUT:   assign file.%a.var, %.loc11_28
-// CHECK:STDOUT:   %a.ref: ref %.2 = name_ref a, file.%a
+// CHECK:STDOUT:   %a.ref: ref %.28 = name_ref a, file.%a
 // CHECK:STDOUT:   %.loc15_26: i32 = int_value 3 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc15_27.1: %.7 = struct_literal (%.loc15_26)
-// CHECK:STDOUT:   %struct: %.7 = struct_value (%.loc15_26) [template = constants.%struct]
-// CHECK:STDOUT:   %.loc15_27.2: %.7 = converted %.loc15_27.1, %struct [template = constants.%struct]
+// CHECK:STDOUT:   %.loc15_27.1: %.33 = struct_literal (%.loc15_26)
+// CHECK:STDOUT:   %struct: %.33 = struct_value (%.loc15_26) [template = constants.%struct]
+// CHECK:STDOUT:   %.loc15_27.2: %.33 = converted %.loc15_27.1, %struct [template = constants.%struct]
 // CHECK:STDOUT:   %.loc15_28: i32 = struct_access %.loc15_27.2, element0 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc15_34.1: ref i32 = array_index %a.ref, %.loc15_28 [template = <error>]
 // CHECK:STDOUT:   %.loc15_34.2: i32 = bind_value %.loc15_34.1

+ 56 - 30
toolchain/check/testdata/array/fail_type_mismatch.carbon

@@ -45,14 +45,20 @@ var d: [i32; 3] = t2;
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.6: String = string_literal "Hello" [template]
-// CHECK:STDOUT:   %.7: String = string_literal "World" [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, i32 [template]
+// CHECK:STDOUT:   %.30: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %.32: String = string_literal "Hello" [template]
+// CHECK:STDOUT:   %.33: String = string_literal "World" [template]
 // CHECK:STDOUT:   %tuple.type.1: type = tuple_type (i32, String, String) [template]
-// CHECK:STDOUT:   %.8: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %.34: i32 = int_value 0 [template]
 // CHECK:STDOUT:   %tuple.type.2: type = tuple_type (type, type, type) [template]
-// CHECK:STDOUT:   %.33: i32 = int_value 2 [template]
+// CHECK:STDOUT:   %.36: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %tuple.type.4: type = tuple_type (i32, i32) [template]
 // CHECK:STDOUT:   %tuple.type.5: type = tuple_type (type, type) [template]
 // CHECK:STDOUT: }
@@ -78,12 +84,17 @@ var d: [i32; 3] = t2;
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %int.make_type_32.loc18: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc18_14: i32 = int_value 3 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc18_14.1: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc18_9.1: type = value_of_initializer %int.make_type_32.loc18 [template = i32]
 // CHECK:STDOUT:   %.loc18_9.2: type = converted %int.make_type_32.loc18, %.loc18_9.1 [template = i32]
-// CHECK:STDOUT:   %.loc18_15: type = array_type %.loc18_14, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %a.var: ref %.2 = var a
-// CHECK:STDOUT:   %a: ref %.2 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc18_14.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc18_14.3: <bound method> = bound_method %.loc18_14.1, %.loc18_14.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked.loc18: init Core.IntLiteral = call %.loc18_14.3(%.loc18_14.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc18_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc18 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc18_14.5: Core.IntLiteral = converted %.loc18_14.1, %.loc18_14.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc18_15: type = array_type %.loc18_14.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %a.var: ref %.28 = var a
+// CHECK:STDOUT:   %a: ref %.28 = bind_name a, %a.var
 // CHECK:STDOUT:   %int.make_type_32.loc20: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc20_29.1: %tuple.type.2 = tuple_literal (%int.make_type_32.loc20, String, String)
 // CHECK:STDOUT:   %.loc20_29.2: type = value_of_initializer %int.make_type_32.loc20 [template = i32]
@@ -92,19 +103,29 @@ var d: [i32; 3] = t2;
 // CHECK:STDOUT:   %t1.var: ref %tuple.type.1 = var t1
 // CHECK:STDOUT:   %t1: ref %tuple.type.1 = bind_name t1, %t1.var
 // CHECK:STDOUT:   %int.make_type_32.loc28: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc28_14: i32 = int_value 3 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc28_14.1: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc28_9.1: type = value_of_initializer %int.make_type_32.loc28 [template = i32]
 // CHECK:STDOUT:   %.loc28_9.2: type = converted %int.make_type_32.loc28, %.loc28_9.1 [template = i32]
-// CHECK:STDOUT:   %.loc28_15: type = array_type %.loc28_14, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %b.var: ref %.2 = var b
-// CHECK:STDOUT:   %b: ref %.2 = bind_name b, %b.var
+// CHECK:STDOUT:   %.loc28_14.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc28_14.3: <bound method> = bound_method %.loc28_14.1, %.loc28_14.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked.loc28: init Core.IntLiteral = call %.loc28_14.3(%.loc28_14.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc28_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc28 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc28_14.5: Core.IntLiteral = converted %.loc28_14.1, %.loc28_14.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc28_15: type = array_type %.loc28_14.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %b.var: ref %.28 = var b
+// CHECK:STDOUT:   %b: ref %.28 = bind_name b, %b.var
 // CHECK:STDOUT:   %int.make_type_32.loc34: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc34_14: i32 = int_value 3 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc34_14.1: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc34_9.1: type = value_of_initializer %int.make_type_32.loc34 [template = i32]
 // CHECK:STDOUT:   %.loc34_9.2: type = converted %int.make_type_32.loc34, %.loc34_9.1 [template = i32]
-// CHECK:STDOUT:   %.loc34_15: type = array_type %.loc34_14, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %c.var: ref %.2 = var c
-// CHECK:STDOUT:   %c: ref %.2 = bind_name c, %c.var
+// CHECK:STDOUT:   %.loc34_14.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc34_14.3: <bound method> = bound_method %.loc34_14.1, %.loc34_14.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked.loc34: init Core.IntLiteral = call %.loc34_14.3(%.loc34_14.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc34_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc34 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc34_14.5: Core.IntLiteral = converted %.loc34_14.1, %.loc34_14.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc34_15: type = array_type %.loc34_14.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %c.var: ref %.28 = var c
+// CHECK:STDOUT:   %c: ref %.28 = bind_name c, %c.var
 // CHECK:STDOUT:   %int.make_type_32.loc36_10: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %int.make_type_32.loc36_15: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc36_18.1: %tuple.type.5 = tuple_literal (%int.make_type_32.loc36_10, %int.make_type_32.loc36_15)
@@ -116,36 +137,41 @@ var d: [i32; 3] = t2;
 // CHECK:STDOUT:   %t2.var: ref %tuple.type.4 = var t2
 // CHECK:STDOUT:   %t2: ref %tuple.type.4 = bind_name t2, %t2.var
 // CHECK:STDOUT:   %int.make_type_32.loc40: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc40_14: i32 = int_value 3 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc40_14.1: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc40_9.1: type = value_of_initializer %int.make_type_32.loc40 [template = i32]
 // CHECK:STDOUT:   %.loc40_9.2: type = converted %int.make_type_32.loc40, %.loc40_9.1 [template = i32]
-// CHECK:STDOUT:   %.loc40_15: type = array_type %.loc40_14, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %d.var: ref %.2 = var d
-// CHECK:STDOUT:   %d: ref %.2 = bind_name d, %d.var
+// CHECK:STDOUT:   %.loc40_14.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc40_14.3: <bound method> = bound_method %.loc40_14.1, %.loc40_14.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked.loc40: init Core.IntLiteral = call %.loc40_14.3(%.loc40_14.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc40_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc40 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc40_14.5: Core.IntLiteral = converted %.loc40_14.1, %.loc40_14.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc40_15: type = array_type %.loc40_14.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %d.var: ref %.28 = var d
+// CHECK:STDOUT:   %d: ref %.28 = bind_name d, %d.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc18_20: i32 = int_value 1 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc18_23: String = string_literal "Hello" [template = constants.%.6]
-// CHECK:STDOUT:   %.loc18_32: String = string_literal "World" [template = constants.%.7]
+// CHECK:STDOUT:   %.loc18_20: i32 = int_value 1 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc18_23: String = string_literal "Hello" [template = constants.%.32]
+// CHECK:STDOUT:   %.loc18_32: String = string_literal "World" [template = constants.%.33]
 // CHECK:STDOUT:   %.loc18_39.1: %tuple.type.1 = tuple_literal (%.loc18_20, %.loc18_23, %.loc18_32)
-// CHECK:STDOUT:   %.loc18_39.2: i32 = int_value 0 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc18_39.2: i32 = int_value 0 [template = constants.%.34]
 // CHECK:STDOUT:   %.loc18_39.3: ref i32 = array_index file.%a.var, %.loc18_39.2
-// CHECK:STDOUT:   %.loc18_39.4: init i32 = initialize_from %.loc18_20 to %.loc18_39.3 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc18_39.4: init i32 = initialize_from %.loc18_20 to %.loc18_39.3 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc18_39.5: i32 = converted %.loc18_23, <error> [template = <error>]
 // CHECK:STDOUT:   assign file.%a.var, <error>
 // CHECK:STDOUT:   %t1.ref: ref %tuple.type.1 = name_ref t1, file.%t1
 // CHECK:STDOUT:   %.loc28_19.1: ref i32 = tuple_access %t1.ref, element0
 // CHECK:STDOUT:   %.loc28_19.2: i32 = bind_value %.loc28_19.1
-// CHECK:STDOUT:   %.loc28_19.3: i32 = int_value 0 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc28_19.3: i32 = int_value 0 [template = constants.%.34]
 // CHECK:STDOUT:   %.loc28_19.4: ref i32 = array_index file.%b.var, %.loc28_19.3
 // CHECK:STDOUT:   %.loc28_19.5: init i32 = initialize_from %.loc28_19.2 to %.loc28_19.4
 // CHECK:STDOUT:   %.loc28_19.6: ref String = tuple_access %t1.ref, element1
 // CHECK:STDOUT:   %.loc28_19.7: i32 = converted %.loc28_19.6, <error> [template = <error>]
 // CHECK:STDOUT:   assign file.%b.var, <error>
-// CHECK:STDOUT:   %.loc34_20: i32 = int_value 1 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc34_23: i32 = int_value 2 [template = constants.%.33]
+// CHECK:STDOUT:   %.loc34_20: i32 = int_value 1 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc34_23: i32 = int_value 2 [template = constants.%.36]
 // CHECK:STDOUT:   %.loc34_24: %tuple.type.4 = tuple_literal (%.loc34_20, %.loc34_23)
 // CHECK:STDOUT:   assign file.%c.var, <error>
 // CHECK:STDOUT:   %t2.ref: ref %tuple.type.4 = name_ref t2, file.%t2

+ 40 - 28
toolchain/check/testdata/array/function_param.carbon

@@ -22,21 +22,28 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, i32 [template]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [template]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [template]
 // CHECK:STDOUT:   %G.type: type = fn_type @G [template]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.5: i32 = int_value 2 [template]
+// CHECK:STDOUT:   %.30: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %.31: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (i32, i32, i32) [template]
-// CHECK:STDOUT:   %.6: i32 = int_value 0 [template]
-// CHECK:STDOUT:   %array: %.2 = tuple_value (%.4, %.5, %.1) [template]
+// CHECK:STDOUT:   %.32: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %array: %.28 = tuple_value (%.30, %.31, %.1) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -50,26 +57,31 @@ fn G() -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [template = constants.%F] {
-// CHECK:STDOUT:     %arr.patt: %.2 = binding_pattern arr
-// CHECK:STDOUT:     %arr.param_patt: %.2 = value_param_pattern %arr.patt, runtime_param0
+// CHECK:STDOUT:     %arr.patt: %.28 = binding_pattern arr
+// CHECK:STDOUT:     %arr.param_patt: %.28 = value_param_pattern %arr.patt, runtime_param0
 // CHECK:STDOUT:     %i.patt: i32 = binding_pattern i
 // CHECK:STDOUT:     %i.param_patt: i32 = value_param_pattern %i.patt, runtime_param1
 // CHECK:STDOUT:     %return.patt: i32 = return_slot_pattern
 // CHECK:STDOUT:     %return.param_patt: i32 = out_param_pattern %return.patt, runtime_param2
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %int.make_type_32.loc11_12: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:     %.loc11_17: i32 = int_value 3 [template = constants.%.1]
+// CHECK:STDOUT:     %.loc11_17.1: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:     %.loc11_12.1: type = value_of_initializer %int.make_type_32.loc11_12 [template = i32]
 // CHECK:STDOUT:     %.loc11_12.2: type = converted %int.make_type_32.loc11_12, %.loc11_12.1 [template = i32]
-// CHECK:STDOUT:     %.loc11_18: type = array_type %.loc11_17, i32 [template = constants.%.2]
+// CHECK:STDOUT:     %.loc11_17.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:     %.loc11_17.3: <bound method> = bound_method %.loc11_17.1, %.loc11_17.2 [template = constants.%.26]
+// CHECK:STDOUT:     %int.convert_checked: init Core.IntLiteral = call %.loc11_17.3(%.loc11_17.1) [template = constants.%.27]
+// CHECK:STDOUT:     %.loc11_17.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:     %.loc11_17.5: Core.IntLiteral = converted %.loc11_17.1, %.loc11_17.4 [template = constants.%.27]
+// CHECK:STDOUT:     %.loc11_18: type = array_type %.loc11_17.5, i32 [template = constants.%.28]
 // CHECK:STDOUT:     %int.make_type_32.loc11_24: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:     %.loc11_24.1: type = value_of_initializer %int.make_type_32.loc11_24 [template = i32]
 // CHECK:STDOUT:     %.loc11_24.2: type = converted %int.make_type_32.loc11_24, %.loc11_24.1 [template = i32]
 // CHECK:STDOUT:     %int.make_type_32.loc11_32: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:     %.loc11_32.1: type = value_of_initializer %int.make_type_32.loc11_32 [template = i32]
 // CHECK:STDOUT:     %.loc11_32.2: type = converted %int.make_type_32.loc11_32, %.loc11_32.1 [template = i32]
-// CHECK:STDOUT:     %arr.param: %.2 = value_param runtime_param0
-// CHECK:STDOUT:     %arr: %.2 = bind_name arr, %arr.param
+// CHECK:STDOUT:     %arr.param: %.28 = value_param runtime_param0
+// CHECK:STDOUT:     %arr: %.28 = bind_name arr, %arr.param
 // CHECK:STDOUT:     %i.param: i32 = value_param runtime_param1
 // CHECK:STDOUT:     %i: i32 = bind_name i, %i.param
 // CHECK:STDOUT:     %return.param: ref i32 = out_param runtime_param2
@@ -87,11 +99,11 @@ fn G() -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F(%arr.param_patt: %.2, %i.param_patt: i32) -> i32 {
+// CHECK:STDOUT: fn @F(%arr.param_patt: %.28, %i.param_patt: i32) -> i32 {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr.ref: %.2 = name_ref arr, %arr
+// CHECK:STDOUT:   %arr.ref: %.28 = name_ref arr, %arr
 // CHECK:STDOUT:   %i.ref: i32 = name_ref i, %i
-// CHECK:STDOUT:   %.loc12_15.1: ref %.2 = value_as_ref %arr.ref
+// CHECK:STDOUT:   %.loc12_15.1: ref %.28 = value_as_ref %arr.ref
 // CHECK:STDOUT:   %.loc12_15.2: ref i32 = array_index %.loc12_15.1, %i.ref
 // CHECK:STDOUT:   %.loc12_15.3: i32 = bind_value %.loc12_15.2
 // CHECK:STDOUT:   return %.loc12_15.3
@@ -100,25 +112,25 @@ fn G() -> i32 {
 // CHECK:STDOUT: fn @G() -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F]
-// CHECK:STDOUT:   %.loc16_13: i32 = int_value 1 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc16_16: i32 = int_value 2 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc16_13: i32 = int_value 1 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc16_16: i32 = int_value 2 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc16_19: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc16_20.1: %tuple.type = tuple_literal (%.loc16_13, %.loc16_16, %.loc16_19)
-// CHECK:STDOUT:   %.loc16_23: i32 = int_value 1 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc16_20.2: ref %.2 = temporary_storage
-// CHECK:STDOUT:   %.loc16_20.3: i32 = int_value 0 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc16_23: i32 = int_value 1 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc16_20.2: ref %.28 = temporary_storage
+// CHECK:STDOUT:   %.loc16_20.3: i32 = int_value 0 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc16_20.4: ref i32 = array_index %.loc16_20.2, %.loc16_20.3
-// CHECK:STDOUT:   %.loc16_20.5: init i32 = initialize_from %.loc16_13 to %.loc16_20.4 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc16_20.6: i32 = int_value 1 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc16_20.5: init i32 = initialize_from %.loc16_13 to %.loc16_20.4 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc16_20.6: i32 = int_value 1 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc16_20.7: ref i32 = array_index %.loc16_20.2, %.loc16_20.6
-// CHECK:STDOUT:   %.loc16_20.8: init i32 = initialize_from %.loc16_16 to %.loc16_20.7 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc16_20.9: i32 = int_value 2 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc16_20.8: init i32 = initialize_from %.loc16_16 to %.loc16_20.7 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc16_20.9: i32 = int_value 2 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc16_20.10: ref i32 = array_index %.loc16_20.2, %.loc16_20.9
 // CHECK:STDOUT:   %.loc16_20.11: init i32 = initialize_from %.loc16_19 to %.loc16_20.10 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc16_20.12: init %.2 = array_init (%.loc16_20.5, %.loc16_20.8, %.loc16_20.11) to %.loc16_20.2 [template = constants.%array]
-// CHECK:STDOUT:   %.loc16_20.13: init %.2 = converted %.loc16_20.1, %.loc16_20.12 [template = constants.%array]
-// CHECK:STDOUT:   %.loc16_20.14: ref %.2 = temporary %.loc16_20.2, %.loc16_20.13
-// CHECK:STDOUT:   %.loc16_20.15: %.2 = bind_value %.loc16_20.14
+// CHECK:STDOUT:   %.loc16_20.12: init %.28 = array_init (%.loc16_20.5, %.loc16_20.8, %.loc16_20.11) to %.loc16_20.2 [template = constants.%array]
+// CHECK:STDOUT:   %.loc16_20.13: init %.28 = converted %.loc16_20.1, %.loc16_20.12 [template = constants.%array]
+// CHECK:STDOUT:   %.loc16_20.14: ref %.28 = temporary %.loc16_20.2, %.loc16_20.13
+// CHECK:STDOUT:   %.loc16_20.15: %.28 = bind_value %.loc16_20.14
 // CHECK:STDOUT:   %F.call: init i32 = call %F.ref(%.loc16_20.15, %.loc16_23)
 // CHECK:STDOUT:   %.loc16_25.1: i32 = value_of_initializer %F.call
 // CHECK:STDOUT:   %.loc16_25.2: i32 = converted %F.call, %.loc16_25.1

+ 22 - 10
toolchain/check/testdata/array/generic_empty.carbon

@@ -22,12 +22,19 @@ fn G(T:! type) {
 // CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [template]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 0 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, %T [symbolic]
-// CHECK:STDOUT:   %array: %.2 = tuple_value () [symbolic]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 0 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, %T [symbolic]
+// CHECK:STDOUT:   %array: %.28 = tuple_value () [symbolic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.1
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -53,19 +60,24 @@ fn G(T:! type) {
 // CHECK:STDOUT:   %T.patt.loc11_6.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc11_6.2 (constants.%T.patt)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %.loc13_17.2: type = array_type constants.%.1, @G.%T.loc11_6.2 (%T) [symbolic = %.loc13_17.2 (constants.%.2)]
-// CHECK:STDOUT:   %array: @G.%.loc13_17.2 (%.2) = tuple_value () [symbolic = %array (constants.%array)]
+// CHECK:STDOUT:   %.loc13_17.2: type = array_type constants.%.27, @G.%T.loc11_6.2 (%T) [symbolic = %.loc13_17.2 (constants.%.28)]
+// CHECK:STDOUT:   %array: @G.%.loc13_17.2 (%.28) = tuple_value () [symbolic = %array (constants.%array)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%T.param_patt: type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc11_6.1 [symbolic = %T.loc11_6.2 (constants.%T)]
-// CHECK:STDOUT:     %.loc13_16: i32 = int_value 0 [template = constants.%.1]
-// CHECK:STDOUT:     %.loc13_17.1: type = array_type %.loc13_16, %T [symbolic = %.loc13_17.2 (constants.%.2)]
-// CHECK:STDOUT:     %arr.var: ref @G.%.loc13_17.2 (%.2) = var arr
-// CHECK:STDOUT:     %arr: ref @G.%.loc13_17.2 (%.2) = bind_name arr, %arr.var
+// CHECK:STDOUT:     %.loc13_16.1: i32 = int_value 0 [template = constants.%.1]
+// CHECK:STDOUT:     %.loc13_16.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:     %.loc13_16.3: <bound method> = bound_method %.loc13_16.1, %.loc13_16.2 [template = constants.%.26]
+// CHECK:STDOUT:     %int.convert_checked: init Core.IntLiteral = call %.loc13_16.3(%.loc13_16.1) [template = constants.%.27]
+// CHECK:STDOUT:     %.loc13_16.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:     %.loc13_16.5: Core.IntLiteral = converted %.loc13_16.1, %.loc13_16.4 [template = constants.%.27]
+// CHECK:STDOUT:     %.loc13_17.1: type = array_type %.loc13_16.5, %T [symbolic = %.loc13_17.2 (constants.%.28)]
+// CHECK:STDOUT:     %arr.var: ref @G.%.loc13_17.2 (%.28) = var arr
+// CHECK:STDOUT:     %arr: ref @G.%.loc13_17.2 (%.28) = bind_name arr, %arr.var
 // CHECK:STDOUT:     %.loc13_22.1: %empty_tuple.type = tuple_literal ()
-// CHECK:STDOUT:     %.loc13_22.2: init @G.%.loc13_17.2 (%.2) = array_init () to %arr.var [symbolic = %array (constants.%array)]
-// CHECK:STDOUT:     %.loc13_23: init @G.%.loc13_17.2 (%.2) = converted %.loc13_22.1, %.loc13_22.2 [symbolic = %array (constants.%array)]
+// CHECK:STDOUT:     %.loc13_22.2: init @G.%.loc13_17.2 (%.28) = array_init () to %arr.var [symbolic = %array (constants.%array)]
+// CHECK:STDOUT:     %.loc13_23: init @G.%.loc13_17.2 (%.28) = converted %.loc13_22.1, %.loc13_22.2 [symbolic = %array (constants.%array)]
 // CHECK:STDOUT:     assign %arr.var, %.loc13_23
 // CHECK:STDOUT:     return
 // CHECK:STDOUT:   }

+ 39 - 27
toolchain/check/testdata/array/index_not_literal.carbon

@@ -17,19 +17,26 @@ var b: i32 = a[{.index = 2}.index];
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.5: i32 = int_value 2 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, i32 [template]
+// CHECK:STDOUT:   %.30: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %.31: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (i32, i32, i32) [template]
-// CHECK:STDOUT:   %.6: i32 = int_value 0 [template]
-// CHECK:STDOUT:   %array: %.2 = tuple_value (%.4, %.5, %.1) [template]
-// CHECK:STDOUT:   %.7: type = struct_type {.index: i32} [template]
-// CHECK:STDOUT:   %struct: %.7 = struct_value (%.5) [template]
+// CHECK:STDOUT:   %.32: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %array: %.28 = tuple_value (%.30, %.31, %.1) [template]
+// CHECK:STDOUT:   %.33: type = struct_type {.index: i32} [template]
+// CHECK:STDOUT:   %struct: %.33 = struct_value (%.31) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -43,12 +50,17 @@ var b: i32 = a[{.index = 2}.index];
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %int.make_type_32.loc11: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc11_14: i32 = int_value 3 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc11_14.1: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc11_9.1: type = value_of_initializer %int.make_type_32.loc11 [template = i32]
 // CHECK:STDOUT:   %.loc11_9.2: type = converted %int.make_type_32.loc11, %.loc11_9.1 [template = i32]
-// CHECK:STDOUT:   %.loc11_15: type = array_type %.loc11_14, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %a.var: ref %.2 = var a
-// CHECK:STDOUT:   %a: ref %.2 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc11_14.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc11_14.3: <bound method> = bound_method %.loc11_14.1, %.loc11_14.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc11_14.3(%.loc11_14.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_14.5: Core.IntLiteral = converted %.loc11_14.1, %.loc11_14.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_15: type = array_type %.loc11_14.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %a.var: ref %.28 = var a
+// CHECK:STDOUT:   %a: ref %.28 = bind_name a, %a.var
 // CHECK:STDOUT:   %int.make_type_32.loc12: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc12_8.1: type = value_of_initializer %int.make_type_32.loc12 [template = i32]
 // CHECK:STDOUT:   %.loc12_8.2: type = converted %int.make_type_32.loc12, %.loc12_8.1 [template = i32]
@@ -58,28 +70,28 @@ var b: i32 = a[{.index = 2}.index];
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc11_20: i32 = int_value 1 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc11_23: i32 = int_value 2 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc11_20: i32 = int_value 1 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc11_23: i32 = int_value 2 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc11_26: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc11_27.1: %tuple.type = tuple_literal (%.loc11_20, %.loc11_23, %.loc11_26)
-// CHECK:STDOUT:   %.loc11_27.2: i32 = int_value 0 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc11_27.2: i32 = int_value 0 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc11_27.3: ref i32 = array_index file.%a.var, %.loc11_27.2
-// CHECK:STDOUT:   %.loc11_27.4: init i32 = initialize_from %.loc11_20 to %.loc11_27.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc11_27.5: i32 = int_value 1 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc11_27.4: init i32 = initialize_from %.loc11_20 to %.loc11_27.3 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc11_27.5: i32 = int_value 1 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc11_27.6: ref i32 = array_index file.%a.var, %.loc11_27.5
-// CHECK:STDOUT:   %.loc11_27.7: init i32 = initialize_from %.loc11_23 to %.loc11_27.6 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc11_27.8: i32 = int_value 2 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc11_27.7: init i32 = initialize_from %.loc11_23 to %.loc11_27.6 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc11_27.8: i32 = int_value 2 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc11_27.9: ref i32 = array_index file.%a.var, %.loc11_27.8
 // CHECK:STDOUT:   %.loc11_27.10: init i32 = initialize_from %.loc11_26 to %.loc11_27.9 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc11_27.11: init %.2 = array_init (%.loc11_27.4, %.loc11_27.7, %.loc11_27.10) to file.%a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc11_28: init %.2 = converted %.loc11_27.1, %.loc11_27.11 [template = constants.%array]
+// CHECK:STDOUT:   %.loc11_27.11: init %.28 = array_init (%.loc11_27.4, %.loc11_27.7, %.loc11_27.10) to file.%a.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc11_28: init %.28 = converted %.loc11_27.1, %.loc11_27.11 [template = constants.%array]
 // CHECK:STDOUT:   assign file.%a.var, %.loc11_28
-// CHECK:STDOUT:   %a.ref: ref %.2 = name_ref a, file.%a
-// CHECK:STDOUT:   %.loc12_26: i32 = int_value 2 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc12_27.1: %.7 = struct_literal (%.loc12_26)
-// CHECK:STDOUT:   %struct: %.7 = struct_value (%.loc12_26) [template = constants.%struct]
-// CHECK:STDOUT:   %.loc12_27.2: %.7 = converted %.loc12_27.1, %struct [template = constants.%struct]
-// CHECK:STDOUT:   %.loc12_28: i32 = struct_access %.loc12_27.2, element0 [template = constants.%.5]
+// CHECK:STDOUT:   %a.ref: ref %.28 = name_ref a, file.%a
+// CHECK:STDOUT:   %.loc12_26: i32 = int_value 2 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc12_27.1: %.33 = struct_literal (%.loc12_26)
+// CHECK:STDOUT:   %struct: %.33 = struct_value (%.loc12_26) [template = constants.%struct]
+// CHECK:STDOUT:   %.loc12_27.2: %.33 = converted %.loc12_27.1, %struct [template = constants.%struct]
+// CHECK:STDOUT:   %.loc12_28: i32 = struct_access %.loc12_27.2, element0 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc12_34.1: ref i32 = array_index %a.ref, %.loc12_28
 // CHECK:STDOUT:   %.loc12_34.2: i32 = bind_value %.loc12_34.1
 // CHECK:STDOUT:   assign file.%b.var, %.loc12_34.2

+ 55 - 43
toolchain/check/testdata/array/nine_elements.carbon

@@ -16,23 +16,30 @@ var a: [i32; 9] = (1, 2, 3, 4, 5, 6, 7, 8, 9);
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 9 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.5: i32 = int_value 2 [template]
-// CHECK:STDOUT:   %.6: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.7: i32 = int_value 4 [template]
-// CHECK:STDOUT:   %.8: i32 = int_value 5 [template]
-// CHECK:STDOUT:   %.9: i32 = int_value 6 [template]
-// CHECK:STDOUT:   %.10: i32 = int_value 7 [template]
-// CHECK:STDOUT:   %.11: i32 = int_value 8 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 9 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, i32 [template]
+// CHECK:STDOUT:   %.30: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %.31: i32 = int_value 2 [template]
+// CHECK:STDOUT:   %.32: i32 = int_value 3 [template]
+// CHECK:STDOUT:   %.33: i32 = int_value 4 [template]
+// CHECK:STDOUT:   %.34: i32 = int_value 5 [template]
+// CHECK:STDOUT:   %.35: i32 = int_value 6 [template]
+// CHECK:STDOUT:   %.36: i32 = int_value 7 [template]
+// CHECK:STDOUT:   %.37: i32 = int_value 8 [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (i32, i32, i32, i32, i32, i32, i32, i32, i32) [template]
-// CHECK:STDOUT:   %.12: i32 = int_value 0 [template]
-// CHECK:STDOUT:   %array: %.2 = tuple_value (%.4, %.5, %.6, %.7, %.8, %.9, %.10, %.11, %.1) [template]
+// CHECK:STDOUT:   %.38: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %array: %.28 = tuple_value (%.30, %.31, %.32, %.33, %.34, %.35, %.36, %.37, %.1) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -45,55 +52,60 @@ var a: [i32; 9] = (1, 2, 3, 4, 5, 6, 7, 8, 9);
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %int.make_type_32: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc11_14: i32 = int_value 9 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc11_14.1: i32 = int_value 9 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc11_9.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:   %.loc11_9.2: type = converted %int.make_type_32, %.loc11_9.1 [template = i32]
-// CHECK:STDOUT:   %.loc11_15: type = array_type %.loc11_14, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %a.var: ref %.2 = var a
-// CHECK:STDOUT:   %a: ref %.2 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc11_14.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc11_14.3: <bound method> = bound_method %.loc11_14.1, %.loc11_14.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc11_14.3(%.loc11_14.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_14.5: Core.IntLiteral = converted %.loc11_14.1, %.loc11_14.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_15: type = array_type %.loc11_14.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %a.var: ref %.28 = var a
+// CHECK:STDOUT:   %a: ref %.28 = bind_name a, %a.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc11_20: i32 = int_value 1 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc11_23: i32 = int_value 2 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc11_26: i32 = int_value 3 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc11_29: i32 = int_value 4 [template = constants.%.7]
-// CHECK:STDOUT:   %.loc11_32: i32 = int_value 5 [template = constants.%.8]
-// CHECK:STDOUT:   %.loc11_35: i32 = int_value 6 [template = constants.%.9]
-// CHECK:STDOUT:   %.loc11_38: i32 = int_value 7 [template = constants.%.10]
-// CHECK:STDOUT:   %.loc11_41: i32 = int_value 8 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc11_20: i32 = int_value 1 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc11_23: i32 = int_value 2 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc11_26: i32 = int_value 3 [template = constants.%.32]
+// CHECK:STDOUT:   %.loc11_29: i32 = int_value 4 [template = constants.%.33]
+// CHECK:STDOUT:   %.loc11_32: i32 = int_value 5 [template = constants.%.34]
+// CHECK:STDOUT:   %.loc11_35: i32 = int_value 6 [template = constants.%.35]
+// CHECK:STDOUT:   %.loc11_38: i32 = int_value 7 [template = constants.%.36]
+// CHECK:STDOUT:   %.loc11_41: i32 = int_value 8 [template = constants.%.37]
 // CHECK:STDOUT:   %.loc11_44: i32 = int_value 9 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc11_45.1: %tuple.type = tuple_literal (%.loc11_20, %.loc11_23, %.loc11_26, %.loc11_29, %.loc11_32, %.loc11_35, %.loc11_38, %.loc11_41, %.loc11_44)
-// CHECK:STDOUT:   %.loc11_45.2: i32 = int_value 0 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc11_45.2: i32 = int_value 0 [template = constants.%.38]
 // CHECK:STDOUT:   %.loc11_45.3: ref i32 = array_index file.%a.var, %.loc11_45.2
-// CHECK:STDOUT:   %.loc11_45.4: init i32 = initialize_from %.loc11_20 to %.loc11_45.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc11_45.5: i32 = int_value 1 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc11_45.4: init i32 = initialize_from %.loc11_20 to %.loc11_45.3 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc11_45.5: i32 = int_value 1 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc11_45.6: ref i32 = array_index file.%a.var, %.loc11_45.5
-// CHECK:STDOUT:   %.loc11_45.7: init i32 = initialize_from %.loc11_23 to %.loc11_45.6 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc11_45.8: i32 = int_value 2 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc11_45.7: init i32 = initialize_from %.loc11_23 to %.loc11_45.6 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc11_45.8: i32 = int_value 2 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc11_45.9: ref i32 = array_index file.%a.var, %.loc11_45.8
-// CHECK:STDOUT:   %.loc11_45.10: init i32 = initialize_from %.loc11_26 to %.loc11_45.9 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc11_45.11: i32 = int_value 3 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc11_45.10: init i32 = initialize_from %.loc11_26 to %.loc11_45.9 [template = constants.%.32]
+// CHECK:STDOUT:   %.loc11_45.11: i32 = int_value 3 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc11_45.12: ref i32 = array_index file.%a.var, %.loc11_45.11
-// CHECK:STDOUT:   %.loc11_45.13: init i32 = initialize_from %.loc11_29 to %.loc11_45.12 [template = constants.%.7]
-// CHECK:STDOUT:   %.loc11_45.14: i32 = int_value 4 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc11_45.13: init i32 = initialize_from %.loc11_29 to %.loc11_45.12 [template = constants.%.33]
+// CHECK:STDOUT:   %.loc11_45.14: i32 = int_value 4 [template = constants.%.33]
 // CHECK:STDOUT:   %.loc11_45.15: ref i32 = array_index file.%a.var, %.loc11_45.14
-// CHECK:STDOUT:   %.loc11_45.16: init i32 = initialize_from %.loc11_32 to %.loc11_45.15 [template = constants.%.8]
-// CHECK:STDOUT:   %.loc11_45.17: i32 = int_value 5 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc11_45.16: init i32 = initialize_from %.loc11_32 to %.loc11_45.15 [template = constants.%.34]
+// CHECK:STDOUT:   %.loc11_45.17: i32 = int_value 5 [template = constants.%.34]
 // CHECK:STDOUT:   %.loc11_45.18: ref i32 = array_index file.%a.var, %.loc11_45.17
-// CHECK:STDOUT:   %.loc11_45.19: init i32 = initialize_from %.loc11_35 to %.loc11_45.18 [template = constants.%.9]
-// CHECK:STDOUT:   %.loc11_45.20: i32 = int_value 6 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc11_45.19: init i32 = initialize_from %.loc11_35 to %.loc11_45.18 [template = constants.%.35]
+// CHECK:STDOUT:   %.loc11_45.20: i32 = int_value 6 [template = constants.%.35]
 // CHECK:STDOUT:   %.loc11_45.21: ref i32 = array_index file.%a.var, %.loc11_45.20
-// CHECK:STDOUT:   %.loc11_45.22: init i32 = initialize_from %.loc11_38 to %.loc11_45.21 [template = constants.%.10]
-// CHECK:STDOUT:   %.loc11_45.23: i32 = int_value 7 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc11_45.22: init i32 = initialize_from %.loc11_38 to %.loc11_45.21 [template = constants.%.36]
+// CHECK:STDOUT:   %.loc11_45.23: i32 = int_value 7 [template = constants.%.36]
 // CHECK:STDOUT:   %.loc11_45.24: ref i32 = array_index file.%a.var, %.loc11_45.23
-// CHECK:STDOUT:   %.loc11_45.25: init i32 = initialize_from %.loc11_41 to %.loc11_45.24 [template = constants.%.11]
-// CHECK:STDOUT:   %.loc11_45.26: i32 = int_value 8 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc11_45.25: init i32 = initialize_from %.loc11_41 to %.loc11_45.24 [template = constants.%.37]
+// CHECK:STDOUT:   %.loc11_45.26: i32 = int_value 8 [template = constants.%.37]
 // CHECK:STDOUT:   %.loc11_45.27: ref i32 = array_index file.%a.var, %.loc11_45.26
 // CHECK:STDOUT:   %.loc11_45.28: init i32 = initialize_from %.loc11_44 to %.loc11_45.27 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc11_45.29: init %.2 = array_init (%.loc11_45.4, %.loc11_45.7, %.loc11_45.10, %.loc11_45.13, %.loc11_45.16, %.loc11_45.19, %.loc11_45.22, %.loc11_45.25, %.loc11_45.28) to file.%a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc11_46: init %.2 = converted %.loc11_45.1, %.loc11_45.29 [template = constants.%array]
+// CHECK:STDOUT:   %.loc11_45.29: init %.28 = array_init (%.loc11_45.4, %.loc11_45.7, %.loc11_45.10, %.loc11_45.13, %.loc11_45.16, %.loc11_45.19, %.loc11_45.22, %.loc11_45.25, %.loc11_45.28) to file.%a.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc11_46: init %.28 = converted %.loc11_45.1, %.loc11_45.29 [template = constants.%array]
 // CHECK:STDOUT:   assign file.%a.var, %.loc11_46
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 87 - 70
toolchain/check/testdata/basics/numeric_literals.carbon

@@ -37,36 +37,43 @@ fn F() {
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 6 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 8 [template]
-// CHECK:STDOUT:   %.5: i32 = int_value 9 [template]
-// CHECK:STDOUT:   %.6: i32 = int_value 2147483647 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 6 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, i32 [template]
+// CHECK:STDOUT:   %.30: i32 = int_value 8 [template]
+// CHECK:STDOUT:   %.31: i32 = int_value 9 [template]
+// CHECK:STDOUT:   %.32: i32 = int_value 2147483647 [template]
 // CHECK:STDOUT:   %tuple.type.1: type = tuple_type (i32, i32, i32, i32, i32, i32) [template]
-// CHECK:STDOUT:   %.7: i32 = int_value 0 [template]
-// CHECK:STDOUT:   %.8: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.9: i32 = int_value 2 [template]
-// CHECK:STDOUT:   %.10: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.11: i32 = int_value 4 [template]
-// CHECK:STDOUT:   %.12: i32 = int_value 5 [template]
-// CHECK:STDOUT:   %array.1: %.2 = tuple_value (%.4, %.5, %.4, %.4, %.6, %.6) [template]
-// CHECK:STDOUT:   %.13: Core.IntLiteral = int_value 64 [template]
+// CHECK:STDOUT:   %.33: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %.34: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %.35: i32 = int_value 2 [template]
+// CHECK:STDOUT:   %.36: i32 = int_value 3 [template]
+// CHECK:STDOUT:   %.37: i32 = int_value 4 [template]
+// CHECK:STDOUT:   %.38: i32 = int_value 5 [template]
+// CHECK:STDOUT:   %array.1: %.28 = tuple_value (%.30, %.31, %.30, %.30, %.32, %.32) [template]
+// CHECK:STDOUT:   %.39: Core.IntLiteral = int_value 64 [template]
 // CHECK:STDOUT:   %Float.type: type = fn_type @Float [template]
 // CHECK:STDOUT:   %Float: %Float.type = struct_value () [template]
-// CHECK:STDOUT:   %.14: type = array_type %.1, f64 [template]
-// CHECK:STDOUT:   %.16: f64 = float_literal 0.90000000000000002 [template]
-// CHECK:STDOUT:   %.17: f64 = float_literal 8 [template]
-// CHECK:STDOUT:   %.18: f64 = float_literal 80 [template]
-// CHECK:STDOUT:   %.19: f64 = float_literal 1.0E+7 [template]
-// CHECK:STDOUT:   %.20: f64 = float_literal 1.0E+8 [template]
-// CHECK:STDOUT:   %.21: f64 = float_literal 1.0E-8 [template]
+// CHECK:STDOUT:   %.40: type = array_type %.27, f64 [template]
+// CHECK:STDOUT:   %.42: f64 = float_literal 0.90000000000000002 [template]
+// CHECK:STDOUT:   %.43: f64 = float_literal 8 [template]
+// CHECK:STDOUT:   %.44: f64 = float_literal 80 [template]
+// CHECK:STDOUT:   %.45: f64 = float_literal 1.0E+7 [template]
+// CHECK:STDOUT:   %.46: f64 = float_literal 1.0E+8 [template]
+// CHECK:STDOUT:   %.47: f64 = float_literal 1.0E-8 [template]
 // CHECK:STDOUT:   %tuple.type.2: type = tuple_type (f64, f64, f64, f64, f64, f64) [template]
-// CHECK:STDOUT:   %array.2: %.14 = tuple_value (%.16, %.17, %.18, %.19, %.20, %.21) [template]
+// CHECK:STDOUT:   %array.2: %.40 = tuple_value (%.42, %.43, %.44, %.45, %.46, %.47) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
 // CHECK:STDOUT:     .Int32 = %import_ref.1
-// CHECK:STDOUT:     .Float = %import_ref.2
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
+// CHECK:STDOUT:     .Float = %import_ref.51
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -84,75 +91,85 @@ fn F() {
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %int.make_type_32: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc14_19: i32 = int_value 6 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc14_19.1: i32 = int_value 6 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc14_14.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:   %.loc14_14.2: type = converted %int.make_type_32, %.loc14_14.1 [template = i32]
-// CHECK:STDOUT:   %.loc14_20: type = array_type %.loc14_19, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %ints.var: ref %.2 = var ints
-// CHECK:STDOUT:   %ints: ref %.2 = bind_name ints, %ints.var
-// CHECK:STDOUT:   %.loc15: i32 = int_value 8 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc16: i32 = int_value 9 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc17: i32 = int_value 8 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc18: i32 = int_value 8 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc19: i32 = int_value 2147483647 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc20: i32 = int_value 2147483647 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc14_19.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc14_19.3: <bound method> = bound_method %.loc14_19.1, %.loc14_19.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked.loc14: init Core.IntLiteral = call %.loc14_19.3(%.loc14_19.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc14_19.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc14 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc14_19.5: Core.IntLiteral = converted %.loc14_19.1, %.loc14_19.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc14_20: type = array_type %.loc14_19.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %ints.var: ref %.28 = var ints
+// CHECK:STDOUT:   %ints: ref %.28 = bind_name ints, %ints.var
+// CHECK:STDOUT:   %.loc15: i32 = int_value 8 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc16: i32 = int_value 9 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc17: i32 = int_value 8 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc18: i32 = int_value 8 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc19: i32 = int_value 2147483647 [template = constants.%.32]
+// CHECK:STDOUT:   %.loc20: i32 = int_value 2147483647 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc21_3.1: %tuple.type.1 = tuple_literal (%.loc15, %.loc16, %.loc17, %.loc18, %.loc19, %.loc20)
-// CHECK:STDOUT:   %.loc21_3.2: i32 = int_value 0 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc21_3.2: i32 = int_value 0 [template = constants.%.33]
 // CHECK:STDOUT:   %.loc21_3.3: ref i32 = array_index %ints.var, %.loc21_3.2
-// CHECK:STDOUT:   %.loc21_3.4: init i32 = initialize_from %.loc15 to %.loc21_3.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc21_3.5: i32 = int_value 1 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc21_3.4: init i32 = initialize_from %.loc15 to %.loc21_3.3 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc21_3.5: i32 = int_value 1 [template = constants.%.34]
 // CHECK:STDOUT:   %.loc21_3.6: ref i32 = array_index %ints.var, %.loc21_3.5
-// CHECK:STDOUT:   %.loc21_3.7: init i32 = initialize_from %.loc16 to %.loc21_3.6 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc21_3.8: i32 = int_value 2 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc21_3.7: init i32 = initialize_from %.loc16 to %.loc21_3.6 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc21_3.8: i32 = int_value 2 [template = constants.%.35]
 // CHECK:STDOUT:   %.loc21_3.9: ref i32 = array_index %ints.var, %.loc21_3.8
-// CHECK:STDOUT:   %.loc21_3.10: init i32 = initialize_from %.loc17 to %.loc21_3.9 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc21_3.11: i32 = int_value 3 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc21_3.10: init i32 = initialize_from %.loc17 to %.loc21_3.9 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc21_3.11: i32 = int_value 3 [template = constants.%.36]
 // CHECK:STDOUT:   %.loc21_3.12: ref i32 = array_index %ints.var, %.loc21_3.11
-// CHECK:STDOUT:   %.loc21_3.13: init i32 = initialize_from %.loc18 to %.loc21_3.12 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc21_3.14: i32 = int_value 4 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc21_3.13: init i32 = initialize_from %.loc18 to %.loc21_3.12 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc21_3.14: i32 = int_value 4 [template = constants.%.37]
 // CHECK:STDOUT:   %.loc21_3.15: ref i32 = array_index %ints.var, %.loc21_3.14
-// CHECK:STDOUT:   %.loc21_3.16: init i32 = initialize_from %.loc19 to %.loc21_3.15 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc21_3.17: i32 = int_value 5 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc21_3.16: init i32 = initialize_from %.loc19 to %.loc21_3.15 [template = constants.%.32]
+// CHECK:STDOUT:   %.loc21_3.17: i32 = int_value 5 [template = constants.%.38]
 // CHECK:STDOUT:   %.loc21_3.18: ref i32 = array_index %ints.var, %.loc21_3.17
-// CHECK:STDOUT:   %.loc21_3.19: init i32 = initialize_from %.loc20 to %.loc21_3.18 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc21_3.20: init %.2 = array_init (%.loc21_3.4, %.loc21_3.7, %.loc21_3.10, %.loc21_3.13, %.loc21_3.16, %.loc21_3.19) to %ints.var [template = constants.%array.1]
-// CHECK:STDOUT:   %.loc21_4: init %.2 = converted %.loc21_3.1, %.loc21_3.20 [template = constants.%array.1]
+// CHECK:STDOUT:   %.loc21_3.19: init i32 = initialize_from %.loc20 to %.loc21_3.18 [template = constants.%.32]
+// CHECK:STDOUT:   %.loc21_3.20: init %.28 = array_init (%.loc21_3.4, %.loc21_3.7, %.loc21_3.10, %.loc21_3.13, %.loc21_3.16, %.loc21_3.19) to %ints.var [template = constants.%array.1]
+// CHECK:STDOUT:   %.loc21_4: init %.28 = converted %.loc21_3.1, %.loc21_3.20 [template = constants.%array.1]
 // CHECK:STDOUT:   assign %ints.var, %.loc21_4
-// CHECK:STDOUT:   %.loc22_16.1: Core.IntLiteral = int_value 64 [template = constants.%.13]
+// CHECK:STDOUT:   %.loc22_16.1: Core.IntLiteral = int_value 64 [template = constants.%.39]
 // CHECK:STDOUT:   %float.make_type: init type = call constants.%Float(%.loc22_16.1) [template = f64]
-// CHECK:STDOUT:   %.loc22_21: i32 = int_value 6 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc22_21.1: i32 = int_value 6 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc22_16.2: type = value_of_initializer %float.make_type [template = f64]
 // CHECK:STDOUT:   %.loc22_16.3: type = converted %float.make_type, %.loc22_16.2 [template = f64]
-// CHECK:STDOUT:   %.loc22_22: type = array_type %.loc22_21, f64 [template = constants.%.14]
-// CHECK:STDOUT:   %floats.var: ref %.14 = var floats
-// CHECK:STDOUT:   %floats: ref %.14 = bind_name floats, %floats.var
-// CHECK:STDOUT:   %.loc23: f64 = float_literal 0.90000000000000002 [template = constants.%.16]
-// CHECK:STDOUT:   %.loc24: f64 = float_literal 8 [template = constants.%.17]
-// CHECK:STDOUT:   %.loc25: f64 = float_literal 80 [template = constants.%.18]
-// CHECK:STDOUT:   %.loc26: f64 = float_literal 1.0E+7 [template = constants.%.19]
-// CHECK:STDOUT:   %.loc27: f64 = float_literal 1.0E+8 [template = constants.%.20]
-// CHECK:STDOUT:   %.loc28: f64 = float_literal 1.0E-8 [template = constants.%.21]
+// CHECK:STDOUT:   %.loc22_21.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc22_21.3: <bound method> = bound_method %.loc22_21.1, %.loc22_21.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked.loc22: init Core.IntLiteral = call %.loc22_21.3(%.loc22_21.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc22_21.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc22 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc22_21.5: Core.IntLiteral = converted %.loc22_21.1, %.loc22_21.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc22_22: type = array_type %.loc22_21.5, f64 [template = constants.%.40]
+// CHECK:STDOUT:   %floats.var: ref %.40 = var floats
+// CHECK:STDOUT:   %floats: ref %.40 = bind_name floats, %floats.var
+// CHECK:STDOUT:   %.loc23: f64 = float_literal 0.90000000000000002 [template = constants.%.42]
+// CHECK:STDOUT:   %.loc24: f64 = float_literal 8 [template = constants.%.43]
+// CHECK:STDOUT:   %.loc25: f64 = float_literal 80 [template = constants.%.44]
+// CHECK:STDOUT:   %.loc26: f64 = float_literal 1.0E+7 [template = constants.%.45]
+// CHECK:STDOUT:   %.loc27: f64 = float_literal 1.0E+8 [template = constants.%.46]
+// CHECK:STDOUT:   %.loc28: f64 = float_literal 1.0E-8 [template = constants.%.47]
 // CHECK:STDOUT:   %.loc29_3.1: %tuple.type.2 = tuple_literal (%.loc23, %.loc24, %.loc25, %.loc26, %.loc27, %.loc28)
-// CHECK:STDOUT:   %.loc29_3.2: i32 = int_value 0 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc29_3.2: i32 = int_value 0 [template = constants.%.33]
 // CHECK:STDOUT:   %.loc29_3.3: ref f64 = array_index %floats.var, %.loc29_3.2
-// CHECK:STDOUT:   %.loc29_3.4: init f64 = initialize_from %.loc23 to %.loc29_3.3 [template = constants.%.16]
-// CHECK:STDOUT:   %.loc29_3.5: i32 = int_value 1 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc29_3.4: init f64 = initialize_from %.loc23 to %.loc29_3.3 [template = constants.%.42]
+// CHECK:STDOUT:   %.loc29_3.5: i32 = int_value 1 [template = constants.%.34]
 // CHECK:STDOUT:   %.loc29_3.6: ref f64 = array_index %floats.var, %.loc29_3.5
-// CHECK:STDOUT:   %.loc29_3.7: init f64 = initialize_from %.loc24 to %.loc29_3.6 [template = constants.%.17]
-// CHECK:STDOUT:   %.loc29_3.8: i32 = int_value 2 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc29_3.7: init f64 = initialize_from %.loc24 to %.loc29_3.6 [template = constants.%.43]
+// CHECK:STDOUT:   %.loc29_3.8: i32 = int_value 2 [template = constants.%.35]
 // CHECK:STDOUT:   %.loc29_3.9: ref f64 = array_index %floats.var, %.loc29_3.8
-// CHECK:STDOUT:   %.loc29_3.10: init f64 = initialize_from %.loc25 to %.loc29_3.9 [template = constants.%.18]
-// CHECK:STDOUT:   %.loc29_3.11: i32 = int_value 3 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc29_3.10: init f64 = initialize_from %.loc25 to %.loc29_3.9 [template = constants.%.44]
+// CHECK:STDOUT:   %.loc29_3.11: i32 = int_value 3 [template = constants.%.36]
 // CHECK:STDOUT:   %.loc29_3.12: ref f64 = array_index %floats.var, %.loc29_3.11
-// CHECK:STDOUT:   %.loc29_3.13: init f64 = initialize_from %.loc26 to %.loc29_3.12 [template = constants.%.19]
-// CHECK:STDOUT:   %.loc29_3.14: i32 = int_value 4 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc29_3.13: init f64 = initialize_from %.loc26 to %.loc29_3.12 [template = constants.%.45]
+// CHECK:STDOUT:   %.loc29_3.14: i32 = int_value 4 [template = constants.%.37]
 // CHECK:STDOUT:   %.loc29_3.15: ref f64 = array_index %floats.var, %.loc29_3.14
-// CHECK:STDOUT:   %.loc29_3.16: init f64 = initialize_from %.loc27 to %.loc29_3.15 [template = constants.%.20]
-// CHECK:STDOUT:   %.loc29_3.17: i32 = int_value 5 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc29_3.16: init f64 = initialize_from %.loc27 to %.loc29_3.15 [template = constants.%.46]
+// CHECK:STDOUT:   %.loc29_3.17: i32 = int_value 5 [template = constants.%.38]
 // CHECK:STDOUT:   %.loc29_3.18: ref f64 = array_index %floats.var, %.loc29_3.17
-// CHECK:STDOUT:   %.loc29_3.19: init f64 = initialize_from %.loc28 to %.loc29_3.18 [template = constants.%.21]
-// CHECK:STDOUT:   %.loc29_3.20: init %.14 = array_init (%.loc29_3.4, %.loc29_3.7, %.loc29_3.10, %.loc29_3.13, %.loc29_3.16, %.loc29_3.19) to %floats.var [template = constants.%array.2]
-// CHECK:STDOUT:   %.loc29_4: init %.14 = converted %.loc29_3.1, %.loc29_3.20 [template = constants.%array.2]
+// CHECK:STDOUT:   %.loc29_3.19: init f64 = initialize_from %.loc28 to %.loc29_3.18 [template = constants.%.47]
+// CHECK:STDOUT:   %.loc29_3.20: init %.40 = array_init (%.loc29_3.4, %.loc29_3.7, %.loc29_3.10, %.loc29_3.13, %.loc29_3.16, %.loc29_3.19) to %floats.var [template = constants.%array.2]
+// CHECK:STDOUT:   %.loc29_4: init %.40 = converted %.loc29_3.1, %.loc29_3.20 [template = constants.%array.2]
 // CHECK:STDOUT:   assign %floats.var, %.loc29_4
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 31 - 12
toolchain/check/testdata/builtins/int/and.carbon

@@ -29,15 +29,22 @@ fn RuntimeCall(a: i32, b: i32) -> i32 {
 // CHECK:STDOUT:   %.1: i32 = int_value 12 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value 10 [template]
 // CHECK:STDOUT:   %.3: i32 = int_value 8 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
-// CHECK:STDOUT:   %.5: type = ptr_type %.4 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.27: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.28: <bound method> = bound_method %.3, %Convert.15 [template]
+// CHECK:STDOUT:   %.29: Core.IntLiteral = int_value 8 [template]
+// CHECK:STDOUT:   %.30: type = array_type %.29, i32 [template]
+// CHECK:STDOUT:   %.31: type = ptr_type %.30 [template]
 // CHECK:STDOUT:   %RuntimeCall.type: type = fn_type @RuntimeCall [template]
 // CHECK:STDOUT:   %RuntimeCall: %RuntimeCall.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -83,15 +90,27 @@ fn RuntimeCall(a: i32, b: i32) -> i32 {
 // CHECK:STDOUT:   %int.and: init i32 = call %And.ref(%.loc4_20, %.loc4_24) [template = constants.%.3]
 // CHECK:STDOUT:   %.loc4_11.1: type = value_of_initializer %int.make_type_32.loc4 [template = i32]
 // CHECK:STDOUT:   %.loc4_11.2: type = converted %int.make_type_32.loc4, %.loc4_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc4_27: type = array_type %int.and, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %arr.var: ref %.4 = var arr
-// CHECK:STDOUT:   %arr: ref %.4 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc4_19.1: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc4_19.2: <bound method> = bound_method %int.and, %.loc4_19.1 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_19.3: i32 = value_of_initializer %int.and [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_19.4: i32 = converted %int.and, %.loc4_19.3 [template = constants.%.3]
+// CHECK:STDOUT:   %int.convert_checked.loc4: init Core.IntLiteral = call %.loc4_19.2(%.loc4_19.4) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.6: Core.IntLiteral = converted %int.and, %.loc4_19.5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_27: type = array_type %.loc4_19.6, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %arr.var: ref %.30 = var arr
+// CHECK:STDOUT:   %arr: ref %.30 = bind_name arr, %arr.var
 // CHECK:STDOUT:   %int.make_type_32.loc5: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc5_18: i32 = int_value 8 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc5_18.1: i32 = int_value 8 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc5_13.1: type = value_of_initializer %int.make_type_32.loc5 [template = i32]
 // CHECK:STDOUT:   %.loc5_13.2: type = converted %int.make_type_32.loc5, %.loc5_13.1 [template = i32]
-// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc5_18.2: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc5_18.3: <bound method> = bound_method %.loc5_18.1, %.loc5_18.2 [template = constants.%.28]
+// CHECK:STDOUT:   %int.convert_checked.loc5: init Core.IntLiteral = call %.loc5_18.3(%.loc5_18.1) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.5: Core.IntLiteral = converted %.loc5_18.1, %.loc5_18.4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18.5, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.30 [template = constants.%.31]
 // CHECK:STDOUT:   %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [template = constants.%RuntimeCall] {
 // CHECK:STDOUT:     %a.patt: i32 = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: i32 = value_param_pattern %a.patt, runtime_param0
@@ -133,9 +152,9 @@ fn RuntimeCall(a: i32, b: i32) -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr.ref: ref %.4 = name_ref arr, file.%arr
-// CHECK:STDOUT:   %.loc5: %.5 = addr_of %arr.ref
-// CHECK:STDOUT:   %arr_p: %.5 = bind_name arr_p, %.loc5
+// CHECK:STDOUT:   %arr.ref: ref %.30 = name_ref arr, file.%arr
+// CHECK:STDOUT:   %.loc5: %.31 = addr_of %arr.ref
+// CHECK:STDOUT:   %arr_p: %.31 = bind_name arr_p, %.loc5
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 31 - 12
toolchain/check/testdata/builtins/int/complement.carbon

@@ -33,15 +33,22 @@ fn RuntimeCall(a: i32) -> i32 {
 // CHECK:STDOUT:   %.2: i32 = int_value -1193047 [template]
 // CHECK:STDOUT:   %.3: i32 = int_value 16777215 [template]
 // CHECK:STDOUT:   %.4: i32 = int_value 15584169 [template]
-// CHECK:STDOUT:   %.5: type = array_type %.4, i32 [template]
-// CHECK:STDOUT:   %.6: type = ptr_type %.5 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.28: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.29: <bound method> = bound_method %.4, %Convert.15 [template]
+// CHECK:STDOUT:   %.30: Core.IntLiteral = int_value 15584169 [template]
+// CHECK:STDOUT:   %.31: type = array_type %.30, i32 [template]
+// CHECK:STDOUT:   %.32: type = ptr_type %.31 [template]
 // CHECK:STDOUT:   %RuntimeCall.type: type = fn_type @RuntimeCall [template]
 // CHECK:STDOUT:   %RuntimeCall: %RuntimeCall.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -109,15 +116,27 @@ fn RuntimeCall(a: i32) -> i32 {
 // CHECK:STDOUT:   %int.and: init i32 = call %And.ref(%.loc5_30.2, %.loc5_42) [template = constants.%.4]
 // CHECK:STDOUT:   %.loc5_11.1: type = value_of_initializer %int.make_type_32.loc5 [template = i32]
 // CHECK:STDOUT:   %.loc5_11.2: type = converted %int.make_type_32.loc5, %.loc5_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc5_51: type = array_type %int.and, i32 [template = constants.%.5]
-// CHECK:STDOUT:   %arr.var: ref %.5 = var arr
-// CHECK:STDOUT:   %arr: ref %.5 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc5_19.1: %Convert.type.2 = interface_witness_access constants.%.28, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc5_19.2: <bound method> = bound_method %int.and, %.loc5_19.1 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_19.3: i32 = value_of_initializer %int.and [template = constants.%.4]
+// CHECK:STDOUT:   %.loc5_19.4: i32 = converted %int.and, %.loc5_19.3 [template = constants.%.4]
+// CHECK:STDOUT:   %int.convert_checked.loc5: init Core.IntLiteral = call %.loc5_19.2(%.loc5_19.4) [template = constants.%.30]
+// CHECK:STDOUT:   %.loc5_19.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc5 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc5_19.6: Core.IntLiteral = converted %int.and, %.loc5_19.5 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc5_51: type = array_type %.loc5_19.6, i32 [template = constants.%.31]
+// CHECK:STDOUT:   %arr.var: ref %.31 = var arr
+// CHECK:STDOUT:   %arr: ref %.31 = bind_name arr, %arr.var
 // CHECK:STDOUT:   %int.make_type_32.loc6: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc6_18: i32 = int_value 15584169 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc6_18.1: i32 = int_value 15584169 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc6_13.1: type = value_of_initializer %int.make_type_32.loc6 [template = i32]
 // CHECK:STDOUT:   %.loc6_13.2: type = converted %int.make_type_32.loc6, %.loc6_13.1 [template = i32]
-// CHECK:STDOUT:   %.loc6_26: type = array_type %.loc6_18, i32 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc6_27: type = ptr_type %.5 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc6_18.2: %Convert.type.2 = interface_witness_access constants.%.28, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc6_18.3: <bound method> = bound_method %.loc6_18.1, %.loc6_18.2 [template = constants.%.29]
+// CHECK:STDOUT:   %int.convert_checked.loc6: init Core.IntLiteral = call %.loc6_18.3(%.loc6_18.1) [template = constants.%.30]
+// CHECK:STDOUT:   %.loc6_18.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc6 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc6_18.5: Core.IntLiteral = converted %.loc6_18.1, %.loc6_18.4 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc6_26: type = array_type %.loc6_18.5, i32 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc6_27: type = ptr_type %.31 [template = constants.%.32]
 // CHECK:STDOUT:   %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [template = constants.%RuntimeCall] {
 // CHECK:STDOUT:     %a.patt: i32 = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: i32 = value_param_pattern %a.patt, runtime_param0
@@ -153,9 +172,9 @@ fn RuntimeCall(a: i32) -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr.ref: ref %.5 = name_ref arr, file.%arr
-// CHECK:STDOUT:   %.loc6: %.6 = addr_of %arr.ref
-// CHECK:STDOUT:   %arr_p: %.6 = bind_name arr_p, %.loc6
+// CHECK:STDOUT:   %arr.ref: ref %.31 = name_ref arr, file.%arr
+// CHECK:STDOUT:   %.loc6: %.32 = addr_of %arr.ref
+// CHECK:STDOUT:   %arr_p: %.32 = bind_name arr_p, %.loc6
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 31 - 12
toolchain/check/testdata/builtins/int/left_shift.carbon

@@ -73,15 +73,22 @@ let negative: i32 = LeftShift(1, Negate(1));
 // CHECK:STDOUT:   %.1: i32 = int_value 5 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %.3: i32 = int_value 20 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
-// CHECK:STDOUT:   %.5: type = ptr_type %.4 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.27: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.28: <bound method> = bound_method %.3, %Convert.15 [template]
+// CHECK:STDOUT:   %.29: Core.IntLiteral = int_value 20 [template]
+// CHECK:STDOUT:   %.30: type = array_type %.29, i32 [template]
+// CHECK:STDOUT:   %.31: type = ptr_type %.30 [template]
 // CHECK:STDOUT:   %RuntimeCall.type: type = fn_type @RuntimeCall [template]
 // CHECK:STDOUT:   %RuntimeCall: %RuntimeCall.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -127,15 +134,27 @@ let negative: i32 = LeftShift(1, Negate(1));
 // CHECK:STDOUT:   %int.left_shift: init i32 = call %LeftShift.ref(%.loc4_26, %.loc4_29) [template = constants.%.3]
 // CHECK:STDOUT:   %.loc4_11.1: type = value_of_initializer %int.make_type_32.loc4 [template = i32]
 // CHECK:STDOUT:   %.loc4_11.2: type = converted %int.make_type_32.loc4, %.loc4_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc4_31: type = array_type %int.left_shift, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %arr.var: ref %.4 = var arr
-// CHECK:STDOUT:   %arr: ref %.4 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc4_25.1: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc4_25.2: <bound method> = bound_method %int.left_shift, %.loc4_25.1 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_25.3: i32 = value_of_initializer %int.left_shift [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_25.4: i32 = converted %int.left_shift, %.loc4_25.3 [template = constants.%.3]
+// CHECK:STDOUT:   %int.convert_checked.loc4: init Core.IntLiteral = call %.loc4_25.2(%.loc4_25.4) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_25.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_25.6: Core.IntLiteral = converted %int.left_shift, %.loc4_25.5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_31: type = array_type %.loc4_25.6, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %arr.var: ref %.30 = var arr
+// CHECK:STDOUT:   %arr: ref %.30 = bind_name arr, %arr.var
 // CHECK:STDOUT:   %int.make_type_32.loc5: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc5_18: i32 = int_value 20 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc5_18.1: i32 = int_value 20 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc5_13.1: type = value_of_initializer %int.make_type_32.loc5 [template = i32]
 // CHECK:STDOUT:   %.loc5_13.2: type = converted %int.make_type_32.loc5, %.loc5_13.1 [template = i32]
-// CHECK:STDOUT:   %.loc5_20: type = array_type %.loc5_18, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc5_21: type = ptr_type %.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc5_18.2: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc5_18.3: <bound method> = bound_method %.loc5_18.1, %.loc5_18.2 [template = constants.%.28]
+// CHECK:STDOUT:   %int.convert_checked.loc5: init Core.IntLiteral = call %.loc5_18.3(%.loc5_18.1) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.5: Core.IntLiteral = converted %.loc5_18.1, %.loc5_18.4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_20: type = array_type %.loc5_18.5, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc5_21: type = ptr_type %.30 [template = constants.%.31]
 // CHECK:STDOUT:   %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [template = constants.%RuntimeCall] {
 // CHECK:STDOUT:     %a.patt: i32 = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: i32 = value_param_pattern %a.patt, runtime_param0
@@ -177,9 +196,9 @@ let negative: i32 = LeftShift(1, Negate(1));
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr.ref: ref %.4 = name_ref arr, file.%arr
-// CHECK:STDOUT:   %.loc5: %.5 = addr_of %arr.ref
-// CHECK:STDOUT:   %arr_p: %.5 = bind_name arr_p, %.loc5
+// CHECK:STDOUT:   %arr.ref: ref %.30 = name_ref arr, file.%arr
+// CHECK:STDOUT:   %.loc5: %.31 = addr_of %arr.ref
+// CHECK:STDOUT:   %arr_p: %.31 = bind_name arr_p, %.loc5
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 31 - 12
toolchain/check/testdata/builtins/int/or.carbon

@@ -29,15 +29,22 @@ fn RuntimeCall(a: i32, b: i32) -> i32 {
 // CHECK:STDOUT:   %.1: i32 = int_value 12 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value 10 [template]
 // CHECK:STDOUT:   %.3: i32 = int_value 14 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
-// CHECK:STDOUT:   %.5: type = ptr_type %.4 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.27: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.28: <bound method> = bound_method %.3, %Convert.15 [template]
+// CHECK:STDOUT:   %.29: Core.IntLiteral = int_value 14 [template]
+// CHECK:STDOUT:   %.30: type = array_type %.29, i32 [template]
+// CHECK:STDOUT:   %.31: type = ptr_type %.30 [template]
 // CHECK:STDOUT:   %RuntimeCall.type: type = fn_type @RuntimeCall [template]
 // CHECK:STDOUT:   %RuntimeCall: %RuntimeCall.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -83,15 +90,27 @@ fn RuntimeCall(a: i32, b: i32) -> i32 {
 // CHECK:STDOUT:   %int.or: init i32 = call %Or.ref(%.loc4_19, %.loc4_23) [template = constants.%.3]
 // CHECK:STDOUT:   %.loc4_11.1: type = value_of_initializer %int.make_type_32.loc4 [template = i32]
 // CHECK:STDOUT:   %.loc4_11.2: type = converted %int.make_type_32.loc4, %.loc4_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc4_26: type = array_type %int.or, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %arr.var: ref %.4 = var arr
-// CHECK:STDOUT:   %arr: ref %.4 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc4_18.1: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc4_18.2: <bound method> = bound_method %int.or, %.loc4_18.1 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_18.3: i32 = value_of_initializer %int.or [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_18.4: i32 = converted %int.or, %.loc4_18.3 [template = constants.%.3]
+// CHECK:STDOUT:   %int.convert_checked.loc4: init Core.IntLiteral = call %.loc4_18.2(%.loc4_18.4) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_18.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_18.6: Core.IntLiteral = converted %int.or, %.loc4_18.5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_26: type = array_type %.loc4_18.6, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %arr.var: ref %.30 = var arr
+// CHECK:STDOUT:   %arr: ref %.30 = bind_name arr, %arr.var
 // CHECK:STDOUT:   %int.make_type_32.loc5: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc5_18: i32 = int_value 14 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc5_18.1: i32 = int_value 14 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc5_13.1: type = value_of_initializer %int.make_type_32.loc5 [template = i32]
 // CHECK:STDOUT:   %.loc5_13.2: type = converted %int.make_type_32.loc5, %.loc5_13.1 [template = i32]
-// CHECK:STDOUT:   %.loc5_20: type = array_type %.loc5_18, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc5_21: type = ptr_type %.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc5_18.2: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc5_18.3: <bound method> = bound_method %.loc5_18.1, %.loc5_18.2 [template = constants.%.28]
+// CHECK:STDOUT:   %int.convert_checked.loc5: init Core.IntLiteral = call %.loc5_18.3(%.loc5_18.1) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.5: Core.IntLiteral = converted %.loc5_18.1, %.loc5_18.4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_20: type = array_type %.loc5_18.5, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc5_21: type = ptr_type %.30 [template = constants.%.31]
 // CHECK:STDOUT:   %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [template = constants.%RuntimeCall] {
 // CHECK:STDOUT:     %a.patt: i32 = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: i32 = value_param_pattern %a.patt, runtime_param0
@@ -133,9 +152,9 @@ fn RuntimeCall(a: i32, b: i32) -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr.ref: ref %.4 = name_ref arr, file.%arr
-// CHECK:STDOUT:   %.loc5: %.5 = addr_of %arr.ref
-// CHECK:STDOUT:   %arr_p: %.5 = bind_name arr_p, %.loc5
+// CHECK:STDOUT:   %arr.ref: ref %.30 = name_ref arr, file.%arr
+// CHECK:STDOUT:   %.loc5: %.31 = addr_of %arr.ref
+// CHECK:STDOUT:   %arr_p: %.31 = bind_name arr_p, %.loc5
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 101 - 49
toolchain/check/testdata/builtins/int/right_shift.carbon

@@ -74,15 +74,22 @@ let negative: i32 = RightShift(1, Negate(1));
 // CHECK:STDOUT:   %.1: i32 = int_value 22 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %.3: i32 = int_value 5 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
-// CHECK:STDOUT:   %.5: type = ptr_type %.4 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.27: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.28: <bound method> = bound_method %.3, %Convert.15 [template]
+// CHECK:STDOUT:   %.29: Core.IntLiteral = int_value 5 [template]
+// CHECK:STDOUT:   %.30: type = array_type %.29, i32 [template]
+// CHECK:STDOUT:   %.31: type = ptr_type %.30 [template]
 // CHECK:STDOUT:   %RuntimeCall.type: type = fn_type @RuntimeCall [template]
 // CHECK:STDOUT:   %RuntimeCall: %RuntimeCall.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -128,15 +135,27 @@ let negative: i32 = RightShift(1, Negate(1));
 // CHECK:STDOUT:   %int.right_shift: init i32 = call %RightShift.ref(%.loc4_27, %.loc4_31) [template = constants.%.3]
 // CHECK:STDOUT:   %.loc4_11.1: type = value_of_initializer %int.make_type_32.loc4 [template = i32]
 // CHECK:STDOUT:   %.loc4_11.2: type = converted %int.make_type_32.loc4, %.loc4_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc4_33: type = array_type %int.right_shift, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %arr.var: ref %.4 = var arr
-// CHECK:STDOUT:   %arr: ref %.4 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc4_26.1: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc4_26.2: <bound method> = bound_method %int.right_shift, %.loc4_26.1 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_26.3: i32 = value_of_initializer %int.right_shift [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_26.4: i32 = converted %int.right_shift, %.loc4_26.3 [template = constants.%.3]
+// CHECK:STDOUT:   %int.convert_checked.loc4: init Core.IntLiteral = call %.loc4_26.2(%.loc4_26.4) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_26.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_26.6: Core.IntLiteral = converted %int.right_shift, %.loc4_26.5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_33: type = array_type %.loc4_26.6, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %arr.var: ref %.30 = var arr
+// CHECK:STDOUT:   %arr: ref %.30 = bind_name arr, %arr.var
 // CHECK:STDOUT:   %int.make_type_32.loc5: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc5_18: i32 = int_value 5 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc5_18.1: i32 = int_value 5 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc5_13.1: type = value_of_initializer %int.make_type_32.loc5 [template = i32]
 // CHECK:STDOUT:   %.loc5_13.2: type = converted %int.make_type_32.loc5, %.loc5_13.1 [template = i32]
-// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc5_18.2: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc5_18.3: <bound method> = bound_method %.loc5_18.1, %.loc5_18.2 [template = constants.%.28]
+// CHECK:STDOUT:   %int.convert_checked.loc5: init Core.IntLiteral = call %.loc5_18.3(%.loc5_18.1) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.5: Core.IntLiteral = converted %.loc5_18.1, %.loc5_18.4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18.5, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.30 [template = constants.%.31]
 // CHECK:STDOUT:   %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [template = constants.%RuntimeCall] {
 // CHECK:STDOUT:     %a.patt: i32 = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: i32 = value_param_pattern %a.patt, runtime_param0
@@ -178,9 +197,9 @@ let negative: i32 = RightShift(1, Negate(1));
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr.ref: ref %.4 = name_ref arr, file.%arr
-// CHECK:STDOUT:   %.loc5: %.5 = addr_of %arr.ref
-// CHECK:STDOUT:   %arr_p: %.5 = bind_name arr_p, %.loc5
+// CHECK:STDOUT:   %arr.ref: ref %.30 = name_ref arr, file.%arr
+// CHECK:STDOUT:   %.loc5: %.31 = addr_of %arr.ref
+// CHECK:STDOUT:   %arr_p: %.31 = bind_name arr_p, %.loc5
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -195,20 +214,29 @@ let negative: i32 = RightShift(1, Negate(1));
 // CHECK:STDOUT:   %Negate: %Negate.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 1 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value -1 [template]
-// CHECK:STDOUT:   %.3: type = array_type %.1, i32 [template]
-// CHECK:STDOUT:   %.4: type = ptr_type %.3 [template]
-// CHECK:STDOUT:   %.5: i32 = int_value 10 [template]
-// CHECK:STDOUT:   %.6: i32 = int_value -10 [template]
-// CHECK:STDOUT:   %.7: i32 = int_value 2 [template]
-// CHECK:STDOUT:   %.8: i32 = int_value -3 [template]
-// CHECK:STDOUT:   %.9: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.10: type = array_type %.9, i32 [template]
-// CHECK:STDOUT:   %.11: type = ptr_type %.10 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.26: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.27: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.28: Core.IntLiteral = int_value 1 [template]
+// CHECK:STDOUT:   %.29: type = array_type %.28, i32 [template]
+// CHECK:STDOUT:   %.30: type = ptr_type %.29 [template]
+// CHECK:STDOUT:   %.31: i32 = int_value 10 [template]
+// CHECK:STDOUT:   %.32: i32 = int_value -10 [template]
+// CHECK:STDOUT:   %.33: i32 = int_value 2 [template]
+// CHECK:STDOUT:   %.34: i32 = int_value -3 [template]
+// CHECK:STDOUT:   %.35: i32 = int_value 3 [template]
+// CHECK:STDOUT:   %.36: <bound method> = bound_method %.35, %Convert.15 [template]
+// CHECK:STDOUT:   %.37: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.38: type = array_type %.37, i32 [template]
+// CHECK:STDOUT:   %.39: type = ptr_type %.38 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -281,39 +309,63 @@ let negative: i32 = RightShift(1, Negate(1));
 // CHECK:STDOUT:   %int.snegate.loc10_23: init i32 = call %Negate.ref.loc10_17(%.loc10_34.2) [template = constants.%.1]
 // CHECK:STDOUT:   %.loc10_12.1: type = value_of_initializer %int.make_type_32.loc10 [template = i32]
 // CHECK:STDOUT:   %.loc10_12.2: type = converted %int.make_type_32.loc10, %.loc10_12.1 [template = i32]
-// CHECK:STDOUT:   %.loc10_49: type = array_type %int.snegate.loc10_23, i32 [template = constants.%.3]
-// CHECK:STDOUT:   %arr1.var: ref %.3 = var arr1
-// CHECK:STDOUT:   %arr1: ref %.3 = bind_name arr1, %arr1.var
+// CHECK:STDOUT:   %.loc10_23.1: %Convert.type.2 = interface_witness_access constants.%.26, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc10_23.2: <bound method> = bound_method %int.snegate.loc10_23, %.loc10_23.1 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc10_23.3: i32 = value_of_initializer %int.snegate.loc10_23 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc10_23.4: i32 = converted %int.snegate.loc10_23, %.loc10_23.3 [template = constants.%.1]
+// CHECK:STDOUT:   %int.convert_checked.loc10: init Core.IntLiteral = call %.loc10_23.2(%.loc10_23.4) [template = constants.%.28]
+// CHECK:STDOUT:   %.loc10_23.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc10 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc10_23.6: Core.IntLiteral = converted %int.snegate.loc10_23, %.loc10_23.5 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc10_49: type = array_type %.loc10_23.6, i32 [template = constants.%.29]
+// CHECK:STDOUT:   %arr1.var: ref %.29 = var arr1
+// CHECK:STDOUT:   %arr1: ref %.29 = bind_name arr1, %arr1.var
 // CHECK:STDOUT:   %int.make_type_32.loc11: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc11_19: i32 = int_value 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc11_19.1: i32 = int_value 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc11_14.1: type = value_of_initializer %int.make_type_32.loc11 [template = i32]
 // CHECK:STDOUT:   %.loc11_14.2: type = converted %int.make_type_32.loc11, %.loc11_14.1 [template = i32]
-// CHECK:STDOUT:   %.loc11_20: type = array_type %.loc11_19, i32 [template = constants.%.3]
-// CHECK:STDOUT:   %.loc11_21: type = ptr_type %.3 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc11_19.2: %Convert.type.2 = interface_witness_access constants.%.26, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc11_19.3: <bound method> = bound_method %.loc11_19.1, %.loc11_19.2 [template = constants.%.27]
+// CHECK:STDOUT:   %int.convert_checked.loc11: init Core.IntLiteral = call %.loc11_19.3(%.loc11_19.1) [template = constants.%.28]
+// CHECK:STDOUT:   %.loc11_19.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc11 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc11_19.5: Core.IntLiteral = converted %.loc11_19.1, %.loc11_19.4 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc11_20: type = array_type %.loc11_19.5, i32 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc11_21: type = ptr_type %.29 [template = constants.%.30]
 // CHECK:STDOUT:   %int.make_type_32.loc14: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %Negate.ref.loc14_17: %Negate.type = name_ref Negate, %Negate.decl [template = constants.%Negate]
 // CHECK:STDOUT:   %RightShift.ref.loc14: %RightShift.type = name_ref RightShift, %RightShift.decl [template = constants.%RightShift]
 // CHECK:STDOUT:   %Negate.ref.loc14_35: %Negate.type = name_ref Negate, %Negate.decl [template = constants.%Negate]
-// CHECK:STDOUT:   %.loc14_42: i32 = int_value 10 [template = constants.%.5]
-// CHECK:STDOUT:   %int.snegate.loc14_41: init i32 = call %Negate.ref.loc14_35(%.loc14_42) [template = constants.%.6]
-// CHECK:STDOUT:   %.loc14_47: i32 = int_value 2 [template = constants.%.7]
-// CHECK:STDOUT:   %.loc14_41.1: i32 = value_of_initializer %int.snegate.loc14_41 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc14_41.2: i32 = converted %int.snegate.loc14_41, %.loc14_41.1 [template = constants.%.6]
-// CHECK:STDOUT:   %int.right_shift.loc14: init i32 = call %RightShift.ref.loc14(%.loc14_41.2, %.loc14_47) [template = constants.%.8]
-// CHECK:STDOUT:   %.loc14_34.1: i32 = value_of_initializer %int.right_shift.loc14 [template = constants.%.8]
-// CHECK:STDOUT:   %.loc14_34.2: i32 = converted %int.right_shift.loc14, %.loc14_34.1 [template = constants.%.8]
-// CHECK:STDOUT:   %int.snegate.loc14_23: init i32 = call %Negate.ref.loc14_17(%.loc14_34.2) [template = constants.%.9]
+// CHECK:STDOUT:   %.loc14_42: i32 = int_value 10 [template = constants.%.31]
+// CHECK:STDOUT:   %int.snegate.loc14_41: init i32 = call %Negate.ref.loc14_35(%.loc14_42) [template = constants.%.32]
+// CHECK:STDOUT:   %.loc14_47: i32 = int_value 2 [template = constants.%.33]
+// CHECK:STDOUT:   %.loc14_41.1: i32 = value_of_initializer %int.snegate.loc14_41 [template = constants.%.32]
+// CHECK:STDOUT:   %.loc14_41.2: i32 = converted %int.snegate.loc14_41, %.loc14_41.1 [template = constants.%.32]
+// CHECK:STDOUT:   %int.right_shift.loc14: init i32 = call %RightShift.ref.loc14(%.loc14_41.2, %.loc14_47) [template = constants.%.34]
+// CHECK:STDOUT:   %.loc14_34.1: i32 = value_of_initializer %int.right_shift.loc14 [template = constants.%.34]
+// CHECK:STDOUT:   %.loc14_34.2: i32 = converted %int.right_shift.loc14, %.loc14_34.1 [template = constants.%.34]
+// CHECK:STDOUT:   %int.snegate.loc14_23: init i32 = call %Negate.ref.loc14_17(%.loc14_34.2) [template = constants.%.35]
 // CHECK:STDOUT:   %.loc14_12.1: type = value_of_initializer %int.make_type_32.loc14 [template = i32]
 // CHECK:STDOUT:   %.loc14_12.2: type = converted %int.make_type_32.loc14, %.loc14_12.1 [template = i32]
-// CHECK:STDOUT:   %.loc14_50: type = array_type %int.snegate.loc14_23, i32 [template = constants.%.10]
-// CHECK:STDOUT:   %arr2.var: ref %.10 = var arr2
-// CHECK:STDOUT:   %arr2: ref %.10 = bind_name arr2, %arr2.var
+// CHECK:STDOUT:   %.loc14_23.1: %Convert.type.2 = interface_witness_access constants.%.26, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc14_23.2: <bound method> = bound_method %int.snegate.loc14_23, %.loc14_23.1 [template = constants.%.36]
+// CHECK:STDOUT:   %.loc14_23.3: i32 = value_of_initializer %int.snegate.loc14_23 [template = constants.%.35]
+// CHECK:STDOUT:   %.loc14_23.4: i32 = converted %int.snegate.loc14_23, %.loc14_23.3 [template = constants.%.35]
+// CHECK:STDOUT:   %int.convert_checked.loc14: init Core.IntLiteral = call %.loc14_23.2(%.loc14_23.4) [template = constants.%.37]
+// CHECK:STDOUT:   %.loc14_23.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc14 [template = constants.%.37]
+// CHECK:STDOUT:   %.loc14_23.6: Core.IntLiteral = converted %int.snegate.loc14_23, %.loc14_23.5 [template = constants.%.37]
+// CHECK:STDOUT:   %.loc14_50: type = array_type %.loc14_23.6, i32 [template = constants.%.38]
+// CHECK:STDOUT:   %arr2.var: ref %.38 = var arr2
+// CHECK:STDOUT:   %arr2: ref %.38 = bind_name arr2, %arr2.var
 // CHECK:STDOUT:   %int.make_type_32.loc15: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc15_19: i32 = int_value 3 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc15_19.1: i32 = int_value 3 [template = constants.%.35]
 // CHECK:STDOUT:   %.loc15_14.1: type = value_of_initializer %int.make_type_32.loc15 [template = i32]
 // CHECK:STDOUT:   %.loc15_14.2: type = converted %int.make_type_32.loc15, %.loc15_14.1 [template = i32]
-// CHECK:STDOUT:   %.loc15_20: type = array_type %.loc15_19, i32 [template = constants.%.10]
-// CHECK:STDOUT:   %.loc15_21: type = ptr_type %.10 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc15_19.2: %Convert.type.2 = interface_witness_access constants.%.26, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc15_19.3: <bound method> = bound_method %.loc15_19.1, %.loc15_19.2 [template = constants.%.36]
+// CHECK:STDOUT:   %int.convert_checked.loc15: init Core.IntLiteral = call %.loc15_19.3(%.loc15_19.1) [template = constants.%.37]
+// CHECK:STDOUT:   %.loc15_19.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc15 [template = constants.%.37]
+// CHECK:STDOUT:   %.loc15_19.5: Core.IntLiteral = converted %.loc15_19.1, %.loc15_19.4 [template = constants.%.37]
+// CHECK:STDOUT:   %.loc15_20: type = array_type %.loc15_19.5, i32 [template = constants.%.38]
+// CHECK:STDOUT:   %.loc15_21: type = ptr_type %.38 [template = constants.%.39]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @RightShift(%a.param_patt: i32, %b.param_patt: i32) -> i32 = "int.right_shift";
@@ -322,12 +374,12 @@ let negative: i32 = RightShift(1, Negate(1));
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr1.ref: ref %.3 = name_ref arr1, file.%arr1
-// CHECK:STDOUT:   %.loc11: %.4 = addr_of %arr1.ref
-// CHECK:STDOUT:   %arr1_p: %.4 = bind_name arr1_p, %.loc11
-// CHECK:STDOUT:   %arr2.ref: ref %.10 = name_ref arr2, file.%arr2
-// CHECK:STDOUT:   %.loc15: %.11 = addr_of %arr2.ref
-// CHECK:STDOUT:   %arr2_p: %.11 = bind_name arr2_p, %.loc15
+// CHECK:STDOUT:   %arr1.ref: ref %.29 = name_ref arr1, file.%arr1
+// CHECK:STDOUT:   %.loc11: %.30 = addr_of %arr1.ref
+// CHECK:STDOUT:   %arr1_p: %.30 = bind_name arr1_p, %.loc11
+// CHECK:STDOUT:   %arr2.ref: ref %.38 = name_ref arr2, file.%arr2
+// CHECK:STDOUT:   %.loc15: %.39 = addr_of %arr2.ref
+// CHECK:STDOUT:   %arr2_p: %.39 = bind_name arr2_p, %.loc15
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 39 - 14
toolchain/check/testdata/builtins/int/sadd.carbon

@@ -99,15 +99,22 @@ let b: i32 = Add(0x7FFFFFFF, 1);
 // CHECK:STDOUT:   %.1: i32 = int_value 1 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %.3: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
-// CHECK:STDOUT:   %.5: type = ptr_type %.4 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.27: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.28: <bound method> = bound_method %.3, %Convert.15 [template]
+// CHECK:STDOUT:   %.29: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.30: type = array_type %.29, i32 [template]
+// CHECK:STDOUT:   %.31: type = ptr_type %.30 [template]
 // CHECK:STDOUT:   %RuntimeCall.type: type = fn_type @RuntimeCall [template]
 // CHECK:STDOUT:   %RuntimeCall: %RuntimeCall.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -153,15 +160,27 @@ let b: i32 = Add(0x7FFFFFFF, 1);
 // CHECK:STDOUT:   %int.sadd: init i32 = call %Add.ref(%.loc4_20, %.loc4_23) [template = constants.%.3]
 // CHECK:STDOUT:   %.loc4_11.1: type = value_of_initializer %int.make_type_32.loc4 [template = i32]
 // CHECK:STDOUT:   %.loc4_11.2: type = converted %int.make_type_32.loc4, %.loc4_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc4_25: type = array_type %int.sadd, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %arr.var: ref %.4 = var arr
-// CHECK:STDOUT:   %arr: ref %.4 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc4_19.1: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc4_19.2: <bound method> = bound_method %int.sadd, %.loc4_19.1 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_19.3: i32 = value_of_initializer %int.sadd [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_19.4: i32 = converted %int.sadd, %.loc4_19.3 [template = constants.%.3]
+// CHECK:STDOUT:   %int.convert_checked.loc4: init Core.IntLiteral = call %.loc4_19.2(%.loc4_19.4) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.6: Core.IntLiteral = converted %int.sadd, %.loc4_19.5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_25: type = array_type %.loc4_19.6, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %arr.var: ref %.30 = var arr
+// CHECK:STDOUT:   %arr: ref %.30 = bind_name arr, %arr.var
 // CHECK:STDOUT:   %int.make_type_32.loc5: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc5_18: i32 = int_value 3 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc5_18.1: i32 = int_value 3 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc5_13.1: type = value_of_initializer %int.make_type_32.loc5 [template = i32]
 // CHECK:STDOUT:   %.loc5_13.2: type = converted %int.make_type_32.loc5, %.loc5_13.1 [template = i32]
-// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc5_18.2: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc5_18.3: <bound method> = bound_method %.loc5_18.1, %.loc5_18.2 [template = constants.%.28]
+// CHECK:STDOUT:   %int.convert_checked.loc5: init Core.IntLiteral = call %.loc5_18.3(%.loc5_18.1) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.5: Core.IntLiteral = converted %.loc5_18.1, %.loc5_18.4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18.5, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.30 [template = constants.%.31]
 // CHECK:STDOUT:   %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [template = constants.%RuntimeCall] {
 // CHECK:STDOUT:     %a.patt: i32 = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: i32 = value_param_pattern %a.patt, runtime_param0
@@ -203,9 +222,9 @@ let b: i32 = Add(0x7FFFFFFF, 1);
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr.ref: ref %.4 = name_ref arr, file.%arr
-// CHECK:STDOUT:   %.loc5: %.5 = addr_of %arr.ref
-// CHECK:STDOUT:   %arr_p: %.5 = bind_name arr_p, %.loc5
+// CHECK:STDOUT:   %arr.ref: ref %.30 = name_ref arr, file.%arr
+// CHECK:STDOUT:   %.loc5: %.31 = addr_of %arr.ref
+// CHECK:STDOUT:   %arr_p: %.31 = bind_name arr_p, %.loc5
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -358,8 +377,10 @@ let b: i32 = Add(0x7FFFFFFF, 1);
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %int.make_type_32.loc25: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %TooFew.ref: %TooFew.type = name_ref TooFew, %TooFew.decl [template = constants.%TooFew]
-// CHECK:STDOUT:   %.loc25: i32 = int_value 1 [template = constants.%.1]
-// CHECK:STDOUT:   %TooFew.call: init i32 = call %TooFew.ref(%.loc25)
+// CHECK:STDOUT:   %.loc25_27: i32 = int_value 1 [template = constants.%.1]
+// CHECK:STDOUT:   %TooFew.call: init i32 = call %TooFew.ref(%.loc25_27)
+// CHECK:STDOUT:   %.loc25_15.1: type = value_of_initializer %int.make_type_32.loc25 [template = i32]
+// CHECK:STDOUT:   %.loc25_15.2: type = converted %int.make_type_32.loc25, %.loc25_15.1 [template = i32]
 // CHECK:STDOUT:   %too_few.var: ref <error> = var too_few
 // CHECK:STDOUT:   %too_few: ref <error> = bind_name too_few, %too_few.var
 // CHECK:STDOUT:   %int.make_type_32.loc30: init type = call constants.%Int32() [template = i32]
@@ -368,6 +389,8 @@ let b: i32 = Add(0x7FFFFFFF, 1);
 // CHECK:STDOUT:   %.loc30_32: i32 = int_value 2 [template = constants.%.2]
 // CHECK:STDOUT:   %.loc30_35: i32 = int_value 3 [template = constants.%.3]
 // CHECK:STDOUT:   %TooMany.call: init i32 = call %TooMany.ref(%.loc30_29, %.loc30_32, %.loc30_35)
+// CHECK:STDOUT:   %.loc30_16.1: type = value_of_initializer %int.make_type_32.loc30 [template = i32]
+// CHECK:STDOUT:   %.loc30_16.2: type = converted %int.make_type_32.loc30, %.loc30_16.1 [template = i32]
 // CHECK:STDOUT:   %too_many.var: ref <error> = var too_many
 // CHECK:STDOUT:   %too_many: ref <error> = bind_name too_many, %too_many.var
 // CHECK:STDOUT:   %int.make_type_32.loc35: init type = call constants.%Int32() [template = i32]
@@ -375,6 +398,8 @@ let b: i32 = Add(0x7FFFFFFF, 1);
 // CHECK:STDOUT:   %.loc35_42: i32 = int_value 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc35_45: i32 = int_value 2 [template = constants.%.2]
 // CHECK:STDOUT:   %BadReturnType.call: init bool = call %BadReturnType.ref(%.loc35_42, %.loc35_45)
+// CHECK:STDOUT:   %.loc35_23.1: type = value_of_initializer %int.make_type_32.loc35 [template = i32]
+// CHECK:STDOUT:   %.loc35_23.2: type = converted %int.make_type_32.loc35, %.loc35_23.1 [template = i32]
 // CHECK:STDOUT:   %bad_return_type.var: ref <error> = var bad_return_type
 // CHECK:STDOUT:   %bad_return_type: ref <error> = bind_name bad_return_type, %bad_return_type.var
 // CHECK:STDOUT:   %int.make_type_32.loc44: init type = call constants.%Int32() [template = i32]

+ 31 - 12
toolchain/check/testdata/builtins/int/sdiv.carbon

@@ -67,15 +67,22 @@ let b: i32 = Div(0, 0);
 // CHECK:STDOUT:   %.1: i32 = int_value 3 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %.3: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
-// CHECK:STDOUT:   %.5: type = ptr_type %.4 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.27: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.28: <bound method> = bound_method %.3, %Convert.15 [template]
+// CHECK:STDOUT:   %.29: Core.IntLiteral = int_value 1 [template]
+// CHECK:STDOUT:   %.30: type = array_type %.29, i32 [template]
+// CHECK:STDOUT:   %.31: type = ptr_type %.30 [template]
 // CHECK:STDOUT:   %RuntimeCall.type: type = fn_type @RuntimeCall [template]
 // CHECK:STDOUT:   %RuntimeCall: %RuntimeCall.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -121,15 +128,27 @@ let b: i32 = Div(0, 0);
 // CHECK:STDOUT:   %int.sdiv: init i32 = call %Div.ref(%.loc4_20, %.loc4_23) [template = constants.%.3]
 // CHECK:STDOUT:   %.loc4_11.1: type = value_of_initializer %int.make_type_32.loc4 [template = i32]
 // CHECK:STDOUT:   %.loc4_11.2: type = converted %int.make_type_32.loc4, %.loc4_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc4_25: type = array_type %int.sdiv, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %arr.var: ref %.4 = var arr
-// CHECK:STDOUT:   %arr: ref %.4 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc4_19.1: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc4_19.2: <bound method> = bound_method %int.sdiv, %.loc4_19.1 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_19.3: i32 = value_of_initializer %int.sdiv [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_19.4: i32 = converted %int.sdiv, %.loc4_19.3 [template = constants.%.3]
+// CHECK:STDOUT:   %int.convert_checked.loc4: init Core.IntLiteral = call %.loc4_19.2(%.loc4_19.4) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.6: Core.IntLiteral = converted %int.sdiv, %.loc4_19.5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_25: type = array_type %.loc4_19.6, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %arr.var: ref %.30 = var arr
+// CHECK:STDOUT:   %arr: ref %.30 = bind_name arr, %arr.var
 // CHECK:STDOUT:   %int.make_type_32.loc5: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc5_18: i32 = int_value 1 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc5_18.1: i32 = int_value 1 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc5_13.1: type = value_of_initializer %int.make_type_32.loc5 [template = i32]
 // CHECK:STDOUT:   %.loc5_13.2: type = converted %int.make_type_32.loc5, %.loc5_13.1 [template = i32]
-// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc5_18.2: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc5_18.3: <bound method> = bound_method %.loc5_18.1, %.loc5_18.2 [template = constants.%.28]
+// CHECK:STDOUT:   %int.convert_checked.loc5: init Core.IntLiteral = call %.loc5_18.3(%.loc5_18.1) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.5: Core.IntLiteral = converted %.loc5_18.1, %.loc5_18.4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18.5, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.30 [template = constants.%.31]
 // CHECK:STDOUT:   %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [template = constants.%RuntimeCall] {
 // CHECK:STDOUT:     %a.patt: i32 = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: i32 = value_param_pattern %a.patt, runtime_param0
@@ -171,9 +190,9 @@ let b: i32 = Div(0, 0);
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr.ref: ref %.4 = name_ref arr, file.%arr
-// CHECK:STDOUT:   %.loc5: %.5 = addr_of %arr.ref
-// CHECK:STDOUT:   %arr_p: %.5 = bind_name arr_p, %.loc5
+// CHECK:STDOUT:   %arr.ref: ref %.30 = name_ref arr, file.%arr
+// CHECK:STDOUT:   %.loc5: %.31 = addr_of %arr.ref
+// CHECK:STDOUT:   %arr_p: %.31 = bind_name arr_p, %.loc5
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 31 - 12
toolchain/check/testdata/builtins/int/smod.carbon

@@ -70,15 +70,22 @@ let b: i32 = Mod(0, 0);
 // CHECK:STDOUT:   %.1: i32 = int_value 5 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value 3 [template]
 // CHECK:STDOUT:   %.3: i32 = int_value 2 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
-// CHECK:STDOUT:   %.5: type = ptr_type %.4 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.27: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.28: <bound method> = bound_method %.3, %Convert.15 [template]
+// CHECK:STDOUT:   %.29: Core.IntLiteral = int_value 2 [template]
+// CHECK:STDOUT:   %.30: type = array_type %.29, i32 [template]
+// CHECK:STDOUT:   %.31: type = ptr_type %.30 [template]
 // CHECK:STDOUT:   %RuntimeCall.type: type = fn_type @RuntimeCall [template]
 // CHECK:STDOUT:   %RuntimeCall: %RuntimeCall.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -124,15 +131,27 @@ let b: i32 = Mod(0, 0);
 // CHECK:STDOUT:   %int.smod: init i32 = call %Mod.ref(%.loc4_20, %.loc4_23) [template = constants.%.3]
 // CHECK:STDOUT:   %.loc4_11.1: type = value_of_initializer %int.make_type_32.loc4 [template = i32]
 // CHECK:STDOUT:   %.loc4_11.2: type = converted %int.make_type_32.loc4, %.loc4_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc4_25: type = array_type %int.smod, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %arr.var: ref %.4 = var arr
-// CHECK:STDOUT:   %arr: ref %.4 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc4_19.1: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc4_19.2: <bound method> = bound_method %int.smod, %.loc4_19.1 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_19.3: i32 = value_of_initializer %int.smod [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_19.4: i32 = converted %int.smod, %.loc4_19.3 [template = constants.%.3]
+// CHECK:STDOUT:   %int.convert_checked.loc4: init Core.IntLiteral = call %.loc4_19.2(%.loc4_19.4) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.6: Core.IntLiteral = converted %int.smod, %.loc4_19.5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_25: type = array_type %.loc4_19.6, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %arr.var: ref %.30 = var arr
+// CHECK:STDOUT:   %arr: ref %.30 = bind_name arr, %arr.var
 // CHECK:STDOUT:   %int.make_type_32.loc5: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc5_18: i32 = int_value 2 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc5_18.1: i32 = int_value 2 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc5_13.1: type = value_of_initializer %int.make_type_32.loc5 [template = i32]
 // CHECK:STDOUT:   %.loc5_13.2: type = converted %int.make_type_32.loc5, %.loc5_13.1 [template = i32]
-// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc5_18.2: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc5_18.3: <bound method> = bound_method %.loc5_18.1, %.loc5_18.2 [template = constants.%.28]
+// CHECK:STDOUT:   %int.convert_checked.loc5: init Core.IntLiteral = call %.loc5_18.3(%.loc5_18.1) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.5: Core.IntLiteral = converted %.loc5_18.1, %.loc5_18.4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18.5, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.30 [template = constants.%.31]
 // CHECK:STDOUT:   %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [template = constants.%RuntimeCall] {
 // CHECK:STDOUT:     %a.patt: i32 = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: i32 = value_param_pattern %a.patt, runtime_param0
@@ -174,9 +193,9 @@ let b: i32 = Mod(0, 0);
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr.ref: ref %.4 = name_ref arr, file.%arr
-// CHECK:STDOUT:   %.loc5: %.5 = addr_of %arr.ref
-// CHECK:STDOUT:   %arr_p: %.5 = bind_name arr_p, %.loc5
+// CHECK:STDOUT:   %arr.ref: ref %.30 = name_ref arr, file.%arr
+// CHECK:STDOUT:   %.loc5: %.31 = addr_of %arr.ref
+// CHECK:STDOUT:   %arr_p: %.31 = bind_name arr_p, %.loc5
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 31 - 12
toolchain/check/testdata/builtins/int/smul.carbon

@@ -41,15 +41,22 @@ let b: i32 = Mul(0x8000, 0x10000);
 // CHECK:STDOUT:   %.1: i32 = int_value 3 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %.3: i32 = int_value 6 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
-// CHECK:STDOUT:   %.5: type = ptr_type %.4 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.27: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.28: <bound method> = bound_method %.3, %Convert.15 [template]
+// CHECK:STDOUT:   %.29: Core.IntLiteral = int_value 6 [template]
+// CHECK:STDOUT:   %.30: type = array_type %.29, i32 [template]
+// CHECK:STDOUT:   %.31: type = ptr_type %.30 [template]
 // CHECK:STDOUT:   %RuntimeCall.type: type = fn_type @RuntimeCall [template]
 // CHECK:STDOUT:   %RuntimeCall: %RuntimeCall.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -95,15 +102,27 @@ let b: i32 = Mul(0x8000, 0x10000);
 // CHECK:STDOUT:   %int.smul: init i32 = call %Mul.ref(%.loc4_20, %.loc4_23) [template = constants.%.3]
 // CHECK:STDOUT:   %.loc4_11.1: type = value_of_initializer %int.make_type_32.loc4 [template = i32]
 // CHECK:STDOUT:   %.loc4_11.2: type = converted %int.make_type_32.loc4, %.loc4_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc4_25: type = array_type %int.smul, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %arr.var: ref %.4 = var arr
-// CHECK:STDOUT:   %arr: ref %.4 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc4_19.1: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc4_19.2: <bound method> = bound_method %int.smul, %.loc4_19.1 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_19.3: i32 = value_of_initializer %int.smul [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_19.4: i32 = converted %int.smul, %.loc4_19.3 [template = constants.%.3]
+// CHECK:STDOUT:   %int.convert_checked.loc4: init Core.IntLiteral = call %.loc4_19.2(%.loc4_19.4) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.6: Core.IntLiteral = converted %int.smul, %.loc4_19.5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_25: type = array_type %.loc4_19.6, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %arr.var: ref %.30 = var arr
+// CHECK:STDOUT:   %arr: ref %.30 = bind_name arr, %arr.var
 // CHECK:STDOUT:   %int.make_type_32.loc5: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc5_18: i32 = int_value 6 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc5_18.1: i32 = int_value 6 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc5_13.1: type = value_of_initializer %int.make_type_32.loc5 [template = i32]
 // CHECK:STDOUT:   %.loc5_13.2: type = converted %int.make_type_32.loc5, %.loc5_13.1 [template = i32]
-// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc5_18.2: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc5_18.3: <bound method> = bound_method %.loc5_18.1, %.loc5_18.2 [template = constants.%.28]
+// CHECK:STDOUT:   %int.convert_checked.loc5: init Core.IntLiteral = call %.loc5_18.3(%.loc5_18.1) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.5: Core.IntLiteral = converted %.loc5_18.1, %.loc5_18.4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18.5, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.30 [template = constants.%.31]
 // CHECK:STDOUT:   %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [template = constants.%RuntimeCall] {
 // CHECK:STDOUT:     %a.patt: i32 = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: i32 = value_param_pattern %a.patt, runtime_param0
@@ -145,9 +164,9 @@ let b: i32 = Mul(0x8000, 0x10000);
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr.ref: ref %.4 = name_ref arr, file.%arr
-// CHECK:STDOUT:   %.loc5: %.5 = addr_of %arr.ref
-// CHECK:STDOUT:   %arr_p: %.5 = bind_name arr_p, %.loc5
+// CHECK:STDOUT:   %arr.ref: ref %.30 = name_ref arr, file.%arr
+// CHECK:STDOUT:   %.loc5: %.31 = addr_of %arr.ref
+// CHECK:STDOUT:   %arr_p: %.31 = bind_name arr_p, %.loc5
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 45 - 20
toolchain/check/testdata/builtins/int/snegate.carbon

@@ -125,17 +125,24 @@ let b: i32 = Negate(Sub(Negate(0x7FFFFFFF), 1));
 // CHECK:STDOUT:   %Negate: %Negate.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 123 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value -123 [template]
-// CHECK:STDOUT:   %.3: type = array_type %.1, i32 [template]
-// CHECK:STDOUT:   %.4: type = ptr_type %.3 [template]
-// CHECK:STDOUT:   %.5: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.6: i32 = int_value -1 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.26: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.27: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.28: Core.IntLiteral = int_value 123 [template]
+// CHECK:STDOUT:   %.29: type = array_type %.28, i32 [template]
+// CHECK:STDOUT:   %.30: type = ptr_type %.29 [template]
+// CHECK:STDOUT:   %.31: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %.32: i32 = int_value -1 [template]
 // CHECK:STDOUT:   %RuntimeCall.type: type = fn_type @RuntimeCall [template]
 // CHECK:STDOUT:   %RuntimeCall: %RuntimeCall.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -178,15 +185,27 @@ let b: i32 = Negate(Sub(Negate(0x7FFFFFFF), 1));
 // CHECK:STDOUT:   %int.snegate.loc4_22: init i32 = call %Negate.ref.loc4_16(%.loc4_29.2) [template = constants.%.1]
 // CHECK:STDOUT:   %.loc4_11.1: type = value_of_initializer %int.make_type_32.loc4 [template = i32]
 // CHECK:STDOUT:   %.loc4_11.2: type = converted %int.make_type_32.loc4, %.loc4_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc4_35: type = array_type %int.snegate.loc4_22, i32 [template = constants.%.3]
-// CHECK:STDOUT:   %arr.var: ref %.3 = var arr
-// CHECK:STDOUT:   %arr: ref %.3 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc4_22.1: %Convert.type.2 = interface_witness_access constants.%.26, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc4_22.2: <bound method> = bound_method %int.snegate.loc4_22, %.loc4_22.1 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc4_22.3: i32 = value_of_initializer %int.snegate.loc4_22 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc4_22.4: i32 = converted %int.snegate.loc4_22, %.loc4_22.3 [template = constants.%.1]
+// CHECK:STDOUT:   %int.convert_checked.loc4: init Core.IntLiteral = call %.loc4_22.2(%.loc4_22.4) [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_22.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc4 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_22.6: Core.IntLiteral = converted %int.snegate.loc4_22, %.loc4_22.5 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_35: type = array_type %.loc4_22.6, i32 [template = constants.%.29]
+// CHECK:STDOUT:   %arr.var: ref %.29 = var arr
+// CHECK:STDOUT:   %arr: ref %.29 = bind_name arr, %arr.var
 // CHECK:STDOUT:   %int.make_type_32.loc5: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc5_18: i32 = int_value 123 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc5_18.1: i32 = int_value 123 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc5_13.1: type = value_of_initializer %int.make_type_32.loc5 [template = i32]
 // CHECK:STDOUT:   %.loc5_13.2: type = converted %int.make_type_32.loc5, %.loc5_13.1 [template = i32]
-// CHECK:STDOUT:   %.loc5_21: type = array_type %.loc5_18, i32 [template = constants.%.3]
-// CHECK:STDOUT:   %.loc5_22: type = ptr_type %.3 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc5_18.2: %Convert.type.2 = interface_witness_access constants.%.26, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc5_18.3: <bound method> = bound_method %.loc5_18.1, %.loc5_18.2 [template = constants.%.27]
+// CHECK:STDOUT:   %int.convert_checked.loc5: init Core.IntLiteral = call %.loc5_18.3(%.loc5_18.1) [template = constants.%.28]
+// CHECK:STDOUT:   %.loc5_18.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc5 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc5_18.5: Core.IntLiteral = converted %.loc5_18.1, %.loc5_18.4 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc5_21: type = array_type %.loc5_18.5, i32 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_22: type = ptr_type %.29 [template = constants.%.30]
 // CHECK:STDOUT:   %int.make_type_32.loc7: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc7_8.1: type = value_of_initializer %int.make_type_32.loc7 [template = i32]
 // CHECK:STDOUT:   %.loc7_8.2: type = converted %int.make_type_32.loc7, %.loc7_8.1 [template = i32]
@@ -230,14 +249,14 @@ let b: i32 = Negate(Sub(Negate(0x7FFFFFFF), 1));
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr.ref: ref %.3 = name_ref arr, file.%arr
-// CHECK:STDOUT:   %.loc5: %.4 = addr_of %arr.ref
-// CHECK:STDOUT:   %arr_p: %.4 = bind_name arr_p, %.loc5
+// CHECK:STDOUT:   %arr.ref: ref %.29 = name_ref arr, file.%arr
+// CHECK:STDOUT:   %.loc5: %.30 = addr_of %arr.ref
+// CHECK:STDOUT:   %arr_p: %.30 = bind_name arr_p, %.loc5
 // CHECK:STDOUT:   %Negate.ref: %Negate.type = name_ref Negate, file.%Negate.decl [template = constants.%Negate]
-// CHECK:STDOUT:   %.loc7_21: i32 = int_value 1 [template = constants.%.5]
-// CHECK:STDOUT:   %int.snegate: init i32 = call %Negate.ref(%.loc7_21) [template = constants.%.6]
-// CHECK:STDOUT:   %.loc7_23.1: i32 = value_of_initializer %int.snegate [template = constants.%.6]
-// CHECK:STDOUT:   %.loc7_23.2: i32 = converted %int.snegate, %.loc7_23.1 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc7_21: i32 = int_value 1 [template = constants.%.31]
+// CHECK:STDOUT:   %int.snegate: init i32 = call %Negate.ref(%.loc7_21) [template = constants.%.32]
+// CHECK:STDOUT:   %.loc7_23.1: i32 = value_of_initializer %int.snegate [template = constants.%.32]
+// CHECK:STDOUT:   %.loc7_23.2: i32 = converted %int.snegate, %.loc7_23.1 [template = constants.%.32]
 // CHECK:STDOUT:   %n: i32 = bind_name n, %.loc7_23.2
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
@@ -363,6 +382,8 @@ let b: i32 = Negate(Sub(Negate(0x7FFFFFFF), 1));
 // CHECK:STDOUT:   %int.make_type_32.loc25: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %TooFew.ref: %TooFew.type = name_ref TooFew, %TooFew.decl [template = constants.%TooFew]
 // CHECK:STDOUT:   %TooFew.call: init i32 = call %TooFew.ref()
+// CHECK:STDOUT:   %.loc25_15.1: type = value_of_initializer %int.make_type_32.loc25 [template = i32]
+// CHECK:STDOUT:   %.loc25_15.2: type = converted %int.make_type_32.loc25, %.loc25_15.1 [template = i32]
 // CHECK:STDOUT:   %too_few.var: ref <error> = var too_few
 // CHECK:STDOUT:   %too_few: ref <error> = bind_name too_few, %too_few.var
 // CHECK:STDOUT:   %int.make_type_32.loc30: init type = call constants.%Int32() [template = i32]
@@ -370,12 +391,16 @@ let b: i32 = Negate(Sub(Negate(0x7FFFFFFF), 1));
 // CHECK:STDOUT:   %.loc30_29: i32 = int_value 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc30_32: i32 = int_value 2 [template = constants.%.2]
 // CHECK:STDOUT:   %TooMany.call: init i32 = call %TooMany.ref(%.loc30_29, %.loc30_32)
+// CHECK:STDOUT:   %.loc30_16.1: type = value_of_initializer %int.make_type_32.loc30 [template = i32]
+// CHECK:STDOUT:   %.loc30_16.2: type = converted %int.make_type_32.loc30, %.loc30_16.1 [template = i32]
 // CHECK:STDOUT:   %too_many.var: ref <error> = var too_many
 // CHECK:STDOUT:   %too_many: ref <error> = bind_name too_many, %too_many.var
 // CHECK:STDOUT:   %int.make_type_32.loc35: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %BadReturnType.ref: %BadReturnType.type = name_ref BadReturnType, %BadReturnType.decl [template = constants.%BadReturnType]
-// CHECK:STDOUT:   %.loc35: i32 = int_value 1 [template = constants.%.1]
-// CHECK:STDOUT:   %BadReturnType.call: init bool = call %BadReturnType.ref(%.loc35)
+// CHECK:STDOUT:   %.loc35_42: i32 = int_value 1 [template = constants.%.1]
+// CHECK:STDOUT:   %BadReturnType.call: init bool = call %BadReturnType.ref(%.loc35_42)
+// CHECK:STDOUT:   %.loc35_23.1: type = value_of_initializer %int.make_type_32.loc35 [template = i32]
+// CHECK:STDOUT:   %.loc35_23.2: type = converted %int.make_type_32.loc35, %.loc35_23.1 [template = i32]
 // CHECK:STDOUT:   %bad_return_type.var: ref <error> = var bad_return_type
 // CHECK:STDOUT:   %bad_return_type: ref <error> = bind_name bad_return_type, %bad_return_type.var
 // CHECK:STDOUT:   %int.make_type_32.loc44: init type = call constants.%Int32() [template = i32]

+ 31 - 12
toolchain/check/testdata/builtins/int/ssub.carbon

@@ -42,15 +42,22 @@ let c: i32 = Sub(Sub(0, 0x7FFFFFFF), 2);
 // CHECK:STDOUT:   %.1: i32 = int_value 3 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %.3: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
-// CHECK:STDOUT:   %.5: type = ptr_type %.4 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.27: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.28: <bound method> = bound_method %.3, %Convert.15 [template]
+// CHECK:STDOUT:   %.29: Core.IntLiteral = int_value 1 [template]
+// CHECK:STDOUT:   %.30: type = array_type %.29, i32 [template]
+// CHECK:STDOUT:   %.31: type = ptr_type %.30 [template]
 // CHECK:STDOUT:   %RuntimeCall.type: type = fn_type @RuntimeCall [template]
 // CHECK:STDOUT:   %RuntimeCall: %RuntimeCall.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -96,15 +103,27 @@ let c: i32 = Sub(Sub(0, 0x7FFFFFFF), 2);
 // CHECK:STDOUT:   %int.ssub: init i32 = call %Sub.ref(%.loc4_20, %.loc4_23) [template = constants.%.3]
 // CHECK:STDOUT:   %.loc4_11.1: type = value_of_initializer %int.make_type_32.loc4 [template = i32]
 // CHECK:STDOUT:   %.loc4_11.2: type = converted %int.make_type_32.loc4, %.loc4_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc4_25: type = array_type %int.ssub, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %arr.var: ref %.4 = var arr
-// CHECK:STDOUT:   %arr: ref %.4 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc4_19.1: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc4_19.2: <bound method> = bound_method %int.ssub, %.loc4_19.1 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_19.3: i32 = value_of_initializer %int.ssub [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_19.4: i32 = converted %int.ssub, %.loc4_19.3 [template = constants.%.3]
+// CHECK:STDOUT:   %int.convert_checked.loc4: init Core.IntLiteral = call %.loc4_19.2(%.loc4_19.4) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.6: Core.IntLiteral = converted %int.ssub, %.loc4_19.5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_25: type = array_type %.loc4_19.6, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %arr.var: ref %.30 = var arr
+// CHECK:STDOUT:   %arr: ref %.30 = bind_name arr, %arr.var
 // CHECK:STDOUT:   %int.make_type_32.loc5: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc5_18: i32 = int_value 1 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc5_18.1: i32 = int_value 1 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc5_13.1: type = value_of_initializer %int.make_type_32.loc5 [template = i32]
 // CHECK:STDOUT:   %.loc5_13.2: type = converted %int.make_type_32.loc5, %.loc5_13.1 [template = i32]
-// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc5_18.2: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc5_18.3: <bound method> = bound_method %.loc5_18.1, %.loc5_18.2 [template = constants.%.28]
+// CHECK:STDOUT:   %int.convert_checked.loc5: init Core.IntLiteral = call %.loc5_18.3(%.loc5_18.1) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.5: Core.IntLiteral = converted %.loc5_18.1, %.loc5_18.4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18.5, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.30 [template = constants.%.31]
 // CHECK:STDOUT:   %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [template = constants.%RuntimeCall] {
 // CHECK:STDOUT:     %a.patt: i32 = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: i32 = value_param_pattern %a.patt, runtime_param0
@@ -146,9 +165,9 @@ let c: i32 = Sub(Sub(0, 0x7FFFFFFF), 2);
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr.ref: ref %.4 = name_ref arr, file.%arr
-// CHECK:STDOUT:   %.loc5: %.5 = addr_of %arr.ref
-// CHECK:STDOUT:   %arr_p: %.5 = bind_name arr_p, %.loc5
+// CHECK:STDOUT:   %arr.ref: ref %.30 = name_ref arr, file.%arr
+// CHECK:STDOUT:   %.loc5: %.31 = addr_of %arr.ref
+// CHECK:STDOUT:   %arr_p: %.31 = bind_name arr_p, %.loc5
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 39 - 14
toolchain/check/testdata/builtins/int/uadd.carbon

@@ -96,15 +96,22 @@ let b: i32 = Add(0x7FFFFFFF, 1);
 // CHECK:STDOUT:   %.1: i32 = int_value 1 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %.3: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
-// CHECK:STDOUT:   %.5: type = ptr_type %.4 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.27: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.28: <bound method> = bound_method %.3, %Convert.15 [template]
+// CHECK:STDOUT:   %.29: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.30: type = array_type %.29, i32 [template]
+// CHECK:STDOUT:   %.31: type = ptr_type %.30 [template]
 // CHECK:STDOUT:   %RuntimeCall.type: type = fn_type @RuntimeCall [template]
 // CHECK:STDOUT:   %RuntimeCall: %RuntimeCall.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -150,15 +157,27 @@ let b: i32 = Add(0x7FFFFFFF, 1);
 // CHECK:STDOUT:   %int.uadd: init i32 = call %Add.ref(%.loc4_20, %.loc4_23) [template = constants.%.3]
 // CHECK:STDOUT:   %.loc4_11.1: type = value_of_initializer %int.make_type_32.loc4 [template = i32]
 // CHECK:STDOUT:   %.loc4_11.2: type = converted %int.make_type_32.loc4, %.loc4_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc4_25: type = array_type %int.uadd, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %arr.var: ref %.4 = var arr
-// CHECK:STDOUT:   %arr: ref %.4 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc4_19.1: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc4_19.2: <bound method> = bound_method %int.uadd, %.loc4_19.1 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_19.3: i32 = value_of_initializer %int.uadd [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_19.4: i32 = converted %int.uadd, %.loc4_19.3 [template = constants.%.3]
+// CHECK:STDOUT:   %int.convert_checked.loc4: init Core.IntLiteral = call %.loc4_19.2(%.loc4_19.4) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.6: Core.IntLiteral = converted %int.uadd, %.loc4_19.5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_25: type = array_type %.loc4_19.6, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %arr.var: ref %.30 = var arr
+// CHECK:STDOUT:   %arr: ref %.30 = bind_name arr, %arr.var
 // CHECK:STDOUT:   %int.make_type_32.loc5: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc5_18: i32 = int_value 3 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc5_18.1: i32 = int_value 3 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc5_13.1: type = value_of_initializer %int.make_type_32.loc5 [template = i32]
 // CHECK:STDOUT:   %.loc5_13.2: type = converted %int.make_type_32.loc5, %.loc5_13.1 [template = i32]
-// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc5_18.2: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc5_18.3: <bound method> = bound_method %.loc5_18.1, %.loc5_18.2 [template = constants.%.28]
+// CHECK:STDOUT:   %int.convert_checked.loc5: init Core.IntLiteral = call %.loc5_18.3(%.loc5_18.1) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.5: Core.IntLiteral = converted %.loc5_18.1, %.loc5_18.4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18.5, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.30 [template = constants.%.31]
 // CHECK:STDOUT:   %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [template = constants.%RuntimeCall] {
 // CHECK:STDOUT:     %a.patt: i32 = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: i32 = value_param_pattern %a.patt, runtime_param0
@@ -200,9 +219,9 @@ let b: i32 = Add(0x7FFFFFFF, 1);
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr.ref: ref %.4 = name_ref arr, file.%arr
-// CHECK:STDOUT:   %.loc5: %.5 = addr_of %arr.ref
-// CHECK:STDOUT:   %arr_p: %.5 = bind_name arr_p, %.loc5
+// CHECK:STDOUT:   %arr.ref: ref %.30 = name_ref arr, file.%arr
+// CHECK:STDOUT:   %.loc5: %.31 = addr_of %arr.ref
+// CHECK:STDOUT:   %arr_p: %.31 = bind_name arr_p, %.loc5
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -355,8 +374,10 @@ let b: i32 = Add(0x7FFFFFFF, 1);
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %int.make_type_32.loc25: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %TooFew.ref: %TooFew.type = name_ref TooFew, %TooFew.decl [template = constants.%TooFew]
-// CHECK:STDOUT:   %.loc25: i32 = int_value 1 [template = constants.%.1]
-// CHECK:STDOUT:   %TooFew.call: init i32 = call %TooFew.ref(%.loc25)
+// CHECK:STDOUT:   %.loc25_27: i32 = int_value 1 [template = constants.%.1]
+// CHECK:STDOUT:   %TooFew.call: init i32 = call %TooFew.ref(%.loc25_27)
+// CHECK:STDOUT:   %.loc25_15.1: type = value_of_initializer %int.make_type_32.loc25 [template = i32]
+// CHECK:STDOUT:   %.loc25_15.2: type = converted %int.make_type_32.loc25, %.loc25_15.1 [template = i32]
 // CHECK:STDOUT:   %too_few.var: ref <error> = var too_few
 // CHECK:STDOUT:   %too_few: ref <error> = bind_name too_few, %too_few.var
 // CHECK:STDOUT:   %int.make_type_32.loc30: init type = call constants.%Int32() [template = i32]
@@ -365,6 +386,8 @@ let b: i32 = Add(0x7FFFFFFF, 1);
 // CHECK:STDOUT:   %.loc30_32: i32 = int_value 2 [template = constants.%.2]
 // CHECK:STDOUT:   %.loc30_35: i32 = int_value 3 [template = constants.%.3]
 // CHECK:STDOUT:   %TooMany.call: init i32 = call %TooMany.ref(%.loc30_29, %.loc30_32, %.loc30_35)
+// CHECK:STDOUT:   %.loc30_16.1: type = value_of_initializer %int.make_type_32.loc30 [template = i32]
+// CHECK:STDOUT:   %.loc30_16.2: type = converted %int.make_type_32.loc30, %.loc30_16.1 [template = i32]
 // CHECK:STDOUT:   %too_many.var: ref <error> = var too_many
 // CHECK:STDOUT:   %too_many: ref <error> = bind_name too_many, %too_many.var
 // CHECK:STDOUT:   %int.make_type_32.loc35: init type = call constants.%Int32() [template = i32]
@@ -372,6 +395,8 @@ let b: i32 = Add(0x7FFFFFFF, 1);
 // CHECK:STDOUT:   %.loc35_42: i32 = int_value 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc35_45: i32 = int_value 2 [template = constants.%.2]
 // CHECK:STDOUT:   %BadReturnType.call: init bool = call %BadReturnType.ref(%.loc35_42, %.loc35_45)
+// CHECK:STDOUT:   %.loc35_23.1: type = value_of_initializer %int.make_type_32.loc35 [template = i32]
+// CHECK:STDOUT:   %.loc35_23.2: type = converted %int.make_type_32.loc35, %.loc35_23.1 [template = i32]
 // CHECK:STDOUT:   %bad_return_type.var: ref <error> = var bad_return_type
 // CHECK:STDOUT:   %bad_return_type: ref <error> = bind_name bad_return_type, %bad_return_type.var
 // CHECK:STDOUT:   %int.make_type_32.loc43: init type = call constants.%Int32() [template = i32]

+ 31 - 12
toolchain/check/testdata/builtins/int/udiv.carbon

@@ -63,15 +63,22 @@ let b: i32 = Div(0, 0);
 // CHECK:STDOUT:   %.1: i32 = int_value 3 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %.3: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
-// CHECK:STDOUT:   %.5: type = ptr_type %.4 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.27: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.28: <bound method> = bound_method %.3, %Convert.15 [template]
+// CHECK:STDOUT:   %.29: Core.IntLiteral = int_value 1 [template]
+// CHECK:STDOUT:   %.30: type = array_type %.29, i32 [template]
+// CHECK:STDOUT:   %.31: type = ptr_type %.30 [template]
 // CHECK:STDOUT:   %RuntimeCall.type: type = fn_type @RuntimeCall [template]
 // CHECK:STDOUT:   %RuntimeCall: %RuntimeCall.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -117,15 +124,27 @@ let b: i32 = Div(0, 0);
 // CHECK:STDOUT:   %int.udiv: init i32 = call %Div.ref(%.loc4_20, %.loc4_23) [template = constants.%.3]
 // CHECK:STDOUT:   %.loc4_11.1: type = value_of_initializer %int.make_type_32.loc4 [template = i32]
 // CHECK:STDOUT:   %.loc4_11.2: type = converted %int.make_type_32.loc4, %.loc4_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc4_25: type = array_type %int.udiv, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %arr.var: ref %.4 = var arr
-// CHECK:STDOUT:   %arr: ref %.4 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc4_19.1: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc4_19.2: <bound method> = bound_method %int.udiv, %.loc4_19.1 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_19.3: i32 = value_of_initializer %int.udiv [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_19.4: i32 = converted %int.udiv, %.loc4_19.3 [template = constants.%.3]
+// CHECK:STDOUT:   %int.convert_checked.loc4: init Core.IntLiteral = call %.loc4_19.2(%.loc4_19.4) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.6: Core.IntLiteral = converted %int.udiv, %.loc4_19.5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_25: type = array_type %.loc4_19.6, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %arr.var: ref %.30 = var arr
+// CHECK:STDOUT:   %arr: ref %.30 = bind_name arr, %arr.var
 // CHECK:STDOUT:   %int.make_type_32.loc5: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc5_18: i32 = int_value 1 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc5_18.1: i32 = int_value 1 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc5_13.1: type = value_of_initializer %int.make_type_32.loc5 [template = i32]
 // CHECK:STDOUT:   %.loc5_13.2: type = converted %int.make_type_32.loc5, %.loc5_13.1 [template = i32]
-// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc5_18.2: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc5_18.3: <bound method> = bound_method %.loc5_18.1, %.loc5_18.2 [template = constants.%.28]
+// CHECK:STDOUT:   %int.convert_checked.loc5: init Core.IntLiteral = call %.loc5_18.3(%.loc5_18.1) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.5: Core.IntLiteral = converted %.loc5_18.1, %.loc5_18.4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18.5, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.30 [template = constants.%.31]
 // CHECK:STDOUT:   %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [template = constants.%RuntimeCall] {
 // CHECK:STDOUT:     %a.patt: i32 = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: i32 = value_param_pattern %a.patt, runtime_param0
@@ -167,9 +186,9 @@ let b: i32 = Div(0, 0);
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr.ref: ref %.4 = name_ref arr, file.%arr
-// CHECK:STDOUT:   %.loc5: %.5 = addr_of %arr.ref
-// CHECK:STDOUT:   %arr_p: %.5 = bind_name arr_p, %.loc5
+// CHECK:STDOUT:   %arr.ref: ref %.30 = name_ref arr, file.%arr
+// CHECK:STDOUT:   %.loc5: %.31 = addr_of %arr.ref
+// CHECK:STDOUT:   %arr_p: %.31 = bind_name arr_p, %.loc5
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 31 - 12
toolchain/check/testdata/builtins/int/umod.carbon

@@ -65,15 +65,22 @@ let b: i32 = Mod(0, 0);
 // CHECK:STDOUT:   %.1: i32 = int_value 5 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value 3 [template]
 // CHECK:STDOUT:   %.3: i32 = int_value 2 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
-// CHECK:STDOUT:   %.5: type = ptr_type %.4 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.27: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.28: <bound method> = bound_method %.3, %Convert.15 [template]
+// CHECK:STDOUT:   %.29: Core.IntLiteral = int_value 2 [template]
+// CHECK:STDOUT:   %.30: type = array_type %.29, i32 [template]
+// CHECK:STDOUT:   %.31: type = ptr_type %.30 [template]
 // CHECK:STDOUT:   %RuntimeCall.type: type = fn_type @RuntimeCall [template]
 // CHECK:STDOUT:   %RuntimeCall: %RuntimeCall.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -119,15 +126,27 @@ let b: i32 = Mod(0, 0);
 // CHECK:STDOUT:   %int.umod: init i32 = call %Mod.ref(%.loc4_20, %.loc4_23) [template = constants.%.3]
 // CHECK:STDOUT:   %.loc4_11.1: type = value_of_initializer %int.make_type_32.loc4 [template = i32]
 // CHECK:STDOUT:   %.loc4_11.2: type = converted %int.make_type_32.loc4, %.loc4_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc4_25: type = array_type %int.umod, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %arr.var: ref %.4 = var arr
-// CHECK:STDOUT:   %arr: ref %.4 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc4_19.1: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc4_19.2: <bound method> = bound_method %int.umod, %.loc4_19.1 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_19.3: i32 = value_of_initializer %int.umod [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_19.4: i32 = converted %int.umod, %.loc4_19.3 [template = constants.%.3]
+// CHECK:STDOUT:   %int.convert_checked.loc4: init Core.IntLiteral = call %.loc4_19.2(%.loc4_19.4) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.6: Core.IntLiteral = converted %int.umod, %.loc4_19.5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_25: type = array_type %.loc4_19.6, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %arr.var: ref %.30 = var arr
+// CHECK:STDOUT:   %arr: ref %.30 = bind_name arr, %arr.var
 // CHECK:STDOUT:   %int.make_type_32.loc5: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc5_18: i32 = int_value 2 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc5_18.1: i32 = int_value 2 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc5_13.1: type = value_of_initializer %int.make_type_32.loc5 [template = i32]
 // CHECK:STDOUT:   %.loc5_13.2: type = converted %int.make_type_32.loc5, %.loc5_13.1 [template = i32]
-// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc5_18.2: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc5_18.3: <bound method> = bound_method %.loc5_18.1, %.loc5_18.2 [template = constants.%.28]
+// CHECK:STDOUT:   %int.convert_checked.loc5: init Core.IntLiteral = call %.loc5_18.3(%.loc5_18.1) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.5: Core.IntLiteral = converted %.loc5_18.1, %.loc5_18.4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18.5, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.30 [template = constants.%.31]
 // CHECK:STDOUT:   %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [template = constants.%RuntimeCall] {
 // CHECK:STDOUT:     %a.patt: i32 = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: i32 = value_param_pattern %a.patt, runtime_param0
@@ -169,9 +188,9 @@ let b: i32 = Mod(0, 0);
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr.ref: ref %.4 = name_ref arr, file.%arr
-// CHECK:STDOUT:   %.loc5: %.5 = addr_of %arr.ref
-// CHECK:STDOUT:   %arr_p: %.5 = bind_name arr_p, %.loc5
+// CHECK:STDOUT:   %arr.ref: ref %.30 = name_ref arr, file.%arr
+// CHECK:STDOUT:   %.loc5: %.31 = addr_of %arr.ref
+// CHECK:STDOUT:   %arr_p: %.31 = bind_name arr_p, %.loc5
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 31 - 12
toolchain/check/testdata/builtins/int/umul.carbon

@@ -38,15 +38,22 @@ let b: i32 = Mul(0x8000, 0x10000);
 // CHECK:STDOUT:   %.1: i32 = int_value 3 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %.3: i32 = int_value 6 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
-// CHECK:STDOUT:   %.5: type = ptr_type %.4 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.27: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.28: <bound method> = bound_method %.3, %Convert.15 [template]
+// CHECK:STDOUT:   %.29: Core.IntLiteral = int_value 6 [template]
+// CHECK:STDOUT:   %.30: type = array_type %.29, i32 [template]
+// CHECK:STDOUT:   %.31: type = ptr_type %.30 [template]
 // CHECK:STDOUT:   %RuntimeCall.type: type = fn_type @RuntimeCall [template]
 // CHECK:STDOUT:   %RuntimeCall: %RuntimeCall.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -92,15 +99,27 @@ let b: i32 = Mul(0x8000, 0x10000);
 // CHECK:STDOUT:   %int.umul: init i32 = call %Mul.ref(%.loc4_20, %.loc4_23) [template = constants.%.3]
 // CHECK:STDOUT:   %.loc4_11.1: type = value_of_initializer %int.make_type_32.loc4 [template = i32]
 // CHECK:STDOUT:   %.loc4_11.2: type = converted %int.make_type_32.loc4, %.loc4_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc4_25: type = array_type %int.umul, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %arr.var: ref %.4 = var arr
-// CHECK:STDOUT:   %arr: ref %.4 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc4_19.1: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc4_19.2: <bound method> = bound_method %int.umul, %.loc4_19.1 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_19.3: i32 = value_of_initializer %int.umul [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_19.4: i32 = converted %int.umul, %.loc4_19.3 [template = constants.%.3]
+// CHECK:STDOUT:   %int.convert_checked.loc4: init Core.IntLiteral = call %.loc4_19.2(%.loc4_19.4) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.6: Core.IntLiteral = converted %int.umul, %.loc4_19.5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_25: type = array_type %.loc4_19.6, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %arr.var: ref %.30 = var arr
+// CHECK:STDOUT:   %arr: ref %.30 = bind_name arr, %arr.var
 // CHECK:STDOUT:   %int.make_type_32.loc5: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc5_18: i32 = int_value 6 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc5_18.1: i32 = int_value 6 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc5_13.1: type = value_of_initializer %int.make_type_32.loc5 [template = i32]
 // CHECK:STDOUT:   %.loc5_13.2: type = converted %int.make_type_32.loc5, %.loc5_13.1 [template = i32]
-// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc5_18.2: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc5_18.3: <bound method> = bound_method %.loc5_18.1, %.loc5_18.2 [template = constants.%.28]
+// CHECK:STDOUT:   %int.convert_checked.loc5: init Core.IntLiteral = call %.loc5_18.3(%.loc5_18.1) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.5: Core.IntLiteral = converted %.loc5_18.1, %.loc5_18.4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18.5, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.30 [template = constants.%.31]
 // CHECK:STDOUT:   %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [template = constants.%RuntimeCall] {
 // CHECK:STDOUT:     %a.patt: i32 = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: i32 = value_param_pattern %a.patt, runtime_param0
@@ -142,9 +161,9 @@ let b: i32 = Mul(0x8000, 0x10000);
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr.ref: ref %.4 = name_ref arr, file.%arr
-// CHECK:STDOUT:   %.loc5: %.5 = addr_of %arr.ref
-// CHECK:STDOUT:   %arr_p: %.5 = bind_name arr_p, %.loc5
+// CHECK:STDOUT:   %arr.ref: ref %.30 = name_ref arr, file.%arr
+// CHECK:STDOUT:   %.loc5: %.31 = addr_of %arr.ref
+// CHECK:STDOUT:   %arr_p: %.31 = bind_name arr_p, %.loc5
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 45 - 20
toolchain/check/testdata/builtins/int/unegate.carbon

@@ -121,17 +121,24 @@ let b: i32 = Negate(Sub(Negate(0x7FFFFFFF), 1));
 // CHECK:STDOUT:   %Negate: %Negate.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 123 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value -123 [template]
-// CHECK:STDOUT:   %.3: type = array_type %.1, i32 [template]
-// CHECK:STDOUT:   %.4: type = ptr_type %.3 [template]
-// CHECK:STDOUT:   %.5: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.6: i32 = int_value -1 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.26: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.27: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.28: Core.IntLiteral = int_value 123 [template]
+// CHECK:STDOUT:   %.29: type = array_type %.28, i32 [template]
+// CHECK:STDOUT:   %.30: type = ptr_type %.29 [template]
+// CHECK:STDOUT:   %.31: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %.32: i32 = int_value -1 [template]
 // CHECK:STDOUT:   %RuntimeCall.type: type = fn_type @RuntimeCall [template]
 // CHECK:STDOUT:   %RuntimeCall: %RuntimeCall.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -174,15 +181,27 @@ let b: i32 = Negate(Sub(Negate(0x7FFFFFFF), 1));
 // CHECK:STDOUT:   %int.unegate.loc4_22: init i32 = call %Negate.ref.loc4_16(%.loc4_29.2) [template = constants.%.1]
 // CHECK:STDOUT:   %.loc4_11.1: type = value_of_initializer %int.make_type_32.loc4 [template = i32]
 // CHECK:STDOUT:   %.loc4_11.2: type = converted %int.make_type_32.loc4, %.loc4_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc4_35: type = array_type %int.unegate.loc4_22, i32 [template = constants.%.3]
-// CHECK:STDOUT:   %arr.var: ref %.3 = var arr
-// CHECK:STDOUT:   %arr: ref %.3 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc4_22.1: %Convert.type.2 = interface_witness_access constants.%.26, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc4_22.2: <bound method> = bound_method %int.unegate.loc4_22, %.loc4_22.1 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc4_22.3: i32 = value_of_initializer %int.unegate.loc4_22 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc4_22.4: i32 = converted %int.unegate.loc4_22, %.loc4_22.3 [template = constants.%.1]
+// CHECK:STDOUT:   %int.convert_checked.loc4: init Core.IntLiteral = call %.loc4_22.2(%.loc4_22.4) [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_22.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc4 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_22.6: Core.IntLiteral = converted %int.unegate.loc4_22, %.loc4_22.5 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_35: type = array_type %.loc4_22.6, i32 [template = constants.%.29]
+// CHECK:STDOUT:   %arr.var: ref %.29 = var arr
+// CHECK:STDOUT:   %arr: ref %.29 = bind_name arr, %arr.var
 // CHECK:STDOUT:   %int.make_type_32.loc5: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc5_18: i32 = int_value 123 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc5_18.1: i32 = int_value 123 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc5_13.1: type = value_of_initializer %int.make_type_32.loc5 [template = i32]
 // CHECK:STDOUT:   %.loc5_13.2: type = converted %int.make_type_32.loc5, %.loc5_13.1 [template = i32]
-// CHECK:STDOUT:   %.loc5_21: type = array_type %.loc5_18, i32 [template = constants.%.3]
-// CHECK:STDOUT:   %.loc5_22: type = ptr_type %.3 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc5_18.2: %Convert.type.2 = interface_witness_access constants.%.26, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc5_18.3: <bound method> = bound_method %.loc5_18.1, %.loc5_18.2 [template = constants.%.27]
+// CHECK:STDOUT:   %int.convert_checked.loc5: init Core.IntLiteral = call %.loc5_18.3(%.loc5_18.1) [template = constants.%.28]
+// CHECK:STDOUT:   %.loc5_18.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc5 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc5_18.5: Core.IntLiteral = converted %.loc5_18.1, %.loc5_18.4 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc5_21: type = array_type %.loc5_18.5, i32 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_22: type = ptr_type %.29 [template = constants.%.30]
 // CHECK:STDOUT:   %int.make_type_32.loc7: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc7_8.1: type = value_of_initializer %int.make_type_32.loc7 [template = i32]
 // CHECK:STDOUT:   %.loc7_8.2: type = converted %int.make_type_32.loc7, %.loc7_8.1 [template = i32]
@@ -226,14 +245,14 @@ let b: i32 = Negate(Sub(Negate(0x7FFFFFFF), 1));
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr.ref: ref %.3 = name_ref arr, file.%arr
-// CHECK:STDOUT:   %.loc5: %.4 = addr_of %arr.ref
-// CHECK:STDOUT:   %arr_p: %.4 = bind_name arr_p, %.loc5
+// CHECK:STDOUT:   %arr.ref: ref %.29 = name_ref arr, file.%arr
+// CHECK:STDOUT:   %.loc5: %.30 = addr_of %arr.ref
+// CHECK:STDOUT:   %arr_p: %.30 = bind_name arr_p, %.loc5
 // CHECK:STDOUT:   %Negate.ref: %Negate.type = name_ref Negate, file.%Negate.decl [template = constants.%Negate]
-// CHECK:STDOUT:   %.loc7_21: i32 = int_value 1 [template = constants.%.5]
-// CHECK:STDOUT:   %int.unegate: init i32 = call %Negate.ref(%.loc7_21) [template = constants.%.6]
-// CHECK:STDOUT:   %.loc7_23.1: i32 = value_of_initializer %int.unegate [template = constants.%.6]
-// CHECK:STDOUT:   %.loc7_23.2: i32 = converted %int.unegate, %.loc7_23.1 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc7_21: i32 = int_value 1 [template = constants.%.31]
+// CHECK:STDOUT:   %int.unegate: init i32 = call %Negate.ref(%.loc7_21) [template = constants.%.32]
+// CHECK:STDOUT:   %.loc7_23.1: i32 = value_of_initializer %int.unegate [template = constants.%.32]
+// CHECK:STDOUT:   %.loc7_23.2: i32 = converted %int.unegate, %.loc7_23.1 [template = constants.%.32]
 // CHECK:STDOUT:   %n: i32 = bind_name n, %.loc7_23.2
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
@@ -359,6 +378,8 @@ let b: i32 = Negate(Sub(Negate(0x7FFFFFFF), 1));
 // CHECK:STDOUT:   %int.make_type_32.loc25: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %TooFew.ref: %TooFew.type = name_ref TooFew, %TooFew.decl [template = constants.%TooFew]
 // CHECK:STDOUT:   %TooFew.call: init i32 = call %TooFew.ref()
+// CHECK:STDOUT:   %.loc25_15.1: type = value_of_initializer %int.make_type_32.loc25 [template = i32]
+// CHECK:STDOUT:   %.loc25_15.2: type = converted %int.make_type_32.loc25, %.loc25_15.1 [template = i32]
 // CHECK:STDOUT:   %too_few.var: ref <error> = var too_few
 // CHECK:STDOUT:   %too_few: ref <error> = bind_name too_few, %too_few.var
 // CHECK:STDOUT:   %int.make_type_32.loc30: init type = call constants.%Int32() [template = i32]
@@ -366,12 +387,16 @@ let b: i32 = Negate(Sub(Negate(0x7FFFFFFF), 1));
 // CHECK:STDOUT:   %.loc30_29: i32 = int_value 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc30_32: i32 = int_value 2 [template = constants.%.2]
 // CHECK:STDOUT:   %TooMany.call: init i32 = call %TooMany.ref(%.loc30_29, %.loc30_32)
+// CHECK:STDOUT:   %.loc30_16.1: type = value_of_initializer %int.make_type_32.loc30 [template = i32]
+// CHECK:STDOUT:   %.loc30_16.2: type = converted %int.make_type_32.loc30, %.loc30_16.1 [template = i32]
 // CHECK:STDOUT:   %too_many.var: ref <error> = var too_many
 // CHECK:STDOUT:   %too_many: ref <error> = bind_name too_many, %too_many.var
 // CHECK:STDOUT:   %int.make_type_32.loc35: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %BadReturnType.ref: %BadReturnType.type = name_ref BadReturnType, %BadReturnType.decl [template = constants.%BadReturnType]
-// CHECK:STDOUT:   %.loc35: i32 = int_value 1 [template = constants.%.1]
-// CHECK:STDOUT:   %BadReturnType.call: init bool = call %BadReturnType.ref(%.loc35)
+// CHECK:STDOUT:   %.loc35_42: i32 = int_value 1 [template = constants.%.1]
+// CHECK:STDOUT:   %BadReturnType.call: init bool = call %BadReturnType.ref(%.loc35_42)
+// CHECK:STDOUT:   %.loc35_23.1: type = value_of_initializer %int.make_type_32.loc35 [template = i32]
+// CHECK:STDOUT:   %.loc35_23.2: type = converted %int.make_type_32.loc35, %.loc35_23.1 [template = i32]
 // CHECK:STDOUT:   %bad_return_type.var: ref <error> = var bad_return_type
 // CHECK:STDOUT:   %bad_return_type: ref <error> = bind_name bad_return_type, %bad_return_type.var
 // CHECK:STDOUT:   %int.make_type_32.loc44: init type = call constants.%Int32() [template = i32]

+ 31 - 12
toolchain/check/testdata/builtins/int/usub.carbon

@@ -39,15 +39,22 @@ let c: i32 = Sub(Sub(0, 0x7FFFFFFF), 2);
 // CHECK:STDOUT:   %.1: i32 = int_value 3 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %.3: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
-// CHECK:STDOUT:   %.5: type = ptr_type %.4 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.27: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.28: <bound method> = bound_method %.3, %Convert.15 [template]
+// CHECK:STDOUT:   %.29: Core.IntLiteral = int_value 1 [template]
+// CHECK:STDOUT:   %.30: type = array_type %.29, i32 [template]
+// CHECK:STDOUT:   %.31: type = ptr_type %.30 [template]
 // CHECK:STDOUT:   %RuntimeCall.type: type = fn_type @RuntimeCall [template]
 // CHECK:STDOUT:   %RuntimeCall: %RuntimeCall.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -93,15 +100,27 @@ let c: i32 = Sub(Sub(0, 0x7FFFFFFF), 2);
 // CHECK:STDOUT:   %int.usub: init i32 = call %Sub.ref(%.loc4_20, %.loc4_23) [template = constants.%.3]
 // CHECK:STDOUT:   %.loc4_11.1: type = value_of_initializer %int.make_type_32.loc4 [template = i32]
 // CHECK:STDOUT:   %.loc4_11.2: type = converted %int.make_type_32.loc4, %.loc4_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc4_25: type = array_type %int.usub, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %arr.var: ref %.4 = var arr
-// CHECK:STDOUT:   %arr: ref %.4 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc4_19.1: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc4_19.2: <bound method> = bound_method %int.usub, %.loc4_19.1 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_19.3: i32 = value_of_initializer %int.usub [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_19.4: i32 = converted %int.usub, %.loc4_19.3 [template = constants.%.3]
+// CHECK:STDOUT:   %int.convert_checked.loc4: init Core.IntLiteral = call %.loc4_19.2(%.loc4_19.4) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.6: Core.IntLiteral = converted %int.usub, %.loc4_19.5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_25: type = array_type %.loc4_19.6, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %arr.var: ref %.30 = var arr
+// CHECK:STDOUT:   %arr: ref %.30 = bind_name arr, %arr.var
 // CHECK:STDOUT:   %int.make_type_32.loc5: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc5_18: i32 = int_value 1 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc5_18.1: i32 = int_value 1 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc5_13.1: type = value_of_initializer %int.make_type_32.loc5 [template = i32]
 // CHECK:STDOUT:   %.loc5_13.2: type = converted %int.make_type_32.loc5, %.loc5_13.1 [template = i32]
-// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc5_18.2: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc5_18.3: <bound method> = bound_method %.loc5_18.1, %.loc5_18.2 [template = constants.%.28]
+// CHECK:STDOUT:   %int.convert_checked.loc5: init Core.IntLiteral = call %.loc5_18.3(%.loc5_18.1) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.5: Core.IntLiteral = converted %.loc5_18.1, %.loc5_18.4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18.5, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.30 [template = constants.%.31]
 // CHECK:STDOUT:   %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [template = constants.%RuntimeCall] {
 // CHECK:STDOUT:     %a.patt: i32 = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: i32 = value_param_pattern %a.patt, runtime_param0
@@ -143,9 +162,9 @@ let c: i32 = Sub(Sub(0, 0x7FFFFFFF), 2);
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr.ref: ref %.4 = name_ref arr, file.%arr
-// CHECK:STDOUT:   %.loc5: %.5 = addr_of %arr.ref
-// CHECK:STDOUT:   %arr_p: %.5 = bind_name arr_p, %.loc5
+// CHECK:STDOUT:   %arr.ref: ref %.30 = name_ref arr, file.%arr
+// CHECK:STDOUT:   %.loc5: %.31 = addr_of %arr.ref
+// CHECK:STDOUT:   %arr_p: %.31 = bind_name arr_p, %.loc5
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 31 - 12
toolchain/check/testdata/builtins/int/xor.carbon

@@ -29,15 +29,22 @@ fn RuntimeCall(a: i32, b: i32) -> i32 {
 // CHECK:STDOUT:   %.1: i32 = int_value 12 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value 10 [template]
 // CHECK:STDOUT:   %.3: i32 = int_value 6 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
-// CHECK:STDOUT:   %.5: type = ptr_type %.4 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.27: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.28: <bound method> = bound_method %.3, %Convert.15 [template]
+// CHECK:STDOUT:   %.29: Core.IntLiteral = int_value 6 [template]
+// CHECK:STDOUT:   %.30: type = array_type %.29, i32 [template]
+// CHECK:STDOUT:   %.31: type = ptr_type %.30 [template]
 // CHECK:STDOUT:   %RuntimeCall.type: type = fn_type @RuntimeCall [template]
 // CHECK:STDOUT:   %RuntimeCall: %RuntimeCall.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -83,15 +90,27 @@ fn RuntimeCall(a: i32, b: i32) -> i32 {
 // CHECK:STDOUT:   %int.xor: init i32 = call %Xor.ref(%.loc4_20, %.loc4_24) [template = constants.%.3]
 // CHECK:STDOUT:   %.loc4_11.1: type = value_of_initializer %int.make_type_32.loc4 [template = i32]
 // CHECK:STDOUT:   %.loc4_11.2: type = converted %int.make_type_32.loc4, %.loc4_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc4_27: type = array_type %int.xor, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %arr.var: ref %.4 = var arr
-// CHECK:STDOUT:   %arr: ref %.4 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc4_19.1: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc4_19.2: <bound method> = bound_method %int.xor, %.loc4_19.1 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc4_19.3: i32 = value_of_initializer %int.xor [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_19.4: i32 = converted %int.xor, %.loc4_19.3 [template = constants.%.3]
+// CHECK:STDOUT:   %int.convert_checked.loc4: init Core.IntLiteral = call %.loc4_19.2(%.loc4_19.4) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.5: Core.IntLiteral = value_of_initializer %int.convert_checked.loc4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_19.6: Core.IntLiteral = converted %int.xor, %.loc4_19.5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc4_27: type = array_type %.loc4_19.6, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %arr.var: ref %.30 = var arr
+// CHECK:STDOUT:   %arr: ref %.30 = bind_name arr, %arr.var
 // CHECK:STDOUT:   %int.make_type_32.loc5: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc5_18: i32 = int_value 6 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc5_18.1: i32 = int_value 6 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc5_13.1: type = value_of_initializer %int.make_type_32.loc5 [template = i32]
 // CHECK:STDOUT:   %.loc5_13.2: type = converted %int.make_type_32.loc5, %.loc5_13.1 [template = i32]
-// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc5_18.2: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc5_18.3: <bound method> = bound_method %.loc5_18.1, %.loc5_18.2 [template = constants.%.28]
+// CHECK:STDOUT:   %int.convert_checked.loc5: init Core.IntLiteral = call %.loc5_18.3(%.loc5_18.1) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_18.5: Core.IntLiteral = converted %.loc5_18.1, %.loc5_18.4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc5_19: type = array_type %.loc5_18.5, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc5_20: type = ptr_type %.30 [template = constants.%.31]
 // CHECK:STDOUT:   %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [template = constants.%RuntimeCall] {
 // CHECK:STDOUT:     %a.patt: i32 = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: i32 = value_param_pattern %a.patt, runtime_param0
@@ -133,9 +152,9 @@ fn RuntimeCall(a: i32, b: i32) -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %arr.ref: ref %.4 = name_ref arr, file.%arr
-// CHECK:STDOUT:   %.loc5: %.5 = addr_of %arr.ref
-// CHECK:STDOUT:   %arr_p: %.5 = bind_name arr_p, %.loc5
+// CHECK:STDOUT:   %arr.ref: ref %.30 = name_ref arr, file.%arr
+// CHECK:STDOUT:   %.loc5: %.31 = addr_of %arr.ref
+// CHECK:STDOUT:   %arr_p: %.31 = bind_name arr_p, %.loc5
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 257 - 153
toolchain/check/testdata/deduce/array.carbon

@@ -106,23 +106,30 @@ fn G() -> C {
 // CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
 // CHECK:STDOUT:   %T.patt: type = symbolic_binding_pattern T, 0 [symbolic]
 // CHECK:STDOUT:   %.3: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, %T [symbolic]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.27: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.28: <bound method> = bound_method %.3, %Convert.15 [template]
+// CHECK:STDOUT:   %.29: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.30: type = array_type %.29, %T [symbolic]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [template]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [template]
-// CHECK:STDOUT:   %.6: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %.32: i32 = int_value 0 [template]
 // CHECK:STDOUT:   %G.type: type = fn_type @G [template]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [template]
-// CHECK:STDOUT:   %.8: type = array_type %.3, %C [template]
+// CHECK:STDOUT:   %.34: type = array_type %.29, %C [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (%.1, %.1, %.1) [template]
 // CHECK:STDOUT:   %struct: %C = struct_value () [template]
-// CHECK:STDOUT:   %.10: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.11: i32 = int_value 2 [template]
-// CHECK:STDOUT:   %array: %.8 = tuple_value (%struct, %struct, %struct) [template]
-// CHECK:STDOUT:   %.12: <specific function> = specific_function %F, @F(%C) [template]
+// CHECK:STDOUT:   %.36: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %.37: i32 = int_value 2 [template]
+// CHECK:STDOUT:   %array: %.34 = tuple_value (%struct, %struct, %struct) [template]
+// CHECK:STDOUT:   %.38: <specific function> = specific_function %F, @F(%C) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.1
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -140,19 +147,24 @@ fn G() -> C {
 // CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [template = constants.%F] {
 // CHECK:STDOUT:     %T.patt.loc6_6.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc6_6.2 (constants.%T.patt)]
 // CHECK:STDOUT:     %T.param_patt: type = value_param_pattern %T.patt.loc6_6.1, runtime_param<invalid> [symbolic = %T.patt.loc6_6.2 (constants.%T.patt)]
-// CHECK:STDOUT:     %a.patt: @F.%.loc6_24.2 (%.4) = binding_pattern a
-// CHECK:STDOUT:     %a.param_patt: @F.%.loc6_24.2 (%.4) = value_param_pattern %a.patt, runtime_param0
+// CHECK:STDOUT:     %a.patt: @F.%.loc6_24.2 (%.30) = binding_pattern a
+// CHECK:STDOUT:     %a.param_patt: @F.%.loc6_24.2 (%.30) = value_param_pattern %a.patt, runtime_param0
 // CHECK:STDOUT:     %return.patt: @F.%T.loc6_6.2 (%T) = return_slot_pattern
 // CHECK:STDOUT:     %return.param_patt: @F.%T.loc6_6.2 (%T) = out_param_pattern %return.patt, runtime_param1
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %T.ref.loc6_20: type = name_ref T, %T.loc6_6.1 [symbolic = %T.loc6_6.2 (constants.%T)]
-// CHECK:STDOUT:     %.loc6_23: i32 = int_value 3 [template = constants.%.3]
-// CHECK:STDOUT:     %.loc6_24.1: type = array_type %.loc6_23, %T [symbolic = %.loc6_24.2 (constants.%.4)]
+// CHECK:STDOUT:     %.loc6_23.1: i32 = int_value 3 [template = constants.%.3]
+// CHECK:STDOUT:     %.loc6_23.2: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:     %.loc6_23.3: <bound method> = bound_method %.loc6_23.1, %.loc6_23.2 [template = constants.%.28]
+// CHECK:STDOUT:     %int.convert_checked: init Core.IntLiteral = call %.loc6_23.3(%.loc6_23.1) [template = constants.%.29]
+// CHECK:STDOUT:     %.loc6_23.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.29]
+// CHECK:STDOUT:     %.loc6_23.5: Core.IntLiteral = converted %.loc6_23.1, %.loc6_23.4 [template = constants.%.29]
+// CHECK:STDOUT:     %.loc6_24.1: type = array_type %.loc6_23.5, %T [symbolic = %.loc6_24.2 (constants.%.30)]
 // CHECK:STDOUT:     %T.ref.loc6_30: type = name_ref T, %T.loc6_6.1 [symbolic = %T.loc6_6.2 (constants.%T)]
 // CHECK:STDOUT:     %T.param: type = value_param runtime_param<invalid>
 // CHECK:STDOUT:     %T.loc6_6.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc6_6.2 (constants.%T)]
-// CHECK:STDOUT:     %a.param: @F.%.loc6_24.2 (%.4) = value_param runtime_param0
-// CHECK:STDOUT:     %a: @F.%.loc6_24.2 (%.4) = bind_name a, %a.param
+// CHECK:STDOUT:     %a.param: @F.%.loc6_24.2 (%.30) = value_param runtime_param0
+// CHECK:STDOUT:     %a: @F.%.loc6_24.2 (%.30) = bind_name a, %a.param
 // CHECK:STDOUT:     %return.param: ref @F.%T.loc6_6.2 (%T) = out_param runtime_param1
 // CHECK:STDOUT:     %return: ref @F.%T.loc6_6.2 (%T) = return_slot %return.param
 // CHECK:STDOUT:   }
@@ -176,15 +188,15 @@ fn G() -> C {
 // CHECK:STDOUT: generic fn @F(%T.loc6_6.1: type) {
 // CHECK:STDOUT:   %T.loc6_6.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc6_6.2 (constants.%T)]
 // CHECK:STDOUT:   %T.patt.loc6_6.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc6_6.2 (constants.%T.patt)]
-// CHECK:STDOUT:   %.loc6_24.2: type = array_type constants.%.3, @F.%T.loc6_6.2 (%T) [symbolic = %.loc6_24.2 (constants.%.4)]
+// CHECK:STDOUT:   %.loc6_24.2: type = array_type constants.%.29, @F.%T.loc6_6.2 (%T) [symbolic = %.loc6_24.2 (constants.%.30)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn[%T.param_patt: type](%a.param_patt: @F.%.loc6_24.2 (%.4)) -> @F.%T.loc6_6.2 (%T) {
+// CHECK:STDOUT:   fn[%T.param_patt: type](%a.param_patt: @F.%.loc6_24.2 (%.30)) -> @F.%T.loc6_6.2 (%T) {
 // CHECK:STDOUT:   !entry:
-// CHECK:STDOUT:     %a.ref: @F.%.loc6_24.2 (%.4) = name_ref a, %a
-// CHECK:STDOUT:     %.loc6_43: i32 = int_value 0 [template = constants.%.6]
-// CHECK:STDOUT:     %.loc6_44.1: ref @F.%.loc6_24.2 (%.4) = value_as_ref %a.ref
+// CHECK:STDOUT:     %a.ref: @F.%.loc6_24.2 (%.30) = name_ref a, %a
+// CHECK:STDOUT:     %.loc6_43: i32 = int_value 0 [template = constants.%.32]
+// CHECK:STDOUT:     %.loc6_44.1: ref @F.%.loc6_24.2 (%.30) = value_as_ref %a.ref
 // CHECK:STDOUT:     %.loc6_44.2: ref @F.%T.loc6_6.2 (%T) = array_index %.loc6_44.1, %.loc6_43
 // CHECK:STDOUT:     %.loc6_44.3: @F.%T.loc6_6.2 (%T) = bind_value %.loc6_44.2
 // CHECK:STDOUT:     return %.loc6_44.3
@@ -194,34 +206,39 @@ fn G() -> C {
 // CHECK:STDOUT: fn @G() -> %return: %C {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %C.ref.loc9: type = name_ref C, file.%C.decl [template = constants.%C]
-// CHECK:STDOUT:   %.loc9_14: i32 = int_value 3 [template = constants.%.3]
-// CHECK:STDOUT:   %.loc9_15: type = array_type %.loc9_14, %C [template = constants.%.8]
-// CHECK:STDOUT:   %a.var: ref %.8 = var a
-// CHECK:STDOUT:   %a: ref %.8 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc9_14.1: i32 = int_value 3 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc9_14.2: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc9_14.3: <bound method> = bound_method %.loc9_14.1, %.loc9_14.2 [template = constants.%.28]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc9_14.3(%.loc9_14.1) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc9_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.29]
+// CHECK:STDOUT:   %.loc9_14.5: Core.IntLiteral = converted %.loc9_14.1, %.loc9_14.4 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc9_15: type = array_type %.loc9_14.5, %C [template = constants.%.34]
+// CHECK:STDOUT:   %a.var: ref %.34 = var a
+// CHECK:STDOUT:   %a: ref %.34 = bind_name a, %a.var
 // CHECK:STDOUT:   %.loc9_21.1: %.1 = struct_literal ()
 // CHECK:STDOUT:   %.loc9_25.1: %.1 = struct_literal ()
 // CHECK:STDOUT:   %.loc9_29.1: %.1 = struct_literal ()
 // CHECK:STDOUT:   %.loc9_30.1: %tuple.type = tuple_literal (%.loc9_21.1, %.loc9_25.1, %.loc9_29.1)
-// CHECK:STDOUT:   %.loc9_30.2: i32 = int_value 0 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc9_30.2: i32 = int_value 0 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc9_30.3: ref %C = array_index %a.var, %.loc9_30.2
 // CHECK:STDOUT:   %.loc9_21.2: init %C = class_init (), %.loc9_30.3 [template = constants.%struct]
 // CHECK:STDOUT:   %.loc9_30.4: init %C = converted %.loc9_21.1, %.loc9_21.2 [template = constants.%struct]
-// CHECK:STDOUT:   %.loc9_30.5: i32 = int_value 1 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc9_30.5: i32 = int_value 1 [template = constants.%.36]
 // CHECK:STDOUT:   %.loc9_30.6: ref %C = array_index %a.var, %.loc9_30.5
 // CHECK:STDOUT:   %.loc9_25.2: init %C = class_init (), %.loc9_30.6 [template = constants.%struct]
 // CHECK:STDOUT:   %.loc9_30.7: init %C = converted %.loc9_25.1, %.loc9_25.2 [template = constants.%struct]
-// CHECK:STDOUT:   %.loc9_30.8: i32 = int_value 2 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc9_30.8: i32 = int_value 2 [template = constants.%.37]
 // CHECK:STDOUT:   %.loc9_30.9: ref %C = array_index %a.var, %.loc9_30.8
 // CHECK:STDOUT:   %.loc9_29.2: init %C = class_init (), %.loc9_30.9 [template = constants.%struct]
 // CHECK:STDOUT:   %.loc9_30.10: init %C = converted %.loc9_29.1, %.loc9_29.2 [template = constants.%struct]
-// CHECK:STDOUT:   %.loc9_30.11: init %.8 = array_init (%.loc9_30.4, %.loc9_30.7, %.loc9_30.10) to %a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc9_31: init %.8 = converted %.loc9_30.1, %.loc9_30.11 [template = constants.%array]
+// CHECK:STDOUT:   %.loc9_30.11: init %.34 = array_init (%.loc9_30.4, %.loc9_30.7, %.loc9_30.10) to %a.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc9_31: init %.34 = converted %.loc9_30.1, %.loc9_30.11 [template = constants.%array]
 // CHECK:STDOUT:   assign %a.var, %.loc9_31
 // CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F]
-// CHECK:STDOUT:   %a.ref: ref %.8 = name_ref a, %a
-// CHECK:STDOUT:   %.loc10_10: <specific function> = specific_function %F.ref, @F(constants.%C) [template = constants.%.12]
+// CHECK:STDOUT:   %a.ref: ref %.34 = name_ref a, %a
+// CHECK:STDOUT:   %.loc10_10: <specific function> = specific_function %F.ref, @F(constants.%C) [template = constants.%.38]
 // CHECK:STDOUT:   %.loc8_8.2: ref %C = splice_block %return {}
-// CHECK:STDOUT:   %.loc10_12: %.8 = bind_value %a.ref
+// CHECK:STDOUT:   %.loc10_12: %.34 = bind_value %a.ref
 // CHECK:STDOUT:   %F.call: init %C = call %.loc10_10(%.loc10_12) to %.loc8_8.2
 // CHECK:STDOUT:   return %F.call to %return
 // CHECK:STDOUT: }
@@ -229,13 +246,13 @@ fn G() -> C {
 // CHECK:STDOUT: specific @F(constants.%T) {
 // CHECK:STDOUT:   %T.loc6_6.2 => constants.%T
 // CHECK:STDOUT:   %T.patt.loc6_6.2 => constants.%T
-// CHECK:STDOUT:   %.loc6_24.2 => constants.%.4
+// CHECK:STDOUT:   %.loc6_24.2 => constants.%.30
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @F(constants.%C) {
 // CHECK:STDOUT:   %T.loc6_6.2 => constants.%C
 // CHECK:STDOUT:   %T.patt.loc6_6.2 => constants.%C
-// CHECK:STDOUT:   %.loc6_24.2 => constants.%.8
+// CHECK:STDOUT:   %.loc6_24.2 => constants.%.34
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT: }
@@ -248,25 +265,34 @@ fn G() -> C {
 // CHECK:STDOUT:   %.2: <witness> = complete_type_witness %.1 [template]
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
-// CHECK:STDOUT:   %N: i32 = bind_symbolic_name N, 0 [symbolic]
-// CHECK:STDOUT:   %N.patt: i32 = symbolic_binding_pattern N, 0 [symbolic]
+// CHECK:STDOUT:   %N.1: i32 = bind_symbolic_name N, 0 [symbolic]
+// CHECK:STDOUT:   %N.patt.1: i32 = symbolic_binding_pattern N, 0 [symbolic]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.26: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.27: <bound method> = bound_method %N.1, %Convert.15 [symbolic]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.27(%N.1) [symbolic]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [template]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [template]
 // CHECK:STDOUT:   %G.type: type = fn_type @G [template]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.5: type = array_type %.4, %C [template]
+// CHECK:STDOUT:   %.29: i32 = int_value 3 [template]
+// CHECK:STDOUT:   %.30: <bound method> = bound_method %.29, %Convert.15 [template]
+// CHECK:STDOUT:   %.31: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.32: type = array_type %.31, %C [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (%.1, %.1, %.1) [template]
-// CHECK:STDOUT:   %.7: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %.34: i32 = int_value 0 [template]
 // CHECK:STDOUT:   %struct: %C = struct_value () [template]
-// CHECK:STDOUT:   %.8: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.9: i32 = int_value 2 [template]
-// CHECK:STDOUT:   %array: %.5 = tuple_value (%struct, %struct, %struct) [template]
+// CHECK:STDOUT:   %.35: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %.36: i32 = int_value 2 [template]
+// CHECK:STDOUT:   %array: %.32 = tuple_value (%struct, %struct, %struct) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -282,8 +308,8 @@ fn G() -> C {
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {} {}
 // CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [template = constants.%F] {
-// CHECK:STDOUT:     %N.patt.loc10_6.1: i32 = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc10_6.2 (constants.%N.patt)]
-// CHECK:STDOUT:     %N.param_patt: i32 = value_param_pattern %N.patt.loc10_6.1, runtime_param<invalid> [symbolic = %N.patt.loc10_6.2 (constants.%N.patt)]
+// CHECK:STDOUT:     %N.patt.loc10_6.1: i32 = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc10_6.2 (constants.%N.patt.1)]
+// CHECK:STDOUT:     %N.param_patt: i32 = value_param_pattern %N.patt.loc10_6.1, runtime_param<invalid> [symbolic = %N.patt.loc10_6.2 (constants.%N.patt.1)]
 // CHECK:STDOUT:     %a.patt: <error> = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: <error> = value_param_pattern %a.patt, runtime_param0
 // CHECK:STDOUT:     %return.patt: i32 = return_slot_pattern
@@ -293,13 +319,18 @@ fn G() -> C {
 // CHECK:STDOUT:     %.loc10_10.1: type = value_of_initializer %int.make_type_32.loc10_10 [template = i32]
 // CHECK:STDOUT:     %.loc10_10.2: type = converted %int.make_type_32.loc10_10, %.loc10_10.1 [template = i32]
 // CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [template = constants.%C]
-// CHECK:STDOUT:     %N.ref.loc10_22: i32 = name_ref N, %N.loc10_6.1 [symbolic = %N.loc10_6.2 (constants.%N)]
-// CHECK:STDOUT:     %.loc10_23: type = array_type %N.ref.loc10_22, %C [template = <error>]
+// CHECK:STDOUT:     %N.ref.loc10_22: i32 = name_ref N, %N.loc10_6.1 [symbolic = %N.loc10_6.2 (constants.%N.1)]
+// CHECK:STDOUT:     %.loc10_22.1: %Convert.type.2 = interface_witness_access constants.%.26, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:     %.loc10_22.2: <bound method> = bound_method %N.ref.loc10_22, %.loc10_22.1 [symbolic = %.loc10_22.5 (constants.%.27)]
+// CHECK:STDOUT:     %int.convert_checked.loc10_22.1: init Core.IntLiteral = call %.loc10_22.2(%N.ref.loc10_22) [symbolic = %int.convert_checked.loc10_22.2 (constants.%int.convert_checked)]
+// CHECK:STDOUT:     %.loc10_22.3: Core.IntLiteral = value_of_initializer %int.convert_checked.loc10_22.1 [symbolic = %int.convert_checked.loc10_22.2 (constants.%int.convert_checked)]
+// CHECK:STDOUT:     %.loc10_22.4: Core.IntLiteral = converted %N.ref.loc10_22, %.loc10_22.3 [symbolic = %int.convert_checked.loc10_22.2 (constants.%int.convert_checked)]
+// CHECK:STDOUT:     %.loc10_23: type = array_type %.loc10_22.4, %C [template = <error>]
 // CHECK:STDOUT:     %int.make_type_32.loc10_29: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:     %.loc10_29.1: type = value_of_initializer %int.make_type_32.loc10_29 [template = i32]
 // CHECK:STDOUT:     %.loc10_29.2: type = converted %int.make_type_32.loc10_29, %.loc10_29.1 [template = i32]
 // CHECK:STDOUT:     %N.param: i32 = value_param runtime_param<invalid>
-// CHECK:STDOUT:     %N.loc10_6.1: i32 = bind_symbolic_name N, 0, %N.param [symbolic = %N.loc10_6.2 (constants.%N)]
+// CHECK:STDOUT:     %N.loc10_6.1: i32 = bind_symbolic_name N, 0, %N.param [symbolic = %N.loc10_6.2 (constants.%N.1)]
 // CHECK:STDOUT:     %a.param: <error> = value_param runtime_param0
 // CHECK:STDOUT:     %a: <error> = bind_name a, %a.param
 // CHECK:STDOUT:     %return.param: ref i32 = out_param runtime_param1
@@ -323,14 +354,16 @@ fn G() -> C {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: generic fn @F(%N.loc10_6.1: i32) {
-// CHECK:STDOUT:   %N.loc10_6.2: i32 = bind_symbolic_name N, 0 [symbolic = %N.loc10_6.2 (constants.%N)]
-// CHECK:STDOUT:   %N.patt.loc10_6.2: i32 = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc10_6.2 (constants.%N.patt)]
+// CHECK:STDOUT:   %N.loc10_6.2: i32 = bind_symbolic_name N, 0 [symbolic = %N.loc10_6.2 (constants.%N.1)]
+// CHECK:STDOUT:   %N.patt.loc10_6.2: i32 = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc10_6.2 (constants.%N.patt.1)]
+// CHECK:STDOUT:   %.loc10_22.5: <bound method> = bound_method %N.loc10_6.2, constants.%Convert.15 [symbolic = %.loc10_22.5 (constants.%.27)]
+// CHECK:STDOUT:   %int.convert_checked.loc10_22.2: init Core.IntLiteral = call %.loc10_22.5(%N.loc10_6.2) [symbolic = %int.convert_checked.loc10_22.2 (constants.%int.convert_checked)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn[%N.param_patt: i32](%a.param_patt: <error>) -> i32 {
 // CHECK:STDOUT:   !entry:
-// CHECK:STDOUT:     %N.ref.loc10_42: i32 = name_ref N, %N.loc10_6.1 [symbolic = %N.loc10_6.2 (constants.%N)]
+// CHECK:STDOUT:     %N.ref.loc10_42: i32 = name_ref N, %N.loc10_6.1 [symbolic = %N.loc10_6.2 (constants.%N.1)]
 // CHECK:STDOUT:     return %N.ref.loc10_42
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -338,37 +371,44 @@ fn G() -> C {
 // CHECK:STDOUT: fn @G() -> %return: %C {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %C.ref.loc13: type = name_ref C, file.%C.decl [template = constants.%C]
-// CHECK:STDOUT:   %.loc13_14: i32 = int_value 3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc13_15: type = array_type %.loc13_14, %C [template = constants.%.5]
-// CHECK:STDOUT:   %a.var: ref %.5 = var a
-// CHECK:STDOUT:   %a: ref %.5 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc13_14.1: i32 = int_value 3 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc13_14.2: %Convert.type.2 = interface_witness_access constants.%.26, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc13_14.3: <bound method> = bound_method %.loc13_14.1, %.loc13_14.2 [template = constants.%.30]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc13_14.3(%.loc13_14.1) [template = constants.%.31]
+// CHECK:STDOUT:   %.loc13_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.31]
+// CHECK:STDOUT:   %.loc13_14.5: Core.IntLiteral = converted %.loc13_14.1, %.loc13_14.4 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc13_15: type = array_type %.loc13_14.5, %C [template = constants.%.32]
+// CHECK:STDOUT:   %a.var: ref %.32 = var a
+// CHECK:STDOUT:   %a: ref %.32 = bind_name a, %a.var
 // CHECK:STDOUT:   %.loc13_21.1: %.1 = struct_literal ()
 // CHECK:STDOUT:   %.loc13_25.1: %.1 = struct_literal ()
 // CHECK:STDOUT:   %.loc13_29.1: %.1 = struct_literal ()
 // CHECK:STDOUT:   %.loc13_30.1: %tuple.type = tuple_literal (%.loc13_21.1, %.loc13_25.1, %.loc13_29.1)
-// CHECK:STDOUT:   %.loc13_30.2: i32 = int_value 0 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc13_30.2: i32 = int_value 0 [template = constants.%.34]
 // CHECK:STDOUT:   %.loc13_30.3: ref %C = array_index %a.var, %.loc13_30.2
 // CHECK:STDOUT:   %.loc13_21.2: init %C = class_init (), %.loc13_30.3 [template = constants.%struct]
 // CHECK:STDOUT:   %.loc13_30.4: init %C = converted %.loc13_21.1, %.loc13_21.2 [template = constants.%struct]
-// CHECK:STDOUT:   %.loc13_30.5: i32 = int_value 1 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc13_30.5: i32 = int_value 1 [template = constants.%.35]
 // CHECK:STDOUT:   %.loc13_30.6: ref %C = array_index %a.var, %.loc13_30.5
 // CHECK:STDOUT:   %.loc13_25.2: init %C = class_init (), %.loc13_30.6 [template = constants.%struct]
 // CHECK:STDOUT:   %.loc13_30.7: init %C = converted %.loc13_25.1, %.loc13_25.2 [template = constants.%struct]
-// CHECK:STDOUT:   %.loc13_30.8: i32 = int_value 2 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc13_30.8: i32 = int_value 2 [template = constants.%.36]
 // CHECK:STDOUT:   %.loc13_30.9: ref %C = array_index %a.var, %.loc13_30.8
 // CHECK:STDOUT:   %.loc13_29.2: init %C = class_init (), %.loc13_30.9 [template = constants.%struct]
 // CHECK:STDOUT:   %.loc13_30.10: init %C = converted %.loc13_29.1, %.loc13_29.2 [template = constants.%struct]
-// CHECK:STDOUT:   %.loc13_30.11: init %.5 = array_init (%.loc13_30.4, %.loc13_30.7, %.loc13_30.10) to %a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc13_31: init %.5 = converted %.loc13_30.1, %.loc13_30.11 [template = constants.%array]
+// CHECK:STDOUT:   %.loc13_30.11: init %.32 = array_init (%.loc13_30.4, %.loc13_30.7, %.loc13_30.10) to %a.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc13_31: init %.32 = converted %.loc13_30.1, %.loc13_30.11 [template = constants.%array]
 // CHECK:STDOUT:   assign %a.var, %.loc13_31
 // CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F]
-// CHECK:STDOUT:   %a.ref: ref %.5 = name_ref a, %a
+// CHECK:STDOUT:   %a.ref: ref %.32 = name_ref a, %a
 // CHECK:STDOUT:   return <error> to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @F(constants.%N) {
-// CHECK:STDOUT:   %N.loc10_6.2 => constants.%N
-// CHECK:STDOUT:   %N.patt.loc10_6.2 => constants.%N
+// CHECK:STDOUT: specific @F(constants.%N.1) {
+// CHECK:STDOUT:   %N.loc10_6.2 => constants.%N.1
+// CHECK:STDOUT:   %N.patt.loc10_6.2 => constants.%N.1
+// CHECK:STDOUT:   %.loc10_22.5 => constants.%.27
+// CHECK:STDOUT:   %int.convert_checked.loc10_22.2 => constants.%int.convert_checked
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: --- fail_todo_type_and_bound.carbon
@@ -381,25 +421,34 @@ fn G() -> C {
 // CHECK:STDOUT:   %T.patt: type = symbolic_binding_pattern T, 0 [symbolic]
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
-// CHECK:STDOUT:   %N: i32 = bind_symbolic_name N, 1 [symbolic]
-// CHECK:STDOUT:   %N.patt: i32 = symbolic_binding_pattern N, 1 [symbolic]
+// CHECK:STDOUT:   %N.1: i32 = bind_symbolic_name N, 1 [symbolic]
+// CHECK:STDOUT:   %N.patt.1: i32 = symbolic_binding_pattern N, 1 [symbolic]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.26: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.27: <bound method> = bound_method %N.1, %Convert.15 [symbolic]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.27(%N.1) [symbolic]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [template]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [template]
 // CHECK:STDOUT:   %G.type: type = fn_type @G [template]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.5: type = array_type %.4, %C [template]
+// CHECK:STDOUT:   %.29: i32 = int_value 3 [template]
+// CHECK:STDOUT:   %.30: <bound method> = bound_method %.29, %Convert.15 [template]
+// CHECK:STDOUT:   %.31: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.32: type = array_type %.31, %C [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (%.1, %.1, %.1) [template]
-// CHECK:STDOUT:   %.7: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %.34: i32 = int_value 0 [template]
 // CHECK:STDOUT:   %struct: %C = struct_value () [template]
-// CHECK:STDOUT:   %.8: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.9: i32 = int_value 2 [template]
-// CHECK:STDOUT:   %array: %.5 = tuple_value (%struct, %struct, %struct) [template]
+// CHECK:STDOUT:   %.35: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %.36: i32 = int_value 2 [template]
+// CHECK:STDOUT:   %array: %.32 = tuple_value (%struct, %struct, %struct) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -417,8 +466,8 @@ fn G() -> C {
 // CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [template = constants.%F] {
 // CHECK:STDOUT:     %T.patt.loc10_6.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc10_6.2 (constants.%T.patt)]
 // CHECK:STDOUT:     %T.param_patt: type = value_param_pattern %T.patt.loc10_6.1, runtime_param<invalid> [symbolic = %T.patt.loc10_6.2 (constants.%T.patt)]
-// CHECK:STDOUT:     %N.patt.loc10_16.1: i32 = symbolic_binding_pattern N, 1 [symbolic = %N.patt.loc10_16.2 (constants.%N.patt)]
-// CHECK:STDOUT:     %N.param_patt: i32 = value_param_pattern %N.patt.loc10_16.1, runtime_param<invalid> [symbolic = %N.patt.loc10_16.2 (constants.%N.patt)]
+// CHECK:STDOUT:     %N.patt.loc10_16.1: i32 = symbolic_binding_pattern N, 1 [symbolic = %N.patt.loc10_16.2 (constants.%N.patt.1)]
+// CHECK:STDOUT:     %N.param_patt: i32 = value_param_pattern %N.patt.loc10_16.1, runtime_param<invalid> [symbolic = %N.patt.loc10_16.2 (constants.%N.patt.1)]
 // CHECK:STDOUT:     %a.patt: <error> = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: <error> = value_param_pattern %a.patt, runtime_param0
 // CHECK:STDOUT:     %return.patt: @F.%T.loc10_6.2 (%T) = return_slot_pattern
@@ -428,13 +477,18 @@ fn G() -> C {
 // CHECK:STDOUT:     %.loc10_20.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:     %.loc10_20.2: type = converted %int.make_type_32, %.loc10_20.1 [template = i32]
 // CHECK:STDOUT:     %T.ref.loc10_29: type = name_ref T, %T.loc10_6.1 [symbolic = %T.loc10_6.2 (constants.%T)]
-// CHECK:STDOUT:     %N.ref: i32 = name_ref N, %N.loc10_16.1 [symbolic = %N.loc10_16.2 (constants.%N)]
-// CHECK:STDOUT:     %.loc10_33: type = array_type %N.ref, %T [template = <error>]
+// CHECK:STDOUT:     %N.ref: i32 = name_ref N, %N.loc10_16.1 [symbolic = %N.loc10_16.2 (constants.%N.1)]
+// CHECK:STDOUT:     %.loc10_32.1: %Convert.type.2 = interface_witness_access constants.%.26, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:     %.loc10_32.2: <bound method> = bound_method %N.ref, %.loc10_32.1 [symbolic = %.loc10_32.5 (constants.%.27)]
+// CHECK:STDOUT:     %int.convert_checked.loc10_32.1: init Core.IntLiteral = call %.loc10_32.2(%N.ref) [symbolic = %int.convert_checked.loc10_32.2 (constants.%int.convert_checked)]
+// CHECK:STDOUT:     %.loc10_32.3: Core.IntLiteral = value_of_initializer %int.convert_checked.loc10_32.1 [symbolic = %int.convert_checked.loc10_32.2 (constants.%int.convert_checked)]
+// CHECK:STDOUT:     %.loc10_32.4: Core.IntLiteral = converted %N.ref, %.loc10_32.3 [symbolic = %int.convert_checked.loc10_32.2 (constants.%int.convert_checked)]
+// CHECK:STDOUT:     %.loc10_33: type = array_type %.loc10_32.4, %T [template = <error>]
 // CHECK:STDOUT:     %T.ref.loc10_39: type = name_ref T, %T.loc10_6.1 [symbolic = %T.loc10_6.2 (constants.%T)]
 // CHECK:STDOUT:     %T.param: type = value_param runtime_param<invalid>
 // CHECK:STDOUT:     %T.loc10_6.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc10_6.2 (constants.%T)]
 // CHECK:STDOUT:     %N.param: i32 = value_param runtime_param<invalid>
-// CHECK:STDOUT:     %N.loc10_16.1: i32 = bind_symbolic_name N, 1, %N.param [symbolic = %N.loc10_16.2 (constants.%N)]
+// CHECK:STDOUT:     %N.loc10_16.1: i32 = bind_symbolic_name N, 1, %N.param [symbolic = %N.loc10_16.2 (constants.%N.1)]
 // CHECK:STDOUT:     %a.param: <error> = value_param runtime_param0
 // CHECK:STDOUT:     %a: <error> = bind_name a, %a.param
 // CHECK:STDOUT:     %return.param: ref @F.%T.loc10_6.2 (%T) = out_param runtime_param1
@@ -460,8 +514,10 @@ fn G() -> C {
 // CHECK:STDOUT: generic fn @F(%T.loc10_6.1: type, %N.loc10_16.1: i32) {
 // CHECK:STDOUT:   %T.loc10_6.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc10_6.2 (constants.%T)]
 // CHECK:STDOUT:   %T.patt.loc10_6.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc10_6.2 (constants.%T.patt)]
-// CHECK:STDOUT:   %N.loc10_16.2: i32 = bind_symbolic_name N, 1 [symbolic = %N.loc10_16.2 (constants.%N)]
-// CHECK:STDOUT:   %N.patt.loc10_16.2: i32 = symbolic_binding_pattern N, 1 [symbolic = %N.patt.loc10_16.2 (constants.%N.patt)]
+// CHECK:STDOUT:   %N.loc10_16.2: i32 = bind_symbolic_name N, 1 [symbolic = %N.loc10_16.2 (constants.%N.1)]
+// CHECK:STDOUT:   %N.patt.loc10_16.2: i32 = symbolic_binding_pattern N, 1 [symbolic = %N.patt.loc10_16.2 (constants.%N.patt.1)]
+// CHECK:STDOUT:   %.loc10_32.5: <bound method> = bound_method %N.loc10_16.2, constants.%Convert.15 [symbolic = %.loc10_32.5 (constants.%.27)]
+// CHECK:STDOUT:   %int.convert_checked.loc10_32.2: init Core.IntLiteral = call %.loc10_32.5(%N.loc10_16.2) [symbolic = %int.convert_checked.loc10_32.2 (constants.%int.convert_checked)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn[%T.param_patt: type, %N.param_patt: i32](%a.param_patt: <error>) -> @F.%T.loc10_6.2 (%T);
 // CHECK:STDOUT: }
@@ -469,39 +525,46 @@ fn G() -> C {
 // CHECK:STDOUT: fn @G() -> %return: %C {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %C.ref.loc13: type = name_ref C, file.%C.decl [template = constants.%C]
-// CHECK:STDOUT:   %.loc13_14: i32 = int_value 3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc13_15: type = array_type %.loc13_14, %C [template = constants.%.5]
-// CHECK:STDOUT:   %a.var: ref %.5 = var a
-// CHECK:STDOUT:   %a: ref %.5 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc13_14.1: i32 = int_value 3 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc13_14.2: %Convert.type.2 = interface_witness_access constants.%.26, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc13_14.3: <bound method> = bound_method %.loc13_14.1, %.loc13_14.2 [template = constants.%.30]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc13_14.3(%.loc13_14.1) [template = constants.%.31]
+// CHECK:STDOUT:   %.loc13_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.31]
+// CHECK:STDOUT:   %.loc13_14.5: Core.IntLiteral = converted %.loc13_14.1, %.loc13_14.4 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc13_15: type = array_type %.loc13_14.5, %C [template = constants.%.32]
+// CHECK:STDOUT:   %a.var: ref %.32 = var a
+// CHECK:STDOUT:   %a: ref %.32 = bind_name a, %a.var
 // CHECK:STDOUT:   %.loc13_21.1: %.1 = struct_literal ()
 // CHECK:STDOUT:   %.loc13_25.1: %.1 = struct_literal ()
 // CHECK:STDOUT:   %.loc13_29.1: %.1 = struct_literal ()
 // CHECK:STDOUT:   %.loc13_30.1: %tuple.type = tuple_literal (%.loc13_21.1, %.loc13_25.1, %.loc13_29.1)
-// CHECK:STDOUT:   %.loc13_30.2: i32 = int_value 0 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc13_30.2: i32 = int_value 0 [template = constants.%.34]
 // CHECK:STDOUT:   %.loc13_30.3: ref %C = array_index %a.var, %.loc13_30.2
 // CHECK:STDOUT:   %.loc13_21.2: init %C = class_init (), %.loc13_30.3 [template = constants.%struct]
 // CHECK:STDOUT:   %.loc13_30.4: init %C = converted %.loc13_21.1, %.loc13_21.2 [template = constants.%struct]
-// CHECK:STDOUT:   %.loc13_30.5: i32 = int_value 1 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc13_30.5: i32 = int_value 1 [template = constants.%.35]
 // CHECK:STDOUT:   %.loc13_30.6: ref %C = array_index %a.var, %.loc13_30.5
 // CHECK:STDOUT:   %.loc13_25.2: init %C = class_init (), %.loc13_30.6 [template = constants.%struct]
 // CHECK:STDOUT:   %.loc13_30.7: init %C = converted %.loc13_25.1, %.loc13_25.2 [template = constants.%struct]
-// CHECK:STDOUT:   %.loc13_30.8: i32 = int_value 2 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc13_30.8: i32 = int_value 2 [template = constants.%.36]
 // CHECK:STDOUT:   %.loc13_30.9: ref %C = array_index %a.var, %.loc13_30.8
 // CHECK:STDOUT:   %.loc13_29.2: init %C = class_init (), %.loc13_30.9 [template = constants.%struct]
 // CHECK:STDOUT:   %.loc13_30.10: init %C = converted %.loc13_29.1, %.loc13_29.2 [template = constants.%struct]
-// CHECK:STDOUT:   %.loc13_30.11: init %.5 = array_init (%.loc13_30.4, %.loc13_30.7, %.loc13_30.10) to %a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc13_31: init %.5 = converted %.loc13_30.1, %.loc13_30.11 [template = constants.%array]
+// CHECK:STDOUT:   %.loc13_30.11: init %.32 = array_init (%.loc13_30.4, %.loc13_30.7, %.loc13_30.10) to %a.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc13_31: init %.32 = converted %.loc13_30.1, %.loc13_30.11 [template = constants.%array]
 // CHECK:STDOUT:   assign %a.var, %.loc13_31
 // CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F]
-// CHECK:STDOUT:   %a.ref: ref %.5 = name_ref a, %a
+// CHECK:STDOUT:   %a.ref: ref %.32 = name_ref a, %a
 // CHECK:STDOUT:   return <error> to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @F(constants.%T, constants.%N) {
+// CHECK:STDOUT: specific @F(constants.%T, constants.%N.1) {
 // CHECK:STDOUT:   %T.loc10_6.2 => constants.%T
 // CHECK:STDOUT:   %T.patt.loc10_6.2 => constants.%T
-// CHECK:STDOUT:   %N.loc10_16.2 => constants.%N
-// CHECK:STDOUT:   %N.patt.loc10_16.2 => constants.%N
+// CHECK:STDOUT:   %N.loc10_16.2 => constants.%N.1
+// CHECK:STDOUT:   %N.patt.loc10_16.2 => constants.%N.1
+// CHECK:STDOUT:   %.loc10_32.5 => constants.%.27
+// CHECK:STDOUT:   %int.convert_checked.loc10_32.2 => constants.%int.convert_checked
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: --- fail_bound_mismatch.carbon
@@ -513,20 +576,28 @@ fn G() -> C {
 // CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
 // CHECK:STDOUT:   %T.patt: type = symbolic_binding_pattern T, 0 [symbolic]
 // CHECK:STDOUT:   %.3: i32 = int_value 2 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, %T [symbolic]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.27: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.28: <bound method> = bound_method %.3, %Convert.15 [template]
+// CHECK:STDOUT:   %.29: Core.IntLiteral = int_value 2 [template]
+// CHECK:STDOUT:   %.30: type = array_type %.29, %T [symbolic]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [template]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [template]
-// CHECK:STDOUT:   %.6: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %.32: i32 = int_value 0 [template]
 // CHECK:STDOUT:   %G.type: type = fn_type @G [template]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [template]
-// CHECK:STDOUT:   %.8: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.9: type = array_type %.8, %C [template]
+// CHECK:STDOUT:   %.34: i32 = int_value 3 [template]
+// CHECK:STDOUT:   %.35: <bound method> = bound_method %.34, %Convert.15 [template]
+// CHECK:STDOUT:   %.36: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.37: type = array_type %.36, %C [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (%.1, %.1, %.1) [template]
 // CHECK:STDOUT:   %struct: %C = struct_value () [template]
-// CHECK:STDOUT:   %.11: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %array: %.9 = tuple_value (%struct, %struct, %struct) [template]
-// CHECK:STDOUT:   %.12: type = array_type %.3, %C [template]
-// CHECK:STDOUT:   %.13: <specific function> = specific_function %F, @F(%C) [template]
+// CHECK:STDOUT:   %.39: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %array: %.37 = tuple_value (%struct, %struct, %struct) [template]
+// CHECK:STDOUT:   %.40: type = array_type %.29, %C [template]
+// CHECK:STDOUT:   %.41: <specific function> = specific_function %F, @F(%C) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -549,19 +620,24 @@ fn G() -> C {
 // CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [template = constants.%F] {
 // CHECK:STDOUT:     %T.patt.loc6_6.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc6_6.2 (constants.%T.patt)]
 // CHECK:STDOUT:     %T.param_patt: type = value_param_pattern %T.patt.loc6_6.1, runtime_param<invalid> [symbolic = %T.patt.loc6_6.2 (constants.%T.patt)]
-// CHECK:STDOUT:     %a.patt: @F.%.loc6_24.2 (%.4) = binding_pattern a
-// CHECK:STDOUT:     %a.param_patt: @F.%.loc6_24.2 (%.4) = value_param_pattern %a.patt, runtime_param0
+// CHECK:STDOUT:     %a.patt: @F.%.loc6_24.2 (%.30) = binding_pattern a
+// CHECK:STDOUT:     %a.param_patt: @F.%.loc6_24.2 (%.30) = value_param_pattern %a.patt, runtime_param0
 // CHECK:STDOUT:     %return.patt: @F.%T.loc6_6.2 (%T) = return_slot_pattern
 // CHECK:STDOUT:     %return.param_patt: @F.%T.loc6_6.2 (%T) = out_param_pattern %return.patt, runtime_param1
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %T.ref.loc6_20: type = name_ref T, %T.loc6_6.1 [symbolic = %T.loc6_6.2 (constants.%T)]
-// CHECK:STDOUT:     %.loc6_23: i32 = int_value 2 [template = constants.%.3]
-// CHECK:STDOUT:     %.loc6_24.1: type = array_type %.loc6_23, %T [symbolic = %.loc6_24.2 (constants.%.4)]
+// CHECK:STDOUT:     %.loc6_23.1: i32 = int_value 2 [template = constants.%.3]
+// CHECK:STDOUT:     %.loc6_23.2: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:     %.loc6_23.3: <bound method> = bound_method %.loc6_23.1, %.loc6_23.2 [template = constants.%.28]
+// CHECK:STDOUT:     %int.convert_checked: init Core.IntLiteral = call %.loc6_23.3(%.loc6_23.1) [template = constants.%.29]
+// CHECK:STDOUT:     %.loc6_23.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.29]
+// CHECK:STDOUT:     %.loc6_23.5: Core.IntLiteral = converted %.loc6_23.1, %.loc6_23.4 [template = constants.%.29]
+// CHECK:STDOUT:     %.loc6_24.1: type = array_type %.loc6_23.5, %T [symbolic = %.loc6_24.2 (constants.%.30)]
 // CHECK:STDOUT:     %T.ref.loc6_30: type = name_ref T, %T.loc6_6.1 [symbolic = %T.loc6_6.2 (constants.%T)]
 // CHECK:STDOUT:     %T.param: type = value_param runtime_param<invalid>
 // CHECK:STDOUT:     %T.loc6_6.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc6_6.2 (constants.%T)]
-// CHECK:STDOUT:     %a.param: @F.%.loc6_24.2 (%.4) = value_param runtime_param0
-// CHECK:STDOUT:     %a: @F.%.loc6_24.2 (%.4) = bind_name a, %a.param
+// CHECK:STDOUT:     %a.param: @F.%.loc6_24.2 (%.30) = value_param runtime_param0
+// CHECK:STDOUT:     %a: @F.%.loc6_24.2 (%.30) = bind_name a, %a.param
 // CHECK:STDOUT:     %return.param: ref @F.%T.loc6_6.2 (%T) = out_param runtime_param1
 // CHECK:STDOUT:     %return: ref @F.%T.loc6_6.2 (%T) = return_slot %return.param
 // CHECK:STDOUT:   }
@@ -585,15 +661,15 @@ fn G() -> C {
 // CHECK:STDOUT: generic fn @F(%T.loc6_6.1: type) {
 // CHECK:STDOUT:   %T.loc6_6.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc6_6.2 (constants.%T)]
 // CHECK:STDOUT:   %T.patt.loc6_6.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc6_6.2 (constants.%T.patt)]
-// CHECK:STDOUT:   %.loc6_24.2: type = array_type constants.%.3, @F.%T.loc6_6.2 (%T) [symbolic = %.loc6_24.2 (constants.%.4)]
+// CHECK:STDOUT:   %.loc6_24.2: type = array_type constants.%.29, @F.%T.loc6_6.2 (%T) [symbolic = %.loc6_24.2 (constants.%.30)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn[%T.param_patt: type](%a.param_patt: @F.%.loc6_24.2 (%.4)) -> @F.%T.loc6_6.2 (%T) {
+// CHECK:STDOUT:   fn[%T.param_patt: type](%a.param_patt: @F.%.loc6_24.2 (%.30)) -> @F.%T.loc6_6.2 (%T) {
 // CHECK:STDOUT:   !entry:
-// CHECK:STDOUT:     %a.ref: @F.%.loc6_24.2 (%.4) = name_ref a, %a
-// CHECK:STDOUT:     %.loc6_43: i32 = int_value 0 [template = constants.%.6]
-// CHECK:STDOUT:     %.loc6_44.1: ref @F.%.loc6_24.2 (%.4) = value_as_ref %a.ref
+// CHECK:STDOUT:     %a.ref: @F.%.loc6_24.2 (%.30) = name_ref a, %a
+// CHECK:STDOUT:     %.loc6_43: i32 = int_value 0 [template = constants.%.32]
+// CHECK:STDOUT:     %.loc6_44.1: ref @F.%.loc6_24.2 (%.30) = value_as_ref %a.ref
 // CHECK:STDOUT:     %.loc6_44.2: ref @F.%T.loc6_6.2 (%T) = array_index %.loc6_44.1, %.loc6_43
 // CHECK:STDOUT:     %.loc6_44.3: @F.%T.loc6_6.2 (%T) = bind_value %.loc6_44.2
 // CHECK:STDOUT:     return %.loc6_44.3
@@ -603,19 +679,24 @@ fn G() -> C {
 // CHECK:STDOUT: fn @G() -> %return: %C {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %C.ref.loc10: type = name_ref C, file.%C.decl [template = constants.%C]
-// CHECK:STDOUT:   %.loc10_14: i32 = int_value 3 [template = constants.%.8]
-// CHECK:STDOUT:   %.loc10_15: type = array_type %.loc10_14, %C [template = constants.%.9]
-// CHECK:STDOUT:   %a.var: ref %.9 = var a
-// CHECK:STDOUT:   %a: ref %.9 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc10_14.1: i32 = int_value 3 [template = constants.%.34]
+// CHECK:STDOUT:   %.loc10_14.2: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc10_14.3: <bound method> = bound_method %.loc10_14.1, %.loc10_14.2 [template = constants.%.35]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc10_14.3(%.loc10_14.1) [template = constants.%.36]
+// CHECK:STDOUT:   %.loc10_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.36]
+// CHECK:STDOUT:   %.loc10_14.5: Core.IntLiteral = converted %.loc10_14.1, %.loc10_14.4 [template = constants.%.36]
+// CHECK:STDOUT:   %.loc10_15: type = array_type %.loc10_14.5, %C [template = constants.%.37]
+// CHECK:STDOUT:   %a.var: ref %.37 = var a
+// CHECK:STDOUT:   %a: ref %.37 = bind_name a, %a.var
 // CHECK:STDOUT:   %.loc10_21.1: %.1 = struct_literal ()
 // CHECK:STDOUT:   %.loc10_25.1: %.1 = struct_literal ()
 // CHECK:STDOUT:   %.loc10_29.1: %.1 = struct_literal ()
 // CHECK:STDOUT:   %.loc10_30.1: %tuple.type = tuple_literal (%.loc10_21.1, %.loc10_25.1, %.loc10_29.1)
-// CHECK:STDOUT:   %.loc10_30.2: i32 = int_value 0 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc10_30.2: i32 = int_value 0 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc10_30.3: ref %C = array_index %a.var, %.loc10_30.2
 // CHECK:STDOUT:   %.loc10_21.2: init %C = class_init (), %.loc10_30.3 [template = constants.%struct]
 // CHECK:STDOUT:   %.loc10_30.4: init %C = converted %.loc10_21.1, %.loc10_21.2 [template = constants.%struct]
-// CHECK:STDOUT:   %.loc10_30.5: i32 = int_value 1 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc10_30.5: i32 = int_value 1 [template = constants.%.39]
 // CHECK:STDOUT:   %.loc10_30.6: ref %C = array_index %a.var, %.loc10_30.5
 // CHECK:STDOUT:   %.loc10_25.2: init %C = class_init (), %.loc10_30.6 [template = constants.%struct]
 // CHECK:STDOUT:   %.loc10_30.7: init %C = converted %.loc10_25.1, %.loc10_25.2 [template = constants.%struct]
@@ -623,14 +704,14 @@ fn G() -> C {
 // CHECK:STDOUT:   %.loc10_30.9: ref %C = array_index %a.var, %.loc10_30.8
 // CHECK:STDOUT:   %.loc10_29.2: init %C = class_init (), %.loc10_30.9 [template = constants.%struct]
 // CHECK:STDOUT:   %.loc10_30.10: init %C = converted %.loc10_29.1, %.loc10_29.2 [template = constants.%struct]
-// CHECK:STDOUT:   %.loc10_30.11: init %.9 = array_init (%.loc10_30.4, %.loc10_30.7, %.loc10_30.10) to %a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc10_31: init %.9 = converted %.loc10_30.1, %.loc10_30.11 [template = constants.%array]
+// CHECK:STDOUT:   %.loc10_30.11: init %.37 = array_init (%.loc10_30.4, %.loc10_30.7, %.loc10_30.10) to %a.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc10_31: init %.37 = converted %.loc10_30.1, %.loc10_30.11 [template = constants.%array]
 // CHECK:STDOUT:   assign %a.var, %.loc10_31
 // CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F]
-// CHECK:STDOUT:   %a.ref: ref %.9 = name_ref a, %a
-// CHECK:STDOUT:   %.loc21_10: <specific function> = specific_function %F.ref, @F(constants.%C) [template = constants.%.13]
+// CHECK:STDOUT:   %a.ref: ref %.37 = name_ref a, %a
+// CHECK:STDOUT:   %.loc21_10: <specific function> = specific_function %F.ref, @F(constants.%C) [template = constants.%.41]
 // CHECK:STDOUT:   %.loc8_8.2: ref %C = splice_block %return {}
-// CHECK:STDOUT:   %.loc21_12: %.12 = converted %a.ref, <error> [template = <error>]
+// CHECK:STDOUT:   %.loc21_12: %.40 = converted %a.ref, <error> [template = <error>]
 // CHECK:STDOUT:   %F.call: init %C = call %.loc21_10(<error>) to %.loc8_8.2
 // CHECK:STDOUT:   return %F.call to %return
 // CHECK:STDOUT: }
@@ -638,13 +719,13 @@ fn G() -> C {
 // CHECK:STDOUT: specific @F(constants.%T) {
 // CHECK:STDOUT:   %T.loc6_6.2 => constants.%T
 // CHECK:STDOUT:   %T.patt.loc6_6.2 => constants.%T
-// CHECK:STDOUT:   %.loc6_24.2 => constants.%.4
+// CHECK:STDOUT:   %.loc6_24.2 => constants.%.30
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @F(constants.%C) {
 // CHECK:STDOUT:   %T.loc6_6.2 => constants.%C
 // CHECK:STDOUT:   %T.patt.loc6_6.2 => constants.%C
-// CHECK:STDOUT:   %.loc6_24.2 => constants.%.12
+// CHECK:STDOUT:   %.loc6_24.2 => constants.%.40
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT: }
@@ -658,25 +739,34 @@ fn G() -> C {
 // CHECK:STDOUT:   %D: type = class_type @D [template]
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
-// CHECK:STDOUT:   %N: i32 = bind_symbolic_name N, 0 [symbolic]
-// CHECK:STDOUT:   %N.patt: i32 = symbolic_binding_pattern N, 0 [symbolic]
+// CHECK:STDOUT:   %N.1: i32 = bind_symbolic_name N, 0 [symbolic]
+// CHECK:STDOUT:   %N.patt.1: i32 = symbolic_binding_pattern N, 0 [symbolic]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.26: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.27: <bound method> = bound_method %N.1, %Convert.15 [symbolic]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.27(%N.1) [symbolic]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [template]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [template]
 // CHECK:STDOUT:   %G.type: type = fn_type @G [template]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.5: type = array_type %.4, %D [template]
+// CHECK:STDOUT:   %.29: i32 = int_value 3 [template]
+// CHECK:STDOUT:   %.30: <bound method> = bound_method %.29, %Convert.15 [template]
+// CHECK:STDOUT:   %.31: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.32: type = array_type %.31, %D [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (%.1, %.1, %.1) [template]
-// CHECK:STDOUT:   %.7: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %.34: i32 = int_value 0 [template]
 // CHECK:STDOUT:   %struct: %D = struct_value () [template]
-// CHECK:STDOUT:   %.8: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.9: i32 = int_value 2 [template]
-// CHECK:STDOUT:   %array: %.5 = tuple_value (%struct, %struct, %struct) [template]
+// CHECK:STDOUT:   %.35: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %.36: i32 = int_value 2 [template]
+// CHECK:STDOUT:   %array: %.32 = tuple_value (%struct, %struct, %struct) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -694,8 +784,8 @@ fn G() -> C {
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {} {}
 // CHECK:STDOUT:   %D.decl: type = class_decl @D [template = constants.%D] {} {}
 // CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [template = constants.%F] {
-// CHECK:STDOUT:     %N.patt.loc10_6.1: i32 = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc10_6.2 (constants.%N.patt)]
-// CHECK:STDOUT:     %N.param_patt: i32 = value_param_pattern %N.patt.loc10_6.1, runtime_param<invalid> [symbolic = %N.patt.loc10_6.2 (constants.%N.patt)]
+// CHECK:STDOUT:     %N.patt.loc10_6.1: i32 = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc10_6.2 (constants.%N.patt.1)]
+// CHECK:STDOUT:     %N.param_patt: i32 = value_param_pattern %N.patt.loc10_6.1, runtime_param<invalid> [symbolic = %N.patt.loc10_6.2 (constants.%N.patt.1)]
 // CHECK:STDOUT:     %a.patt: <error> = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: <error> = value_param_pattern %a.patt, runtime_param0
 // CHECK:STDOUT:     %return.patt: i32 = return_slot_pattern
@@ -705,13 +795,18 @@ fn G() -> C {
 // CHECK:STDOUT:     %.loc10_10.1: type = value_of_initializer %int.make_type_32.loc10_10 [template = i32]
 // CHECK:STDOUT:     %.loc10_10.2: type = converted %int.make_type_32.loc10_10, %.loc10_10.1 [template = i32]
 // CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [template = constants.%C]
-// CHECK:STDOUT:     %N.ref.loc10_22: i32 = name_ref N, %N.loc10_6.1 [symbolic = %N.loc10_6.2 (constants.%N)]
-// CHECK:STDOUT:     %.loc10_23: type = array_type %N.ref.loc10_22, %C [template = <error>]
+// CHECK:STDOUT:     %N.ref.loc10_22: i32 = name_ref N, %N.loc10_6.1 [symbolic = %N.loc10_6.2 (constants.%N.1)]
+// CHECK:STDOUT:     %.loc10_22.1: %Convert.type.2 = interface_witness_access constants.%.26, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:     %.loc10_22.2: <bound method> = bound_method %N.ref.loc10_22, %.loc10_22.1 [symbolic = %.loc10_22.5 (constants.%.27)]
+// CHECK:STDOUT:     %int.convert_checked.loc10_22.1: init Core.IntLiteral = call %.loc10_22.2(%N.ref.loc10_22) [symbolic = %int.convert_checked.loc10_22.2 (constants.%int.convert_checked)]
+// CHECK:STDOUT:     %.loc10_22.3: Core.IntLiteral = value_of_initializer %int.convert_checked.loc10_22.1 [symbolic = %int.convert_checked.loc10_22.2 (constants.%int.convert_checked)]
+// CHECK:STDOUT:     %.loc10_22.4: Core.IntLiteral = converted %N.ref.loc10_22, %.loc10_22.3 [symbolic = %int.convert_checked.loc10_22.2 (constants.%int.convert_checked)]
+// CHECK:STDOUT:     %.loc10_23: type = array_type %.loc10_22.4, %C [template = <error>]
 // CHECK:STDOUT:     %int.make_type_32.loc10_29: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:     %.loc10_29.1: type = value_of_initializer %int.make_type_32.loc10_29 [template = i32]
 // CHECK:STDOUT:     %.loc10_29.2: type = converted %int.make_type_32.loc10_29, %.loc10_29.1 [template = i32]
 // CHECK:STDOUT:     %N.param: i32 = value_param runtime_param<invalid>
-// CHECK:STDOUT:     %N.loc10_6.1: i32 = bind_symbolic_name N, 0, %N.param [symbolic = %N.loc10_6.2 (constants.%N)]
+// CHECK:STDOUT:     %N.loc10_6.1: i32 = bind_symbolic_name N, 0, %N.param [symbolic = %N.loc10_6.2 (constants.%N.1)]
 // CHECK:STDOUT:     %a.param: <error> = value_param runtime_param0
 // CHECK:STDOUT:     %a: <error> = bind_name a, %a.param
 // CHECK:STDOUT:     %return.param: ref i32 = out_param runtime_param1
@@ -742,14 +837,16 @@ fn G() -> C {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: generic fn @F(%N.loc10_6.1: i32) {
-// CHECK:STDOUT:   %N.loc10_6.2: i32 = bind_symbolic_name N, 0 [symbolic = %N.loc10_6.2 (constants.%N)]
-// CHECK:STDOUT:   %N.patt.loc10_6.2: i32 = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc10_6.2 (constants.%N.patt)]
+// CHECK:STDOUT:   %N.loc10_6.2: i32 = bind_symbolic_name N, 0 [symbolic = %N.loc10_6.2 (constants.%N.1)]
+// CHECK:STDOUT:   %N.patt.loc10_6.2: i32 = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc10_6.2 (constants.%N.patt.1)]
+// CHECK:STDOUT:   %.loc10_22.5: <bound method> = bound_method %N.loc10_6.2, constants.%Convert.15 [symbolic = %.loc10_22.5 (constants.%.27)]
+// CHECK:STDOUT:   %int.convert_checked.loc10_22.2: init Core.IntLiteral = call %.loc10_22.5(%N.loc10_6.2) [symbolic = %int.convert_checked.loc10_22.2 (constants.%int.convert_checked)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn[%N.param_patt: i32](%a.param_patt: <error>) -> i32 {
 // CHECK:STDOUT:   !entry:
-// CHECK:STDOUT:     %N.ref.loc10_42: i32 = name_ref N, %N.loc10_6.1 [symbolic = %N.loc10_6.2 (constants.%N)]
+// CHECK:STDOUT:     %N.ref.loc10_42: i32 = name_ref N, %N.loc10_6.1 [symbolic = %N.loc10_6.2 (constants.%N.1)]
 // CHECK:STDOUT:     return %N.ref.loc10_42
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -757,36 +854,43 @@ fn G() -> C {
 // CHECK:STDOUT: fn @G() -> %return: %C {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %D.ref: type = name_ref D, file.%D.decl [template = constants.%D]
-// CHECK:STDOUT:   %.loc13_14: i32 = int_value 3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc13_15: type = array_type %.loc13_14, %D [template = constants.%.5]
-// CHECK:STDOUT:   %a.var: ref %.5 = var a
-// CHECK:STDOUT:   %a: ref %.5 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc13_14.1: i32 = int_value 3 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc13_14.2: %Convert.type.2 = interface_witness_access constants.%.26, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc13_14.3: <bound method> = bound_method %.loc13_14.1, %.loc13_14.2 [template = constants.%.30]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc13_14.3(%.loc13_14.1) [template = constants.%.31]
+// CHECK:STDOUT:   %.loc13_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.31]
+// CHECK:STDOUT:   %.loc13_14.5: Core.IntLiteral = converted %.loc13_14.1, %.loc13_14.4 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc13_15: type = array_type %.loc13_14.5, %D [template = constants.%.32]
+// CHECK:STDOUT:   %a.var: ref %.32 = var a
+// CHECK:STDOUT:   %a: ref %.32 = bind_name a, %a.var
 // CHECK:STDOUT:   %.loc13_21.1: %.1 = struct_literal ()
 // CHECK:STDOUT:   %.loc13_25.1: %.1 = struct_literal ()
 // CHECK:STDOUT:   %.loc13_29.1: %.1 = struct_literal ()
 // CHECK:STDOUT:   %.loc13_30.1: %tuple.type = tuple_literal (%.loc13_21.1, %.loc13_25.1, %.loc13_29.1)
-// CHECK:STDOUT:   %.loc13_30.2: i32 = int_value 0 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc13_30.2: i32 = int_value 0 [template = constants.%.34]
 // CHECK:STDOUT:   %.loc13_30.3: ref %D = array_index %a.var, %.loc13_30.2
 // CHECK:STDOUT:   %.loc13_21.2: init %D = class_init (), %.loc13_30.3 [template = constants.%struct]
 // CHECK:STDOUT:   %.loc13_30.4: init %D = converted %.loc13_21.1, %.loc13_21.2 [template = constants.%struct]
-// CHECK:STDOUT:   %.loc13_30.5: i32 = int_value 1 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc13_30.5: i32 = int_value 1 [template = constants.%.35]
 // CHECK:STDOUT:   %.loc13_30.6: ref %D = array_index %a.var, %.loc13_30.5
 // CHECK:STDOUT:   %.loc13_25.2: init %D = class_init (), %.loc13_30.6 [template = constants.%struct]
 // CHECK:STDOUT:   %.loc13_30.7: init %D = converted %.loc13_25.1, %.loc13_25.2 [template = constants.%struct]
-// CHECK:STDOUT:   %.loc13_30.8: i32 = int_value 2 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc13_30.8: i32 = int_value 2 [template = constants.%.36]
 // CHECK:STDOUT:   %.loc13_30.9: ref %D = array_index %a.var, %.loc13_30.8
 // CHECK:STDOUT:   %.loc13_29.2: init %D = class_init (), %.loc13_30.9 [template = constants.%struct]
 // CHECK:STDOUT:   %.loc13_30.10: init %D = converted %.loc13_29.1, %.loc13_29.2 [template = constants.%struct]
-// CHECK:STDOUT:   %.loc13_30.11: init %.5 = array_init (%.loc13_30.4, %.loc13_30.7, %.loc13_30.10) to %a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc13_31: init %.5 = converted %.loc13_30.1, %.loc13_30.11 [template = constants.%array]
+// CHECK:STDOUT:   %.loc13_30.11: init %.32 = array_init (%.loc13_30.4, %.loc13_30.7, %.loc13_30.10) to %a.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc13_31: init %.32 = converted %.loc13_30.1, %.loc13_30.11 [template = constants.%array]
 // CHECK:STDOUT:   assign %a.var, %.loc13_31
 // CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F]
-// CHECK:STDOUT:   %a.ref: ref %.5 = name_ref a, %a
+// CHECK:STDOUT:   %a.ref: ref %.32 = name_ref a, %a
 // CHECK:STDOUT:   return <error> to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @F(constants.%N) {
-// CHECK:STDOUT:   %N.loc10_6.2 => constants.%N
-// CHECK:STDOUT:   %N.patt.loc10_6.2 => constants.%N
+// CHECK:STDOUT: specific @F(constants.%N.1) {
+// CHECK:STDOUT:   %N.loc10_6.2 => constants.%N.1
+// CHECK:STDOUT:   %N.patt.loc10_6.2 => constants.%N.1
+// CHECK:STDOUT:   %.loc10_22.5 => constants.%.27
+// CHECK:STDOUT:   %int.convert_checked.loc10_22.2 => constants.%int.convert_checked
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 67 - 40
toolchain/check/testdata/eval/aggregate.carbon

@@ -32,22 +32,29 @@ var struct_access: [i32; 1] = (0,) as [i32; {.a = 3, .b = 1}.b];
 // CHECK:STDOUT:   %.8: type = struct_type {.b: i32, .a: i32, .c: i32} [template]
 // CHECK:STDOUT:   %struct.1: %.8 = struct_value (%.3, %.2, %.6) [template]
 // CHECK:STDOUT:   %struct.2: %.4 = struct_value (%.2, %.3, %.6) [template]
-// CHECK:STDOUT:   %.10: type = array_type %.2, i32 [template]
-// CHECK:STDOUT:   %.12: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.33: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.34: <bound method> = bound_method %.2, %Convert.15 [template]
+// CHECK:STDOUT:   %.35: Core.IntLiteral = int_value 1 [template]
+// CHECK:STDOUT:   %.36: type = array_type %.35, i32 [template]
+// CHECK:STDOUT:   %.38: i32 = int_value 0 [template]
 // CHECK:STDOUT:   %tuple.type.3: type = tuple_type (i32) [template]
-// CHECK:STDOUT:   %.13: i32 = int_value 5 [template]
-// CHECK:STDOUT:   %.14: i32 = int_value 7 [template]
-// CHECK:STDOUT:   %.15: i32 = int_value 9 [template]
+// CHECK:STDOUT:   %.39: i32 = int_value 5 [template]
+// CHECK:STDOUT:   %.40: i32 = int_value 7 [template]
+// CHECK:STDOUT:   %.41: i32 = int_value 9 [template]
 // CHECK:STDOUT:   %tuple.type.4: type = tuple_type (i32, i32, i32, i32) [template]
-// CHECK:STDOUT:   %tuple.2: %tuple.type.4 = tuple_value (%.13, %.14, %.2, %.15) [template]
-// CHECK:STDOUT:   %array: %.10 = tuple_value (%.12) [template]
-// CHECK:STDOUT:   %.17: type = struct_type {.a: i32, .b: i32} [template]
-// CHECK:STDOUT:   %struct.3: %.17 = struct_value (%.6, %.2) [template]
+// CHECK:STDOUT:   %tuple.2: %tuple.type.4 = tuple_value (%.39, %.40, %.2, %.41) [template]
+// CHECK:STDOUT:   %array: %.36 = tuple_value (%.38) [template]
+// CHECK:STDOUT:   %.43: type = struct_type {.a: i32, .b: i32} [template]
+// CHECK:STDOUT:   %struct.3: %.43 = struct_value (%.6, %.2) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -85,19 +92,29 @@ var struct_access: [i32; 1] = (0,) as [i32; {.a = 3, .b = 1}.b];
 // CHECK:STDOUT:   %struct_copy.var: ref %.4 = var struct_copy
 // CHECK:STDOUT:   %struct_copy: ref %.4 = bind_name struct_copy, %struct_copy.var
 // CHECK:STDOUT:   %int.make_type_32.loc15: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc15_24: i32 = int_value 1 [template = constants.%.2]
+// CHECK:STDOUT:   %.loc15_24.1: i32 = int_value 1 [template = constants.%.2]
 // CHECK:STDOUT:   %.loc15_19.1: type = value_of_initializer %int.make_type_32.loc15 [template = i32]
 // CHECK:STDOUT:   %.loc15_19.2: type = converted %int.make_type_32.loc15, %.loc15_19.1 [template = i32]
-// CHECK:STDOUT:   %.loc15_25: type = array_type %.loc15_24, i32 [template = constants.%.10]
-// CHECK:STDOUT:   %tuple_index.var: ref %.10 = var tuple_index
-// CHECK:STDOUT:   %tuple_index: ref %.10 = bind_name tuple_index, %tuple_index.var
+// CHECK:STDOUT:   %.loc15_24.2: %Convert.type.2 = interface_witness_access constants.%.33, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc15_24.3: <bound method> = bound_method %.loc15_24.1, %.loc15_24.2 [template = constants.%.34]
+// CHECK:STDOUT:   %int.convert_checked.loc15: init Core.IntLiteral = call %.loc15_24.3(%.loc15_24.1) [template = constants.%.35]
+// CHECK:STDOUT:   %.loc15_24.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc15 [template = constants.%.35]
+// CHECK:STDOUT:   %.loc15_24.5: Core.IntLiteral = converted %.loc15_24.1, %.loc15_24.4 [template = constants.%.35]
+// CHECK:STDOUT:   %.loc15_25: type = array_type %.loc15_24.5, i32 [template = constants.%.36]
+// CHECK:STDOUT:   %tuple_index.var: ref %.36 = var tuple_index
+// CHECK:STDOUT:   %tuple_index: ref %.36 = bind_name tuple_index, %tuple_index.var
 // CHECK:STDOUT:   %int.make_type_32.loc17: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc17_26: i32 = int_value 1 [template = constants.%.2]
+// CHECK:STDOUT:   %.loc17_26.1: i32 = int_value 1 [template = constants.%.2]
 // CHECK:STDOUT:   %.loc17_21.1: type = value_of_initializer %int.make_type_32.loc17 [template = i32]
 // CHECK:STDOUT:   %.loc17_21.2: type = converted %int.make_type_32.loc17, %.loc17_21.1 [template = i32]
-// CHECK:STDOUT:   %.loc17_27: type = array_type %.loc17_26, i32 [template = constants.%.10]
-// CHECK:STDOUT:   %struct_access.var: ref %.10 = var struct_access
-// CHECK:STDOUT:   %struct_access: ref %.10 = bind_name struct_access, %struct_access.var
+// CHECK:STDOUT:   %.loc17_26.2: %Convert.type.2 = interface_witness_access constants.%.33, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc17_26.3: <bound method> = bound_method %.loc17_26.1, %.loc17_26.2 [template = constants.%.34]
+// CHECK:STDOUT:   %int.convert_checked.loc17: init Core.IntLiteral = call %.loc17_26.3(%.loc17_26.1) [template = constants.%.35]
+// CHECK:STDOUT:   %.loc17_26.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc17 [template = constants.%.35]
+// CHECK:STDOUT:   %.loc17_26.5: Core.IntLiteral = converted %.loc17_26.1, %.loc17_26.4 [template = constants.%.35]
+// CHECK:STDOUT:   %.loc17_27: type = array_type %.loc17_26.5, i32 [template = constants.%.36]
+// CHECK:STDOUT:   %struct_access.var: ref %.36 = var struct_access
+// CHECK:STDOUT:   %struct_access: ref %.36 = bind_name struct_access, %struct_access.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
@@ -148,46 +165,56 @@ var struct_access: [i32; 1] = (0,) as [i32; {.a = 3, .b = 1}.b];
 // CHECK:STDOUT:   %.loc13_73.11: init %.4 = struct_init (%.loc13_73.4, %.loc13_73.7, %.loc13_73.10) to file.%struct_copy.var [template = constants.%struct.2]
 // CHECK:STDOUT:   %.loc13_103: init %.4 = converted %.loc13_73.1, %.loc13_73.11 [template = constants.%struct.2]
 // CHECK:STDOUT:   assign file.%struct_copy.var, %.loc13_103
-// CHECK:STDOUT:   %.loc15_30: i32 = int_value 0 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc15_30: i32 = int_value 0 [template = constants.%.38]
 // CHECK:STDOUT:   %.loc15_32.1: %tuple.type.3 = tuple_literal (%.loc15_30)
 // CHECK:STDOUT:   %int.make_type_32.loc15: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc15_44: i32 = int_value 5 [template = constants.%.13]
-// CHECK:STDOUT:   %.loc15_47: i32 = int_value 7 [template = constants.%.14]
+// CHECK:STDOUT:   %.loc15_44: i32 = int_value 5 [template = constants.%.39]
+// CHECK:STDOUT:   %.loc15_47: i32 = int_value 7 [template = constants.%.40]
 // CHECK:STDOUT:   %.loc15_50: i32 = int_value 1 [template = constants.%.2]
-// CHECK:STDOUT:   %.loc15_53: i32 = int_value 9 [template = constants.%.15]
+// CHECK:STDOUT:   %.loc15_53: i32 = int_value 9 [template = constants.%.41]
 // CHECK:STDOUT:   %.loc15_54.1: %tuple.type.4 = tuple_literal (%.loc15_44, %.loc15_47, %.loc15_50, %.loc15_53)
 // CHECK:STDOUT:   %.loc15_56: i32 = int_value 2 [template = constants.%.3]
 // CHECK:STDOUT:   %tuple: %tuple.type.4 = tuple_value (%.loc15_44, %.loc15_47, %.loc15_50, %.loc15_53) [template = constants.%tuple.2]
 // CHECK:STDOUT:   %.loc15_54.2: %tuple.type.4 = converted %.loc15_54.1, %tuple [template = constants.%tuple.2]
-// CHECK:STDOUT:   %.loc15_55: i32 = tuple_access %.loc15_54.2, element2 [template = constants.%.2]
+// CHECK:STDOUT:   %.loc15_55.1: i32 = tuple_access %.loc15_54.2, element2 [template = constants.%.2]
 // CHECK:STDOUT:   %.loc15_38.1: type = value_of_initializer %int.make_type_32.loc15 [template = i32]
 // CHECK:STDOUT:   %.loc15_38.2: type = converted %int.make_type_32.loc15, %.loc15_38.1 [template = i32]
-// CHECK:STDOUT:   %.loc15_57: type = array_type %.loc15_55, i32 [template = constants.%.10]
-// CHECK:STDOUT:   %.loc15_5: ref %.10 = splice_block file.%tuple_index.var {}
-// CHECK:STDOUT:   %.loc15_32.2: i32 = int_value 0 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc15_55.2: %Convert.type.2 = interface_witness_access constants.%.33, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc15_55.3: <bound method> = bound_method %.loc15_55.1, %.loc15_55.2 [template = constants.%.34]
+// CHECK:STDOUT:   %int.convert_checked.loc15: init Core.IntLiteral = call %.loc15_55.3(%.loc15_55.1) [template = constants.%.35]
+// CHECK:STDOUT:   %.loc15_55.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc15 [template = constants.%.35]
+// CHECK:STDOUT:   %.loc15_55.5: Core.IntLiteral = converted %.loc15_55.1, %.loc15_55.4 [template = constants.%.35]
+// CHECK:STDOUT:   %.loc15_57: type = array_type %.loc15_55.5, i32 [template = constants.%.36]
+// CHECK:STDOUT:   %.loc15_5: ref %.36 = splice_block file.%tuple_index.var {}
+// CHECK:STDOUT:   %.loc15_32.2: i32 = int_value 0 [template = constants.%.38]
 // CHECK:STDOUT:   %.loc15_32.3: ref i32 = array_index %.loc15_5, %.loc15_32.2
-// CHECK:STDOUT:   %.loc15_32.4: init i32 = initialize_from %.loc15_30 to %.loc15_32.3 [template = constants.%.12]
-// CHECK:STDOUT:   %.loc15_32.5: init %.10 = array_init (%.loc15_32.4) to %.loc15_5 [template = constants.%array]
-// CHECK:STDOUT:   %.loc15_34: init %.10 = converted %.loc15_32.1, %.loc15_32.5 [template = constants.%array]
+// CHECK:STDOUT:   %.loc15_32.4: init i32 = initialize_from %.loc15_30 to %.loc15_32.3 [template = constants.%.38]
+// CHECK:STDOUT:   %.loc15_32.5: init %.36 = array_init (%.loc15_32.4) to %.loc15_5 [template = constants.%array]
+// CHECK:STDOUT:   %.loc15_34: init %.36 = converted %.loc15_32.1, %.loc15_32.5 [template = constants.%array]
 // CHECK:STDOUT:   assign file.%tuple_index.var, %.loc15_34
-// CHECK:STDOUT:   %.loc17_32: i32 = int_value 0 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc17_32: i32 = int_value 0 [template = constants.%.38]
 // CHECK:STDOUT:   %.loc17_34.1: %tuple.type.3 = tuple_literal (%.loc17_32)
 // CHECK:STDOUT:   %int.make_type_32.loc17: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc17_51: i32 = int_value 3 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc17_59: i32 = int_value 1 [template = constants.%.2]
-// CHECK:STDOUT:   %.loc17_60.1: %.17 = struct_literal (%.loc17_51, %.loc17_59)
-// CHECK:STDOUT:   %struct.loc17: %.17 = struct_value (%.loc17_51, %.loc17_59) [template = constants.%struct.3]
-// CHECK:STDOUT:   %.loc17_60.2: %.17 = converted %.loc17_60.1, %struct.loc17 [template = constants.%struct.3]
-// CHECK:STDOUT:   %.loc17_61: i32 = struct_access %.loc17_60.2, element1 [template = constants.%.2]
+// CHECK:STDOUT:   %.loc17_60.1: %.43 = struct_literal (%.loc17_51, %.loc17_59)
+// CHECK:STDOUT:   %struct.loc17: %.43 = struct_value (%.loc17_51, %.loc17_59) [template = constants.%struct.3]
+// CHECK:STDOUT:   %.loc17_60.2: %.43 = converted %.loc17_60.1, %struct.loc17 [template = constants.%struct.3]
+// CHECK:STDOUT:   %.loc17_61.1: i32 = struct_access %.loc17_60.2, element1 [template = constants.%.2]
 // CHECK:STDOUT:   %.loc17_40.1: type = value_of_initializer %int.make_type_32.loc17 [template = i32]
 // CHECK:STDOUT:   %.loc17_40.2: type = converted %int.make_type_32.loc17, %.loc17_40.1 [template = i32]
-// CHECK:STDOUT:   %.loc17_63: type = array_type %.loc17_61, i32 [template = constants.%.10]
-// CHECK:STDOUT:   %.loc17_5: ref %.10 = splice_block file.%struct_access.var {}
-// CHECK:STDOUT:   %.loc17_34.2: i32 = int_value 0 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc17_61.2: %Convert.type.2 = interface_witness_access constants.%.33, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc17_61.3: <bound method> = bound_method %.loc17_61.1, %.loc17_61.2 [template = constants.%.34]
+// CHECK:STDOUT:   %int.convert_checked.loc17: init Core.IntLiteral = call %.loc17_61.3(%.loc17_61.1) [template = constants.%.35]
+// CHECK:STDOUT:   %.loc17_61.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc17 [template = constants.%.35]
+// CHECK:STDOUT:   %.loc17_61.5: Core.IntLiteral = converted %.loc17_61.1, %.loc17_61.4 [template = constants.%.35]
+// CHECK:STDOUT:   %.loc17_63: type = array_type %.loc17_61.5, i32 [template = constants.%.36]
+// CHECK:STDOUT:   %.loc17_5: ref %.36 = splice_block file.%struct_access.var {}
+// CHECK:STDOUT:   %.loc17_34.2: i32 = int_value 0 [template = constants.%.38]
 // CHECK:STDOUT:   %.loc17_34.3: ref i32 = array_index %.loc17_5, %.loc17_34.2
-// CHECK:STDOUT:   %.loc17_34.4: init i32 = initialize_from %.loc17_32 to %.loc17_34.3 [template = constants.%.12]
-// CHECK:STDOUT:   %.loc17_34.5: init %.10 = array_init (%.loc17_34.4) to %.loc17_5 [template = constants.%array]
-// CHECK:STDOUT:   %.loc17_36: init %.10 = converted %.loc17_34.1, %.loc17_34.5 [template = constants.%array]
+// CHECK:STDOUT:   %.loc17_34.4: init i32 = initialize_from %.loc17_32 to %.loc17_34.3 [template = constants.%.38]
+// CHECK:STDOUT:   %.loc17_34.5: init %.36 = array_init (%.loc17_34.4) to %.loc17_5 [template = constants.%array]
+// CHECK:STDOUT:   %.loc17_36: init %.36 = converted %.loc17_34.1, %.loc17_34.5 [template = constants.%array]
 // CHECK:STDOUT:   assign file.%struct_access.var, %.loc17_36
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 53 - 32
toolchain/check/testdata/eval/fail_aggregate.carbon

@@ -21,23 +21,32 @@ var array_index: [i32; 1] = (0,) as [i32; ((5, 7, 1, 9) as [i32; 4])[2]];
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 1 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, i32 [template]
+// CHECK:STDOUT:   %.30: i32 = int_value 0 [template]
 // CHECK:STDOUT:   %tuple.type.1: type = tuple_type (i32) [template]
-// CHECK:STDOUT:   %.5: i32 = int_value 5 [template]
-// CHECK:STDOUT:   %.6: i32 = int_value 7 [template]
-// CHECK:STDOUT:   %.7: i32 = int_value 9 [template]
+// CHECK:STDOUT:   %.31: i32 = int_value 5 [template]
+// CHECK:STDOUT:   %.32: i32 = int_value 7 [template]
+// CHECK:STDOUT:   %.33: i32 = int_value 9 [template]
 // CHECK:STDOUT:   %tuple.type.2: type = tuple_type (i32, i32, i32, i32) [template]
-// CHECK:STDOUT:   %.8: i32 = int_value 4 [template]
-// CHECK:STDOUT:   %.9: type = array_type %.8, i32 [template]
-// CHECK:STDOUT:   %.11: i32 = int_value 2 [template]
-// CHECK:STDOUT:   %.12: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %array: %.9 = tuple_value (%.5, %.6, %.1, %.7) [template]
+// CHECK:STDOUT:   %.34: i32 = int_value 4 [template]
+// CHECK:STDOUT:   %.35: <bound method> = bound_method %.34, %Convert.15 [template]
+// CHECK:STDOUT:   %.36: Core.IntLiteral = int_value 4 [template]
+// CHECK:STDOUT:   %.37: type = array_type %.36, i32 [template]
+// CHECK:STDOUT:   %.39: i32 = int_value 2 [template]
+// CHECK:STDOUT:   %.40: i32 = int_value 3 [template]
+// CHECK:STDOUT:   %array: %.37 = tuple_value (%.31, %.32, %.1, %.33) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -50,48 +59,60 @@ var array_index: [i32; 1] = (0,) as [i32; ((5, 7, 1, 9) as [i32; 4])[2]];
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %int.make_type_32: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc16_24: i32 = int_value 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc16_24.1: i32 = int_value 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc16_19.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:   %.loc16_19.2: type = converted %int.make_type_32, %.loc16_19.1 [template = i32]
-// CHECK:STDOUT:   %.loc16_25: type = array_type %.loc16_24, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %array_index.var: ref %.2 = var array_index
-// CHECK:STDOUT:   %array_index: ref %.2 = bind_name array_index, %array_index.var
+// CHECK:STDOUT:   %.loc16_24.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc16_24.3: <bound method> = bound_method %.loc16_24.1, %.loc16_24.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc16_24.3(%.loc16_24.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc16_24.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:   %.loc16_24.5: Core.IntLiteral = converted %.loc16_24.1, %.loc16_24.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc16_25: type = array_type %.loc16_24.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %array_index.var: ref %.28 = var array_index
+// CHECK:STDOUT:   %array_index: ref %.28 = bind_name array_index, %array_index.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc16_30: i32 = int_value 0 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc16_30: i32 = int_value 0 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc16_32: %tuple.type.1 = tuple_literal (%.loc16_30)
 // CHECK:STDOUT:   %int.make_type_32.loc16_38: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc16_45: i32 = int_value 5 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc16_48: i32 = int_value 7 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc16_45: i32 = int_value 5 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc16_48: i32 = int_value 7 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc16_51: i32 = int_value 1 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc16_54: i32 = int_value 9 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc16_54: i32 = int_value 9 [template = constants.%.33]
 // CHECK:STDOUT:   %.loc16_55.1: %tuple.type.2 = tuple_literal (%.loc16_45, %.loc16_48, %.loc16_51, %.loc16_54)
 // CHECK:STDOUT:   %int.make_type_32.loc16_61: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc16_66: i32 = int_value 4 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc16_66.1: i32 = int_value 4 [template = constants.%.34]
 // CHECK:STDOUT:   %.loc16_61.1: type = value_of_initializer %int.make_type_32.loc16_61 [template = i32]
 // CHECK:STDOUT:   %.loc16_61.2: type = converted %int.make_type_32.loc16_61, %.loc16_61.1 [template = i32]
-// CHECK:STDOUT:   %.loc16_67: type = array_type %.loc16_66, i32 [template = constants.%.9]
-// CHECK:STDOUT:   %.loc16_55.2: ref %.9 = temporary_storage
-// CHECK:STDOUT:   %.loc16_55.3: i32 = int_value 0 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc16_66.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc16_66.3: <bound method> = bound_method %.loc16_66.1, %.loc16_66.2 [template = constants.%.35]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc16_66.3(%.loc16_66.1) [template = constants.%.36]
+// CHECK:STDOUT:   %.loc16_66.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.36]
+// CHECK:STDOUT:   %.loc16_66.5: Core.IntLiteral = converted %.loc16_66.1, %.loc16_66.4 [template = constants.%.36]
+// CHECK:STDOUT:   %.loc16_67: type = array_type %.loc16_66.5, i32 [template = constants.%.37]
+// CHECK:STDOUT:   %.loc16_55.2: ref %.37 = temporary_storage
+// CHECK:STDOUT:   %.loc16_55.3: i32 = int_value 0 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc16_55.4: ref i32 = array_index %.loc16_55.2, %.loc16_55.3
-// CHECK:STDOUT:   %.loc16_55.5: init i32 = initialize_from %.loc16_45 to %.loc16_55.4 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc16_55.5: init i32 = initialize_from %.loc16_45 to %.loc16_55.4 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc16_55.6: i32 = int_value 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc16_55.7: ref i32 = array_index %.loc16_55.2, %.loc16_55.6
-// CHECK:STDOUT:   %.loc16_55.8: init i32 = initialize_from %.loc16_48 to %.loc16_55.7 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc16_55.9: i32 = int_value 2 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc16_55.8: init i32 = initialize_from %.loc16_48 to %.loc16_55.7 [template = constants.%.32]
+// CHECK:STDOUT:   %.loc16_55.9: i32 = int_value 2 [template = constants.%.39]
 // CHECK:STDOUT:   %.loc16_55.10: ref i32 = array_index %.loc16_55.2, %.loc16_55.9
 // CHECK:STDOUT:   %.loc16_55.11: init i32 = initialize_from %.loc16_51 to %.loc16_55.10 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc16_55.12: i32 = int_value 3 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc16_55.12: i32 = int_value 3 [template = constants.%.40]
 // CHECK:STDOUT:   %.loc16_55.13: ref i32 = array_index %.loc16_55.2, %.loc16_55.12
-// CHECK:STDOUT:   %.loc16_55.14: init i32 = initialize_from %.loc16_54 to %.loc16_55.13 [template = constants.%.7]
-// CHECK:STDOUT:   %.loc16_55.15: init %.9 = array_init (%.loc16_55.5, %.loc16_55.8, %.loc16_55.11, %.loc16_55.14) to %.loc16_55.2 [template = constants.%array]
-// CHECK:STDOUT:   %.loc16_57.1: init %.9 = converted %.loc16_55.1, %.loc16_55.15 [template = constants.%array]
-// CHECK:STDOUT:   %.loc16_70: i32 = int_value 2 [template = constants.%.11]
-// CHECK:STDOUT:   %.loc16_57.2: ref %.9 = temporary %.loc16_55.2, %.loc16_57.1
+// CHECK:STDOUT:   %.loc16_55.14: init i32 = initialize_from %.loc16_54 to %.loc16_55.13 [template = constants.%.33]
+// CHECK:STDOUT:   %.loc16_55.15: init %.37 = array_init (%.loc16_55.5, %.loc16_55.8, %.loc16_55.11, %.loc16_55.14) to %.loc16_55.2 [template = constants.%array]
+// CHECK:STDOUT:   %.loc16_57.1: init %.37 = converted %.loc16_55.1, %.loc16_55.15 [template = constants.%array]
+// CHECK:STDOUT:   %.loc16_70: i32 = int_value 2 [template = constants.%.39]
+// CHECK:STDOUT:   %.loc16_57.2: ref %.37 = temporary %.loc16_55.2, %.loc16_57.1
 // CHECK:STDOUT:   %.loc16_71.1: ref i32 = array_index %.loc16_57.2, %.loc16_70
 // CHECK:STDOUT:   %.loc16_71.2: i32 = bind_value %.loc16_71.1
+// CHECK:STDOUT:   %.loc16_38.1: type = value_of_initializer %int.make_type_32.loc16_38 [template = i32]
+// CHECK:STDOUT:   %.loc16_38.2: type = converted %int.make_type_32.loc16_38, %.loc16_38.1 [template = i32]
 // CHECK:STDOUT:   assign file.%array_index.var, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 27 - 13
toolchain/check/testdata/eval/fail_symbolic.carbon

@@ -21,15 +21,22 @@ fn G(N:! i32) {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
-// CHECK:STDOUT:   %N: i32 = bind_symbolic_name N, 0 [symbolic]
-// CHECK:STDOUT:   %N.patt: i32 = symbolic_binding_pattern N, 0 [symbolic]
+// CHECK:STDOUT:   %N.1: i32 = bind_symbolic_name N, 0 [symbolic]
+// CHECK:STDOUT:   %N.patt.1: i32 = symbolic_binding_pattern N, 0 [symbolic]
 // CHECK:STDOUT:   %G.type: type = fn_type @G [template]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.24: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.25: <bound method> = bound_method %N.1, %Convert.15 [symbolic]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.25(%N.1) [symbolic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -42,38 +49,45 @@ fn G(N:! i32) {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [template = constants.%G] {
-// CHECK:STDOUT:     %N.patt.loc12_6.1: i32 = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc12_6.2 (constants.%N.patt)]
-// CHECK:STDOUT:     %N.param_patt: i32 = value_param_pattern %N.patt.loc12_6.1, runtime_param<invalid> [symbolic = %N.patt.loc12_6.2 (constants.%N.patt)]
+// CHECK:STDOUT:     %N.patt.loc12_6.1: i32 = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc12_6.2 (constants.%N.patt.1)]
+// CHECK:STDOUT:     %N.param_patt: i32 = value_param_pattern %N.patt.loc12_6.1, runtime_param<invalid> [symbolic = %N.patt.loc12_6.2 (constants.%N.patt.1)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %int.make_type_32.loc12: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:     %.loc12_10.1: type = value_of_initializer %int.make_type_32.loc12 [template = i32]
 // CHECK:STDOUT:     %.loc12_10.2: type = converted %int.make_type_32.loc12, %.loc12_10.1 [template = i32]
 // CHECK:STDOUT:     %N.param: i32 = value_param runtime_param<invalid>
-// CHECK:STDOUT:     %N.loc12_6.1: i32 = bind_symbolic_name N, 0, %N.param [symbolic = %N.loc12_6.2 (constants.%N)]
+// CHECK:STDOUT:     %N.loc12_6.1: i32 = bind_symbolic_name N, 0, %N.param [symbolic = %N.loc12_6.2 (constants.%N.1)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: generic fn @G(%N.loc12_6.1: i32) {
-// CHECK:STDOUT:   %N.loc12_6.2: i32 = bind_symbolic_name N, 0 [symbolic = %N.loc12_6.2 (constants.%N)]
-// CHECK:STDOUT:   %N.patt.loc12_6.2: i32 = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc12_6.2 (constants.%N.patt)]
+// CHECK:STDOUT:   %N.loc12_6.2: i32 = bind_symbolic_name N, 0 [symbolic = %N.loc12_6.2 (constants.%N.1)]
+// CHECK:STDOUT:   %N.patt.loc12_6.2: i32 = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc12_6.2 (constants.%N.patt.1)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %.loc16_16.5: <bound method> = bound_method %N.loc12_6.2, constants.%Convert.15 [symbolic = %.loc16_16.5 (constants.%.25)]
+// CHECK:STDOUT:   %int.convert_checked.loc16_16.2: init Core.IntLiteral = call %.loc16_16.5(%N.loc12_6.2) [symbolic = %int.convert_checked.loc16_16.2 (constants.%int.convert_checked)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%N.param_patt: i32) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %int.make_type_32.loc16: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:     %N.ref: i32 = name_ref N, %N.loc12_6.1 [symbolic = %N.loc12_6.2 (constants.%N)]
+// CHECK:STDOUT:     %N.ref: i32 = name_ref N, %N.loc12_6.1 [symbolic = %N.loc12_6.2 (constants.%N.1)]
 // CHECK:STDOUT:     %.loc16_11.1: type = value_of_initializer %int.make_type_32.loc16 [template = i32]
 // CHECK:STDOUT:     %.loc16_11.2: type = converted %int.make_type_32.loc16, %.loc16_11.1 [template = i32]
-// CHECK:STDOUT:     %.loc16_17: type = array_type %N.ref, i32 [template = <error>]
+// CHECK:STDOUT:     %.loc16_16.1: %Convert.type.2 = interface_witness_access constants.%.24, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:     %.loc16_16.2: <bound method> = bound_method %N.ref, %.loc16_16.1 [symbolic = %.loc16_16.5 (constants.%.25)]
+// CHECK:STDOUT:     %int.convert_checked.loc16_16.1: init Core.IntLiteral = call %.loc16_16.2(%N.ref) [symbolic = %int.convert_checked.loc16_16.2 (constants.%int.convert_checked)]
+// CHECK:STDOUT:     %.loc16_16.3: Core.IntLiteral = value_of_initializer %int.convert_checked.loc16_16.1 [symbolic = %int.convert_checked.loc16_16.2 (constants.%int.convert_checked)]
+// CHECK:STDOUT:     %.loc16_16.4: Core.IntLiteral = converted %N.ref, %.loc16_16.3 [symbolic = %int.convert_checked.loc16_16.2 (constants.%int.convert_checked)]
+// CHECK:STDOUT:     %.loc16_17: type = array_type %.loc16_16.4, i32 [template = <error>]
 // CHECK:STDOUT:     %k.var: ref <error> = var k
 // CHECK:STDOUT:     %k: ref <error> = bind_name k, %k.var
 // CHECK:STDOUT:     return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @G(constants.%N) {
-// CHECK:STDOUT:   %N.loc12_6.2 => constants.%N
-// CHECK:STDOUT:   %N.patt.loc12_6.2 => constants.%N
+// CHECK:STDOUT: specific @G(constants.%N.1) {
+// CHECK:STDOUT:   %N.loc12_6.2 => constants.%N.1
+// CHECK:STDOUT:   %N.patt.loc12_6.2 => constants.%N.1
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 18 - 6
toolchain/check/testdata/eval/symbolic.carbon

@@ -28,11 +28,18 @@ fn F(T:! type) {
 // CHECK:STDOUT:   %tuple.type.2: type = tuple_type (%.1, %.2) [symbolic]
 // CHECK:STDOUT:   %.4: type = struct_type {.a: %T} [symbolic]
 // CHECK:STDOUT:   %.5: i32 = int_value 5 [template]
-// CHECK:STDOUT:   %.6: type = array_type %.5, %T [symbolic]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.29: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.30: <bound method> = bound_method %.5, %Convert.15 [template]
+// CHECK:STDOUT:   %.31: Core.IntLiteral = int_value 5 [template]
+// CHECK:STDOUT:   %.32: type = array_type %.31, %T [symbolic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.1
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -62,7 +69,7 @@ fn F(T:! type) {
 // CHECK:STDOUT:   %.loc13_15.2: type = const_type @F.%T.loc12_6.2 (%T) [symbolic = %.loc13_15.2 (constants.%.2)]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (@F.%.loc13_12.2 (%.1), @F.%.loc13_15.2 (%.2)) [symbolic = %tuple.type (constants.%tuple.type.2)]
 // CHECK:STDOUT:   %.loc14_16.2: type = struct_type {.a: @F.%T.loc12_6.2 (%T)} [symbolic = %.loc14_16.2 (constants.%.4)]
-// CHECK:STDOUT:   %.loc15_15.2: type = array_type constants.%.5, @F.%T.loc12_6.2 (%T) [symbolic = %.loc15_15.2 (constants.%.6)]
+// CHECK:STDOUT:   %.loc15_15.2: type = array_type constants.%.31, @F.%T.loc12_6.2 (%T) [symbolic = %.loc15_15.2 (constants.%.32)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%T.param_patt: type) {
 // CHECK:STDOUT:   !entry:
@@ -79,10 +86,15 @@ fn F(T:! type) {
 // CHECK:STDOUT:     %v.var: ref @F.%.loc14_16.2 (%.4) = var v
 // CHECK:STDOUT:     %v: ref @F.%.loc14_16.2 (%.4) = bind_name v, %v.var
 // CHECK:STDOUT:     %T.ref.loc15: type = name_ref T, %T.loc12_6.1 [symbolic = %T.loc12_6.2 (constants.%T)]
-// CHECK:STDOUT:     %.loc15_14: i32 = int_value 5 [template = constants.%.5]
-// CHECK:STDOUT:     %.loc15_15.1: type = array_type %.loc15_14, %T [symbolic = %.loc15_15.2 (constants.%.6)]
-// CHECK:STDOUT:     %w.var: ref @F.%.loc15_15.2 (%.6) = var w
-// CHECK:STDOUT:     %w: ref @F.%.loc15_15.2 (%.6) = bind_name w, %w.var
+// CHECK:STDOUT:     %.loc15_14.1: i32 = int_value 5 [template = constants.%.5]
+// CHECK:STDOUT:     %.loc15_14.2: %Convert.type.2 = interface_witness_access constants.%.29, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:     %.loc15_14.3: <bound method> = bound_method %.loc15_14.1, %.loc15_14.2 [template = constants.%.30]
+// CHECK:STDOUT:     %int.convert_checked: init Core.IntLiteral = call %.loc15_14.3(%.loc15_14.1) [template = constants.%.31]
+// CHECK:STDOUT:     %.loc15_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.31]
+// CHECK:STDOUT:     %.loc15_14.5: Core.IntLiteral = converted %.loc15_14.1, %.loc15_14.4 [template = constants.%.31]
+// CHECK:STDOUT:     %.loc15_15.1: type = array_type %.loc15_14.5, %T [symbolic = %.loc15_15.2 (constants.%.32)]
+// CHECK:STDOUT:     %w.var: ref @F.%.loc15_15.2 (%.32) = var w
+// CHECK:STDOUT:     %w: ref @F.%.loc15_15.2 (%.32) = bind_name w, %w.var
 // CHECK:STDOUT:     return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 19 - 5
toolchain/check/testdata/function/builtin/call.carbon

@@ -22,12 +22,19 @@ var arr: [i32; Add(1, 2)];
 // CHECK:STDOUT:   %.1: i32 = int_value 1 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %.3: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.27: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.28: <bound method> = bound_method %.3, %Convert.15 [template]
+// CHECK:STDOUT:   %.29: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.30: type = array_type %.29, i32 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -71,9 +78,16 @@ var arr: [i32; Add(1, 2)];
 // CHECK:STDOUT:   %int.sadd: init i32 = call %Add.ref(%.loc13_20, %.loc13_23) [template = constants.%.3]
 // CHECK:STDOUT:   %.loc13_11.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:   %.loc13_11.2: type = converted %int.make_type_32, %.loc13_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc13_25: type = array_type %int.sadd, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %arr.var: ref %.4 = var arr
-// CHECK:STDOUT:   %arr: ref %.4 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc13_19.1: %Convert.type.2 = interface_witness_access constants.%.27, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc13_19.2: <bound method> = bound_method %int.sadd, %.loc13_19.1 [template = constants.%.28]
+// CHECK:STDOUT:   %.loc13_19.3: i32 = value_of_initializer %int.sadd [template = constants.%.3]
+// CHECK:STDOUT:   %.loc13_19.4: i32 = converted %int.sadd, %.loc13_19.3 [template = constants.%.3]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc13_19.2(%.loc13_19.4) [template = constants.%.29]
+// CHECK:STDOUT:   %.loc13_19.5: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.29]
+// CHECK:STDOUT:   %.loc13_19.6: Core.IntLiteral = converted %int.sadd, %.loc13_19.5 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc13_25: type = array_type %.loc13_19.6, i32 [template = constants.%.30]
+// CHECK:STDOUT:   %arr.var: ref %.30 = var arr
+// CHECK:STDOUT:   %arr: ref %.30 = bind_name arr, %arr.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Add(%a.param_patt: i32, %b.param_patt: i32) -> i32 = "int.sadd";

+ 48 - 34
toolchain/check/testdata/function/builtin/method.carbon

@@ -22,7 +22,7 @@ var arr: [i32; 1.(I.F)(2)];
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %I.type: type = facet_type <@I> [template]
-// CHECK:STDOUT:   %Self: %I.type = bind_symbolic_name Self, 0 [symbolic]
+// CHECK:STDOUT:   %Self.1: %I.type = bind_symbolic_name Self, 0 [symbolic]
 // CHECK:STDOUT:   %F.type.1: type = fn_type @F.1 [template]
 // CHECK:STDOUT:   %F.1: %F.type.1 = struct_value () [template]
 // CHECK:STDOUT:   %.1: type = assoc_entity_type %I.type, %F.type.1 [template]
@@ -36,12 +36,19 @@ var arr: [i32; 1.(I.F)(2)];
 // CHECK:STDOUT:   %.5: <bound method> = bound_method %.4, %F.2 [template]
 // CHECK:STDOUT:   %.6: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %.7: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.8: type = array_type %.7, i32 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.31: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.32: <bound method> = bound_method %.7, %Convert.15 [template]
+// CHECK:STDOUT:   %.33: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.34: type = array_type %.33, i32 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -55,7 +62,7 @@ var arr: [i32; 1.(I.F)(2)];
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %I.decl: type = interface_decl @I [template = constants.%I.type] {} {}
-// CHECK:STDOUT:   impl_decl @impl [template] {} {
+// CHECK:STDOUT:   impl_decl @impl.1 [template] {} {
 // CHECK:STDOUT:     %int.make_type_32: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:     %.loc15_6.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:     %.loc15_6.2: type = converted %int.make_type_32, %.loc15_6.1 [template = i32]
@@ -71,36 +78,43 @@ var arr: [i32; 1.(I.F)(2)];
 // CHECK:STDOUT:   %int.sadd: init i32 = call %.loc19_17.2(%.loc19_16, %.loc19_24) [template = constants.%.7]
 // CHECK:STDOUT:   %.loc19_11.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:   %.loc19_11.2: type = converted %int.make_type_32, %.loc19_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc19_26: type = array_type %int.sadd, i32 [template = constants.%.8]
-// CHECK:STDOUT:   %arr.var: ref %.8 = var arr
-// CHECK:STDOUT:   %arr: ref %.8 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc19_23.1: %Convert.type.2 = interface_witness_access constants.%.31, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc19_23.2: <bound method> = bound_method %int.sadd, %.loc19_23.1 [template = constants.%.32]
+// CHECK:STDOUT:   %.loc19_23.3: i32 = value_of_initializer %int.sadd [template = constants.%.7]
+// CHECK:STDOUT:   %.loc19_23.4: i32 = converted %int.sadd, %.loc19_23.3 [template = constants.%.7]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc19_23.2(%.loc19_23.4) [template = constants.%.33]
+// CHECK:STDOUT:   %.loc19_23.5: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.33]
+// CHECK:STDOUT:   %.loc19_23.6: Core.IntLiteral = converted %int.sadd, %.loc19_23.5 [template = constants.%.33]
+// CHECK:STDOUT:   %.loc19_26: type = array_type %.loc19_23.6, i32 [template = constants.%.34]
+// CHECK:STDOUT:   %arr.var: ref %.34 = var arr
+// CHECK:STDOUT:   %arr: ref %.34 = bind_name arr, %arr.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: interface @I {
-// CHECK:STDOUT:   %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self]
+// CHECK:STDOUT:   %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self.1]
 // CHECK:STDOUT:   %F.decl: %F.type.1 = fn_decl @F.1 [template = constants.%F.1] {
-// CHECK:STDOUT:     %self.patt: @F.1.%Self (%Self) = binding_pattern self
-// CHECK:STDOUT:     %self.param_patt: @F.1.%Self (%Self) = value_param_pattern %self.patt, runtime_param0
-// CHECK:STDOUT:     %other.patt: @F.1.%Self (%Self) = binding_pattern other
-// CHECK:STDOUT:     %other.param_patt: @F.1.%Self (%Self) = value_param_pattern %other.patt, runtime_param1
-// CHECK:STDOUT:     %return.patt: @F.1.%Self (%Self) = return_slot_pattern
-// CHECK:STDOUT:     %return.param_patt: @F.1.%Self (%Self) = out_param_pattern %return.patt, runtime_param2
+// CHECK:STDOUT:     %self.patt: @F.1.%Self (%Self.1) = binding_pattern self
+// CHECK:STDOUT:     %self.param_patt: @F.1.%Self (%Self.1) = value_param_pattern %self.patt, runtime_param0
+// CHECK:STDOUT:     %other.patt: @F.1.%Self (%Self.1) = binding_pattern other
+// CHECK:STDOUT:     %other.param_patt: @F.1.%Self (%Self.1) = value_param_pattern %other.patt, runtime_param1
+// CHECK:STDOUT:     %return.patt: @F.1.%Self (%Self.1) = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: @F.1.%Self (%Self.1) = out_param_pattern %return.patt, runtime_param2
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %Self.ref.loc12_14: %I.type = name_ref Self, @I.%Self [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:     %.loc12_14.1: type = facet_type_access %Self.ref.loc12_14 [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:     %.loc12_14.2: type = converted %Self.ref.loc12_14, %.loc12_14.1 [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:     %Self.ref.loc12_27: %I.type = name_ref Self, @I.%Self [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:     %.loc12_27.1: type = facet_type_access %Self.ref.loc12_27 [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:     %.loc12_27.2: type = converted %Self.ref.loc12_27, %.loc12_27.1 [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:     %Self.ref.loc12_36: %I.type = name_ref Self, @I.%Self [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:     %.loc12_36.1: type = facet_type_access %Self.ref.loc12_36 [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:     %.loc12_36.2: type = converted %Self.ref.loc12_36, %.loc12_36.1 [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:     %self.param: @F.1.%Self (%Self) = value_param runtime_param0
-// CHECK:STDOUT:     %self: @F.1.%Self (%Self) = bind_name self, %self.param
-// CHECK:STDOUT:     %other.param: @F.1.%Self (%Self) = value_param runtime_param1
-// CHECK:STDOUT:     %other: @F.1.%Self (%Self) = bind_name other, %other.param
-// CHECK:STDOUT:     %return.param: ref @F.1.%Self (%Self) = out_param runtime_param2
-// CHECK:STDOUT:     %return: ref @F.1.%Self (%Self) = return_slot %return.param
+// CHECK:STDOUT:     %Self.ref.loc12_14: %I.type = name_ref Self, @I.%Self [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:     %.loc12_14.1: type = facet_type_access %Self.ref.loc12_14 [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:     %.loc12_14.2: type = converted %Self.ref.loc12_14, %.loc12_14.1 [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:     %Self.ref.loc12_27: %I.type = name_ref Self, @I.%Self [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:     %.loc12_27.1: type = facet_type_access %Self.ref.loc12_27 [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:     %.loc12_27.2: type = converted %Self.ref.loc12_27, %.loc12_27.1 [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:     %Self.ref.loc12_36: %I.type = name_ref Self, @I.%Self [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:     %.loc12_36.1: type = facet_type_access %Self.ref.loc12_36 [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:     %.loc12_36.2: type = converted %Self.ref.loc12_36, %.loc12_36.1 [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:     %self.param: @F.1.%Self (%Self.1) = value_param runtime_param0
+// CHECK:STDOUT:     %self: @F.1.%Self (%Self.1) = bind_name self, %self.param
+// CHECK:STDOUT:     %other.param: @F.1.%Self (%Self.1) = value_param runtime_param1
+// CHECK:STDOUT:     %other: @F.1.%Self (%Self.1) = bind_name other, %other.param
+// CHECK:STDOUT:     %return.param: ref @F.1.%Self (%Self.1) = out_param runtime_param2
+// CHECK:STDOUT:     %return: ref @F.1.%Self (%Self.1) = return_slot %return.param
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %.loc12: %.1 = assoc_entity element0, %F.decl [template = constants.%.2]
 // CHECK:STDOUT:
@@ -110,7 +124,7 @@ var arr: [i32; 1.(I.F)(2)];
 // CHECK:STDOUT:   witness = (%F.decl)
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: impl @impl: %.loc15_6.2 as %I.ref {
+// CHECK:STDOUT: impl @impl.1: %.loc15_6.2 as %I.ref {
 // CHECK:STDOUT:   %F.decl: %F.type.2 = fn_decl @F.2 [template = constants.%F.2] {
 // CHECK:STDOUT:     %self.patt: i32 = binding_pattern self
 // CHECK:STDOUT:     %self.param_patt: i32 = value_param_pattern %self.patt, runtime_param0
@@ -143,15 +157,15 @@ var arr: [i32; 1.(I.F)(2)];
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: generic fn @F.1(@I.%Self: %I.type) {
-// CHECK:STDOUT:   %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self)]
+// CHECK:STDOUT:   %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self.1)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn[%self.param_patt: @F.1.%Self (%Self)](%other.param_patt: @F.1.%Self (%Self)) -> @F.1.%Self (%Self);
+// CHECK:STDOUT:   fn[%self.param_patt: @F.1.%Self (%Self.1)](%other.param_patt: @F.1.%Self (%Self.1)) -> @F.1.%Self (%Self.1);
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F.2[%self.param_patt: i32](%other.param_patt: i32) -> i32 = "int.sadd";
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @F.1(constants.%Self) {
-// CHECK:STDOUT:   %Self => constants.%Self
+// CHECK:STDOUT: specific @F.1(constants.%Self.1) {
+// CHECK:STDOUT:   %Self => constants.%Self.1
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @F.1(i32) {

+ 408 - 125
toolchain/check/testdata/function/builtin/no_prelude/call_from_operator.carbon

@@ -13,21 +13,28 @@
 package Core;
 
 fn Int32() -> type = "int.make_type_32";
+fn IntLiteral() -> type = "int_literal.make_type";
 
 interface Add {
   fn Op[self: Self](other: Self) -> Self;
 }
 
-// --- user.carbon
-
-import Core;
+interface ImplicitAs(T:! type) {
+  fn Convert[self: Self]() -> T;
+}
 
-// TODO: This should be in `Core`, but currently impl lookup only looks in the
-// current file.
-impl i32 as Core.Add {
+impl i32 as Add {
   fn Op[self: Self](other: Self) -> Self = "int.sadd";
 }
 
+impl i32 as ImplicitAs(IntLiteral()) {
+  fn Convert[self: Self]() -> IntLiteral() = "int.convert_checked";
+}
+
+// --- user.carbon
+
+import Core;
+
 var arr: [i32; 1 + 2] = (3, 4, 3 + 4);
 
 // CHECK:STDOUT: --- core.carbon
@@ -35,18 +42,43 @@ var arr: [i32; 1 + 2] = (3, 4, 3 + 4);
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
+// CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [template]
+// CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [template]
 // CHECK:STDOUT:   %Add.type: type = facet_type <@Add> [template]
-// CHECK:STDOUT:   %Self: %Add.type = bind_symbolic_name Self, 0 [symbolic]
-// CHECK:STDOUT:   %Op.type: type = fn_type @Op [template]
-// CHECK:STDOUT:   %Op: %Op.type = struct_value () [template]
-// CHECK:STDOUT:   %.1: type = assoc_entity_type %Add.type, %Op.type [template]
+// CHECK:STDOUT:   %Self.1: %Add.type = bind_symbolic_name Self, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.1: type = fn_type @Op.1 [template]
+// CHECK:STDOUT:   %Op.1: %Op.type.1 = struct_value () [template]
+// CHECK:STDOUT:   %.1: type = assoc_entity_type %Add.type, %Op.type.1 [template]
 // CHECK:STDOUT:   %.2: %.1 = assoc_entity element0, @Add.%Op.decl [template]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %T.patt: type = symbolic_binding_pattern T, 0 [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.type.1: type = generic_interface_type @ImplicitAs [template]
+// CHECK:STDOUT:   %ImplicitAs: %ImplicitAs.type.1 = struct_value () [template]
+// CHECK:STDOUT:   %ImplicitAs.type.2: type = facet_type <@ImplicitAs, @ImplicitAs(%T)> [symbolic]
+// CHECK:STDOUT:   %Self.2: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic]
+// CHECK:STDOUT:   %Convert.type.1: type = fn_type @Convert.1, @ImplicitAs(%T) [symbolic]
+// CHECK:STDOUT:   %Convert.1: %Convert.type.1 = struct_value () [symbolic]
+// CHECK:STDOUT:   %.3: type = assoc_entity_type %ImplicitAs.type.2, %Convert.type.1 [symbolic]
+// CHECK:STDOUT:   %.4: %.3 = assoc_entity element0, @ImplicitAs.%Convert.decl [symbolic]
+// CHECK:STDOUT:   %Op.type.2: type = fn_type @Op.2 [template]
+// CHECK:STDOUT:   %Op.2: %Op.type.2 = struct_value () [template]
+// CHECK:STDOUT:   %.5: <witness> = interface_witness (%Op.2) [template]
+// CHECK:STDOUT:   %ImplicitAs.type.3: type = facet_type <@ImplicitAs, @ImplicitAs(Core.IntLiteral)> [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.2 [template]
+// CHECK:STDOUT:   %Convert.2: %Convert.type.2 = struct_value () [template]
+// CHECK:STDOUT:   %Convert.type.3: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.3: %Convert.type.3 = struct_value () [template]
+// CHECK:STDOUT:   %.6: type = assoc_entity_type %ImplicitAs.type.3, %Convert.type.3 [template]
+// CHECK:STDOUT:   %.7: %.6 = assoc_entity element0, @ImplicitAs.%Convert.decl [template]
+// CHECK:STDOUT:   %.8: <witness> = interface_witness (%Convert.2) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Int32 = %Int32.decl
+// CHECK:STDOUT:     .IntLiteral = %IntLiteral.decl
 // CHECK:STDOUT:     .Add = %Add.decl
+// CHECK:STDOUT:     .ImplicitAs = %ImplicitAs.decl
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Int32.decl: %Int32.type = fn_decl @Int32 [template = constants.%Int32] {
 // CHECK:STDOUT:     %return.patt: type = return_slot_pattern
@@ -55,53 +87,231 @@ var arr: [i32; 1 + 2] = (3, 4, 3 + 4);
 // CHECK:STDOUT:     %return.param: ref type = out_param runtime_param0
 // CHECK:STDOUT:     %return: ref type = return_slot %return.param
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   %IntLiteral.decl: %IntLiteral.type = fn_decl @IntLiteral [template = constants.%IntLiteral] {
+// CHECK:STDOUT:     %return.patt: type = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: type = out_param_pattern %return.patt, runtime_param0
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %return.param: ref type = out_param runtime_param0
+// CHECK:STDOUT:     %return: ref type = return_slot %return.param
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Add.decl: type = interface_decl @Add [template = constants.%Add.type] {} {}
+// CHECK:STDOUT:   %ImplicitAs.decl: %ImplicitAs.type.1 = interface_decl @ImplicitAs [template = constants.%ImplicitAs] {
+// CHECK:STDOUT:     %T.patt.loc11_22.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc11_22.2 (constants.%T.patt)]
+// CHECK:STDOUT:     %T.param_patt: type = value_param_pattern %T.patt.loc11_22.1, runtime_param<invalid> [symbolic = %T.patt.loc11_22.2 (constants.%T.patt)]
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %T.param: type = value_param runtime_param<invalid>
+// CHECK:STDOUT:     %T.loc11_22.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc11_22.2 (constants.%T)]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   impl_decl @impl.1 [template] {} {
+// CHECK:STDOUT:     %int.make_type_32: init type = call constants.%Int32() [template = i32]
+// CHECK:STDOUT:     %.loc15_6.1: type = value_of_initializer %int.make_type_32 [template = i32]
+// CHECK:STDOUT:     %.loc15_6.2: type = converted %int.make_type_32, %.loc15_6.1 [template = i32]
+// CHECK:STDOUT:     %Add.ref: type = name_ref Add, file.%Add.decl [template = constants.%Add.type]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   impl_decl @impl.2 [template] {} {
+// CHECK:STDOUT:     %int.make_type_32: init type = call constants.%Int32() [template = i32]
+// CHECK:STDOUT:     %.loc19_6.1: type = value_of_initializer %int.make_type_32 [template = i32]
+// CHECK:STDOUT:     %.loc19_6.2: type = converted %int.make_type_32, %.loc19_6.1 [template = i32]
+// CHECK:STDOUT:     %ImplicitAs.ref: %ImplicitAs.type.1 = name_ref ImplicitAs, file.%ImplicitAs.decl [template = constants.%ImplicitAs]
+// CHECK:STDOUT:     %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, file.%IntLiteral.decl [template = constants.%IntLiteral]
+// CHECK:STDOUT:     %int_literal.make_type: init type = call %IntLiteral.ref() [template = Core.IntLiteral]
+// CHECK:STDOUT:     %.loc19_23.1: type = value_of_initializer %int_literal.make_type [template = Core.IntLiteral]
+// CHECK:STDOUT:     %.loc19_23.2: type = converted %int_literal.make_type, %.loc19_23.1 [template = Core.IntLiteral]
+// CHECK:STDOUT:     %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(Core.IntLiteral)> [template = constants.%ImplicitAs.type.3]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: interface @Add {
-// CHECK:STDOUT:   %Self: %Add.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self]
-// CHECK:STDOUT:   %Op.decl: %Op.type = fn_decl @Op [template = constants.%Op] {
-// CHECK:STDOUT:     %self.patt: @Op.%Self (%Self) = binding_pattern self
-// CHECK:STDOUT:     %self.param_patt: @Op.%Self (%Self) = value_param_pattern %self.patt, runtime_param0
-// CHECK:STDOUT:     %other.patt: @Op.%Self (%Self) = binding_pattern other
-// CHECK:STDOUT:     %other.param_patt: @Op.%Self (%Self) = value_param_pattern %other.patt, runtime_param1
-// CHECK:STDOUT:     %return.patt: @Op.%Self (%Self) = return_slot_pattern
-// CHECK:STDOUT:     %return.param_patt: @Op.%Self (%Self) = out_param_pattern %return.patt, runtime_param2
+// CHECK:STDOUT:   %Self: %Add.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self.1]
+// CHECK:STDOUT:   %Op.decl: %Op.type.1 = fn_decl @Op.1 [template = constants.%Op.1] {
+// CHECK:STDOUT:     %self.patt: @Op.1.%Self (%Self.1) = binding_pattern self
+// CHECK:STDOUT:     %self.param_patt: @Op.1.%Self (%Self.1) = value_param_pattern %self.patt, runtime_param0
+// CHECK:STDOUT:     %other.patt: @Op.1.%Self (%Self.1) = binding_pattern other
+// CHECK:STDOUT:     %other.param_patt: @Op.1.%Self (%Self.1) = value_param_pattern %other.patt, runtime_param1
+// CHECK:STDOUT:     %return.patt: @Op.1.%Self (%Self.1) = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: @Op.1.%Self (%Self.1) = out_param_pattern %return.patt, runtime_param2
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %Self.ref.loc7_15: %Add.type = name_ref Self, @Add.%Self [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:     %.loc7_15.1: type = facet_type_access %Self.ref.loc7_15 [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:     %.loc7_15.2: type = converted %Self.ref.loc7_15, %.loc7_15.1 [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:     %Self.ref.loc7_28: %Add.type = name_ref Self, @Add.%Self [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:     %.loc7_28.1: type = facet_type_access %Self.ref.loc7_28 [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:     %.loc7_28.2: type = converted %Self.ref.loc7_28, %.loc7_28.1 [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:     %Self.ref.loc7_37: %Add.type = name_ref Self, @Add.%Self [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:     %.loc7_37.1: type = facet_type_access %Self.ref.loc7_37 [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:     %.loc7_37.2: type = converted %Self.ref.loc7_37, %.loc7_37.1 [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:     %self.param: @Op.%Self (%Self) = value_param runtime_param0
-// CHECK:STDOUT:     %self: @Op.%Self (%Self) = bind_name self, %self.param
-// CHECK:STDOUT:     %other.param: @Op.%Self (%Self) = value_param runtime_param1
-// CHECK:STDOUT:     %other: @Op.%Self (%Self) = bind_name other, %other.param
-// CHECK:STDOUT:     %return.param: ref @Op.%Self (%Self) = out_param runtime_param2
-// CHECK:STDOUT:     %return: ref @Op.%Self (%Self) = return_slot %return.param
+// CHECK:STDOUT:     %Self.ref.loc8_15: %Add.type = name_ref Self, @Add.%Self [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:     %.loc8_15.1: type = facet_type_access %Self.ref.loc8_15 [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:     %.loc8_15.2: type = converted %Self.ref.loc8_15, %.loc8_15.1 [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:     %Self.ref.loc8_28: %Add.type = name_ref Self, @Add.%Self [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:     %.loc8_28.1: type = facet_type_access %Self.ref.loc8_28 [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:     %.loc8_28.2: type = converted %Self.ref.loc8_28, %.loc8_28.1 [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:     %Self.ref.loc8_37: %Add.type = name_ref Self, @Add.%Self [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:     %.loc8_37.1: type = facet_type_access %Self.ref.loc8_37 [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:     %.loc8_37.2: type = converted %Self.ref.loc8_37, %.loc8_37.1 [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:     %self.param: @Op.1.%Self (%Self.1) = value_param runtime_param0
+// CHECK:STDOUT:     %self: @Op.1.%Self (%Self.1) = bind_name self, %self.param
+// CHECK:STDOUT:     %other.param: @Op.1.%Self (%Self.1) = value_param runtime_param1
+// CHECK:STDOUT:     %other: @Op.1.%Self (%Self.1) = bind_name other, %other.param
+// CHECK:STDOUT:     %return.param: ref @Op.1.%Self (%Self.1) = out_param runtime_param2
+// CHECK:STDOUT:     %return: ref @Op.1.%Self (%Self.1) = return_slot %return.param
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.loc7: %.1 = assoc_entity element0, %Op.decl [template = constants.%.2]
+// CHECK:STDOUT:   %.loc8: %.1 = assoc_entity element0, %Op.decl [template = constants.%.2]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .Self = %Self
-// CHECK:STDOUT:   .Op = %.loc7
+// CHECK:STDOUT:   .Op = %.loc8
 // CHECK:STDOUT:   witness = (%Op.decl)
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: generic interface @ImplicitAs(%T.loc11_22.1: type) {
+// CHECK:STDOUT:   %T.loc11_22.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc11_22.2 (constants.%T)]
+// CHECK:STDOUT:   %T.patt.loc11_22.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc11_22.2 (constants.%T.patt)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%T.loc11_22.2)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.2)]
+// CHECK:STDOUT:   %Self.2: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self.2 (constants.%Self.2)]
+// CHECK:STDOUT:   %Convert.type: type = fn_type @Convert.1, @ImplicitAs(%T.loc11_22.2) [symbolic = %Convert.type (constants.%Convert.type.1)]
+// CHECK:STDOUT:   %Convert: @ImplicitAs.%Convert.type (%Convert.type.1) = struct_value () [symbolic = %Convert (constants.%Convert.1)]
+// CHECK:STDOUT:   %.loc12_32.2: type = assoc_entity_type @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2), @ImplicitAs.%Convert.type (%Convert.type.1) [symbolic = %.loc12_32.2 (constants.%.3)]
+// CHECK:STDOUT:   %.loc12_32.3: @ImplicitAs.%.loc12_32.2 (%.3) = assoc_entity element0, %Convert.decl [symbolic = %.loc12_32.3 (constants.%.4)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   interface {
+// CHECK:STDOUT:     %Self.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2) = bind_symbolic_name Self, 1 [symbolic = %Self.2 (constants.%Self.2)]
+// CHECK:STDOUT:     %Convert.decl: @ImplicitAs.%Convert.type (%Convert.type.1) = fn_decl @Convert.1 [symbolic = @ImplicitAs.%Convert (constants.%Convert.1)] {
+// CHECK:STDOUT:       %self.patt: @Convert.1.%Self (%Self.2) = binding_pattern self
+// CHECK:STDOUT:       %self.param_patt: @Convert.1.%Self (%Self.2) = value_param_pattern %self.patt, runtime_param0
+// CHECK:STDOUT:       %return.patt: @Convert.1.%T (%T) = return_slot_pattern
+// CHECK:STDOUT:       %return.param_patt: @Convert.1.%T (%T) = out_param_pattern %return.patt, runtime_param1
+// CHECK:STDOUT:     } {
+// CHECK:STDOUT:       %.loc12_20.1: @Convert.1.%ImplicitAs.type (%ImplicitAs.type.2) = specific_constant @ImplicitAs.%Self.1, @ImplicitAs(constants.%T) [symbolic = %Self (constants.%Self.2)]
+// CHECK:STDOUT:       %Self.ref: @Convert.1.%ImplicitAs.type (%ImplicitAs.type.2) = name_ref Self, %.loc12_20.1 [symbolic = %Self (constants.%Self.2)]
+// CHECK:STDOUT:       %.loc12_20.2: type = facet_type_access %Self.ref [symbolic = %Self (constants.%Self.2)]
+// CHECK:STDOUT:       %.loc12_20.3: type = converted %Self.ref, %.loc12_20.2 [symbolic = %Self (constants.%Self.2)]
+// CHECK:STDOUT:       %T.ref: type = name_ref T, @ImplicitAs.%T.loc11_22.1 [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:       %self.param: @Convert.1.%Self (%Self.2) = value_param runtime_param0
+// CHECK:STDOUT:       %self: @Convert.1.%Self (%Self.2) = bind_name self, %self.param
+// CHECK:STDOUT:       %return.param: ref @Convert.1.%T (%T) = out_param runtime_param1
+// CHECK:STDOUT:       %return: ref @Convert.1.%T (%T) = return_slot %return.param
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:     %.loc12_32.1: @ImplicitAs.%.loc12_32.2 (%.3) = assoc_entity element0, %Convert.decl [symbolic = %.loc12_32.3 (constants.%.4)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Self = %Self.1
+// CHECK:STDOUT:     .Convert = %.loc12_32.1
+// CHECK:STDOUT:     witness = (%Convert.decl)
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @impl.1: %.loc15_6.2 as %Add.ref {
+// CHECK:STDOUT:   %Op.decl: %Op.type.2 = fn_decl @Op.2 [template = constants.%Op.2] {
+// CHECK:STDOUT:     %self.patt: i32 = binding_pattern self
+// CHECK:STDOUT:     %self.param_patt: i32 = value_param_pattern %self.patt, runtime_param0
+// CHECK:STDOUT:     %other.patt: i32 = binding_pattern other
+// CHECK:STDOUT:     %other.param_patt: i32 = value_param_pattern %other.patt, runtime_param1
+// CHECK:STDOUT:     %return.patt: i32 = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: i32 = out_param_pattern %return.patt, runtime_param2
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %Self.ref.loc16_15: type = name_ref Self, @impl.1.%.loc15_6.2 [template = i32]
+// CHECK:STDOUT:     %Self.ref.loc16_28: type = name_ref Self, @impl.1.%.loc15_6.2 [template = i32]
+// CHECK:STDOUT:     %Self.ref.loc16_37: type = name_ref Self, @impl.1.%.loc15_6.2 [template = i32]
+// CHECK:STDOUT:     %self.param: i32 = value_param runtime_param0
+// CHECK:STDOUT:     %self: i32 = bind_name self, %self.param
+// CHECK:STDOUT:     %other.param: i32 = value_param runtime_param1
+// CHECK:STDOUT:     %other: i32 = bind_name other, %other.param
+// CHECK:STDOUT:     %return.param: ref i32 = out_param runtime_param2
+// CHECK:STDOUT:     %return: ref i32 = return_slot %return.param
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc15_17: <witness> = interface_witness (%Op.decl) [template = constants.%.5]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Op = %Op.decl
+// CHECK:STDOUT:   witness = %.loc15_17
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @impl.2: %.loc19_6.2 as %ImplicitAs.type {
+// CHECK:STDOUT:   %Convert.decl: %Convert.type.2 = fn_decl @Convert.2 [template = constants.%Convert.2] {
+// CHECK:STDOUT:     %self.patt: i32 = binding_pattern self
+// CHECK:STDOUT:     %self.param_patt: i32 = value_param_pattern %self.patt, runtime_param0
+// CHECK:STDOUT:     %return.patt: Core.IntLiteral = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: Core.IntLiteral = out_param_pattern %return.patt, runtime_param1
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %Self.ref: type = name_ref Self, @impl.2.%.loc19_6.2 [template = i32]
+// CHECK:STDOUT:     %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, file.%IntLiteral.decl [template = constants.%IntLiteral]
+// CHECK:STDOUT:     %int_literal.make_type: init type = call %IntLiteral.ref() [template = Core.IntLiteral]
+// CHECK:STDOUT:     %.loc20_42.1: type = value_of_initializer %int_literal.make_type [template = Core.IntLiteral]
+// CHECK:STDOUT:     %.loc20_42.2: type = converted %int_literal.make_type, %.loc20_42.1 [template = Core.IntLiteral]
+// CHECK:STDOUT:     %self.param: i32 = value_param runtime_param0
+// CHECK:STDOUT:     %self: i32 = bind_name self, %self.param
+// CHECK:STDOUT:     %return.param: ref Core.IntLiteral = out_param runtime_param1
+// CHECK:STDOUT:     %return: ref Core.IntLiteral = return_slot %return.param
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc19_38: <witness> = interface_witness (%Convert.decl) [template = constants.%.8]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Convert = %Convert.decl
+// CHECK:STDOUT:   witness = %.loc19_38
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
 // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32";
 // CHECK:STDOUT:
-// CHECK:STDOUT: generic fn @Op(@Add.%Self: %Add.type) {
-// CHECK:STDOUT:   %Self: %Add.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self)]
+// CHECK:STDOUT: fn @IntLiteral() -> type = "int_literal.make_type";
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn[%self.param_patt: @Op.%Self (%Self)](%other.param_patt: @Op.%Self (%Self)) -> @Op.%Self (%Self);
+// CHECK:STDOUT: generic fn @Op.1(@Add.%Self: %Add.type) {
+// CHECK:STDOUT:   %Self: %Add.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   fn[%self.param_patt: @Op.1.%Self (%Self.1)](%other.param_patt: @Op.1.%Self (%Self.1)) -> @Op.1.%Self (%Self.1);
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic fn @Convert.1(@ImplicitAs.%T.loc11_22.1: type, @ImplicitAs.%Self.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2)) {
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%T)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.2)]
+// CHECK:STDOUT:   %Self: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.2)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   fn[%self.param_patt: @Convert.1.%Self (%Self.2)]() -> @Convert.1.%T (%T);
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @Op.2[%self.param_patt: i32](%other.param_patt: i32) -> i32 = "int.sadd";
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @Convert.2[%self.param_patt: i32]() -> Core.IntLiteral = "int.convert_checked";
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Op.1(constants.%Self.1) {
+// CHECK:STDOUT:   %Self => constants.%Self.1
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @Op(constants.%Self) {
-// CHECK:STDOUT:   %Self => constants.%Self
+// CHECK:STDOUT: specific @ImplicitAs(constants.%T) {
+// CHECK:STDOUT:   %T.loc11_22.2 => constants.%T
+// CHECK:STDOUT:   %T.patt.loc11_22.2 => constants.%T
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @ImplicitAs(@Convert.1.%T) {
+// CHECK:STDOUT:   %T.loc11_22.2 => constants.%T
+// CHECK:STDOUT:   %T.patt.loc11_22.2 => constants.%T
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Convert.1(constants.%T, constants.%Self.2) {
+// CHECK:STDOUT:   %T => constants.%T
+// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.2
+// CHECK:STDOUT:   %Self => constants.%Self.2
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @ImplicitAs(%T.loc11_22.2) {
+// CHECK:STDOUT:   %T.loc11_22.2 => constants.%T
+// CHECK:STDOUT:   %T.patt.loc11_22.2 => constants.%T
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Op.1(i32) {
+// CHECK:STDOUT:   %Self => i32
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @ImplicitAs(Core.IntLiteral) {
+// CHECK:STDOUT:   %T.loc11_22.2 => Core.IntLiteral
+// CHECK:STDOUT:   %T.patt.loc11_22.2 => Core.IntLiteral
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.3
+// CHECK:STDOUT:   %Self.2 => constants.%Self.2
+// CHECK:STDOUT:   %Convert.type => constants.%Convert.type.3
+// CHECK:STDOUT:   %Convert => constants.%Convert.3
+// CHECK:STDOUT:   %.loc12_32.2 => constants.%.6
+// CHECK:STDOUT:   %.loc12_32.3 => constants.%.7
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Convert.1(Core.IntLiteral, i32) {
+// CHECK:STDOUT:   %T => Core.IntLiteral
+// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.3
+// CHECK:STDOUT:   %Self => i32
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: --- user.carbon
@@ -109,38 +319,67 @@ var arr: [i32; 1 + 2] = (3, 4, 3 + 4);
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
+// CHECK:STDOUT:   %.1: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %.2: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %Add.type: type = facet_type <@Add> [template]
-// CHECK:STDOUT:   %Self: %Add.type = bind_symbolic_name Self, 0 [symbolic]
+// CHECK:STDOUT:   %Self.1: %Add.type = bind_symbolic_name Self, 0 [symbolic]
 // CHECK:STDOUT:   %Op.type.1: type = fn_type @Op.1 [template]
-// CHECK:STDOUT:   %Op.1: %Op.type.1 = struct_value () [template]
+// CHECK:STDOUT:   %.3: type = assoc_entity_type %Add.type, %Op.type.1 [template]
+// CHECK:STDOUT:   %.4: %.3 = assoc_entity element0, imports.%import_ref.6 [template]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.type.2: type = facet_type <@ImplicitAs, @ImplicitAs(%T)> [symbolic]
+// CHECK:STDOUT:   %Self.2: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2) = bind_symbolic_name Self, 1 [symbolic]
+// CHECK:STDOUT:   %T.patt: type = symbolic_binding_pattern T, 0 [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.type.3: type = facet_type <@ImplicitAs, @ImplicitAs(Core.IntLiteral)> [template]
+// CHECK:STDOUT:   %Self.3: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic]
+// CHECK:STDOUT:   %Convert.type.1: type = fn_type @Convert.1, @ImplicitAs(%T) [symbolic]
+// CHECK:STDOUT:   %Convert.1: %Convert.type.1 = struct_value () [symbolic]
+// CHECK:STDOUT:   %.5: type = assoc_entity_type %ImplicitAs.type.2, %Convert.type.1 [symbolic]
+// CHECK:STDOUT:   %.6: %.5 = assoc_entity element0, imports.%import_ref.16 [symbolic]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.2: %Convert.type.2 = struct_value () [template]
+// CHECK:STDOUT:   %.7: type = assoc_entity_type %ImplicitAs.type.3, %Convert.type.2 [template]
+// CHECK:STDOUT:   %.8: %.7 = assoc_entity element0, imports.%import_ref.17 [template]
 // CHECK:STDOUT:   %Op.type.2: type = fn_type @Op.2 [template]
 // CHECK:STDOUT:   %Op.2: %Op.type.2 = struct_value () [template]
-// CHECK:STDOUT:   %.1: <witness> = interface_witness (%Op.1) [template]
-// CHECK:STDOUT:   %.2: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.3: i32 = int_value 2 [template]
-// CHECK:STDOUT:   %.4: type = assoc_entity_type %Add.type, %Op.type.2 [template]
-// CHECK:STDOUT:   %.5: %.4 = assoc_entity element0, imports.%import_ref.6 [template]
-// CHECK:STDOUT:   %.6: <bound method> = bound_method %.2, %Op.1 [template]
-// CHECK:STDOUT:   %.7: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.8: type = array_type %.7, i32 [template]
-// CHECK:STDOUT:   %.10: i32 = int_value 4 [template]
-// CHECK:STDOUT:   %.11: <bound method> = bound_method %.7, %Op.1 [template]
-// CHECK:STDOUT:   %.12: i32 = int_value 7 [template]
+// CHECK:STDOUT:   %.9: <witness> = interface_witness (%Op.2) [template]
+// CHECK:STDOUT:   %.10: <bound method> = bound_method %.1, %Op.2 [template]
+// CHECK:STDOUT:   %.11: i32 = int_value 3 [template]
+// CHECK:STDOUT:   %.12: %.5 = assoc_entity element0, imports.%import_ref.19 [symbolic]
+// CHECK:STDOUT:   %Convert.type.3: type = fn_type @Convert.2 [template]
+// CHECK:STDOUT:   %Convert.3: %Convert.type.3 = struct_value () [template]
+// CHECK:STDOUT:   %.13: <witness> = interface_witness (%Convert.3) [template]
+// CHECK:STDOUT:   %.14: <bound method> = bound_method %.11, %Convert.3 [template]
+// CHECK:STDOUT:   %.15: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.16: type = array_type %.15, i32 [template]
+// CHECK:STDOUT:   %.18: i32 = int_value 4 [template]
+// CHECK:STDOUT:   %.19: <bound method> = bound_method %.11, %Op.2 [template]
+// CHECK:STDOUT:   %.20: i32 = int_value 7 [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (i32, i32, i32) [template]
-// CHECK:STDOUT:   %.13: i32 = int_value 0 [template]
-// CHECK:STDOUT:   %array: %.8 = tuple_value (%.7, %.10, %.12) [template]
+// CHECK:STDOUT:   %.21: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %array: %.16 = tuple_value (%.11, %.18, %.20) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
 // CHECK:STDOUT:     .Int32 = %import_ref.1
 // CHECK:STDOUT:     .Add = %import_ref.2
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.18
 // CHECK:STDOUT:     import Core//default
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.2: type = import_ref Core//default, inst+9, loaded [template = constants.%Add.type]
-// CHECK:STDOUT:   %import_ref.3 = import_ref Core//default, inst+11, unloaded
-// CHECK:STDOUT:   %import_ref.4: %.4 = import_ref Core//default, inst+39, loaded [template = constants.%.5]
-// CHECK:STDOUT:   %import_ref.5: %Op.type.2 = import_ref Core//default, inst+34, loaded [template = constants.%Op.2]
+// CHECK:STDOUT:   %import_ref.3 = import_ref Core//default, inst+18, unloaded
+// CHECK:STDOUT:   %import_ref.4: %.3 = import_ref Core//default, inst+46, loaded [template = constants.%.4]
+// CHECK:STDOUT:   %import_ref.5 = import_ref Core//default, inst+41, unloaded
+// CHECK:STDOUT:   %import_ref.7: type = import_ref Core//default, inst+92, loaded [template = i32]
+// CHECK:STDOUT:   %import_ref.8: type = import_ref Core//default, inst+93, loaded [template = constants.%Add.type]
+// CHECK:STDOUT:   %import_ref.9: <witness> = import_ref Core//default, inst+113, loaded [template = constants.%.9]
+// CHECK:STDOUT:   %import_ref.10 = import_ref Core//default, inst+60, unloaded
+// CHECK:STDOUT:   %import_ref.11: @ImplicitAs.%.1 (%.5) = import_ref Core//default, inst+82, loaded [symbolic = @ImplicitAs.%.2 (constants.%.12)]
+// CHECK:STDOUT:   %import_ref.12 = import_ref Core//default, inst+75, unloaded
+// CHECK:STDOUT:   %import_ref.13: type = import_ref Core//default, inst+117, loaded [template = i32]
+// CHECK:STDOUT:   %import_ref.14: type = import_ref Core//default, inst+123, loaded [template = constants.%ImplicitAs.type.3]
+// CHECK:STDOUT:   %import_ref.15: <witness> = import_ref Core//default, inst+146, loaded [template = constants.%.13]
+// CHECK:STDOUT:   %import_ref.16 = import_ref Core//default, inst+75, unloaded
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -149,24 +388,24 @@ var arr: [i32; 1 + 2] = (3, 4, 3 + 4);
 // CHECK:STDOUT:     .arr = %arr
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
-// CHECK:STDOUT:   impl_decl @impl [template] {} {
-// CHECK:STDOUT:     %int.make_type_32: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:     %.loc6_6.1: type = value_of_initializer %int.make_type_32 [template = i32]
-// CHECK:STDOUT:     %.loc6_6.2: type = converted %int.make_type_32, %.loc6_6.1 [template = i32]
-// CHECK:STDOUT:     %Core.ref: <namespace> = name_ref Core, imports.%Core [template = imports.%Core]
-// CHECK:STDOUT:     %Add.ref: type = name_ref Add, imports.%import_ref.2 [template = constants.%Add.type]
-// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %int.make_type_32: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc10_16: i32 = int_value 1 [template = constants.%.2]
-// CHECK:STDOUT:   %.loc10_20: i32 = int_value 2 [template = constants.%.3]
-// CHECK:STDOUT:   %.loc10_18.1: %Op.type.2 = interface_witness_access constants.%.1, element0 [template = constants.%Op.1]
-// CHECK:STDOUT:   %.loc10_18.2: <bound method> = bound_method %.loc10_16, %.loc10_18.1 [template = constants.%.6]
-// CHECK:STDOUT:   %int.sadd: init i32 = call %.loc10_18.2(%.loc10_16, %.loc10_20) [template = constants.%.7]
-// CHECK:STDOUT:   %.loc10_11.1: type = value_of_initializer %int.make_type_32 [template = i32]
-// CHECK:STDOUT:   %.loc10_11.2: type = converted %int.make_type_32, %.loc10_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc10_21: type = array_type %int.sadd, i32 [template = constants.%.8]
-// CHECK:STDOUT:   %arr.var: ref %.8 = var arr
-// CHECK:STDOUT:   %arr: ref %.8 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc4_16: i32 = int_value 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc4_20: i32 = int_value 2 [template = constants.%.2]
+// CHECK:STDOUT:   %.loc4_18.1: %Op.type.1 = interface_witness_access constants.%.9, element0 [template = constants.%Op.2]
+// CHECK:STDOUT:   %.loc4_18.2: <bound method> = bound_method %.loc4_16, %.loc4_18.1 [template = constants.%.10]
+// CHECK:STDOUT:   %int.sadd: init i32 = call %.loc4_18.2(%.loc4_16, %.loc4_20) [template = constants.%.11]
+// CHECK:STDOUT:   %.loc4_11.1: type = value_of_initializer %int.make_type_32 [template = i32]
+// CHECK:STDOUT:   %.loc4_11.2: type = converted %int.make_type_32, %.loc4_11.1 [template = i32]
+// CHECK:STDOUT:   %.loc4_18.3: %Convert.type.2 = interface_witness_access constants.%.13, element0 [template = constants.%Convert.3]
+// CHECK:STDOUT:   %.loc4_18.4: <bound method> = bound_method %int.sadd, %.loc4_18.3 [template = constants.%.14]
+// CHECK:STDOUT:   %.loc4_18.5: i32 = value_of_initializer %int.sadd [template = constants.%.11]
+// CHECK:STDOUT:   %.loc4_18.6: i32 = converted %int.sadd, %.loc4_18.5 [template = constants.%.11]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc4_18.4(%.loc4_18.6) [template = constants.%.15]
+// CHECK:STDOUT:   %.loc4_18.7: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.15]
+// CHECK:STDOUT:   %.loc4_18.8: Core.IntLiteral = converted %int.sadd, %.loc4_18.7 [template = constants.%.15]
+// CHECK:STDOUT:   %.loc4_21: type = array_type %.loc4_18.8, i32 [template = constants.%.16]
+// CHECK:STDOUT:   %arr.var: ref %.16 = var arr
+// CHECK:STDOUT:   %arr: ref %.16 = bind_name arr, %arr.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: interface @Add {
@@ -176,72 +415,116 @@ var arr: [i32; 1 + 2] = (3, 4, 3 + 4);
 // CHECK:STDOUT:   witness = (imports.%import_ref.5)
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: impl @impl: %.loc6_6.2 as %Add.ref {
-// CHECK:STDOUT:   %Op.decl: %Op.type.1 = fn_decl @Op.1 [template = constants.%Op.1] {
-// CHECK:STDOUT:     %self.patt: i32 = binding_pattern self
-// CHECK:STDOUT:     %self.param_patt: i32 = value_param_pattern %self.patt, runtime_param0
-// CHECK:STDOUT:     %other.patt: i32 = binding_pattern other
-// CHECK:STDOUT:     %other.param_patt: i32 = value_param_pattern %other.patt, runtime_param1
-// CHECK:STDOUT:     %return.patt: i32 = return_slot_pattern
-// CHECK:STDOUT:     %return.param_patt: i32 = out_param_pattern %return.patt, runtime_param2
-// CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %Self.ref.loc7_15: type = name_ref Self, @impl.%.loc6_6.2 [template = i32]
-// CHECK:STDOUT:     %Self.ref.loc7_28: type = name_ref Self, @impl.%.loc6_6.2 [template = i32]
-// CHECK:STDOUT:     %Self.ref.loc7_37: type = name_ref Self, @impl.%.loc6_6.2 [template = i32]
-// CHECK:STDOUT:     %self.param: i32 = value_param runtime_param0
-// CHECK:STDOUT:     %self: i32 = bind_name self, %self.param
-// CHECK:STDOUT:     %other.param: i32 = value_param runtime_param1
-// CHECK:STDOUT:     %other: i32 = bind_name other, %other.param
-// CHECK:STDOUT:     %return.param: ref i32 = out_param runtime_param2
-// CHECK:STDOUT:     %return: ref i32 = return_slot %return.param
+// CHECK:STDOUT: generic interface @ImplicitAs(constants.%T: type) {
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:   %T.patt: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt (constants.%T.patt)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%T)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.2)]
+// CHECK:STDOUT:   %Self: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.3)]
+// CHECK:STDOUT:   %Convert.type: type = fn_type @Convert.1, @ImplicitAs(%T) [symbolic = %Convert.type (constants.%Convert.type.1)]
+// CHECK:STDOUT:   %Convert: @ImplicitAs.%Convert.type (%Convert.type.1) = struct_value () [symbolic = %Convert (constants.%Convert.1)]
+// CHECK:STDOUT:   %.1: type = assoc_entity_type @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2), @ImplicitAs.%Convert.type (%Convert.type.1) [symbolic = %.1 (constants.%.5)]
+// CHECK:STDOUT:   %.2: @ImplicitAs.%.1 (%.5) = assoc_entity element0, imports.%import_ref.16 [symbolic = %.2 (constants.%.6)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   interface {
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Self = imports.%import_ref.10
+// CHECK:STDOUT:     .Convert = imports.%import_ref.11
+// CHECK:STDOUT:     witness = (imports.%import_ref.12)
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.loc6_22: <witness> = interface_witness (%Op.decl) [template = constants.%.1]
+// CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: impl @impl.1: imports.%import_ref.7 as imports.%import_ref.8 {
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .Op = %Op.decl
-// CHECK:STDOUT:   witness = %.loc6_22
+// CHECK:STDOUT:   witness = imports.%import_ref.9
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @impl.2: imports.%import_ref.13 as imports.%import_ref.14 {
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   witness = imports.%import_ref.15
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32";
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @Op.1[%self.param_patt: i32](%other.param_patt: i32) -> i32 = "int.sadd";
+// CHECK:STDOUT: generic fn @Op.1(constants.%Self.1: %Add.type) {
+// CHECK:STDOUT:   %Self: %Add.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self.1)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   fn[%self.param_patt: @Op.1.%Self (%Self.1)](%other.param_patt: @Op.1.%Self (%Self.1)) -> @Op.1.%Self (%Self.1);
+// CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: generic fn @Op.2(constants.%Self: %Add.type) {
-// CHECK:STDOUT:   %Self: %Add.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self)]
+// CHECK:STDOUT: generic fn @Convert.1(constants.%T: type, constants.%Self.2: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2)) {
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%T)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.2)]
+// CHECK:STDOUT:   %Self: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.3)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn[%self.param_patt: @Op.2.%Self (%Self)](%other.param_patt: @Op.2.%Self (%Self)) -> @Op.2.%Self (%Self);
+// CHECK:STDOUT:   fn[%self.param_patt: @Convert.1.%Self (%Self.3)]() -> @Convert.1.%T (%T);
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: fn @Op.2[%self.param_patt: i32](%other.param_patt: i32) -> i32 = "int.sadd";
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @Convert.2[%self.param_patt: i32]() -> Core.IntLiteral = "int.convert_checked";
+// CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc10_26: i32 = int_value 3 [template = constants.%.7]
-// CHECK:STDOUT:   %.loc10_29: i32 = int_value 4 [template = constants.%.10]
-// CHECK:STDOUT:   %.loc10_32: i32 = int_value 3 [template = constants.%.7]
-// CHECK:STDOUT:   %.loc10_36: i32 = int_value 4 [template = constants.%.10]
-// CHECK:STDOUT:   %.loc10_34.1: %Op.type.2 = interface_witness_access constants.%.1, element0 [template = constants.%Op.1]
-// CHECK:STDOUT:   %.loc10_34.2: <bound method> = bound_method %.loc10_32, %.loc10_34.1 [template = constants.%.11]
-// CHECK:STDOUT:   %int.sadd: init i32 = call %.loc10_34.2(%.loc10_32, %.loc10_36) [template = constants.%.12]
-// CHECK:STDOUT:   %.loc10_37.1: %tuple.type = tuple_literal (%.loc10_26, %.loc10_29, %int.sadd)
-// CHECK:STDOUT:   %.loc10_37.2: i32 = int_value 0 [template = constants.%.13]
-// CHECK:STDOUT:   %.loc10_37.3: ref i32 = array_index file.%arr.var, %.loc10_37.2
-// CHECK:STDOUT:   %.loc10_37.4: init i32 = initialize_from %.loc10_26 to %.loc10_37.3 [template = constants.%.7]
-// CHECK:STDOUT:   %.loc10_37.5: i32 = int_value 1 [template = constants.%.2]
-// CHECK:STDOUT:   %.loc10_37.6: ref i32 = array_index file.%arr.var, %.loc10_37.5
-// CHECK:STDOUT:   %.loc10_37.7: init i32 = initialize_from %.loc10_29 to %.loc10_37.6 [template = constants.%.10]
-// CHECK:STDOUT:   %.loc10_37.8: i32 = int_value 2 [template = constants.%.3]
-// CHECK:STDOUT:   %.loc10_37.9: ref i32 = array_index file.%arr.var, %.loc10_37.8
-// CHECK:STDOUT:   %.loc10_37.10: init i32 = initialize_from %int.sadd to %.loc10_37.9 [template = constants.%.12]
-// CHECK:STDOUT:   %.loc10_37.11: init %.8 = array_init (%.loc10_37.4, %.loc10_37.7, %.loc10_37.10) to file.%arr.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc10_38: init %.8 = converted %.loc10_37.1, %.loc10_37.11 [template = constants.%array]
-// CHECK:STDOUT:   assign file.%arr.var, %.loc10_38
+// CHECK:STDOUT:   %.loc4_26: i32 = int_value 3 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc4_29: i32 = int_value 4 [template = constants.%.18]
+// CHECK:STDOUT:   %.loc4_32: i32 = int_value 3 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc4_36: i32 = int_value 4 [template = constants.%.18]
+// CHECK:STDOUT:   %.loc4_34.1: %Op.type.1 = interface_witness_access constants.%.9, element0 [template = constants.%Op.2]
+// CHECK:STDOUT:   %.loc4_34.2: <bound method> = bound_method %.loc4_32, %.loc4_34.1 [template = constants.%.19]
+// CHECK:STDOUT:   %int.sadd: init i32 = call %.loc4_34.2(%.loc4_32, %.loc4_36) [template = constants.%.20]
+// CHECK:STDOUT:   %.loc4_37.1: %tuple.type = tuple_literal (%.loc4_26, %.loc4_29, %int.sadd)
+// CHECK:STDOUT:   %.loc4_37.2: i32 = int_value 0 [template = constants.%.21]
+// CHECK:STDOUT:   %.loc4_37.3: ref i32 = array_index file.%arr.var, %.loc4_37.2
+// CHECK:STDOUT:   %.loc4_37.4: init i32 = initialize_from %.loc4_26 to %.loc4_37.3 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc4_37.5: i32 = int_value 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc4_37.6: ref i32 = array_index file.%arr.var, %.loc4_37.5
+// CHECK:STDOUT:   %.loc4_37.7: init i32 = initialize_from %.loc4_29 to %.loc4_37.6 [template = constants.%.18]
+// CHECK:STDOUT:   %.loc4_37.8: i32 = int_value 2 [template = constants.%.2]
+// CHECK:STDOUT:   %.loc4_37.9: ref i32 = array_index file.%arr.var, %.loc4_37.8
+// CHECK:STDOUT:   %.loc4_37.10: init i32 = initialize_from %int.sadd to %.loc4_37.9 [template = constants.%.20]
+// CHECK:STDOUT:   %.loc4_37.11: init %.16 = array_init (%.loc4_37.4, %.loc4_37.7, %.loc4_37.10) to file.%arr.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc4_38: init %.16 = converted %.loc4_37.1, %.loc4_37.11 [template = constants.%array]
+// CHECK:STDOUT:   assign file.%arr.var, %.loc4_38
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @Op.2(constants.%Self) {
-// CHECK:STDOUT:   %Self => constants.%Self
+// CHECK:STDOUT: specific @Op.1(constants.%Self.1) {
+// CHECK:STDOUT:   %Self => constants.%Self.1
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @Op.2(i32) {
-// CHECK:STDOUT:   %Self => i32
+// CHECK:STDOUT: specific @ImplicitAs(constants.%T) {
+// CHECK:STDOUT:   %T => constants.%T
+// CHECK:STDOUT:   %T.patt => constants.%T
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @ImplicitAs(Core.IntLiteral) {
+// CHECK:STDOUT:   %T => Core.IntLiteral
+// CHECK:STDOUT:   %T.patt => Core.IntLiteral
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.3
+// CHECK:STDOUT:   %Self => constants.%Self.3
+// CHECK:STDOUT:   %Convert.type => constants.%Convert.type.2
+// CHECK:STDOUT:   %Convert => constants.%Convert.2
+// CHECK:STDOUT:   %.1 => constants.%.7
+// CHECK:STDOUT:   %.2 => constants.%.8
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @ImplicitAs(%T) {
+// CHECK:STDOUT:   %T => constants.%T
+// CHECK:STDOUT:   %T.patt => constants.%T
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @ImplicitAs(@Convert.1.%T) {
+// CHECK:STDOUT:   %T => constants.%T
+// CHECK:STDOUT:   %T.patt => constants.%T
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Convert.1(constants.%T, constants.%Self.2) {
+// CHECK:STDOUT:   %T => constants.%T
+// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.2
+// CHECK:STDOUT:   %Self => constants.%Self.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 82 - 30
toolchain/check/testdata/function/builtin/no_prelude/import.carbon

@@ -15,11 +15,14 @@ package Core library "[[@TEST_NAME]]";
 fn Int32() -> type = "int.make_type_32";
 fn TestAdd(a: i32, b: i32) -> i32 = "int.sadd";
 
+fn IntLiteral() -> type = "int_literal.make_type";
+fn AsIntLiteral(a: i32) -> IntLiteral() = "int.convert_checked";
+
 // --- use.carbon
 
 import Core library "core";
 
-var arr: [i32; Core.TestAdd(1, 2)] = (1, 2, 3);
+var arr: [i32; Core.AsIntLiteral(Core.TestAdd(1, 2))] = (1, 2, 3);
 
 // CHECK:STDOUT: --- core.carbon
 // CHECK:STDOUT:
@@ -28,12 +31,18 @@ var arr: [i32; Core.TestAdd(1, 2)] = (1, 2, 3);
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %TestAdd.type: type = fn_type @TestAdd [template]
 // CHECK:STDOUT:   %TestAdd: %TestAdd.type = struct_value () [template]
+// CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [template]
+// CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [template]
+// CHECK:STDOUT:   %AsIntLiteral.type: type = fn_type @AsIntLiteral [template]
+// CHECK:STDOUT:   %AsIntLiteral: %AsIntLiteral.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Int32 = %Int32.decl
 // CHECK:STDOUT:     .TestAdd = %TestAdd.decl
+// CHECK:STDOUT:     .IntLiteral = %IntLiteral.decl
+// CHECK:STDOUT:     .AsIntLiteral = %AsIntLiteral.decl
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Int32.decl: %Int32.type = fn_decl @Int32 [template = constants.%Int32] {
 // CHECK:STDOUT:     %return.patt: type = return_slot_pattern
@@ -66,35 +75,69 @@ var arr: [i32; Core.TestAdd(1, 2)] = (1, 2, 3);
 // CHECK:STDOUT:     %return.param: ref i32 = out_param runtime_param2
 // CHECK:STDOUT:     %return: ref i32 = return_slot %return.param
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   %IntLiteral.decl: %IntLiteral.type = fn_decl @IntLiteral [template = constants.%IntLiteral] {
+// CHECK:STDOUT:     %return.patt: type = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: type = out_param_pattern %return.patt, runtime_param0
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %return.param: ref type = out_param runtime_param0
+// CHECK:STDOUT:     %return: ref type = return_slot %return.param
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %AsIntLiteral.decl: %AsIntLiteral.type = fn_decl @AsIntLiteral [template = constants.%AsIntLiteral] {
+// CHECK:STDOUT:     %a.patt: i32 = binding_pattern a
+// CHECK:STDOUT:     %a.param_patt: i32 = value_param_pattern %a.patt, runtime_param0
+// CHECK:STDOUT:     %return.patt: Core.IntLiteral = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: Core.IntLiteral = out_param_pattern %return.patt, runtime_param1
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %int.make_type_32: init type = call constants.%Int32() [template = i32]
+// CHECK:STDOUT:     %.loc8_20.1: type = value_of_initializer %int.make_type_32 [template = i32]
+// CHECK:STDOUT:     %.loc8_20.2: type = converted %int.make_type_32, %.loc8_20.1 [template = i32]
+// CHECK:STDOUT:     %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, file.%IntLiteral.decl [template = constants.%IntLiteral]
+// CHECK:STDOUT:     %int_literal.make_type: init type = call %IntLiteral.ref() [template = Core.IntLiteral]
+// CHECK:STDOUT:     %.loc8_39.1: type = value_of_initializer %int_literal.make_type [template = Core.IntLiteral]
+// CHECK:STDOUT:     %.loc8_39.2: type = converted %int_literal.make_type, %.loc8_39.1 [template = Core.IntLiteral]
+// CHECK:STDOUT:     %a.param: i32 = value_param runtime_param0
+// CHECK:STDOUT:     %a: i32 = bind_name a, %a.param
+// CHECK:STDOUT:     %return.param: ref Core.IntLiteral = out_param runtime_param1
+// CHECK:STDOUT:     %return: ref Core.IntLiteral = return_slot %return.param
+// CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32";
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @TestAdd(%a.param_patt: i32, %b.param_patt: i32) -> i32 = "int.sadd";
 // CHECK:STDOUT:
+// CHECK:STDOUT: fn @IntLiteral() -> type = "int_literal.make_type";
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @AsIntLiteral(%a.param_patt: i32) -> Core.IntLiteral = "int.convert_checked";
+// CHECK:STDOUT:
 // CHECK:STDOUT: --- use.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
+// CHECK:STDOUT:   %AsIntLiteral.type: type = fn_type @AsIntLiteral [template]
+// CHECK:STDOUT:   %AsIntLiteral: %AsIntLiteral.type = struct_value () [template]
 // CHECK:STDOUT:   %TestAdd.type: type = fn_type @TestAdd [template]
 // CHECK:STDOUT:   %TestAdd: %TestAdd.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 1 [template]
 // CHECK:STDOUT:   %.2: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %.3: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
+// CHECK:STDOUT:   %.4: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.5: type = array_type %.4, i32 [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (i32, i32, i32) [template]
-// CHECK:STDOUT:   %.6: i32 = int_value 0 [template]
-// CHECK:STDOUT:   %array: %.4 = tuple_value (%.1, %.2, %.3) [template]
+// CHECK:STDOUT:   %.7: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %array: %.5 = tuple_value (%.1, %.2, %.3) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
 // CHECK:STDOUT:     .Int32 = %import_ref.1
-// CHECK:STDOUT:     .TestAdd = %import_ref.2
+// CHECK:STDOUT:     .AsIntLiteral = %import_ref.2
+// CHECK:STDOUT:     .TestAdd = %import_ref.3
 // CHECK:STDOUT:     import Core//core
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.2: %TestAdd.type = import_ref Core//core, inst+30, loaded [template = constants.%TestAdd]
+// CHECK:STDOUT:   %import_ref.2: %AsIntLiteral.type = import_ref Core//core, inst+55, loaded [template = constants.%AsIntLiteral]
+// CHECK:STDOUT:   %import_ref.3: %TestAdd.type = import_ref Core//core, inst+30, loaded [template = constants.%TestAdd]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -104,40 +147,49 @@ var arr: [i32; Core.TestAdd(1, 2)] = (1, 2, 3);
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %int.make_type_32: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %Core.ref: <namespace> = name_ref Core, imports.%Core [template = imports.%Core]
-// CHECK:STDOUT:   %TestAdd.ref: %TestAdd.type = name_ref TestAdd, imports.%import_ref.2 [template = constants.%TestAdd]
-// CHECK:STDOUT:   %.loc4_29: i32 = int_value 1 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc4_32: i32 = int_value 2 [template = constants.%.2]
-// CHECK:STDOUT:   %int.sadd: init i32 = call %TestAdd.ref(%.loc4_29, %.loc4_32) [template = constants.%.3]
+// CHECK:STDOUT:   %Core.ref.loc4_16: <namespace> = name_ref Core, imports.%Core [template = imports.%Core]
+// CHECK:STDOUT:   %AsIntLiteral.ref: %AsIntLiteral.type = name_ref AsIntLiteral, imports.%import_ref.2 [template = constants.%AsIntLiteral]
+// CHECK:STDOUT:   %Core.ref.loc4_34: <namespace> = name_ref Core, imports.%Core [template = imports.%Core]
+// CHECK:STDOUT:   %TestAdd.ref: %TestAdd.type = name_ref TestAdd, imports.%import_ref.3 [template = constants.%TestAdd]
+// CHECK:STDOUT:   %.loc4_47: i32 = int_value 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc4_50: i32 = int_value 2 [template = constants.%.2]
+// CHECK:STDOUT:   %int.sadd: init i32 = call %TestAdd.ref(%.loc4_47, %.loc4_50) [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_46.1: i32 = value_of_initializer %int.sadd [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_46.2: i32 = converted %int.sadd, %.loc4_46.1 [template = constants.%.3]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %AsIntLiteral.ref(%.loc4_46.2) [template = constants.%.4]
 // CHECK:STDOUT:   %.loc4_11.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:   %.loc4_11.2: type = converted %int.make_type_32, %.loc4_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc4_34: type = array_type %int.sadd, i32 [template = constants.%.4]
-// CHECK:STDOUT:   %arr.var: ref %.4 = var arr
-// CHECK:STDOUT:   %arr: ref %.4 = bind_name arr, %arr.var
+// CHECK:STDOUT:   %.loc4_33.1: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.4]
+// CHECK:STDOUT:   %.loc4_33.2: Core.IntLiteral = converted %int.convert_checked, %.loc4_33.1 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc4_53: type = array_type %.loc4_33.2, i32 [template = constants.%.5]
+// CHECK:STDOUT:   %arr.var: ref %.5 = var arr
+// CHECK:STDOUT:   %arr: ref %.5 = bind_name arr, %arr.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32";
 // CHECK:STDOUT:
+// CHECK:STDOUT: fn @AsIntLiteral(%a.param_patt: i32) -> Core.IntLiteral = "int.convert_checked";
+// CHECK:STDOUT:
 // CHECK:STDOUT: fn @TestAdd(%a.param_patt: i32, %b.param_patt: i32) -> i32 = "int.sadd";
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc4_39: i32 = int_value 1 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc4_42: i32 = int_value 2 [template = constants.%.2]
-// CHECK:STDOUT:   %.loc4_45: i32 = int_value 3 [template = constants.%.3]
-// CHECK:STDOUT:   %.loc4_46.1: %tuple.type = tuple_literal (%.loc4_39, %.loc4_42, %.loc4_45)
-// CHECK:STDOUT:   %.loc4_46.2: i32 = int_value 0 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc4_46.3: ref i32 = array_index file.%arr.var, %.loc4_46.2
-// CHECK:STDOUT:   %.loc4_46.4: init i32 = initialize_from %.loc4_39 to %.loc4_46.3 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc4_46.5: i32 = int_value 1 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc4_46.6: ref i32 = array_index file.%arr.var, %.loc4_46.5
-// CHECK:STDOUT:   %.loc4_46.7: init i32 = initialize_from %.loc4_42 to %.loc4_46.6 [template = constants.%.2]
-// CHECK:STDOUT:   %.loc4_46.8: i32 = int_value 2 [template = constants.%.2]
-// CHECK:STDOUT:   %.loc4_46.9: ref i32 = array_index file.%arr.var, %.loc4_46.8
-// CHECK:STDOUT:   %.loc4_46.10: init i32 = initialize_from %.loc4_45 to %.loc4_46.9 [template = constants.%.3]
-// CHECK:STDOUT:   %.loc4_46.11: init %.4 = array_init (%.loc4_46.4, %.loc4_46.7, %.loc4_46.10) to file.%arr.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc4_47: init %.4 = converted %.loc4_46.1, %.loc4_46.11 [template = constants.%array]
-// CHECK:STDOUT:   assign file.%arr.var, %.loc4_47
+// CHECK:STDOUT:   %.loc4_58: i32 = int_value 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc4_61: i32 = int_value 2 [template = constants.%.2]
+// CHECK:STDOUT:   %.loc4_64: i32 = int_value 3 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_65.1: %tuple.type = tuple_literal (%.loc4_58, %.loc4_61, %.loc4_64)
+// CHECK:STDOUT:   %.loc4_65.2: i32 = int_value 0 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc4_65.3: ref i32 = array_index file.%arr.var, %.loc4_65.2
+// CHECK:STDOUT:   %.loc4_65.4: init i32 = initialize_from %.loc4_58 to %.loc4_65.3 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc4_65.5: i32 = int_value 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc4_65.6: ref i32 = array_index file.%arr.var, %.loc4_65.5
+// CHECK:STDOUT:   %.loc4_65.7: init i32 = initialize_from %.loc4_61 to %.loc4_65.6 [template = constants.%.2]
+// CHECK:STDOUT:   %.loc4_65.8: i32 = int_value 2 [template = constants.%.2]
+// CHECK:STDOUT:   %.loc4_65.9: ref i32 = array_index file.%arr.var, %.loc4_65.8
+// CHECK:STDOUT:   %.loc4_65.10: init i32 = initialize_from %.loc4_64 to %.loc4_65.9 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_65.11: init %.5 = array_init (%.loc4_65.4, %.loc4_65.7, %.loc4_65.10) to file.%arr.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc4_66: init %.5 = converted %.loc4_65.1, %.loc4_65.11 [template = constants.%array]
+// CHECK:STDOUT:   assign file.%arr.var, %.loc4_66
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 2 - 0
toolchain/check/testdata/function/declaration/fail_param_in_type.carbon

@@ -47,6 +47,8 @@ fn F(n: i32, a: [i32; n]*);
 // CHECK:STDOUT:     %.loc14_9.2: type = converted %int.make_type_32.loc14_9, %.loc14_9.1 [template = i32]
 // CHECK:STDOUT:     %int.make_type_32.loc14_18: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:     %n.ref: i32 = name_ref n, %n
+// CHECK:STDOUT:     %.loc14_18.1: type = value_of_initializer %int.make_type_32.loc14_18 [template = i32]
+// CHECK:STDOUT:     %.loc14_18.2: type = converted %int.make_type_32.loc14_18, %.loc14_18.1 [template = i32]
 // CHECK:STDOUT:     %.loc14_25: type = ptr_type <error> [template = <error>]
 // CHECK:STDOUT:     %n.param: i32 = value_param runtime_param0
 // CHECK:STDOUT:     %n: i32 = bind_name n, %n.param

+ 29 - 13
toolchain/check/testdata/function/generic/fail_todo_param_in_type.carbon

@@ -18,15 +18,22 @@ fn F(N:! i32, a: [i32; N]*);
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
-// CHECK:STDOUT:   %N: i32 = bind_symbolic_name N, 0 [symbolic]
-// CHECK:STDOUT:   %N.patt: i32 = symbolic_binding_pattern N, 0 [symbolic]
+// CHECK:STDOUT:   %N.1: i32 = bind_symbolic_name N, 0 [symbolic]
+// CHECK:STDOUT:   %N.patt.1: i32 = symbolic_binding_pattern N, 0 [symbolic]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.24: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.25: <bound method> = bound_method %N.1, %Convert.15 [symbolic]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.25(%N.1) [symbolic]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [template]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -39,8 +46,8 @@ fn F(N:! i32, a: [i32; N]*);
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [template = constants.%F] {
-// CHECK:STDOUT:     %N.patt.loc14_6.1: i32 = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc14_6.2 (constants.%N.patt)]
-// CHECK:STDOUT:     %N.param_patt: i32 = value_param_pattern %N.patt.loc14_6.1, runtime_param<invalid> [symbolic = %N.patt.loc14_6.2 (constants.%N.patt)]
+// CHECK:STDOUT:     %N.patt.loc14_6.1: i32 = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc14_6.2 (constants.%N.patt.1)]
+// CHECK:STDOUT:     %N.param_patt: i32 = value_param_pattern %N.patt.loc14_6.1, runtime_param<invalid> [symbolic = %N.patt.loc14_6.2 (constants.%N.patt.1)]
 // CHECK:STDOUT:     %a.patt: <error> = binding_pattern a
 // CHECK:STDOUT:     %a.param_patt: <error> = value_param_pattern %a.patt, runtime_param0
 // CHECK:STDOUT:   } {
@@ -48,27 +55,36 @@ fn F(N:! i32, a: [i32; N]*);
 // CHECK:STDOUT:     %.loc14_10.1: type = value_of_initializer %int.make_type_32.loc14_10 [template = i32]
 // CHECK:STDOUT:     %.loc14_10.2: type = converted %int.make_type_32.loc14_10, %.loc14_10.1 [template = i32]
 // CHECK:STDOUT:     %int.make_type_32.loc14_19: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:     %N.ref: i32 = name_ref N, %N.loc14_6.1 [symbolic = %N.loc14_6.2 (constants.%N)]
+// CHECK:STDOUT:     %N.ref: i32 = name_ref N, %N.loc14_6.1 [symbolic = %N.loc14_6.2 (constants.%N.1)]
 // CHECK:STDOUT:     %.loc14_19.1: type = value_of_initializer %int.make_type_32.loc14_19 [template = i32]
 // CHECK:STDOUT:     %.loc14_19.2: type = converted %int.make_type_32.loc14_19, %.loc14_19.1 [template = i32]
-// CHECK:STDOUT:     %.loc14_25: type = array_type %N.ref, i32 [template = <error>]
+// CHECK:STDOUT:     %.loc14_24.1: %Convert.type.2 = interface_witness_access constants.%.24, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:     %.loc14_24.2: <bound method> = bound_method %N.ref, %.loc14_24.1 [symbolic = %.loc14_24.5 (constants.%.25)]
+// CHECK:STDOUT:     %int.convert_checked.loc14_24.1: init Core.IntLiteral = call %.loc14_24.2(%N.ref) [symbolic = %int.convert_checked.loc14_24.2 (constants.%int.convert_checked)]
+// CHECK:STDOUT:     %.loc14_24.3: Core.IntLiteral = value_of_initializer %int.convert_checked.loc14_24.1 [symbolic = %int.convert_checked.loc14_24.2 (constants.%int.convert_checked)]
+// CHECK:STDOUT:     %.loc14_24.4: Core.IntLiteral = converted %N.ref, %.loc14_24.3 [symbolic = %int.convert_checked.loc14_24.2 (constants.%int.convert_checked)]
+// CHECK:STDOUT:     %.loc14_25: type = array_type %.loc14_24.4, i32 [template = <error>]
 // CHECK:STDOUT:     %.loc14_26: type = ptr_type <error> [template = <error>]
 // CHECK:STDOUT:     %N.param: i32 = value_param runtime_param<invalid>
-// CHECK:STDOUT:     %N.loc14_6.1: i32 = bind_symbolic_name N, 0, %N.param [symbolic = %N.loc14_6.2 (constants.%N)]
+// CHECK:STDOUT:     %N.loc14_6.1: i32 = bind_symbolic_name N, 0, %N.param [symbolic = %N.loc14_6.2 (constants.%N.1)]
 // CHECK:STDOUT:     %a.param: <error> = value_param runtime_param0
 // CHECK:STDOUT:     %a: <error> = bind_name a, %a.param
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: generic fn @F(%N.loc14_6.1: i32) {
-// CHECK:STDOUT:   %N.loc14_6.2: i32 = bind_symbolic_name N, 0 [symbolic = %N.loc14_6.2 (constants.%N)]
-// CHECK:STDOUT:   %N.patt.loc14_6.2: i32 = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc14_6.2 (constants.%N.patt)]
+// CHECK:STDOUT:   %N.loc14_6.2: i32 = bind_symbolic_name N, 0 [symbolic = %N.loc14_6.2 (constants.%N.1)]
+// CHECK:STDOUT:   %N.patt.loc14_6.2: i32 = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc14_6.2 (constants.%N.patt.1)]
+// CHECK:STDOUT:   %.loc14_24.5: <bound method> = bound_method %N.loc14_6.2, constants.%Convert.15 [symbolic = %.loc14_24.5 (constants.%.25)]
+// CHECK:STDOUT:   %int.convert_checked.loc14_24.2: init Core.IntLiteral = call %.loc14_24.5(%N.loc14_6.2) [symbolic = %int.convert_checked.loc14_24.2 (constants.%int.convert_checked)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%N.param_patt: i32, %a.param_patt: <error>);
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @F(constants.%N) {
-// CHECK:STDOUT:   %N.loc14_6.2 => constants.%N
-// CHECK:STDOUT:   %N.patt.loc14_6.2 => constants.%N
+// CHECK:STDOUT: specific @F(constants.%N.1) {
+// CHECK:STDOUT:   %N.loc14_6.2 => constants.%N.1
+// CHECK:STDOUT:   %N.patt.loc14_6.2 => constants.%N.1
+// CHECK:STDOUT:   %.loc14_24.5 => constants.%.25
+// CHECK:STDOUT:   %int.convert_checked.loc14_24.2 => constants.%int.convert_checked
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 30 - 18
toolchain/check/testdata/function/generic/return_slot.carbon

@@ -38,29 +38,36 @@ fn G() {
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %.4: i32 = int_value 100 [template]
-// CHECK:STDOUT:   %.5: type = array_type %.4, i32 [template]
-// CHECK:STDOUT:   %.7: type = unbound_element_type %C, %.5 [template]
-// CHECK:STDOUT:   %.8: type = struct_type {.arr: %.5} [template]
-// CHECK:STDOUT:   %.9: <witness> = complete_type_witness %.8 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.28: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.29: <bound method> = bound_method %.4, %Convert.15 [template]
+// CHECK:STDOUT:   %.30: Core.IntLiteral = int_value 100 [template]
+// CHECK:STDOUT:   %.31: type = array_type %.30, i32 [template]
+// CHECK:STDOUT:   %.33: type = unbound_element_type %C, %.31 [template]
+// CHECK:STDOUT:   %.34: type = struct_type {.arr: %.31} [template]
+// CHECK:STDOUT:   %.35: <witness> = complete_type_witness %.34 [template]
 // CHECK:STDOUT:   %G.type: type = fn_type @G [template]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [template]
 // CHECK:STDOUT:   %Wrap.3: type = class_type @Wrap, @Wrap(i32) [template]
 // CHECK:STDOUT:   %Make.type.2: type = fn_type @Make, @Wrap(i32) [template]
 // CHECK:STDOUT:   %Make.2: %Make.type.2 = struct_value () [template]
-// CHECK:STDOUT:   %.11: <specific function> = specific_function %Make.2, @Make(i32) [template]
+// CHECK:STDOUT:   %.37: <specific function> = specific_function %Make.2, @Make(i32) [template]
 // CHECK:STDOUT:   %Wrap.4: type = class_type @Wrap, @Wrap(%empty_tuple.type) [template]
 // CHECK:STDOUT:   %Make.type.3: type = fn_type @Make, @Wrap(%empty_tuple.type) [template]
 // CHECK:STDOUT:   %Make.3: %Make.type.3 = struct_value () [template]
-// CHECK:STDOUT:   %.12: <specific function> = specific_function %Make.3, @Make(%empty_tuple.type) [template]
+// CHECK:STDOUT:   %.38: <specific function> = specific_function %Make.3, @Make(%empty_tuple.type) [template]
 // CHECK:STDOUT:   %Wrap.5: type = class_type @Wrap, @Wrap(%C) [template]
 // CHECK:STDOUT:   %Make.type.4: type = fn_type @Make, @Wrap(%C) [template]
 // CHECK:STDOUT:   %Make.4: %Make.type.4 = struct_value () [template]
-// CHECK:STDOUT:   %.15: <specific function> = specific_function %Make.4, @Make(%C) [template]
+// CHECK:STDOUT:   %.41: <specific function> = specific_function %Make.4, @Make(%C) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -112,12 +119,17 @@ fn G() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
 // CHECK:STDOUT:   %int.make_type_32: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc15_26: i32 = int_value 100 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc15_26.1: i32 = int_value 100 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc15_21.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:   %.loc15_21.2: type = converted %int.make_type_32, %.loc15_21.1 [template = i32]
-// CHECK:STDOUT:   %.loc15_29: type = array_type %.loc15_26, i32 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc15_18: %.7 = field_decl arr, element0 [template]
-// CHECK:STDOUT:   %.loc15_32: <witness> = complete_type_witness %.8 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc15_26.2: %Convert.type.2 = interface_witness_access constants.%.28, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc15_26.3: <bound method> = bound_method %.loc15_26.1, %.loc15_26.2 [template = constants.%.29]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc15_26.3(%.loc15_26.1) [template = constants.%.30]
+// CHECK:STDOUT:   %.loc15_26.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.30]
+// CHECK:STDOUT:   %.loc15_26.5: Core.IntLiteral = converted %.loc15_26.1, %.loc15_26.4 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc15_29: type = array_type %.loc15_26.5, i32 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc15_18: %.33 = field_decl arr, element0 [template]
+// CHECK:STDOUT:   %.loc15_32: <witness> = complete_type_witness %.34 [template = constants.%.35]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .Self = constants.%C
@@ -158,7 +170,7 @@ fn G() {
 // CHECK:STDOUT:   %Wrap.loc18: type = class_type @Wrap, @Wrap(i32) [template = constants.%Wrap.3]
 // CHECK:STDOUT:   %.loc18_25.1: %Make.type.2 = specific_constant @Wrap.%Make.decl, @Wrap(i32) [template = constants.%Make.2]
 // CHECK:STDOUT:   %Make.ref.loc18: %Make.type.2 = name_ref Make, %.loc18_25.1 [template = constants.%Make.2]
-// CHECK:STDOUT:   %.loc18_25.2: <specific function> = specific_function %Make.ref.loc18, @Make(i32) [template = constants.%.11]
+// CHECK:STDOUT:   %.loc18_25.2: <specific function> = specific_function %Make.ref.loc18, @Make(i32) [template = constants.%.37]
 // CHECK:STDOUT:   %Make.call.loc18: init i32 = call %.loc18_25.2()
 // CHECK:STDOUT:   assign %a.var, %Make.call.loc18
 // CHECK:STDOUT:   %.loc19_11.1: %empty_tuple.type = tuple_literal ()
@@ -171,7 +183,7 @@ fn G() {
 // CHECK:STDOUT:   %Wrap.loc19: type = class_type @Wrap, @Wrap(constants.%empty_tuple.type) [template = constants.%Wrap.4]
 // CHECK:STDOUT:   %.loc19_23.1: %Make.type.3 = specific_constant @Wrap.%Make.decl, @Wrap(constants.%empty_tuple.type) [template = constants.%Make.3]
 // CHECK:STDOUT:   %Make.ref.loc19: %Make.type.3 = name_ref Make, %.loc19_23.1 [template = constants.%Make.3]
-// CHECK:STDOUT:   %.loc19_23.2: <specific function> = specific_function %Make.ref.loc19, @Make(constants.%empty_tuple.type) [template = constants.%.12]
+// CHECK:STDOUT:   %.loc19_23.2: <specific function> = specific_function %Make.ref.loc19, @Make(constants.%empty_tuple.type) [template = constants.%.38]
 // CHECK:STDOUT:   %Make.call.loc19: init %empty_tuple.type = call %.loc19_23.2()
 // CHECK:STDOUT:   assign %b.var, %Make.call.loc19
 // CHECK:STDOUT:   %C.ref.loc20_10: type = name_ref C, file.%C.decl [template = constants.%C]
@@ -182,7 +194,7 @@ fn G() {
 // CHECK:STDOUT:   %Wrap.loc20: type = class_type @Wrap, @Wrap(constants.%C) [template = constants.%Wrap.5]
 // CHECK:STDOUT:   %.loc20_21.1: %Make.type.4 = specific_constant @Wrap.%Make.decl, @Wrap(constants.%C) [template = constants.%Make.4]
 // CHECK:STDOUT:   %Make.ref.loc20: %Make.type.4 = name_ref Make, %.loc20_21.1 [template = constants.%Make.4]
-// CHECK:STDOUT:   %.loc20_21.2: <specific function> = specific_function %Make.ref.loc20, @Make(constants.%C) [template = constants.%.15]
+// CHECK:STDOUT:   %.loc20_21.2: <specific function> = specific_function %Make.ref.loc20, @Make(constants.%C) [template = constants.%.41]
 // CHECK:STDOUT:   %.loc20_7: ref %C = splice_block %c.var {}
 // CHECK:STDOUT:   %Make.call.loc20: init %C = call %.loc20_21.2() to %.loc20_7
 // CHECK:STDOUT:   assign %c.var, %Make.call.loc20
@@ -236,7 +248,7 @@ fn G() {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %Make.type => constants.%Make.type.2
 // CHECK:STDOUT:   %Make => constants.%Make.2
-// CHECK:STDOUT:   %.loc12_27.3 => constants.%.11
+// CHECK:STDOUT:   %.loc12_27.3 => constants.%.37
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @Wrap(constants.%empty_tuple.type) {
@@ -254,7 +266,7 @@ fn G() {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %Make.type => constants.%Make.type.3
 // CHECK:STDOUT:   %Make => constants.%Make.3
-// CHECK:STDOUT:   %.loc12_27.3 => constants.%.12
+// CHECK:STDOUT:   %.loc12_27.3 => constants.%.38
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @Wrap(constants.%C) {
@@ -272,6 +284,6 @@ fn G() {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %Make.type => constants.%Make.type.4
 // CHECK:STDOUT:   %Make => constants.%Make.4
-// CHECK:STDOUT:   %.loc12_27.3 => constants.%.15
+// CHECK:STDOUT:   %.loc12_27.3 => constants.%.41
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 26 - 14
toolchain/check/testdata/if_expr/basic.carbon

@@ -23,16 +23,23 @@ fn F(b: bool, n: i32, m: i32) -> i32 {
 // CHECK:STDOUT:   %F.type: type = fn_type @F [template]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 1 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, i32 [template]
+// CHECK:STDOUT:   %.30: i32 = int_value 0 [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (i32) [template]
-// CHECK:STDOUT:   %array: %.2 = tuple_value (%.4) [template]
+// CHECK:STDOUT:   %array: %.28 = tuple_value (%.30) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
 // CHECK:STDOUT:     .Bool = %import_ref.1
 // CHECK:STDOUT:     .Int32 = %import_ref.2
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.3
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -80,32 +87,37 @@ fn F(b: bool, n: i32, m: i32) -> i32 {
 // CHECK:STDOUT: fn @F(%b.param_patt: bool, %n.param_patt: i32, %m.param_patt: i32) -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %int.make_type_32.loc12: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc12_16: i32 = int_value 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc12_16.1: i32 = int_value 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc12_11.1: type = value_of_initializer %int.make_type_32.loc12 [template = i32]
 // CHECK:STDOUT:   %.loc12_11.2: type = converted %int.make_type_32.loc12, %.loc12_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc12_17: type = array_type %.loc12_16, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %x.var: ref %.2 = var x
-// CHECK:STDOUT:   %x: ref %.2 = bind_name x, %x.var
-// CHECK:STDOUT:   %.loc12_22: i32 = int_value 0 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc12_16.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc12_16.3: <bound method> = bound_method %.loc12_16.1, %.loc12_16.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc12_16.3(%.loc12_16.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc12_16.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:   %.loc12_16.5: Core.IntLiteral = converted %.loc12_16.1, %.loc12_16.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc12_17: type = array_type %.loc12_16.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %x.var: ref %.28 = var x
+// CHECK:STDOUT:   %x: ref %.28 = bind_name x, %x.var
+// CHECK:STDOUT:   %.loc12_22: i32 = int_value 0 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc12_24.1: %tuple.type = tuple_literal (%.loc12_22)
-// CHECK:STDOUT:   %.loc12_24.2: i32 = int_value 0 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc12_24.2: i32 = int_value 0 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc12_24.3: ref i32 = array_index %x.var, %.loc12_24.2
-// CHECK:STDOUT:   %.loc12_24.4: init i32 = initialize_from %.loc12_22 to %.loc12_24.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc12_24.5: init %.2 = array_init (%.loc12_24.4) to %x.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc12_25: init %.2 = converted %.loc12_24.1, %.loc12_24.5 [template = constants.%array]
+// CHECK:STDOUT:   %.loc12_24.4: init i32 = initialize_from %.loc12_22 to %.loc12_24.3 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc12_24.5: init %.28 = array_init (%.loc12_24.4) to %x.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc12_25: init %.28 = converted %.loc12_24.1, %.loc12_24.5 [template = constants.%array]
 // CHECK:STDOUT:   assign %x.var, %.loc12_25
 // CHECK:STDOUT:   %b.ref: bool = name_ref b, %b
 // CHECK:STDOUT:   if %b.ref br !if.expr.then else br !if.expr.else
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.expr.then:
-// CHECK:STDOUT:   %x.ref.loc13_20: ref %.2 = name_ref x, %x
+// CHECK:STDOUT:   %x.ref.loc13_20: ref %.28 = name_ref x, %x
 // CHECK:STDOUT:   %m.ref: i32 = name_ref m, %m
 // CHECK:STDOUT:   %.loc13_23.1: ref i32 = array_index %x.ref.loc13_20, %m.ref
 // CHECK:STDOUT:   %.loc13_23.2: i32 = bind_value %.loc13_23.1
 // CHECK:STDOUT:   br !if.expr.result(%.loc13_23.2)
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.expr.else:
-// CHECK:STDOUT:   %x.ref.loc13_30: ref %.2 = name_ref x, %x
+// CHECK:STDOUT:   %x.ref.loc13_30: ref %.28 = name_ref x, %x
 // CHECK:STDOUT:   %n.ref: i32 = name_ref n, %n
 // CHECK:STDOUT:   %.loc13_33.1: ref i32 = array_index %x.ref.loc13_30, %n.ref
 // CHECK:STDOUT:   %.loc13_33.2: i32 = bind_value %.loc13_33.1

+ 73 - 51
toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon

@@ -277,33 +277,40 @@ class SelfNestedBadReturnType {
 // CHECK:STDOUT:   %tuple.type.1: type = tuple_type (type, type) [template]
 // CHECK:STDOUT:   %tuple.type.2: type = tuple_type (%.7, %.8) [symbolic]
 // CHECK:STDOUT:   %.9: i32 = int_value 4 [template]
-// CHECK:STDOUT:   %.10: type = array_type %.9, %Self.3 [symbolic]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.33: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.34: <bound method> = bound_method %.9, %Convert.15 [template]
+// CHECK:STDOUT:   %.35: Core.IntLiteral = int_value 4 [template]
+// CHECK:STDOUT:   %.36: type = array_type %.35, %Self.3 [symbolic]
 // CHECK:STDOUT:   %F.type.13: type = fn_type @F.13 [template]
 // CHECK:STDOUT:   %F.14: %F.type.13 = struct_value () [template]
-// CHECK:STDOUT:   %.11: type = assoc_entity_type %SelfNested.type, %F.type.13 [template]
-// CHECK:STDOUT:   %.12: %.11 = assoc_entity element0, @SelfNested.%F.decl [template]
+// CHECK:STDOUT:   %.37: type = assoc_entity_type %SelfNested.type, %F.type.13 [template]
+// CHECK:STDOUT:   %.38: %.37 = assoc_entity element0, @SelfNested.%F.decl [template]
 // CHECK:STDOUT:   %SelfNestedBadParam: type = class_type @SelfNestedBadParam [template]
-// CHECK:STDOUT:   %.13: type = ptr_type %SelfNestedBadParam [template]
-// CHECK:STDOUT:   %.14: type = struct_type {.x: i32, .y: i32} [template]
-// CHECK:STDOUT:   %tuple.type.3: type = tuple_type (%.13, %.14) [template]
-// CHECK:STDOUT:   %.15: type = array_type %.9, %SelfNestedBadParam [template]
+// CHECK:STDOUT:   %.39: type = ptr_type %SelfNestedBadParam [template]
+// CHECK:STDOUT:   %.40: type = struct_type {.x: i32, .y: i32} [template]
+// CHECK:STDOUT:   %tuple.type.3: type = tuple_type (%.39, %.40) [template]
+// CHECK:STDOUT:   %.41: type = array_type %.35, %SelfNestedBadParam [template]
 // CHECK:STDOUT:   %F.type.14: type = fn_type @F.14 [template]
 // CHECK:STDOUT:   %F.15: %F.type.14 = struct_value () [template]
-// CHECK:STDOUT:   %.16: type = struct_type {.x: %SelfNestedBadParam, .y: i32} [template]
-// CHECK:STDOUT:   %tuple.type.4: type = tuple_type (%.13, %.16) [template]
+// CHECK:STDOUT:   %.42: type = struct_type {.x: %SelfNestedBadParam, .y: i32} [template]
+// CHECK:STDOUT:   %tuple.type.4: type = tuple_type (%.39, %.42) [template]
 // CHECK:STDOUT:   %SelfNestedBadReturnType: type = class_type @SelfNestedBadReturnType [template]
-// CHECK:STDOUT:   %.17: type = ptr_type %SelfNestedBadReturnType [template]
-// CHECK:STDOUT:   %.18: type = struct_type {.x: %SelfNestedBadReturnType, .y: i32} [template]
-// CHECK:STDOUT:   %tuple.type.5: type = tuple_type (%.17, %.18) [template]
+// CHECK:STDOUT:   %.43: type = ptr_type %SelfNestedBadReturnType [template]
+// CHECK:STDOUT:   %.44: type = struct_type {.x: %SelfNestedBadReturnType, .y: i32} [template]
+// CHECK:STDOUT:   %tuple.type.5: type = tuple_type (%.43, %.44) [template]
 // CHECK:STDOUT:   %F.type.15: type = fn_type @F.15 [template]
 // CHECK:STDOUT:   %F.16: %F.type.15 = struct_value () [template]
-// CHECK:STDOUT:   %.19: type = array_type %.9, %SelfNestedBadReturnType [template]
+// CHECK:STDOUT:   %.45: type = array_type %.35, %SelfNestedBadReturnType [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
 // CHECK:STDOUT:     .Bool = %import_ref.1
 // CHECK:STDOUT:     .Int32 = %import_ref.2
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.3
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -404,8 +411,8 @@ class SelfNestedBadReturnType {
 // CHECK:STDOUT:   %F.decl: %F.type.13 = fn_decl @F.13 [template = constants.%F.14] {
 // CHECK:STDOUT:     %x.patt: @F.13.%tuple.type (%tuple.type.2) = binding_pattern x
 // CHECK:STDOUT:     %x.param_patt: @F.13.%tuple.type (%tuple.type.2) = value_param_pattern %x.patt, runtime_param0
-// CHECK:STDOUT:     %return.patt: @F.13.%.loc188_52.1 (%.10) = return_slot_pattern
-// CHECK:STDOUT:     %return.param_patt: @F.13.%.loc188_52.1 (%.10) = out_param_pattern %return.patt, runtime_param1
+// CHECK:STDOUT:     %return.patt: @F.13.%.loc188_52.1 (%.36) = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: @F.13.%.loc188_52.1 (%.36) = out_param_pattern %return.patt, runtime_param1
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %Self.ref.loc188_12: %SelfNested.type = name_ref Self, @SelfNested.%Self [symbolic = %Self (constants.%Self.3)]
 // CHECK:STDOUT:     %.loc188_16.2: type = facet_type_access %Self.ref.loc188_12 [symbolic = %Self (constants.%Self.3)]
@@ -421,16 +428,21 @@ class SelfNestedBadReturnType {
 // CHECK:STDOUT:     %.loc188_38.1: %tuple.type.1 = tuple_literal (%.loc188_16.4, %.loc188_37.2)
 // CHECK:STDOUT:     %.loc188_38.2: type = converted %.loc188_38.1, constants.%tuple.type.2 [symbolic = %tuple.type (constants.%tuple.type.2)]
 // CHECK:STDOUT:     %Self.ref.loc188_45: %SelfNested.type = name_ref Self, @SelfNested.%Self [symbolic = %Self (constants.%Self.3)]
-// CHECK:STDOUT:     %.loc188_51: i32 = int_value 4 [template = constants.%.9]
+// CHECK:STDOUT:     %.loc188_51.1: i32 = int_value 4 [template = constants.%.9]
 // CHECK:STDOUT:     %.loc188_45.1: type = facet_type_access %Self.ref.loc188_45 [symbolic = %Self (constants.%Self.3)]
 // CHECK:STDOUT:     %.loc188_45.2: type = converted %Self.ref.loc188_45, %.loc188_45.1 [symbolic = %Self (constants.%Self.3)]
-// CHECK:STDOUT:     %.loc188_52.2: type = array_type %.loc188_51, %Self.3 [symbolic = %.loc188_52.1 (constants.%.10)]
+// CHECK:STDOUT:     %.loc188_51.2: %Convert.type.2 = interface_witness_access constants.%.33, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:     %.loc188_51.3: <bound method> = bound_method %.loc188_51.1, %.loc188_51.2 [template = constants.%.34]
+// CHECK:STDOUT:     %int.convert_checked: init Core.IntLiteral = call %.loc188_51.3(%.loc188_51.1) [template = constants.%.35]
+// CHECK:STDOUT:     %.loc188_51.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.35]
+// CHECK:STDOUT:     %.loc188_51.5: Core.IntLiteral = converted %.loc188_51.1, %.loc188_51.4 [template = constants.%.35]
+// CHECK:STDOUT:     %.loc188_52.2: type = array_type %.loc188_51.5, %Self.3 [symbolic = %.loc188_52.1 (constants.%.36)]
 // CHECK:STDOUT:     %x.param: @F.13.%tuple.type (%tuple.type.2) = value_param runtime_param0
 // CHECK:STDOUT:     %x: @F.13.%tuple.type (%tuple.type.2) = bind_name x, %x.param
-// CHECK:STDOUT:     %return.param: ref @F.13.%.loc188_52.1 (%.10) = out_param runtime_param1
-// CHECK:STDOUT:     %return: ref @F.13.%.loc188_52.1 (%.10) = return_slot %return.param
+// CHECK:STDOUT:     %return.param: ref @F.13.%.loc188_52.1 (%.36) = out_param runtime_param1
+// CHECK:STDOUT:     %return: ref @F.13.%.loc188_52.1 (%.36) = return_slot %return.param
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.loc188: %.11 = assoc_entity element0, %F.decl [template = constants.%.12]
+// CHECK:STDOUT:   %.loc188: %.37 = assoc_entity element0, %F.decl [template = constants.%.38]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .Self = %Self
@@ -713,31 +725,36 @@ class SelfNestedBadReturnType {
 // CHECK:STDOUT:   witness = %.loc175
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: impl @impl.14: %Self.ref as %SelfNested.ref {
+// CHECK:STDOUT: impl @impl.26: %Self.ref as %SelfNested.ref {
 // CHECK:STDOUT:   %F.decl: %F.type.14 = fn_decl @F.14 [template = constants.%F.15] {
 // CHECK:STDOUT:     %x.patt: %tuple.type.3 = binding_pattern x
 // CHECK:STDOUT:     %x.param_patt: %tuple.type.3 = value_param_pattern %x.patt, runtime_param0
-// CHECK:STDOUT:     %return.patt: %.15 = return_slot_pattern
-// CHECK:STDOUT:     %return.param_patt: %.15 = out_param_pattern %return.patt, runtime_param1
+// CHECK:STDOUT:     %return.patt: %.41 = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: %.41 = out_param_pattern %return.patt, runtime_param1
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %SelfNestedBadParam.ref.loc200_14: type = name_ref SelfNestedBadParam, file.%SelfNestedBadParam.decl [template = constants.%SelfNestedBadParam]
-// CHECK:STDOUT:     %.loc200_32: type = ptr_type %SelfNestedBadParam [template = constants.%.13]
+// CHECK:STDOUT:     %.loc200_32: type = ptr_type %SelfNestedBadParam [template = constants.%.39]
 // CHECK:STDOUT:     %int.make_type_32.loc200_40: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:     %.loc200_40.1: type = value_of_initializer %int.make_type_32.loc200_40 [template = i32]
 // CHECK:STDOUT:     %.loc200_40.2: type = converted %int.make_type_32.loc200_40, %.loc200_40.1 [template = i32]
 // CHECK:STDOUT:     %int.make_type_32.loc200_49: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:     %.loc200_49.1: type = value_of_initializer %int.make_type_32.loc200_49 [template = i32]
 // CHECK:STDOUT:     %.loc200_49.2: type = converted %int.make_type_32.loc200_49, %.loc200_49.1 [template = i32]
-// CHECK:STDOUT:     %.loc200_52: type = struct_type {.x: i32, .y: i32} [template = constants.%.14]
+// CHECK:STDOUT:     %.loc200_52: type = struct_type {.x: i32, .y: i32} [template = constants.%.40]
 // CHECK:STDOUT:     %.loc200_53.1: %tuple.type.1 = tuple_literal (%.loc200_32, %.loc200_52)
 // CHECK:STDOUT:     %.loc200_53.2: type = converted %.loc200_53.1, constants.%tuple.type.3 [template = constants.%tuple.type.3]
 // CHECK:STDOUT:     %SelfNestedBadParam.ref.loc200_60: type = name_ref SelfNestedBadParam, file.%SelfNestedBadParam.decl [template = constants.%SelfNestedBadParam]
-// CHECK:STDOUT:     %.loc200_80: i32 = int_value 4 [template = constants.%.9]
-// CHECK:STDOUT:     %.loc200_81: type = array_type %.loc200_80, %SelfNestedBadParam [template = constants.%.15]
+// CHECK:STDOUT:     %.loc200_80.1: i32 = int_value 4 [template = constants.%.9]
+// CHECK:STDOUT:     %.loc200_80.2: %Convert.type.2 = interface_witness_access constants.%.33, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:     %.loc200_80.3: <bound method> = bound_method %.loc200_80.1, %.loc200_80.2 [template = constants.%.34]
+// CHECK:STDOUT:     %int.convert_checked: init Core.IntLiteral = call %.loc200_80.3(%.loc200_80.1) [template = constants.%.35]
+// CHECK:STDOUT:     %.loc200_80.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.35]
+// CHECK:STDOUT:     %.loc200_80.5: Core.IntLiteral = converted %.loc200_80.1, %.loc200_80.4 [template = constants.%.35]
+// CHECK:STDOUT:     %.loc200_81: type = array_type %.loc200_80.5, %SelfNestedBadParam [template = constants.%.41]
 // CHECK:STDOUT:     %x.param: %tuple.type.3 = value_param runtime_param0
 // CHECK:STDOUT:     %x: %tuple.type.3 = bind_name x, %x.param
-// CHECK:STDOUT:     %return.param: ref %.15 = out_param runtime_param1
-// CHECK:STDOUT:     %return: ref %.15 = return_slot %return.param
+// CHECK:STDOUT:     %return.param: ref %.41 = out_param runtime_param1
+// CHECK:STDOUT:     %return: ref %.41 = return_slot %return.param
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %.loc192: <witness> = interface_witness (<error>) [template = <error>]
 // CHECK:STDOUT:
@@ -746,29 +763,34 @@ class SelfNestedBadReturnType {
 // CHECK:STDOUT:   witness = %.loc192
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: impl @impl.15: %Self.ref as %SelfNested.ref {
+// CHECK:STDOUT: impl @impl.27: %Self.ref as %SelfNested.ref {
 // CHECK:STDOUT:   %F.decl: %F.type.15 = fn_decl @F.15 [template = constants.%F.16] {
 // CHECK:STDOUT:     %x.patt: %tuple.type.5 = binding_pattern x
 // CHECK:STDOUT:     %x.param_patt: %tuple.type.5 = value_param_pattern %x.patt, runtime_param0
-// CHECK:STDOUT:     %return.patt: %.15 = return_slot_pattern
-// CHECK:STDOUT:     %return.param_patt: %.15 = out_param_pattern %return.patt, runtime_param1
+// CHECK:STDOUT:     %return.patt: %.41 = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: %.41 = out_param_pattern %return.patt, runtime_param1
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %SelfNestedBadReturnType.ref.loc212_14: type = name_ref SelfNestedBadReturnType, file.%SelfNestedBadReturnType.decl [template = constants.%SelfNestedBadReturnType]
-// CHECK:STDOUT:     %.loc212_37: type = ptr_type %SelfNestedBadReturnType [template = constants.%.17]
+// CHECK:STDOUT:     %.loc212_37: type = ptr_type %SelfNestedBadReturnType [template = constants.%.43]
 // CHECK:STDOUT:     %SelfNestedBadReturnType.ref.loc212_45: type = name_ref SelfNestedBadReturnType, file.%SelfNestedBadReturnType.decl [template = constants.%SelfNestedBadReturnType]
 // CHECK:STDOUT:     %int.make_type_32: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:     %.loc212_74.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:     %.loc212_74.2: type = converted %int.make_type_32, %.loc212_74.1 [template = i32]
-// CHECK:STDOUT:     %.loc212_77: type = struct_type {.x: %SelfNestedBadReturnType, .y: i32} [template = constants.%.18]
+// CHECK:STDOUT:     %.loc212_77: type = struct_type {.x: %SelfNestedBadReturnType, .y: i32} [template = constants.%.44]
 // CHECK:STDOUT:     %.loc212_78.1: %tuple.type.1 = tuple_literal (%.loc212_37, %.loc212_77)
 // CHECK:STDOUT:     %.loc212_78.2: type = converted %.loc212_78.1, constants.%tuple.type.5 [template = constants.%tuple.type.5]
 // CHECK:STDOUT:     %SelfNestedBadParam.ref: type = name_ref SelfNestedBadParam, file.%SelfNestedBadParam.decl [template = constants.%SelfNestedBadParam]
-// CHECK:STDOUT:     %.loc212_105: i32 = int_value 4 [template = constants.%.9]
-// CHECK:STDOUT:     %.loc212_106: type = array_type %.loc212_105, %SelfNestedBadParam [template = constants.%.15]
+// CHECK:STDOUT:     %.loc212_105.1: i32 = int_value 4 [template = constants.%.9]
+// CHECK:STDOUT:     %.loc212_105.2: %Convert.type.2 = interface_witness_access constants.%.33, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:     %.loc212_105.3: <bound method> = bound_method %.loc212_105.1, %.loc212_105.2 [template = constants.%.34]
+// CHECK:STDOUT:     %int.convert_checked: init Core.IntLiteral = call %.loc212_105.3(%.loc212_105.1) [template = constants.%.35]
+// CHECK:STDOUT:     %.loc212_105.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.35]
+// CHECK:STDOUT:     %.loc212_105.5: Core.IntLiteral = converted %.loc212_105.1, %.loc212_105.4 [template = constants.%.35]
+// CHECK:STDOUT:     %.loc212_106: type = array_type %.loc212_105.5, %SelfNestedBadParam [template = constants.%.41]
 // CHECK:STDOUT:     %x.param: %tuple.type.5 = value_param runtime_param0
 // CHECK:STDOUT:     %x: %tuple.type.5 = bind_name x, %x.param
-// CHECK:STDOUT:     %return.param: ref %.15 = out_param runtime_param1
-// CHECK:STDOUT:     %return: ref %.15 = return_slot %return.param
+// CHECK:STDOUT:     %return.param: ref %.41 = out_param runtime_param1
+// CHECK:STDOUT:     %return: ref %.41 = return_slot %return.param
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %.loc205: <witness> = interface_witness (<error>) [template = <error>]
 // CHECK:STDOUT:
@@ -923,7 +945,7 @@ class SelfNestedBadReturnType {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @SelfNestedBadParam {
-// CHECK:STDOUT:   impl_decl @impl.14 [template] {} {
+// CHECK:STDOUT:   impl_decl @impl.26 [template] {} {
 // CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%SelfNestedBadParam [template = constants.%SelfNestedBadParam]
 // CHECK:STDOUT:     %SelfNested.ref: type = name_ref SelfNested, file.%SelfNested.decl [template = constants.%SelfNested.type]
 // CHECK:STDOUT:   }
@@ -934,7 +956,7 @@ class SelfNestedBadReturnType {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @SelfNestedBadReturnType {
-// CHECK:STDOUT:   impl_decl @impl.15 [template] {} {
+// CHECK:STDOUT:   impl_decl @impl.27 [template] {} {
 // CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%SelfNestedBadReturnType [template = constants.%SelfNestedBadReturnType]
 // CHECK:STDOUT:     %SelfNested.ref: type = name_ref SelfNested, file.%SelfNested.decl [template = constants.%SelfNested.type]
 // CHECK:STDOUT:   }
@@ -981,14 +1003,14 @@ class SelfNestedBadReturnType {
 // CHECK:STDOUT:   %.loc188_16.1: type = ptr_type @F.13.%Self (%Self.3) [symbolic = %.loc188_16.1 (constants.%.7)]
 // CHECK:STDOUT:   %.loc188_37.1: type = struct_type {.x: @F.13.%Self (%Self.3), .y: i32} [symbolic = %.loc188_37.1 (constants.%.8)]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (@F.13.%.loc188_16.1 (%.7), @F.13.%.loc188_37.1 (%.8)) [symbolic = %tuple.type (constants.%tuple.type.2)]
-// CHECK:STDOUT:   %.loc188_52.1: type = array_type constants.%.9, @F.13.%Self (%Self.3) [symbolic = %.loc188_52.1 (constants.%.10)]
+// CHECK:STDOUT:   %.loc188_52.1: type = array_type constants.%.35, @F.13.%Self (%Self.3) [symbolic = %.loc188_52.1 (constants.%.36)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%x.param_patt: @F.13.%tuple.type (%tuple.type.2)) -> @F.13.%.loc188_52.1 (%.10);
+// CHECK:STDOUT:   fn(%x.param_patt: @F.13.%tuple.type (%tuple.type.2)) -> @F.13.%.loc188_52.1 (%.36);
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F.14(%x.param_patt: %tuple.type.3) -> %.15;
+// CHECK:STDOUT: fn @F.14(%x.param_patt: %tuple.type.3) -> %.41;
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F.15(%x.param_patt: %tuple.type.5) -> %.15;
+// CHECK:STDOUT: fn @F.15(%x.param_patt: %tuple.type.5) -> %.41;
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @F.1(constants.%Self.1) {}
 // CHECK:STDOUT:
@@ -1019,22 +1041,22 @@ class SelfNestedBadReturnType {
 // CHECK:STDOUT:   %.loc188_16.1 => constants.%.7
 // CHECK:STDOUT:   %.loc188_37.1 => constants.%.8
 // CHECK:STDOUT:   %tuple.type => constants.%tuple.type.2
-// CHECK:STDOUT:   %.loc188_52.1 => constants.%.10
+// CHECK:STDOUT:   %.loc188_52.1 => constants.%.36
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @F.13(constants.%SelfNestedBadParam) {
 // CHECK:STDOUT:   %Self => constants.%SelfNestedBadParam
-// CHECK:STDOUT:   %.loc188_16.1 => constants.%.13
-// CHECK:STDOUT:   %.loc188_37.1 => constants.%.16
+// CHECK:STDOUT:   %.loc188_16.1 => constants.%.39
+// CHECK:STDOUT:   %.loc188_37.1 => constants.%.42
 // CHECK:STDOUT:   %tuple.type => constants.%tuple.type.4
-// CHECK:STDOUT:   %.loc188_52.1 => constants.%.15
+// CHECK:STDOUT:   %.loc188_52.1 => constants.%.41
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @F.13(constants.%SelfNestedBadReturnType) {
 // CHECK:STDOUT:   %Self => constants.%SelfNestedBadReturnType
-// CHECK:STDOUT:   %.loc188_16.1 => constants.%.17
-// CHECK:STDOUT:   %.loc188_37.1 => constants.%.18
+// CHECK:STDOUT:   %.loc188_16.1 => constants.%.43
+// CHECK:STDOUT:   %.loc188_37.1 => constants.%.44
 // CHECK:STDOUT:   %tuple.type => constants.%tuple.type.5
-// CHECK:STDOUT:   %.loc188_52.1 => constants.%.19
+// CHECK:STDOUT:   %.loc188_52.1 => constants.%.45
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 35 - 23
toolchain/check/testdata/index/array_element_access.carbon

@@ -19,18 +19,25 @@ var d: i32 = a[b];
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 2 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 12 [template]
-// CHECK:STDOUT:   %.5: i32 = int_value 24 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 2 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, i32 [template]
+// CHECK:STDOUT:   %.30: i32 = int_value 12 [template]
+// CHECK:STDOUT:   %.31: i32 = int_value 24 [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (i32, i32) [template]
-// CHECK:STDOUT:   %.6: i32 = int_value 0 [template]
-// CHECK:STDOUT:   %.7: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %array: %.2 = tuple_value (%.4, %.5) [template]
+// CHECK:STDOUT:   %.32: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %.33: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %array: %.28 = tuple_value (%.30, %.31) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -46,12 +53,17 @@ var d: i32 = a[b];
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %int.make_type_32.loc11: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc11_14: i32 = int_value 2 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc11_14.1: i32 = int_value 2 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc11_9.1: type = value_of_initializer %int.make_type_32.loc11 [template = i32]
 // CHECK:STDOUT:   %.loc11_9.2: type = converted %int.make_type_32.loc11, %.loc11_9.1 [template = i32]
-// CHECK:STDOUT:   %.loc11_15: type = array_type %.loc11_14, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %a.var: ref %.2 = var a
-// CHECK:STDOUT:   %a: ref %.2 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc11_14.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc11_14.3: <bound method> = bound_method %.loc11_14.1, %.loc11_14.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc11_14.3(%.loc11_14.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_14.5: Core.IntLiteral = converted %.loc11_14.1, %.loc11_14.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_15: type = array_type %.loc11_14.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %a.var: ref %.28 = var a
+// CHECK:STDOUT:   %a: ref %.28 = bind_name a, %a.var
 // CHECK:STDOUT:   %int.make_type_32.loc12: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc12_8.1: type = value_of_initializer %int.make_type_32.loc12 [template = i32]
 // CHECK:STDOUT:   %.loc12_8.2: type = converted %int.make_type_32.loc12, %.loc12_8.1 [template = i32]
@@ -71,26 +83,26 @@ var d: i32 = a[b];
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc11_20: i32 = int_value 12 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc11_24: i32 = int_value 24 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc11_20: i32 = int_value 12 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc11_24: i32 = int_value 24 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc11_26.1: %tuple.type = tuple_literal (%.loc11_20, %.loc11_24)
-// CHECK:STDOUT:   %.loc11_26.2: i32 = int_value 0 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc11_26.2: i32 = int_value 0 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc11_26.3: ref i32 = array_index file.%a.var, %.loc11_26.2
-// CHECK:STDOUT:   %.loc11_26.4: init i32 = initialize_from %.loc11_20 to %.loc11_26.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc11_26.5: i32 = int_value 1 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc11_26.4: init i32 = initialize_from %.loc11_20 to %.loc11_26.3 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc11_26.5: i32 = int_value 1 [template = constants.%.33]
 // CHECK:STDOUT:   %.loc11_26.6: ref i32 = array_index file.%a.var, %.loc11_26.5
-// CHECK:STDOUT:   %.loc11_26.7: init i32 = initialize_from %.loc11_24 to %.loc11_26.6 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc11_26.8: init %.2 = array_init (%.loc11_26.4, %.loc11_26.7) to file.%a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc11_27: init %.2 = converted %.loc11_26.1, %.loc11_26.8 [template = constants.%array]
+// CHECK:STDOUT:   %.loc11_26.7: init i32 = initialize_from %.loc11_24 to %.loc11_26.6 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc11_26.8: init %.28 = array_init (%.loc11_26.4, %.loc11_26.7) to file.%a.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc11_27: init %.28 = converted %.loc11_26.1, %.loc11_26.8 [template = constants.%array]
 // CHECK:STDOUT:   assign file.%a.var, %.loc11_27
-// CHECK:STDOUT:   %.loc12: i32 = int_value 1 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc12: i32 = int_value 1 [template = constants.%.33]
 // CHECK:STDOUT:   assign file.%b.var, %.loc12
-// CHECK:STDOUT:   %a.ref.loc13: ref %.2 = name_ref a, file.%a
-// CHECK:STDOUT:   %.loc13_16: i32 = int_value 0 [template = constants.%.6]
+// CHECK:STDOUT:   %a.ref.loc13: ref %.28 = name_ref a, file.%a
+// CHECK:STDOUT:   %.loc13_16: i32 = int_value 0 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc13_17.1: ref i32 = array_index %a.ref.loc13, %.loc13_16
 // CHECK:STDOUT:   %.loc13_17.2: i32 = bind_value %.loc13_17.1
 // CHECK:STDOUT:   assign file.%c.var, %.loc13_17.2
-// CHECK:STDOUT:   %a.ref.loc14: ref %.2 = name_ref a, file.%a
+// CHECK:STDOUT:   %a.ref.loc14: ref %.28 = name_ref a, file.%a
 // CHECK:STDOUT:   %b.ref: ref i32 = name_ref b, file.%b
 // CHECK:STDOUT:   %.loc14_16: i32 = bind_value %b.ref
 // CHECK:STDOUT:   %.loc14_17.1: ref i32 = array_index %a.ref.loc14, %.loc14_16

+ 105 - 73
toolchain/check/testdata/index/expr_category.carbon

@@ -34,25 +34,32 @@ fn ValueBinding(b: [i32; 3]) {
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, i32 [template]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [template]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [template]
 // CHECK:STDOUT:   %G.type: type = fn_type @G [template]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.5: i32 = int_value 2 [template]
+// CHECK:STDOUT:   %.30: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %.31: i32 = int_value 2 [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (i32, i32, i32) [template]
-// CHECK:STDOUT:   %.6: i32 = int_value 0 [template]
-// CHECK:STDOUT:   %array: %.2 = tuple_value (%.4, %.5, %.1) [template]
-// CHECK:STDOUT:   %.7: type = ptr_type i32 [template]
-// CHECK:STDOUT:   %.8: i32 = int_value 4 [template]
+// CHECK:STDOUT:   %.32: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %array: %.28 = tuple_value (%.30, %.31, %.1) [template]
+// CHECK:STDOUT:   %.33: type = ptr_type i32 [template]
+// CHECK:STDOUT:   %.34: i32 = int_value 4 [template]
 // CHECK:STDOUT:   %ValueBinding.type: type = fn_type @ValueBinding [template]
 // CHECK:STDOUT:   %ValueBinding: %ValueBinding.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -67,127 +74,152 @@ fn ValueBinding(b: [i32; 3]) {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [template = constants.%F] {
-// CHECK:STDOUT:     %return.patt: %.2 = return_slot_pattern
-// CHECK:STDOUT:     %return.param_patt: %.2 = out_param_pattern %return.patt, runtime_param0
+// CHECK:STDOUT:     %return.patt: %.28 = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: %.28 = out_param_pattern %return.patt, runtime_param0
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %int.make_type_32: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:     %.loc11_17: i32 = int_value 3 [template = constants.%.1]
+// CHECK:STDOUT:     %.loc11_17.1: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:     %.loc11_12.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:     %.loc11_12.2: type = converted %int.make_type_32, %.loc11_12.1 [template = i32]
-// CHECK:STDOUT:     %.loc11_18: type = array_type %.loc11_17, i32 [template = constants.%.2]
-// CHECK:STDOUT:     %return.param: ref %.2 = out_param runtime_param0
-// CHECK:STDOUT:     %return: ref %.2 = return_slot %return.param
+// CHECK:STDOUT:     %.loc11_17.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:     %.loc11_17.3: <bound method> = bound_method %.loc11_17.1, %.loc11_17.2 [template = constants.%.26]
+// CHECK:STDOUT:     %int.convert_checked: init Core.IntLiteral = call %.loc11_17.3(%.loc11_17.1) [template = constants.%.27]
+// CHECK:STDOUT:     %.loc11_17.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:     %.loc11_17.5: Core.IntLiteral = converted %.loc11_17.1, %.loc11_17.4 [template = constants.%.27]
+// CHECK:STDOUT:     %.loc11_18: type = array_type %.loc11_17.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:     %return.param: ref %.28 = out_param runtime_param0
+// CHECK:STDOUT:     %return: ref %.28 = return_slot %return.param
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [template = constants.%G] {
-// CHECK:STDOUT:     %b.patt: %.2 = binding_pattern b
-// CHECK:STDOUT:     %b.param_patt: %.2 = value_param_pattern %b.patt, runtime_param0
+// CHECK:STDOUT:     %b.patt: %.28 = binding_pattern b
+// CHECK:STDOUT:     %b.param_patt: %.28 = value_param_pattern %b.patt, runtime_param0
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %int.make_type_32.loc13: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:     %.loc13_15: i32 = int_value 3 [template = constants.%.1]
+// CHECK:STDOUT:     %.loc13_15.1: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:     %.loc13_10.1: type = value_of_initializer %int.make_type_32.loc13 [template = i32]
 // CHECK:STDOUT:     %.loc13_10.2: type = converted %int.make_type_32.loc13, %.loc13_10.1 [template = i32]
-// CHECK:STDOUT:     %.loc13_16: type = array_type %.loc13_15, i32 [template = constants.%.2]
-// CHECK:STDOUT:     %b.param: %.2 = value_param runtime_param0
-// CHECK:STDOUT:     %b: %.2 = bind_name b, %b.param
+// CHECK:STDOUT:     %.loc13_15.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:     %.loc13_15.3: <bound method> = bound_method %.loc13_15.1, %.loc13_15.2 [template = constants.%.26]
+// CHECK:STDOUT:     %int.convert_checked.loc13: init Core.IntLiteral = call %.loc13_15.3(%.loc13_15.1) [template = constants.%.27]
+// CHECK:STDOUT:     %.loc13_15.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc13 [template = constants.%.27]
+// CHECK:STDOUT:     %.loc13_15.5: Core.IntLiteral = converted %.loc13_15.1, %.loc13_15.4 [template = constants.%.27]
+// CHECK:STDOUT:     %.loc13_16: type = array_type %.loc13_15.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:     %b.param: %.28 = value_param runtime_param0
+// CHECK:STDOUT:     %b: %.28 = bind_name b, %b.param
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %ValueBinding.decl: %ValueBinding.type = fn_decl @ValueBinding [template = constants.%ValueBinding] {
-// CHECK:STDOUT:     %b.patt: %.2 = binding_pattern b
-// CHECK:STDOUT:     %b.param_patt: %.2 = value_param_pattern %b.patt, runtime_param0
+// CHECK:STDOUT:     %b.patt: %.28 = binding_pattern b
+// CHECK:STDOUT:     %b.param_patt: %.28 = value_param_pattern %b.patt, runtime_param0
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %int.make_type_32.loc21: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:     %.loc21_26: i32 = int_value 3 [template = constants.%.1]
+// CHECK:STDOUT:     %.loc21_26.1: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:     %.loc21_21.1: type = value_of_initializer %int.make_type_32.loc21 [template = i32]
 // CHECK:STDOUT:     %.loc21_21.2: type = converted %int.make_type_32.loc21, %.loc21_21.1 [template = i32]
-// CHECK:STDOUT:     %.loc21_27: type = array_type %.loc21_26, i32 [template = constants.%.2]
-// CHECK:STDOUT:     %b.param: %.2 = value_param runtime_param0
-// CHECK:STDOUT:     %b: %.2 = bind_name b, %b.param
+// CHECK:STDOUT:     %.loc21_26.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:     %.loc21_26.3: <bound method> = bound_method %.loc21_26.1, %.loc21_26.2 [template = constants.%.26]
+// CHECK:STDOUT:     %int.convert_checked.loc21: init Core.IntLiteral = call %.loc21_26.3(%.loc21_26.1) [template = constants.%.27]
+// CHECK:STDOUT:     %.loc21_26.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc21 [template = constants.%.27]
+// CHECK:STDOUT:     %.loc21_26.5: Core.IntLiteral = converted %.loc21_26.1, %.loc21_26.4 [template = constants.%.27]
+// CHECK:STDOUT:     %.loc21_27: type = array_type %.loc21_26.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:     %b.param: %.28 = value_param runtime_param0
+// CHECK:STDOUT:     %b: %.28 = bind_name b, %b.param
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F() -> %.2;
+// CHECK:STDOUT: fn @F() -> %.28;
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @G(%b.param_patt: %.2) {
+// CHECK:STDOUT: fn @G(%b.param_patt: %.28) {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %int.make_type_32.loc14: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc14_16: i32 = int_value 3 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc14_16.1: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc14_11.1: type = value_of_initializer %int.make_type_32.loc14 [template = i32]
 // CHECK:STDOUT:   %.loc14_11.2: type = converted %int.make_type_32.loc14, %.loc14_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc14_17: type = array_type %.loc14_16, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %a.var: ref %.2 = var a
-// CHECK:STDOUT:   %a: ref %.2 = bind_name a, %a.var
-// CHECK:STDOUT:   %.loc14_22: i32 = int_value 1 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc14_25: i32 = int_value 2 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc14_16.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc14_16.3: <bound method> = bound_method %.loc14_16.1, %.loc14_16.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked.loc14: init Core.IntLiteral = call %.loc14_16.3(%.loc14_16.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc14_16.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc14 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc14_16.5: Core.IntLiteral = converted %.loc14_16.1, %.loc14_16.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc14_17: type = array_type %.loc14_16.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %a.var: ref %.28 = var a
+// CHECK:STDOUT:   %a: ref %.28 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc14_22: i32 = int_value 1 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc14_25: i32 = int_value 2 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc14_28: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc14_29.1: %tuple.type = tuple_literal (%.loc14_22, %.loc14_25, %.loc14_28)
-// CHECK:STDOUT:   %.loc14_29.2: i32 = int_value 0 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc14_29.2: i32 = int_value 0 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc14_29.3: ref i32 = array_index %a.var, %.loc14_29.2
-// CHECK:STDOUT:   %.loc14_29.4: init i32 = initialize_from %.loc14_22 to %.loc14_29.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc14_29.5: i32 = int_value 1 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc14_29.4: init i32 = initialize_from %.loc14_22 to %.loc14_29.3 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc14_29.5: i32 = int_value 1 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc14_29.6: ref i32 = array_index %a.var, %.loc14_29.5
-// CHECK:STDOUT:   %.loc14_29.7: init i32 = initialize_from %.loc14_25 to %.loc14_29.6 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc14_29.8: i32 = int_value 2 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc14_29.7: init i32 = initialize_from %.loc14_25 to %.loc14_29.6 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc14_29.8: i32 = int_value 2 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc14_29.9: ref i32 = array_index %a.var, %.loc14_29.8
 // CHECK:STDOUT:   %.loc14_29.10: init i32 = initialize_from %.loc14_28 to %.loc14_29.9 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc14_29.11: init %.2 = array_init (%.loc14_29.4, %.loc14_29.7, %.loc14_29.10) to %a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc14_30: init %.2 = converted %.loc14_29.1, %.loc14_29.11 [template = constants.%array]
+// CHECK:STDOUT:   %.loc14_29.11: init %.28 = array_init (%.loc14_29.4, %.loc14_29.7, %.loc14_29.10) to %a.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc14_30: init %.28 = converted %.loc14_29.1, %.loc14_29.11 [template = constants.%array]
 // CHECK:STDOUT:   assign %a.var, %.loc14_30
 // CHECK:STDOUT:   %int.make_type_32.loc17: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc17_14.1: type = value_of_initializer %int.make_type_32.loc17 [template = i32]
 // CHECK:STDOUT:   %.loc17_14.2: type = converted %int.make_type_32.loc17, %.loc17_14.1 [template = i32]
-// CHECK:STDOUT:   %.loc17_14.3: type = ptr_type i32 [template = constants.%.7]
-// CHECK:STDOUT:   %pa.var: ref %.7 = var pa
-// CHECK:STDOUT:   %pa: ref %.7 = bind_name pa, %pa.var
-// CHECK:STDOUT:   %a.ref.loc17: ref %.2 = name_ref a, %a
-// CHECK:STDOUT:   %.loc17_21: i32 = int_value 0 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc17_14.3: type = ptr_type i32 [template = constants.%.33]
+// CHECK:STDOUT:   %pa.var: ref %.33 = var pa
+// CHECK:STDOUT:   %pa: ref %.33 = bind_name pa, %pa.var
+// CHECK:STDOUT:   %a.ref.loc17: ref %.28 = name_ref a, %a
+// CHECK:STDOUT:   %.loc17_21: i32 = int_value 0 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc17_22: ref i32 = array_index %a.ref.loc17, %.loc17_21
-// CHECK:STDOUT:   %.loc17_18: %.7 = addr_of %.loc17_22
+// CHECK:STDOUT:   %.loc17_18: %.33 = addr_of %.loc17_22
 // CHECK:STDOUT:   assign %pa.var, %.loc17_18
-// CHECK:STDOUT:   %a.ref.loc18: ref %.2 = name_ref a, %a
-// CHECK:STDOUT:   %.loc18_5: i32 = int_value 0 [template = constants.%.6]
+// CHECK:STDOUT:   %a.ref.loc18: ref %.28 = name_ref a, %a
+// CHECK:STDOUT:   %.loc18_5: i32 = int_value 0 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc18_6: ref i32 = array_index %a.ref.loc18, %.loc18_5
-// CHECK:STDOUT:   %.loc18_10: i32 = int_value 4 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc18_10: i32 = int_value 4 [template = constants.%.34]
 // CHECK:STDOUT:   assign %.loc18_6, %.loc18_10
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @ValueBinding(%b.param_patt: %.2) {
+// CHECK:STDOUT: fn @ValueBinding(%b.param_patt: %.28) {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %int.make_type_32.loc22: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc22_16: i32 = int_value 3 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc22_16.1: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc22_11.1: type = value_of_initializer %int.make_type_32.loc22 [template = i32]
 // CHECK:STDOUT:   %.loc22_11.2: type = converted %int.make_type_32.loc22, %.loc22_11.1 [template = i32]
-// CHECK:STDOUT:   %.loc22_17: type = array_type %.loc22_16, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %a.var: ref %.2 = var a
-// CHECK:STDOUT:   %a: ref %.2 = bind_name a, %a.var
-// CHECK:STDOUT:   %.loc22_22: i32 = int_value 1 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc22_25: i32 = int_value 2 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc22_16.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc22_16.3: <bound method> = bound_method %.loc22_16.1, %.loc22_16.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked.loc22: init Core.IntLiteral = call %.loc22_16.3(%.loc22_16.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc22_16.4: Core.IntLiteral = value_of_initializer %int.convert_checked.loc22 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc22_16.5: Core.IntLiteral = converted %.loc22_16.1, %.loc22_16.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc22_17: type = array_type %.loc22_16.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %a.var: ref %.28 = var a
+// CHECK:STDOUT:   %a: ref %.28 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc22_22: i32 = int_value 1 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc22_25: i32 = int_value 2 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc22_28: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc22_29.1: %tuple.type = tuple_literal (%.loc22_22, %.loc22_25, %.loc22_28)
-// CHECK:STDOUT:   %.loc22_29.2: i32 = int_value 0 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc22_29.2: i32 = int_value 0 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc22_29.3: ref i32 = array_index %a.var, %.loc22_29.2
-// CHECK:STDOUT:   %.loc22_29.4: init i32 = initialize_from %.loc22_22 to %.loc22_29.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc22_29.5: i32 = int_value 1 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc22_29.4: init i32 = initialize_from %.loc22_22 to %.loc22_29.3 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc22_29.5: i32 = int_value 1 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc22_29.6: ref i32 = array_index %a.var, %.loc22_29.5
-// CHECK:STDOUT:   %.loc22_29.7: init i32 = initialize_from %.loc22_25 to %.loc22_29.6 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc22_29.8: i32 = int_value 2 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc22_29.7: init i32 = initialize_from %.loc22_25 to %.loc22_29.6 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc22_29.8: i32 = int_value 2 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc22_29.9: ref i32 = array_index %a.var, %.loc22_29.8
 // CHECK:STDOUT:   %.loc22_29.10: init i32 = initialize_from %.loc22_28 to %.loc22_29.9 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc22_29.11: init %.2 = array_init (%.loc22_29.4, %.loc22_29.7, %.loc22_29.10) to %a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc22_30: init %.2 = converted %.loc22_29.1, %.loc22_29.11 [template = constants.%array]
+// CHECK:STDOUT:   %.loc22_29.11: init %.28 = array_init (%.loc22_29.4, %.loc22_29.7, %.loc22_29.10) to %a.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc22_30: init %.28 = converted %.loc22_29.1, %.loc22_29.11 [template = constants.%array]
 // CHECK:STDOUT:   assign %a.var, %.loc22_30
-// CHECK:STDOUT:   %a.ref: ref %.2 = name_ref a, %a
-// CHECK:STDOUT:   %.loc26_5: i32 = int_value 0 [template = constants.%.6]
+// CHECK:STDOUT:   %a.ref: ref %.28 = name_ref a, %a
+// CHECK:STDOUT:   %.loc26_5: i32 = int_value 0 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc26_6: ref i32 = array_index %a.ref, %.loc26_5
-// CHECK:STDOUT:   %b.ref: %.2 = name_ref b, %b
-// CHECK:STDOUT:   %.loc27_5: i32 = int_value 0 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc27_6.1: ref %.2 = value_as_ref %b.ref
+// CHECK:STDOUT:   %b.ref: %.28 = name_ref b, %b
+// CHECK:STDOUT:   %.loc27_5: i32 = int_value 0 [template = constants.%.32]
+// CHECK:STDOUT:   %.loc27_6.1: ref %.28 = value_as_ref %b.ref
 // CHECK:STDOUT:   %.loc27_6.2: ref i32 = array_index %.loc27_6.1, %.loc27_5
 // CHECK:STDOUT:   %.loc27_6.3: i32 = bind_value %.loc27_6.2
 // CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F]
-// CHECK:STDOUT:   %.loc28_4.1: ref %.2 = temporary_storage
-// CHECK:STDOUT:   %F.call: init %.2 = call %F.ref() to %.loc28_4.1
-// CHECK:STDOUT:   %.loc28_7: i32 = int_value 0 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc28_4.2: ref %.2 = temporary %.loc28_4.1, %F.call
+// CHECK:STDOUT:   %.loc28_4.1: ref %.28 = temporary_storage
+// CHECK:STDOUT:   %F.call: init %.28 = call %F.ref() to %.loc28_4.1
+// CHECK:STDOUT:   %.loc28_7: i32 = int_value 0 [template = constants.%.32]
+// CHECK:STDOUT:   %.loc28_4.2: ref %.28 = temporary %.loc28_4.1, %F.call
 // CHECK:STDOUT:   %.loc28_8.1: ref i32 = array_index %.loc28_4.2, %.loc28_7
 // CHECK:STDOUT:   %.loc28_8.2: i32 = bind_value %.loc28_8.1
 // CHECK:STDOUT:   return

+ 30 - 18
toolchain/check/testdata/index/fail_array_large_index.carbon

@@ -27,17 +27,24 @@ var c: i32 = a[0x7FFF_FFFF];
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 12 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 1 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, i32 [template]
+// CHECK:STDOUT:   %.30: i32 = int_value 12 [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (i32) [template]
-// CHECK:STDOUT:   %.5: i32 = int_value 0 [template]
-// CHECK:STDOUT:   %array: %.2 = tuple_value (%.4) [template]
-// CHECK:STDOUT:   %.6: i32 = int_value 2147483647 [template]
+// CHECK:STDOUT:   %.31: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %array: %.28 = tuple_value (%.30) [template]
+// CHECK:STDOUT:   %.32: i32 = int_value 2147483647 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -52,12 +59,17 @@ var c: i32 = a[0x7FFF_FFFF];
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %int.make_type_32.loc11: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc11_14: i32 = int_value 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc11_14.1: i32 = int_value 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc11_9.1: type = value_of_initializer %int.make_type_32.loc11 [template = i32]
 // CHECK:STDOUT:   %.loc11_9.2: type = converted %int.make_type_32.loc11, %.loc11_9.1 [template = i32]
-// CHECK:STDOUT:   %.loc11_15: type = array_type %.loc11_14, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %a.var: ref %.2 = var a
-// CHECK:STDOUT:   %a: ref %.2 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc11_14.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc11_14.3: <bound method> = bound_method %.loc11_14.1, %.loc11_14.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc11_14.3(%.loc11_14.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_14.5: Core.IntLiteral = converted %.loc11_14.1, %.loc11_14.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_15: type = array_type %.loc11_14.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %a.var: ref %.28 = var a
+// CHECK:STDOUT:   %a: ref %.28 = bind_name a, %a.var
 // CHECK:STDOUT:   %int.make_type_32.loc17: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc17_8.1: type = value_of_initializer %int.make_type_32.loc17 [template = i32]
 // CHECK:STDOUT:   %.loc17_8.2: type = converted %int.make_type_32.loc17, %.loc17_8.1 [template = i32]
@@ -72,21 +84,21 @@ var c: i32 = a[0x7FFF_FFFF];
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc11_20: i32 = int_value 12 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc11_20: i32 = int_value 12 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc11_23.1: %tuple.type = tuple_literal (%.loc11_20)
-// CHECK:STDOUT:   %.loc11_23.2: i32 = int_value 0 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc11_23.2: i32 = int_value 0 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc11_23.3: ref i32 = array_index file.%a.var, %.loc11_23.2
-// CHECK:STDOUT:   %.loc11_23.4: init i32 = initialize_from %.loc11_20 to %.loc11_23.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc11_23.5: init %.2 = array_init (%.loc11_23.4) to file.%a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc11_24: init %.2 = converted %.loc11_23.1, %.loc11_23.5 [template = constants.%array]
+// CHECK:STDOUT:   %.loc11_23.4: init i32 = initialize_from %.loc11_20 to %.loc11_23.3 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc11_23.5: init %.28 = array_init (%.loc11_23.4) to file.%a.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc11_24: init %.28 = converted %.loc11_23.1, %.loc11_23.5 [template = constants.%array]
 // CHECK:STDOUT:   assign file.%a.var, %.loc11_24
-// CHECK:STDOUT:   %a.ref.loc17: ref %.2 = name_ref a, file.%a
+// CHECK:STDOUT:   %a.ref.loc17: ref %.28 = name_ref a, file.%a
 // CHECK:STDOUT:   %.loc17_16: i32 = int_value 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc17_17.1: ref i32 = array_index %a.ref.loc17, %.loc17_16 [template = <error>]
 // CHECK:STDOUT:   %.loc17_17.2: i32 = bind_value %.loc17_17.1
 // CHECK:STDOUT:   assign file.%b.var, %.loc17_17.2
-// CHECK:STDOUT:   %a.ref.loc22: ref %.2 = name_ref a, file.%a
-// CHECK:STDOUT:   %.loc22_16: i32 = int_value 2147483647 [template = constants.%.6]
+// CHECK:STDOUT:   %a.ref.loc22: ref %.28 = name_ref a, file.%a
+// CHECK:STDOUT:   %.loc22_16: i32 = int_value 2147483647 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc22_27.1: ref i32 = array_index %a.ref.loc22, %.loc22_16 [template = <error>]
 // CHECK:STDOUT:   %.loc22_27.2: i32 = bind_value %.loc22_27.1
 // CHECK:STDOUT:   assign file.%c.var, %.loc22_27.2

+ 27 - 16
toolchain/check/testdata/index/fail_array_non_int_indexing.carbon

@@ -23,12 +23,18 @@ var b: i32 = a[2.6];
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 12 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 1 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, i32 [template]
+// CHECK:STDOUT:   %.30: i32 = int_value 12 [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (i32) [template]
-// CHECK:STDOUT:   %.5: i32 = int_value 0 [template]
-// CHECK:STDOUT:   %array: %.2 = tuple_value (%.4) [template]
-// CHECK:STDOUT:   %.6: f64 = float_literal 2.6000000000000001 [template]
+// CHECK:STDOUT:   %.31: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %array: %.28 = tuple_value (%.30) [template]
+// CHECK:STDOUT:   %.32: f64 = float_literal 2.6000000000000001 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -48,12 +54,17 @@ var b: i32 = a[2.6];
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %int.make_type_32.loc11: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc11_14: i32 = int_value 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc11_14.1: i32 = int_value 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc11_9.1: type = value_of_initializer %int.make_type_32.loc11 [template = i32]
 // CHECK:STDOUT:   %.loc11_9.2: type = converted %int.make_type_32.loc11, %.loc11_9.1 [template = i32]
-// CHECK:STDOUT:   %.loc11_15: type = array_type %.loc11_14, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %a.var: ref %.2 = var a
-// CHECK:STDOUT:   %a: ref %.2 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc11_14.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc11_14.3: <bound method> = bound_method %.loc11_14.1, %.loc11_14.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc11_14.3(%.loc11_14.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_14.5: Core.IntLiteral = converted %.loc11_14.1, %.loc11_14.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_15: type = array_type %.loc11_14.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %a.var: ref %.28 = var a
+// CHECK:STDOUT:   %a: ref %.28 = bind_name a, %a.var
 // CHECK:STDOUT:   %int.make_type_32.loc18: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc18_8.1: type = value_of_initializer %int.make_type_32.loc18 [template = i32]
 // CHECK:STDOUT:   %.loc18_8.2: type = converted %int.make_type_32.loc18, %.loc18_8.1 [template = i32]
@@ -63,16 +74,16 @@ var b: i32 = a[2.6];
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc11_20: i32 = int_value 12 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc11_20: i32 = int_value 12 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc11_23.1: %tuple.type = tuple_literal (%.loc11_20)
-// CHECK:STDOUT:   %.loc11_23.2: i32 = int_value 0 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc11_23.2: i32 = int_value 0 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc11_23.3: ref i32 = array_index file.%a.var, %.loc11_23.2
-// CHECK:STDOUT:   %.loc11_23.4: init i32 = initialize_from %.loc11_20 to %.loc11_23.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc11_23.5: init %.2 = array_init (%.loc11_23.4) to file.%a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc11_24: init %.2 = converted %.loc11_23.1, %.loc11_23.5 [template = constants.%array]
+// CHECK:STDOUT:   %.loc11_23.4: init i32 = initialize_from %.loc11_20 to %.loc11_23.3 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc11_23.5: init %.28 = array_init (%.loc11_23.4) to file.%a.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc11_24: init %.28 = converted %.loc11_23.1, %.loc11_23.5 [template = constants.%array]
 // CHECK:STDOUT:   assign file.%a.var, %.loc11_24
-// CHECK:STDOUT:   %a.ref: ref %.2 = name_ref a, file.%a
-// CHECK:STDOUT:   %.loc18_16.1: f64 = float_literal 2.6000000000000001 [template = constants.%.6]
+// CHECK:STDOUT:   %a.ref: ref %.28 = name_ref a, file.%a
+// CHECK:STDOUT:   %.loc18_16.1: f64 = float_literal 2.6000000000000001 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc18_16.2: i32 = converted %.loc18_16.1, <error> [template = <error>]
 // CHECK:STDOUT:   %.loc18_19.1: ref i32 = array_index %a.ref, <error> [template = <error>]
 // CHECK:STDOUT:   %.loc18_19.2: i32 = bind_value %.loc18_19.1

+ 27 - 15
toolchain/check/testdata/index/fail_array_out_of_bound_access.carbon

@@ -20,16 +20,23 @@ var b: i32 = a[1];
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 12 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 1 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, i32 [template]
+// CHECK:STDOUT:   %.30: i32 = int_value 12 [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (i32) [template]
-// CHECK:STDOUT:   %.5: i32 = int_value 0 [template]
-// CHECK:STDOUT:   %array: %.2 = tuple_value (%.4) [template]
+// CHECK:STDOUT:   %.31: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %array: %.28 = tuple_value (%.30) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -43,12 +50,17 @@ var b: i32 = a[1];
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %int.make_type_32.loc11: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc11_14: i32 = int_value 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc11_14.1: i32 = int_value 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc11_9.1: type = value_of_initializer %int.make_type_32.loc11 [template = i32]
 // CHECK:STDOUT:   %.loc11_9.2: type = converted %int.make_type_32.loc11, %.loc11_9.1 [template = i32]
-// CHECK:STDOUT:   %.loc11_15: type = array_type %.loc11_14, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %a.var: ref %.2 = var a
-// CHECK:STDOUT:   %a: ref %.2 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc11_14.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc11_14.3: <bound method> = bound_method %.loc11_14.1, %.loc11_14.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc11_14.3(%.loc11_14.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_14.5: Core.IntLiteral = converted %.loc11_14.1, %.loc11_14.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_15: type = array_type %.loc11_14.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %a.var: ref %.28 = var a
+// CHECK:STDOUT:   %a: ref %.28 = bind_name a, %a.var
 // CHECK:STDOUT:   %int.make_type_32.loc15: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc15_8.1: type = value_of_initializer %int.make_type_32.loc15 [template = i32]
 // CHECK:STDOUT:   %.loc15_8.2: type = converted %int.make_type_32.loc15, %.loc15_8.1 [template = i32]
@@ -58,15 +70,15 @@ var b: i32 = a[1];
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc11_20: i32 = int_value 12 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc11_20: i32 = int_value 12 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc11_23.1: %tuple.type = tuple_literal (%.loc11_20)
-// CHECK:STDOUT:   %.loc11_23.2: i32 = int_value 0 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc11_23.2: i32 = int_value 0 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc11_23.3: ref i32 = array_index file.%a.var, %.loc11_23.2
-// CHECK:STDOUT:   %.loc11_23.4: init i32 = initialize_from %.loc11_20 to %.loc11_23.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc11_23.5: init %.2 = array_init (%.loc11_23.4) to file.%a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc11_24: init %.2 = converted %.loc11_23.1, %.loc11_23.5 [template = constants.%array]
+// CHECK:STDOUT:   %.loc11_23.4: init i32 = initialize_from %.loc11_20 to %.loc11_23.3 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc11_23.5: init %.28 = array_init (%.loc11_23.4) to file.%a.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc11_24: init %.28 = converted %.loc11_23.1, %.loc11_23.5 [template = constants.%array]
 // CHECK:STDOUT:   assign file.%a.var, %.loc11_24
-// CHECK:STDOUT:   %a.ref: ref %.2 = name_ref a, file.%a
+// CHECK:STDOUT:   %a.ref: ref %.28 = name_ref a, file.%a
 // CHECK:STDOUT:   %.loc15_16: i32 = int_value 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc15_17.1: ref i32 = array_index %a.ref, %.loc15_16 [template = <error>]
 // CHECK:STDOUT:   %.loc15_17.2: i32 = bind_value %.loc15_17.1

+ 60 - 43
toolchain/check/testdata/index/fail_expr_category.carbon

@@ -42,19 +42,26 @@ fn G(b: [i32; 3]) {
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 3 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 3 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, i32 [template]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [template]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [template]
 // CHECK:STDOUT:   %G.type: type = fn_type @G [template]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [template]
-// CHECK:STDOUT:   %.4: type = ptr_type i32 [template]
-// CHECK:STDOUT:   %.5: i32 = int_value 0 [template]
-// CHECK:STDOUT:   %.6: i32 = int_value 4 [template]
+// CHECK:STDOUT:   %.30: type = ptr_type i32 [template]
+// CHECK:STDOUT:   %.31: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %.32: i32 = int_value 4 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
-// CHECK:STDOUT:     .Int32 = %import_ref
+// CHECK:STDOUT:     .Int32 = %import_ref.1
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -68,78 +75,88 @@ fn G(b: [i32; 3]) {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [template = constants.%F] {
-// CHECK:STDOUT:     %return.patt: %.2 = return_slot_pattern
-// CHECK:STDOUT:     %return.param_patt: %.2 = out_param_pattern %return.patt, runtime_param0
+// CHECK:STDOUT:     %return.patt: %.28 = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: %.28 = out_param_pattern %return.patt, runtime_param0
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %int.make_type_32: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:     %.loc11_17: i32 = int_value 3 [template = constants.%.1]
+// CHECK:STDOUT:     %.loc11_17.1: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:     %.loc11_12.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:     %.loc11_12.2: type = converted %int.make_type_32, %.loc11_12.1 [template = i32]
-// CHECK:STDOUT:     %.loc11_18: type = array_type %.loc11_17, i32 [template = constants.%.2]
-// CHECK:STDOUT:     %return.param: ref %.2 = out_param runtime_param0
-// CHECK:STDOUT:     %return: ref %.2 = return_slot %return.param
+// CHECK:STDOUT:     %.loc11_17.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:     %.loc11_17.3: <bound method> = bound_method %.loc11_17.1, %.loc11_17.2 [template = constants.%.26]
+// CHECK:STDOUT:     %int.convert_checked: init Core.IntLiteral = call %.loc11_17.3(%.loc11_17.1) [template = constants.%.27]
+// CHECK:STDOUT:     %.loc11_17.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:     %.loc11_17.5: Core.IntLiteral = converted %.loc11_17.1, %.loc11_17.4 [template = constants.%.27]
+// CHECK:STDOUT:     %.loc11_18: type = array_type %.loc11_17.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:     %return.param: ref %.28 = out_param runtime_param0
+// CHECK:STDOUT:     %return: ref %.28 = return_slot %return.param
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [template = constants.%G] {
-// CHECK:STDOUT:     %b.patt: %.2 = binding_pattern b
-// CHECK:STDOUT:     %b.param_patt: %.2 = value_param_pattern %b.patt, runtime_param0
+// CHECK:STDOUT:     %b.patt: %.28 = binding_pattern b
+// CHECK:STDOUT:     %b.param_patt: %.28 = value_param_pattern %b.patt, runtime_param0
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %int.make_type_32.loc13: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:     %.loc13_15: i32 = int_value 3 [template = constants.%.1]
+// CHECK:STDOUT:     %.loc13_15.1: i32 = int_value 3 [template = constants.%.1]
 // CHECK:STDOUT:     %.loc13_10.1: type = value_of_initializer %int.make_type_32.loc13 [template = i32]
 // CHECK:STDOUT:     %.loc13_10.2: type = converted %int.make_type_32.loc13, %.loc13_10.1 [template = i32]
-// CHECK:STDOUT:     %.loc13_16: type = array_type %.loc13_15, i32 [template = constants.%.2]
-// CHECK:STDOUT:     %b.param: %.2 = value_param runtime_param0
-// CHECK:STDOUT:     %b: %.2 = bind_name b, %b.param
+// CHECK:STDOUT:     %.loc13_15.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:     %.loc13_15.3: <bound method> = bound_method %.loc13_15.1, %.loc13_15.2 [template = constants.%.26]
+// CHECK:STDOUT:     %int.convert_checked: init Core.IntLiteral = call %.loc13_15.3(%.loc13_15.1) [template = constants.%.27]
+// CHECK:STDOUT:     %.loc13_15.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:     %.loc13_15.5: Core.IntLiteral = converted %.loc13_15.1, %.loc13_15.4 [template = constants.%.27]
+// CHECK:STDOUT:     %.loc13_16: type = array_type %.loc13_15.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:     %b.param: %.28 = value_param runtime_param0
+// CHECK:STDOUT:     %b: %.28 = bind_name b, %b.param
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F() -> %.2;
+// CHECK:STDOUT: fn @F() -> %.28;
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @G(%b.param_patt: %.2) {
+// CHECK:STDOUT: fn @G(%b.param_patt: %.28) {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %int.make_type_32.loc19: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc19_14.1: type = value_of_initializer %int.make_type_32.loc19 [template = i32]
 // CHECK:STDOUT:   %.loc19_14.2: type = converted %int.make_type_32.loc19, %.loc19_14.1 [template = i32]
-// CHECK:STDOUT:   %.loc19_14.3: type = ptr_type i32 [template = constants.%.4]
-// CHECK:STDOUT:   %pb.var: ref %.4 = var pb
-// CHECK:STDOUT:   %pb: ref %.4 = bind_name pb, %pb.var
-// CHECK:STDOUT:   %b.ref.loc19: %.2 = name_ref b, %b
-// CHECK:STDOUT:   %.loc19_21: i32 = int_value 0 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc19_22.1: ref %.2 = value_as_ref %b.ref.loc19
+// CHECK:STDOUT:   %.loc19_14.3: type = ptr_type i32 [template = constants.%.30]
+// CHECK:STDOUT:   %pb.var: ref %.30 = var pb
+// CHECK:STDOUT:   %pb: ref %.30 = bind_name pb, %pb.var
+// CHECK:STDOUT:   %b.ref.loc19: %.28 = name_ref b, %b
+// CHECK:STDOUT:   %.loc19_21: i32 = int_value 0 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc19_22.1: ref %.28 = value_as_ref %b.ref.loc19
 // CHECK:STDOUT:   %.loc19_22.2: ref i32 = array_index %.loc19_22.1, %.loc19_21
 // CHECK:STDOUT:   %.loc19_22.3: i32 = bind_value %.loc19_22.2
-// CHECK:STDOUT:   %.loc19_18: %.4 = addr_of <error> [template = <error>]
+// CHECK:STDOUT:   %.loc19_18: %.30 = addr_of <error> [template = <error>]
 // CHECK:STDOUT:   assign %pb.var, %.loc19_18
-// CHECK:STDOUT:   %b.ref.loc24: %.2 = name_ref b, %b
-// CHECK:STDOUT:   %.loc24_5: i32 = int_value 0 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc24_6.1: ref %.2 = value_as_ref %b.ref.loc24
+// CHECK:STDOUT:   %b.ref.loc24: %.28 = name_ref b, %b
+// CHECK:STDOUT:   %.loc24_5: i32 = int_value 0 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc24_6.1: ref %.28 = value_as_ref %b.ref.loc24
 // CHECK:STDOUT:   %.loc24_6.2: ref i32 = array_index %.loc24_6.1, %.loc24_5
 // CHECK:STDOUT:   %.loc24_6.3: i32 = bind_value %.loc24_6.2
-// CHECK:STDOUT:   %.loc24_10: i32 = int_value 4 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc24_10: i32 = int_value 4 [template = constants.%.32]
 // CHECK:STDOUT:   assign %.loc24_6.3, %.loc24_10
 // CHECK:STDOUT:   %int.make_type_32.loc32: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc32_14.1: type = value_of_initializer %int.make_type_32.loc32 [template = i32]
 // CHECK:STDOUT:   %.loc32_14.2: type = converted %int.make_type_32.loc32, %.loc32_14.1 [template = i32]
-// CHECK:STDOUT:   %.loc32_14.3: type = ptr_type i32 [template = constants.%.4]
-// CHECK:STDOUT:   %pf.var: ref %.4 = var pf
-// CHECK:STDOUT:   %pf: ref %.4 = bind_name pf, %pf.var
+// CHECK:STDOUT:   %.loc32_14.3: type = ptr_type i32 [template = constants.%.30]
+// CHECK:STDOUT:   %pf.var: ref %.30 = var pf
+// CHECK:STDOUT:   %pf: ref %.30 = bind_name pf, %pf.var
 // CHECK:STDOUT:   %F.ref.loc32: %F.type = name_ref F, file.%F.decl [template = constants.%F]
-// CHECK:STDOUT:   %.loc32_20.1: ref %.2 = temporary_storage
-// CHECK:STDOUT:   %F.call.loc32: init %.2 = call %F.ref.loc32() to %.loc32_20.1
-// CHECK:STDOUT:   %.loc32_23: i32 = int_value 0 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc32_20.2: ref %.2 = temporary %.loc32_20.1, %F.call.loc32
+// CHECK:STDOUT:   %.loc32_20.1: ref %.28 = temporary_storage
+// CHECK:STDOUT:   %F.call.loc32: init %.28 = call %F.ref.loc32() to %.loc32_20.1
+// CHECK:STDOUT:   %.loc32_23: i32 = int_value 0 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc32_20.2: ref %.28 = temporary %.loc32_20.1, %F.call.loc32
 // CHECK:STDOUT:   %.loc32_24.1: ref i32 = array_index %.loc32_20.2, %.loc32_23
 // CHECK:STDOUT:   %.loc32_24.2: i32 = bind_value %.loc32_24.1
-// CHECK:STDOUT:   %.loc32_18: %.4 = addr_of <error> [template = <error>]
+// CHECK:STDOUT:   %.loc32_18: %.30 = addr_of <error> [template = <error>]
 // CHECK:STDOUT:   assign %pf.var, %.loc32_18
 // CHECK:STDOUT:   %F.ref.loc36: %F.type = name_ref F, file.%F.decl [template = constants.%F]
-// CHECK:STDOUT:   %.loc36_4.1: ref %.2 = temporary_storage
-// CHECK:STDOUT:   %F.call.loc36: init %.2 = call %F.ref.loc36() to %.loc36_4.1
-// CHECK:STDOUT:   %.loc36_7: i32 = int_value 0 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc36_4.2: ref %.2 = temporary %.loc36_4.1, %F.call.loc36
+// CHECK:STDOUT:   %.loc36_4.1: ref %.28 = temporary_storage
+// CHECK:STDOUT:   %F.call.loc36: init %.28 = call %F.ref.loc36() to %.loc36_4.1
+// CHECK:STDOUT:   %.loc36_7: i32 = int_value 0 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc36_4.2: ref %.28 = temporary %.loc36_4.1, %F.call.loc36
 // CHECK:STDOUT:   %.loc36_8.1: ref i32 = array_index %.loc36_4.2, %.loc36_7
 // CHECK:STDOUT:   %.loc36_8.2: i32 = bind_value %.loc36_8.1
-// CHECK:STDOUT:   %.loc36_12: i32 = int_value 4 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc36_12: i32 = int_value 4 [template = constants.%.32]
 // CHECK:STDOUT:   assign %.loc36_8.2, %.loc36_12
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 33 - 21
toolchain/check/testdata/index/fail_negative_indexing.carbon

@@ -21,19 +21,26 @@ var d: i32 = c[-10];
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 2 [template]
-// CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
-// CHECK:STDOUT:   %.4: i32 = int_value 42 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.25: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.26: <bound method> = bound_method %.1, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 2 [template]
+// CHECK:STDOUT:   %.28: type = array_type %.27, i32 [template]
+// CHECK:STDOUT:   %.30: i32 = int_value 42 [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (i32, i32) [template]
-// CHECK:STDOUT:   %.5: i32 = int_value 0 [template]
-// CHECK:STDOUT:   %.6: i32 = int_value 1 [template]
-// CHECK:STDOUT:   %array: %.2 = tuple_value (%.4, %.4) [template]
-// CHECK:STDOUT:   %.7: i32 = int_value 10 [template]
+// CHECK:STDOUT:   %.31: i32 = int_value 0 [template]
+// CHECK:STDOUT:   %.32: i32 = int_value 1 [template]
+// CHECK:STDOUT:   %array: %.28 = tuple_value (%.30, %.30) [template]
+// CHECK:STDOUT:   %.33: i32 = int_value 10 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
 // CHECK:STDOUT:     .Int32 = %import_ref.1
-// CHECK:STDOUT:     .Negate = %import_ref.2
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.2
+// CHECK:STDOUT:     .Negate = %import_ref.51
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -47,12 +54,17 @@ var d: i32 = c[-10];
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %int.make_type_32.loc11: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc11_14: i32 = int_value 2 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc11_14.1: i32 = int_value 2 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc11_9.1: type = value_of_initializer %int.make_type_32.loc11 [template = i32]
 // CHECK:STDOUT:   %.loc11_9.2: type = converted %int.make_type_32.loc11, %.loc11_9.1 [template = i32]
-// CHECK:STDOUT:   %.loc11_15: type = array_type %.loc11_14, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %c.var: ref %.2 = var c
-// CHECK:STDOUT:   %c: ref %.2 = bind_name c, %c.var
+// CHECK:STDOUT:   %.loc11_14.2: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc11_14.3: <bound method> = bound_method %.loc11_14.1, %.loc11_14.2 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc11_14.3(%.loc11_14.1) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_14.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_14.5: Core.IntLiteral = converted %.loc11_14.1, %.loc11_14.4 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc11_15: type = array_type %.loc11_14.5, i32 [template = constants.%.28]
+// CHECK:STDOUT:   %c.var: ref %.28 = var c
+// CHECK:STDOUT:   %c: ref %.28 = bind_name c, %c.var
 // CHECK:STDOUT:   %int.make_type_32.loc15: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc15_8.1: type = value_of_initializer %int.make_type_32.loc15 [template = i32]
 // CHECK:STDOUT:   %.loc15_8.2: type = converted %int.make_type_32.loc15, %.loc15_8.1 [template = i32]
@@ -62,20 +74,20 @@ var d: i32 = c[-10];
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc11_20: i32 = int_value 42 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc11_24: i32 = int_value 42 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc11_20: i32 = int_value 42 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc11_24: i32 = int_value 42 [template = constants.%.30]
 // CHECK:STDOUT:   %.loc11_26.1: %tuple.type = tuple_literal (%.loc11_20, %.loc11_24)
-// CHECK:STDOUT:   %.loc11_26.2: i32 = int_value 0 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc11_26.2: i32 = int_value 0 [template = constants.%.31]
 // CHECK:STDOUT:   %.loc11_26.3: ref i32 = array_index file.%c.var, %.loc11_26.2
-// CHECK:STDOUT:   %.loc11_26.4: init i32 = initialize_from %.loc11_20 to %.loc11_26.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc11_26.5: i32 = int_value 1 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc11_26.4: init i32 = initialize_from %.loc11_20 to %.loc11_26.3 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc11_26.5: i32 = int_value 1 [template = constants.%.32]
 // CHECK:STDOUT:   %.loc11_26.6: ref i32 = array_index file.%c.var, %.loc11_26.5
-// CHECK:STDOUT:   %.loc11_26.7: init i32 = initialize_from %.loc11_24 to %.loc11_26.6 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc11_26.8: init %.2 = array_init (%.loc11_26.4, %.loc11_26.7) to file.%c.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc11_27: init %.2 = converted %.loc11_26.1, %.loc11_26.8 [template = constants.%array]
+// CHECK:STDOUT:   %.loc11_26.7: init i32 = initialize_from %.loc11_24 to %.loc11_26.6 [template = constants.%.30]
+// CHECK:STDOUT:   %.loc11_26.8: init %.28 = array_init (%.loc11_26.4, %.loc11_26.7) to file.%c.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc11_27: init %.28 = converted %.loc11_26.1, %.loc11_26.8 [template = constants.%array]
 // CHECK:STDOUT:   assign file.%c.var, %.loc11_27
-// CHECK:STDOUT:   %c.ref: ref %.2 = name_ref c, file.%c
-// CHECK:STDOUT:   %.loc15_17: i32 = int_value 10 [template = constants.%.7]
+// CHECK:STDOUT:   %c.ref: ref %.28 = name_ref c, file.%c
+// CHECK:STDOUT:   %.loc15_17: i32 = int_value 10 [template = constants.%.33]
 // CHECK:STDOUT:   %.loc15_19.1: ref i32 = array_index %c.ref, <error> [template = <error>]
 // CHECK:STDOUT:   %.loc15_19.2: i32 = bind_value %.loc15_19.1
 // CHECK:STDOUT:   assign file.%d.var, %.loc15_19.2

+ 1 - 0
toolchain/check/testdata/interface/fail_todo_define_default_fn_inline.carbon

@@ -102,6 +102,7 @@ interface Interface {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: generic fn @G(@Interface.%Self: %Interface.type) {
+// CHECK:STDOUT: !definition:
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%a.param_patt: i32, %b.param_patt: i32) -> i32 = "int.sadd";
 // CHECK:STDOUT: }

+ 1 - 0
toolchain/check/testdata/interface/fail_todo_define_default_fn_out_of_line.carbon

@@ -183,6 +183,7 @@ fn Interface.C.F[self: Self](U:! type, u: U) -> U { return u; }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: generic fn @.2(@Interface.%Self: %Interface.type) {
+// CHECK:STDOUT: !definition:
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%a.param_patt: i32, %b.param_patt: i32) -> i32 = "int.sadd";
 // CHECK:STDOUT: }

+ 1 - 0
toolchain/check/testdata/interface/todo_define_not_default.carbon

@@ -125,6 +125,7 @@ interface I {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: generic fn @G(@I.%Self: %I.type) {
+// CHECK:STDOUT: !definition:
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%a.param_patt: i32, %b.param_patt: i32) -> i32 = "int.sadd";
 // CHECK:STDOUT: }

+ 26 - 14
toolchain/check/testdata/tuple/access/fail_non_tuple_access.carbon

@@ -32,16 +32,23 @@ fn Main() {
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %.5: i32 = int_value 2 [template]
-// CHECK:STDOUT:   %.6: type = array_type %.5, i32 [template]
-// CHECK:STDOUT:   %.8: i32 = int_value 5 [template]
+// CHECK:STDOUT:   %Convert.type.2: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %Convert.type.15: type = fn_type @Convert.11 [template]
+// CHECK:STDOUT:   %Convert.15: %Convert.type.15 = struct_value () [template]
+// CHECK:STDOUT:   %.29: <witness> = interface_witness (%Convert.15) [template]
+// CHECK:STDOUT:   %.30: <bound method> = bound_method %.5, %Convert.15 [template]
+// CHECK:STDOUT:   %.31: Core.IntLiteral = int_value 2 [template]
+// CHECK:STDOUT:   %.32: type = array_type %.31, i32 [template]
+// CHECK:STDOUT:   %.34: i32 = int_value 5 [template]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (i32, i32) [template]
-// CHECK:STDOUT:   %array: %.6 = tuple_value (%.8, %.8) [template]
+// CHECK:STDOUT:   %array: %.32 = tuple_value (%.34, %.34) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
 // CHECK:STDOUT:     .IndexWith = %import_ref.1
 // CHECK:STDOUT:     .Int32 = %import_ref.6
+// CHECK:STDOUT:     .ImplicitAs = %import_ref.7
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -61,30 +68,35 @@ fn Main() {
 // CHECK:STDOUT:   %.loc16_3: i32 = int_value 0 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc16_5: i32 = int_value 1 [template = constants.%.2]
 // CHECK:STDOUT:   %int.make_type_32.loc18: init type = call constants.%Int32() [template = i32]
-// CHECK:STDOUT:   %.loc18_24: i32 = int_value 2 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc18_24.1: i32 = int_value 2 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc18_19.1: type = value_of_initializer %int.make_type_32.loc18 [template = i32]
 // CHECK:STDOUT:   %.loc18_19.2: type = converted %int.make_type_32.loc18, %.loc18_19.1 [template = i32]
-// CHECK:STDOUT:   %.loc18_25: type = array_type %.loc18_24, i32 [template = constants.%.6]
-// CHECK:STDOUT:   %non_tuple.var: ref %.6 = var non_tuple
-// CHECK:STDOUT:   %non_tuple: ref %.6 = bind_name non_tuple, %non_tuple.var
-// CHECK:STDOUT:   %.loc18_30: i32 = int_value 5 [template = constants.%.8]
-// CHECK:STDOUT:   %.loc18_33: i32 = int_value 5 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc18_24.2: %Convert.type.2 = interface_witness_access constants.%.29, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc18_24.3: <bound method> = bound_method %.loc18_24.1, %.loc18_24.2 [template = constants.%.30]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc18_24.3(%.loc18_24.1) [template = constants.%.31]
+// CHECK:STDOUT:   %.loc18_24.4: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.31]
+// CHECK:STDOUT:   %.loc18_24.5: Core.IntLiteral = converted %.loc18_24.1, %.loc18_24.4 [template = constants.%.31]
+// CHECK:STDOUT:   %.loc18_25: type = array_type %.loc18_24.5, i32 [template = constants.%.32]
+// CHECK:STDOUT:   %non_tuple.var: ref %.32 = var non_tuple
+// CHECK:STDOUT:   %non_tuple: ref %.32 = bind_name non_tuple, %non_tuple.var
+// CHECK:STDOUT:   %.loc18_30: i32 = int_value 5 [template = constants.%.34]
+// CHECK:STDOUT:   %.loc18_33: i32 = int_value 5 [template = constants.%.34]
 // CHECK:STDOUT:   %.loc18_34.1: %tuple.type = tuple_literal (%.loc18_30, %.loc18_33)
 // CHECK:STDOUT:   %.loc18_34.2: i32 = int_value 0 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc18_34.3: ref i32 = array_index %non_tuple.var, %.loc18_34.2
-// CHECK:STDOUT:   %.loc18_34.4: init i32 = initialize_from %.loc18_30 to %.loc18_34.3 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc18_34.4: init i32 = initialize_from %.loc18_30 to %.loc18_34.3 [template = constants.%.34]
 // CHECK:STDOUT:   %.loc18_34.5: i32 = int_value 1 [template = constants.%.2]
 // CHECK:STDOUT:   %.loc18_34.6: ref i32 = array_index %non_tuple.var, %.loc18_34.5
-// CHECK:STDOUT:   %.loc18_34.7: init i32 = initialize_from %.loc18_33 to %.loc18_34.6 [template = constants.%.8]
-// CHECK:STDOUT:   %.loc18_34.8: init %.6 = array_init (%.loc18_34.4, %.loc18_34.7) to %non_tuple.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc18_35: init %.6 = converted %.loc18_34.1, %.loc18_34.8 [template = constants.%array]
+// CHECK:STDOUT:   %.loc18_34.7: init i32 = initialize_from %.loc18_33 to %.loc18_34.6 [template = constants.%.34]
+// CHECK:STDOUT:   %.loc18_34.8: init %.32 = array_init (%.loc18_34.4, %.loc18_34.7) to %non_tuple.var [template = constants.%array]
+// CHECK:STDOUT:   %.loc18_35: init %.32 = converted %.loc18_34.1, %.loc18_34.8 [template = constants.%array]
 // CHECK:STDOUT:   assign %non_tuple.var, %.loc18_35
 // CHECK:STDOUT:   %int.make_type_32.loc22: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc22_14.1: type = value_of_initializer %int.make_type_32.loc22 [template = i32]
 // CHECK:STDOUT:   %.loc22_14.2: type = converted %int.make_type_32.loc22, %.loc22_14.1 [template = i32]
 // CHECK:STDOUT:   %first.var: ref i32 = var first
 // CHECK:STDOUT:   %first: ref i32 = bind_name first, %first.var
-// CHECK:STDOUT:   %non_tuple.ref: ref %.6 = name_ref non_tuple, %non_tuple
+// CHECK:STDOUT:   %non_tuple.ref: ref %.32 = name_ref non_tuple, %non_tuple
 // CHECK:STDOUT:   %.loc22_30: i32 = int_value 0 [template = constants.%.1]
 // CHECK:STDOUT:   assign %first.var, <error>
 // CHECK:STDOUT:   return