Просмотр исходного кода

Add prelude support for implicit conversion between integer literals and sized integer types. (#4525)

In preparation for changing integer literals to be of `IntLiteral` type.
Conversions from the integer literal type are only permitted when the
value fits within the destination type.

For now, if conversion cannot be checked because the source value is a
symbolic constant, produce a symbolic constant representing the
conversion rather than rejecting it.
Richard Smith 1 год назад
Родитель
Сommit
ff530305d1

+ 55 - 0
core/prelude/operators/as.carbon

@@ -4,6 +4,10 @@
 
 package Core library "prelude/operators/as";
 
+// For Core.Int, used below.
+// TODO: Remove this when the below `impl`s are removed.
+import library "prelude/types";
+
 interface As(Dest:! type) {
   fn Convert[self: Self]() -> Dest;
 }
@@ -12,3 +16,54 @@ interface ImplicitAs(Dest:! type) {
   // TODO: extend As(Dest);
   fn Convert[self: Self]() -> Dest;
 }
+
+// TODO: These impls should live with Core.Int, but currently that's a builtin
+// not a class type, so there is no other library these can go in.
+impl IntLiteral() as ImplicitAs(i32) {
+  fn Convert[self: Self]() -> i32 = "int.convert_checked";
+}
+
+impl forall [N:! IntLiteral()] IntLiteral() as ImplicitAs(Int(N)) {
+  fn Convert[self: Self]() -> Int(N) = "int.convert_checked";
+}
+
+impl forall [N:! IntLiteral()] IntLiteral() as ImplicitAs(UInt(N)) {
+  fn Convert[self: Self]() -> UInt(N) = "int.convert_checked";
+}
+
+impl i32 as ImplicitAs(IntLiteral()) {
+  fn Convert[self: Self]() -> IntLiteral() = "int.convert_checked";
+}
+
+impl forall [N:! IntLiteral()] Int(N) as ImplicitAs(IntLiteral()) {
+  fn Convert[self: Self]() -> IntLiteral() = "int.convert_checked";
+}
+
+impl forall [N:! IntLiteral()] UInt(N) as ImplicitAs(IntLiteral()) {
+  fn Convert[self: Self]() -> IntLiteral() = "int.convert_checked";
+}
+
+// TODO: Remove these once ImplicitAs extends As.
+impl IntLiteral() as As(i32) {
+  fn Convert[self: Self]() -> i32 = "int.convert_checked";
+}
+
+impl forall [N:! IntLiteral()] IntLiteral() as As(Int(N)) {
+  fn Convert[self: Self]() -> Int(N) = "int.convert_checked";
+}
+
+impl forall [N:! IntLiteral()] IntLiteral() as As(UInt(N)) {
+  fn Convert[self: Self]() -> UInt(N) = "int.convert_checked";
+}
+
+impl i32 as As(IntLiteral()) {
+  fn Convert[self: Self]() -> IntLiteral() = "int.convert_checked";
+}
+
+impl forall [N:! IntLiteral()] Int(N) as As(IntLiteral()) {
+  fn Convert[self: Self]() -> IntLiteral() = "int.convert_checked";
+}
+
+impl forall [N:! IntLiteral()] UInt(N) as As(IntLiteral()) {
+  fn Convert[self: Self]() -> IntLiteral() = "int.convert_checked";
+}

+ 18 - 17
toolchain/check/call.cpp

@@ -41,7 +41,6 @@ enum class EntityKind : uint8_t {
 static auto ResolveCalleeInCall(Context& context, SemIR::LocId loc_id,
                                 const SemIR::EntityWithParamsBase& entity,
                                 EntityKind entity_kind_for_diagnostic,
-                                SemIR::GenericId entity_generic_id,
                                 SemIR::SpecificId enclosing_specific_id,
                                 SemIR::InstId self_id,
                                 llvm::ArrayRef<SemIR::InstId> arg_ids)
@@ -70,9 +69,9 @@ static auto ResolveCalleeInCall(Context& context, SemIR::LocId loc_id,
 
   // Perform argument deduction.
   auto specific_id = SemIR::SpecificId::Invalid;
-  if (entity_generic_id.is_valid()) {
+  if (entity.generic_id.is_valid()) {
     specific_id = DeduceGenericCallArguments(
-        context, loc_id, entity_generic_id, enclosing_specific_id,
+        context, loc_id, entity.generic_id, enclosing_specific_id,
         entity.implicit_param_patterns_id, entity.param_patterns_id, self_id,
         arg_ids);
     if (!specific_id.is_valid()) {
@@ -90,10 +89,10 @@ static auto PerformCallToGenericClass(Context& context, SemIR::LocId loc_id,
                                       llvm::ArrayRef<SemIR::InstId> arg_ids)
     -> SemIR::InstId {
   const auto& generic_class = context.classes().Get(class_id);
-  auto callee_specific_id = ResolveCalleeInCall(
-      context, loc_id, generic_class, EntityKind::GenericClass,
-      generic_class.generic_id, enclosing_specific_id,
-      /*self_id=*/SemIR::InstId::Invalid, arg_ids);
+  auto callee_specific_id =
+      ResolveCalleeInCall(context, loc_id, generic_class,
+                          EntityKind::GenericClass, enclosing_specific_id,
+                          /*self_id=*/SemIR::InstId::Invalid, arg_ids);
   if (!callee_specific_id) {
     return SemIR::InstId::BuiltinError;
   }
@@ -110,10 +109,10 @@ static auto PerformCallToGenericInterface(
     SemIR::SpecificId enclosing_specific_id,
     llvm::ArrayRef<SemIR::InstId> arg_ids) -> SemIR::InstId {
   const auto& interface = context.interfaces().Get(interface_id);
-  auto callee_specific_id = ResolveCalleeInCall(
-      context, loc_id, interface, EntityKind::GenericInterface,
-      interface.generic_id, enclosing_specific_id,
-      /*self_id=*/SemIR::InstId::Invalid, arg_ids);
+  auto callee_specific_id =
+      ResolveCalleeInCall(context, loc_id, interface,
+                          EntityKind::GenericInterface, enclosing_specific_id,
+                          /*self_id=*/SemIR::InstId::Invalid, arg_ids);
   if (!callee_specific_id) {
     return SemIR::InstId::BuiltinError;
   }
@@ -149,13 +148,13 @@ auto PerformCall(Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id,
       }
     }
   }
-  auto& function = context.functions().Get(callee_function.function_id);
 
   // If the callee is a generic function, determine the generic argument values
   // for the call.
   auto callee_specific_id = ResolveCalleeInCall(
-      context, loc_id, function, EntityKind::Function, function.generic_id,
-      callee_function.enclosing_specific_id, callee_function.self_id, arg_ids);
+      context, loc_id, context.functions().Get(callee_function.function_id),
+      EntityKind::Function, callee_function.enclosing_specific_id,
+      callee_function.self_id, arg_ids);
   if (!callee_specific_id) {
     return SemIR::InstId::BuiltinError;
   }
@@ -173,6 +172,7 @@ auto PerformCall(Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id,
   // If there is a return slot, build storage for the result.
   SemIR::InstId return_slot_arg_id = SemIR::InstId::Invalid;
   SemIR::ReturnTypeInfo return_info = [&] {
+    auto& function = context.functions().Get(callee_function.function_id);
     DiagnosticAnnotationScope annotate_diagnostics(
         &context.emitter(), [&](auto& builder) {
           CARBON_DIAGNOSTIC(IncompleteReturnTypeHere, Note,
@@ -206,9 +206,10 @@ auto PerformCall(Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id,
   }
 
   // Convert the arguments to match the parameters.
-  auto converted_args_id =
-      ConvertCallArgs(context, loc_id, callee_function.self_id, arg_ids,
-                      return_slot_arg_id, function, *callee_specific_id);
+  auto converted_args_id = ConvertCallArgs(
+      context, loc_id, callee_function.self_id, arg_ids, return_slot_arg_id,
+      context.functions().Get(callee_function.function_id),
+      *callee_specific_id);
   auto call_inst_id =
       context.GetOrAddInst<SemIR::Call>(loc_id, {.type_id = return_info.type_id,
                                                  .callee_id = callee_id,

+ 3 - 0
toolchain/check/eval.cpp

@@ -1088,6 +1088,9 @@ static auto MakeConstantForBuiltinCall(Context& context, SemIRLoc loc,
 
     // Integer conversions.
     case SemIR::BuiltinFunctionKind::IntConvertChecked: {
+      if (phase == Phase::Symbolic) {
+        return MakeConstantResult(context, call, phase);
+      }
       return PerformCheckedIntConvert(context, loc, arg_ids[0], call.type_id);
     }
 

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

@@ -52,7 +52,7 @@ var d: [i32; 3] = t2;
 // CHECK:STDOUT:   %tuple.type.1: type = tuple_type (i32, String, String) [template]
 // CHECK:STDOUT:   %.8: i32 = int_value 0 [template]
 // CHECK:STDOUT:   %tuple.type.2: type = tuple_type (type, type, type) [template]
-// CHECK:STDOUT:   %.15: i32 = int_value 2 [template]
+// CHECK:STDOUT:   %.33: 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: }
@@ -145,7 +145,7 @@ var d: [i32; 3] = t2;
 // 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.%.15]
+// CHECK:STDOUT:   %.loc34_23: i32 = int_value 2 [template = constants.%.33]
 // 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

+ 3 - 3
toolchain/check/testdata/as/overloaded.carbon

@@ -44,7 +44,7 @@ let n: i32 = ((4 as i32) as X) as i32;
 // CHECK:STDOUT:   %Convert.type.5: type = fn_type @Convert.1, @As(i32) [template]
 // CHECK:STDOUT:   %.12: <witness> = interface_witness (%Convert.4) [template]
 // CHECK:STDOUT:   %.13: i32 = int_value 4 [template]
-// CHECK:STDOUT:   %.15: <bound method> = bound_method %.13, %Convert.2 [template]
+// CHECK:STDOUT:   %.33: <bound method> = bound_method %.13, %Convert.2 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -54,7 +54,7 @@ let n: i32 = ((4 as i32) as X) as i32;
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.2: %As.type.1 = import_ref Core//prelude/operators/as, inst+7, loaded [template = constants.%As]
+// CHECK:STDOUT:   %import_ref.2: %As.type.1 = import_ref Core//prelude/operators/as, inst+14, loaded [template = constants.%As]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -174,7 +174,7 @@ let n: i32 = ((4 as i32) as X) as i32;
 // CHECK:STDOUT:   %.loc23_21.2: type = converted %int.make_type_32.loc23_21, %.loc23_21.1 [template = i32]
 // CHECK:STDOUT:   %X.ref: type = name_ref X, file.%X.decl [template = constants.%X]
 // CHECK:STDOUT:   %.loc23_26.1: %Convert.type.3 = interface_witness_access constants.%.8, element0 [template = constants.%Convert.2]
-// CHECK:STDOUT:   %.loc23_26.2: <bound method> = bound_method %.loc23_16, %.loc23_26.1 [template = constants.%.15]
+// CHECK:STDOUT:   %.loc23_26.2: <bound method> = bound_method %.loc23_16, %.loc23_26.1 [template = constants.%.33]
 // CHECK:STDOUT:   %.loc23_26.3: ref %X = temporary_storage
 // CHECK:STDOUT:   %Convert.call.loc23_26: init %X = call %.loc23_26.2(%.loc23_16) to %.loc23_26.3
 // CHECK:STDOUT:   %.loc23_26.4: init %X = converted %.loc23_16, %Convert.call.loc23_26

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

@@ -247,7 +247,7 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %DeriveFromNonType: type = class_type @DeriveFromNonType [template]
 // CHECK:STDOUT:   %.1: i32 = int_value 32 [template]
-// CHECK:STDOUT:   %.7: type = ptr_type %DeriveFromNonType [template]
+// CHECK:STDOUT:   %.27: type = ptr_type %DeriveFromNonType [template]
 // CHECK:STDOUT:   %Int32.type: type = fn_type @Int32 [template]
 // CHECK:STDOUT:   %Int32: %Int32.type = struct_value () [template]
 // CHECK:STDOUT:   %AccessMemberWithInvalidBasNonType.type: type = fn_type @AccessMemberWithInvalidBasNonType [template]
@@ -257,7 +257,7 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
 // CHECK:STDOUT:     .ImplicitAs = %import_ref.1
-// CHECK:STDOUT:     .Int32 = %import_ref.7
+// CHECK:STDOUT:     .Int32 = %import_ref.51
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -272,18 +272,18 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %DeriveFromNonType.decl: type = class_decl @DeriveFromNonType [template = constants.%DeriveFromNonType] {} {}
 // CHECK:STDOUT:   %AccessMemberWithInvalidBasNonType.decl: %AccessMemberWithInvalidBasNonType.type = fn_decl @AccessMemberWithInvalidBasNonType [template = constants.%AccessMemberWithInvalidBasNonType] {
-// CHECK:STDOUT:     %p.patt: %.7 = binding_pattern p
-// CHECK:STDOUT:     %p.param_patt: %.7 = value_param_pattern %p.patt, runtime_param0
+// CHECK:STDOUT:     %p.patt: %.27 = binding_pattern p
+// CHECK:STDOUT:     %p.param_patt: %.27 = value_param_pattern %p.patt, runtime_param0
 // CHECK:STDOUT:     %return.patt: i32 = return_slot_pattern
 // CHECK:STDOUT:     %return.param_patt: i32 = out_param_pattern %return.patt, runtime_param1
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %DeriveFromNonType.ref: type = name_ref DeriveFromNonType, file.%DeriveFromNonType.decl [template = constants.%DeriveFromNonType]
-// CHECK:STDOUT:     %.loc15_58: type = ptr_type %DeriveFromNonType [template = constants.%.7]
+// CHECK:STDOUT:     %.loc15_58: type = ptr_type %DeriveFromNonType [template = constants.%.27]
 // CHECK:STDOUT:     %int.make_type_32: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:     %.loc15_64.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:     %.loc15_64.2: type = converted %int.make_type_32, %.loc15_64.1 [template = i32]
-// CHECK:STDOUT:     %p.param: %.7 = value_param runtime_param0
-// CHECK:STDOUT:     %p: %.7 = bind_name p, %p.param
+// CHECK:STDOUT:     %p.param: %.27 = value_param runtime_param0
+// CHECK:STDOUT:     %p: %.27 = bind_name p, %p.param
 // CHECK:STDOUT:     %return.param: ref i32 = out_param runtime_param1
 // CHECK:STDOUT:     %return: ref i32 = return_slot %return.param
 // CHECK:STDOUT:   }
@@ -301,9 +301,9 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT:   has_error
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @AccessMemberWithInvalidBasNonType(%p.param_patt: %.7) -> i32 {
+// CHECK:STDOUT: fn @AccessMemberWithInvalidBasNonType(%p.param_patt: %.27) -> i32 {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %p.ref: %.7 = name_ref p, %p
+// CHECK:STDOUT:   %p.ref: %.27 = name_ref p, %p
 // CHECK:STDOUT:   %.loc15_78: ref %DeriveFromNonType = deref %p.ref
 // CHECK:STDOUT:   %n.ref: <error> = name_ref n, <error> [template = <error>]
 // CHECK:STDOUT:   return <error>
@@ -426,7 +426,7 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
 // CHECK:STDOUT:     .ImplicitAs = %import_ref.1
-// CHECK:STDOUT:     .Int32 = %import_ref.7
+// CHECK:STDOUT:     .Int32 = %import_ref.51
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -635,7 +635,7 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
 // CHECK:STDOUT:     .ImplicitAs = %import_ref.1
-// CHECK:STDOUT:     .Int32 = %import_ref.7
+// CHECK:STDOUT:     .Int32 = %import_ref.51
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }

+ 15 - 15
toolchain/check/testdata/class/fail_derived_to_base.carbon

@@ -61,8 +61,8 @@ fn ConvertIncomplete(p: Incomplete*) -> A2* { return p; }
 // CHECK:STDOUT:   %ConvertUnrelated.type: type = fn_type @ConvertUnrelated [template]
 // CHECK:STDOUT:   %ConvertUnrelated: %ConvertUnrelated.type = struct_value () [template]
 // CHECK:STDOUT:   %Incomplete: type = class_type @Incomplete [template]
-// CHECK:STDOUT:   %.20: type = ptr_type %Incomplete [template]
-// CHECK:STDOUT:   %.21: type = ptr_type %A2 [template]
+// CHECK:STDOUT:   %.40: type = ptr_type %Incomplete [template]
+// CHECK:STDOUT:   %.41: type = ptr_type %A2 [template]
 // CHECK:STDOUT:   %ConvertIncomplete.type: type = fn_type @ConvertIncomplete [template]
 // CHECK:STDOUT:   %ConvertIncomplete: %ConvertIncomplete.type = struct_value () [template]
 // CHECK:STDOUT: }
@@ -107,19 +107,19 @@ fn ConvertIncomplete(p: Incomplete*) -> A2* { return p; }
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Incomplete.decl: type = class_decl @Incomplete [template = constants.%Incomplete] {} {}
 // CHECK:STDOUT:   %ConvertIncomplete.decl: %ConvertIncomplete.type = fn_decl @ConvertIncomplete [template = constants.%ConvertIncomplete] {
-// CHECK:STDOUT:     %p.patt: %.20 = binding_pattern p
-// CHECK:STDOUT:     %p.param_patt: %.20 = value_param_pattern %p.patt, runtime_param0
-// CHECK:STDOUT:     %return.patt: %.21 = return_slot_pattern
-// CHECK:STDOUT:     %return.param_patt: %.21 = out_param_pattern %return.patt, runtime_param1
+// CHECK:STDOUT:     %p.patt: %.40 = binding_pattern p
+// CHECK:STDOUT:     %p.param_patt: %.40 = value_param_pattern %p.patt, runtime_param0
+// 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:     %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [template = constants.%Incomplete]
-// CHECK:STDOUT:     %.loc41_35: type = ptr_type %Incomplete [template = constants.%.20]
+// CHECK:STDOUT:     %.loc41_35: type = ptr_type %Incomplete [template = constants.%.40]
 // CHECK:STDOUT:     %A2.ref: type = name_ref A2, file.%A2.decl [template = constants.%A2]
-// CHECK:STDOUT:     %.loc41_43: type = ptr_type %A2 [template = constants.%.21]
-// CHECK:STDOUT:     %p.param: %.20 = value_param runtime_param0
-// CHECK:STDOUT:     %p: %.20 = bind_name p, %p.param
-// CHECK:STDOUT:     %return.param: ref %.21 = out_param runtime_param1
-// CHECK:STDOUT:     %return: ref %.21 = return_slot %return.param
+// CHECK:STDOUT:     %.loc41_43: type = ptr_type %A2 [template = constants.%.41]
+// CHECK:STDOUT:     %p.param: %.40 = value_param runtime_param0
+// CHECK:STDOUT:     %p: %.40 = bind_name p, %p.param
+// CHECK:STDOUT:     %return.param: ref %.41 = out_param runtime_param1
+// CHECK:STDOUT:     %return: ref %.41 = return_slot %return.param
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -172,10 +172,10 @@ fn ConvertIncomplete(p: Incomplete*) -> A2* { return p; }
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @ConvertIncomplete(%p.param_patt: %.20) -> %.21 {
+// CHECK:STDOUT: fn @ConvertIncomplete(%p.param_patt: %.40) -> %.41 {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %p.ref: %.20 = name_ref p, %p
-// CHECK:STDOUT:   %.loc41_55: %.21 = converted %p.ref, <error> [template = <error>]
+// CHECK:STDOUT:   %p.ref: %.40 = name_ref p, %p
+// CHECK:STDOUT:   %.loc41_55: %.41 = converted %p.ref, <error> [template = <error>]
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 11 - 11
toolchain/check/testdata/class/generic/call.carbon

@@ -363,11 +363,11 @@ class Outer(T:! type) {
 // 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:   %Class.type: type = generic_class_type @Class [template]
 // CHECK:STDOUT:   %Class.1: %Class.type = struct_value () [template]
-// CHECK:STDOUT:   %Class.2: type = class_type @Class, @Class(%T, %N) [symbolic]
+// CHECK:STDOUT:   %Class.2: type = class_type @Class, @Class(%T, %N.1) [symbolic]
 // CHECK:STDOUT:   %.1: type = struct_type {} [template]
 // CHECK:STDOUT:   %.2: <witness> = complete_type_witness %.1 [template]
 // CHECK:STDOUT:   %.3: i32 = int_value 5 [template]
@@ -393,8 +393,8 @@ class Outer(T:! type) {
 // CHECK:STDOUT:   %Class.decl: %Class.type = class_decl @Class [template = constants.%Class.1] {
 // CHECK:STDOUT:     %T.patt.loc4_13.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_13.2 (constants.%T.patt)]
 // CHECK:STDOUT:     %T.param_patt: type = value_param_pattern %T.patt.loc4_13.1, runtime_param<invalid> [symbolic = %T.patt.loc4_13.2 (constants.%T.patt)]
-// CHECK:STDOUT:     %N.patt.loc4_23.1: i32 = symbolic_binding_pattern N, 1 [symbolic = %N.patt.loc4_23.2 (constants.%N.patt)]
-// CHECK:STDOUT:     %N.param_patt: i32 = value_param_pattern %N.patt.loc4_23.1, runtime_param<invalid> [symbolic = %N.patt.loc4_23.2 (constants.%N.patt)]
+// CHECK:STDOUT:     %N.patt.loc4_23.1: i32 = symbolic_binding_pattern N, 1 [symbolic = %N.patt.loc4_23.2 (constants.%N.patt.1)]
+// CHECK:STDOUT:     %N.param_patt: i32 = value_param_pattern %N.patt.loc4_23.1, runtime_param<invalid> [symbolic = %N.patt.loc4_23.2 (constants.%N.patt.1)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %int.make_type_32: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:     %.loc4_27.1: type = value_of_initializer %int.make_type_32 [template = i32]
@@ -402,7 +402,7 @@ class Outer(T:! type) {
 // CHECK:STDOUT:     %T.param: type = value_param runtime_param<invalid>
 // CHECK:STDOUT:     %T.loc4_13.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc4_13.2 (constants.%T)]
 // CHECK:STDOUT:     %N.param: i32 = value_param runtime_param<invalid>
-// CHECK:STDOUT:     %N.loc4_23.1: i32 = bind_symbolic_name N, 1, %N.param [symbolic = %N.loc4_23.2 (constants.%N)]
+// CHECK:STDOUT:     %N.loc4_23.1: i32 = bind_symbolic_name N, 1, %N.param [symbolic = %N.loc4_23.2 (constants.%N.1)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Class.ref: %Class.type = name_ref Class, %Class.decl [template = constants.%Class.1]
 // CHECK:STDOUT:   %.loc15_14: i32 = int_value 5 [template = constants.%.3]
@@ -418,8 +418,8 @@ class Outer(T:! type) {
 // CHECK:STDOUT: generic class @Class(%T.loc4_13.1: type, %N.loc4_23.1: i32) {
 // CHECK:STDOUT:   %T.loc4_13.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_13.2 (constants.%T)]
 // CHECK:STDOUT:   %T.patt.loc4_13.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_13.2 (constants.%T.patt)]
-// CHECK:STDOUT:   %N.loc4_23.2: i32 = bind_symbolic_name N, 1 [symbolic = %N.loc4_23.2 (constants.%N)]
-// CHECK:STDOUT:   %N.patt.loc4_23.2: i32 = symbolic_binding_pattern N, 1 [symbolic = %N.patt.loc4_23.2 (constants.%N.patt)]
+// CHECK:STDOUT:   %N.loc4_23.2: i32 = bind_symbolic_name N, 1 [symbolic = %N.loc4_23.2 (constants.%N.1)]
+// CHECK:STDOUT:   %N.patt.loc4_23.2: i32 = symbolic_binding_pattern N, 1 [symbolic = %N.patt.loc4_23.2 (constants.%N.patt.1)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:
@@ -431,11 +431,11 @@ class Outer(T:! type) {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @Class(constants.%T, constants.%N) {
+// CHECK:STDOUT: specific @Class(constants.%T, constants.%N.1) {
 // CHECK:STDOUT:   %T.loc4_13.2 => constants.%T
 // CHECK:STDOUT:   %T.patt.loc4_13.2 => constants.%T
-// CHECK:STDOUT:   %N.loc4_23.2 => constants.%N
-// CHECK:STDOUT:   %N.patt.loc4_23.2 => constants.%N
+// CHECK:STDOUT:   %N.loc4_23.2 => constants.%N.1
+// CHECK:STDOUT:   %N.patt.loc4_23.2 => constants.%N.1
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: --- call_in_nested_return_type.carbon

+ 3 - 3
toolchain/check/testdata/class/self.carbon

@@ -177,8 +177,8 @@ class Class {
 // CHECK:STDOUT:   %Class: type = class_type @Class [template]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [template]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [template]
-// CHECK:STDOUT:   %.6: type = struct_type {} [template]
-// CHECK:STDOUT:   %.7: <witness> = complete_type_witness %.6 [template]
+// CHECK:STDOUT:   %.26: type = struct_type {} [template]
+// CHECK:STDOUT:   %.27: <witness> = complete_type_witness %.26 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -213,7 +213,7 @@ class Class {
 // CHECK:STDOUT:     %return.param: ref <error> = out_param runtime_param1
 // CHECK:STDOUT:     %return: ref <error> = return_slot %return.param
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.loc12: <witness> = complete_type_witness %.6 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc12: <witness> = complete_type_witness %.26 [template = constants.%.27]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .Self = constants.%Class

+ 34 - 20
toolchain/check/testdata/function/generic/resolve_used.carbon

@@ -17,21 +17,13 @@ fn ErrorIfNIsZero(N:! Core.IntLiteral()) {
   // ensuring we produce an error when doing so. Notionally this error is
   // produced as a result of instantiating the `Core.Int` template, although
   // that's not how we currently model `Core.Int`.
+  // CHECK:STDERR: fail_todo_call_monomorphization_error.carbon:[[@LINE+3]]:10: error: integer type width of 0 is not positive [IntWidthNotPositive]
+  // CHECK:STDERR:   var v: Core.Int(N);
+  // CHECK:STDERR:          ^~~~~~~~~
   var v: Core.Int(N);
 }
 
 fn CallNegative() {
-  // TODO: This should fail during monomorphization once integer literals have
-  // the type `Core.IntLiteral`.
-  // CHECK:STDERR: fail_todo_call_monomorphization_error.carbon:[[@LINE+9]]:3: error: cannot implicitly convert from `i32` to `Core.IntLiteral` [ImplicitAsConversionFailure]
-  // CHECK:STDERR:   ErrorIfNIsZero(0);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~
-  // CHECK:STDERR: fail_todo_call_monomorphization_error.carbon:[[@LINE+6]]:3: note: type `i32` does not implement interface `ImplicitAs(Core.IntLiteral)` [MissingImplInMemberAccessNote]
-  // CHECK:STDERR:   ErrorIfNIsZero(0);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~
-  // CHECK:STDERR: fail_todo_call_monomorphization_error.carbon:[[@LINE-17]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
-  // CHECK:STDERR: fn ErrorIfNIsZero(N:! Core.IntLiteral()) {
-  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ErrorIfNIsZero(0);
 }
 
@@ -39,6 +31,7 @@ fn CallNegative() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [template]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [template]
 // CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [template]
 // CHECK:STDOUT:   %N: Core.IntLiteral = bind_symbolic_name N, 0 [symbolic]
 // CHECK:STDOUT:   %N.patt: Core.IntLiteral = symbolic_binding_pattern N, 0 [symbolic]
@@ -50,6 +43,13 @@ fn CallNegative() {
 // CHECK:STDOUT:   %CallNegative.type: type = fn_type @CallNegative [template]
 // CHECK:STDOUT:   %CallNegative: %CallNegative.type = struct_value () [template]
 // CHECK:STDOUT:   %.2: 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 %.2, %Convert.15 [template]
+// CHECK:STDOUT:   %.27: Core.IntLiteral = int_value 0 [template]
+// CHECK:STDOUT:   %.28: <specific function> = specific_function %ErrorIfNIsZero, @ErrorIfNIsZero(%.27) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -91,18 +91,18 @@ fn CallNegative() {
 // CHECK:STDOUT:   %N.patt.loc4_19.2: Core.IntLiteral = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc4_19.2 (constants.%N.patt)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %.loc9_18: type = int_type signed, %N.loc4_19.2 [symbolic = %.loc9_18 (constants.%.1)]
+// CHECK:STDOUT:   %.loc12_18: type = int_type signed, %N.loc4_19.2 [symbolic = %.loc12_18 (constants.%.1)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%N.param_patt: Core.IntLiteral) {
 // CHECK:STDOUT:   !entry:
-// CHECK:STDOUT:     %Core.ref.loc9: <namespace> = name_ref Core, imports.%Core [template = imports.%Core]
+// CHECK:STDOUT:     %Core.ref.loc12: <namespace> = name_ref Core, imports.%Core [template = imports.%Core]
 // CHECK:STDOUT:     %Int.ref: %Int.type = name_ref Int, imports.%import_ref.2 [template = constants.%Int]
 // CHECK:STDOUT:     %N.ref: Core.IntLiteral = name_ref N, %N.loc4_19.1 [symbolic = %N.loc4_19.2 (constants.%N)]
-// CHECK:STDOUT:     %int.make_type_signed: init type = call %Int.ref(%N.ref) [symbolic = %.loc9_18 (constants.%.1)]
-// CHECK:STDOUT:     %.loc9_20.1: type = value_of_initializer %int.make_type_signed [symbolic = %.loc9_18 (constants.%.1)]
-// CHECK:STDOUT:     %.loc9_20.2: type = converted %int.make_type_signed, %.loc9_20.1 [symbolic = %.loc9_18 (constants.%.1)]
-// CHECK:STDOUT:     %v.var: ref @ErrorIfNIsZero.%.loc9_18 (%.1) = var v
-// CHECK:STDOUT:     %v: ref @ErrorIfNIsZero.%.loc9_18 (%.1) = bind_name v, %v.var
+// CHECK:STDOUT:     %int.make_type_signed: init type = call %Int.ref(%N.ref) [symbolic = %.loc12_18 (constants.%.1)]
+// CHECK:STDOUT:     %.loc12_20.1: type = value_of_initializer %int.make_type_signed [symbolic = %.loc12_18 (constants.%.1)]
+// CHECK:STDOUT:     %.loc12_20.2: type = converted %int.make_type_signed, %.loc12_20.1 [symbolic = %.loc12_18 (constants.%.1)]
+// CHECK:STDOUT:     %v.var: ref @ErrorIfNIsZero.%.loc12_18 (%.1) = var v
+// CHECK:STDOUT:     %v: ref @ErrorIfNIsZero.%.loc12_18 (%.1) = bind_name v, %v.var
 // CHECK:STDOUT:     return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -110,8 +110,14 @@ fn CallNegative() {
 // CHECK:STDOUT: fn @CallNegative() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %ErrorIfNIsZero.ref: %ErrorIfNIsZero.type = name_ref ErrorIfNIsZero, file.%ErrorIfNIsZero.decl [template = constants.%ErrorIfNIsZero]
-// CHECK:STDOUT:   %.loc24_18: i32 = int_value 0 [template = constants.%.2]
-// CHECK:STDOUT:   %.loc24_17: Core.IntLiteral = converted %.loc24_18, <error> [template = <error>]
+// CHECK:STDOUT:   %.loc16_18: i32 = int_value 0 [template = constants.%.2]
+// CHECK:STDOUT:   %.loc16_17.1: %Convert.type.2 = interface_witness_access constants.%.25, element0 [template = constants.%Convert.15]
+// CHECK:STDOUT:   %.loc16_17.2: <bound method> = bound_method %.loc16_18, %.loc16_17.1 [template = constants.%.26]
+// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %.loc16_17.2(%.loc16_18) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc16_17.3: Core.IntLiteral = value_of_initializer %int.convert_checked [template = constants.%.27]
+// CHECK:STDOUT:   %.loc16_17.4: Core.IntLiteral = converted %.loc16_18, %.loc16_17.3 [template = constants.%.27]
+// CHECK:STDOUT:   %.loc16_3: <specific function> = specific_function %ErrorIfNIsZero.ref, @ErrorIfNIsZero(constants.%.27) [template = constants.%.28]
+// CHECK:STDOUT:   %ErrorIfNIsZero.call: init %empty_tuple.type = call %.loc16_3()
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -120,3 +126,11 @@ fn CallNegative() {
 // CHECK:STDOUT:   %N.patt.loc4_19.2 => constants.%N
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: specific @ErrorIfNIsZero(constants.%.27) {
+// CHECK:STDOUT:   %N.loc4_19.2 => constants.%.27
+// CHECK:STDOUT:   %N.patt.loc4_19.2 => constants.%.27
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %.loc12_18 => <error>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:

+ 3 - 3
toolchain/check/testdata/impl/fail_impl_bad_interface.carbon

@@ -65,8 +65,8 @@ impl f64 as type where .Self impls type {}
 // CHECK:STDOUT:     .Core = imports.%Core
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
-// CHECK:STDOUT:   %.loc11: type = converted @impl.%.loc11_13, <error> [template = <error>]
-// CHECK:STDOUT:   impl_decl @impl [template] {} {
+// CHECK:STDOUT:   %.loc11: type = converted @impl.13.%.loc11_13, <error> [template = <error>]
+// CHECK:STDOUT:   impl_decl @impl.13 [template] {} {
 // CHECK:STDOUT:     %int.make_type_32: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:     %.loc11_6.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:     %.loc11_6.2: type = converted %int.make_type_32, %.loc11_6.1 [template = i32]
@@ -74,7 +74,7 @@ impl f64 as type where .Self impls type {}
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: impl @impl: %.loc11_6.2 as <error> {
+// CHECK:STDOUT: impl @impl.13: %.loc11_6.2 as <error> {
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   witness = <error>
 // CHECK:STDOUT: }

+ 2 - 2
toolchain/check/testdata/impl/fail_todo_impl_assoc_const.carbon

@@ -51,7 +51,7 @@ impl bool as I where .T = bool {}
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %I.decl: type = interface_decl @I [template = constants.%I.type.1] {} {}
-// CHECK:STDOUT:   impl_decl @impl [template] {} {
+// CHECK:STDOUT:   impl_decl @impl.13 [template] {} {
 // CHECK:STDOUT:     %bool.make_type.loc23_6: init type = call constants.%Bool() [template = bool]
 // CHECK:STDOUT:     %.loc23_6.1: type = value_of_initializer %bool.make_type.loc23_6 [template = bool]
 // CHECK:STDOUT:     %.loc23_6.2: type = converted %bool.make_type.loc23_6, %.loc23_6.1 [template = bool]
@@ -78,7 +78,7 @@ impl bool as I where .T = bool {}
 // CHECK:STDOUT:   witness = (%T)
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: impl @impl: %.loc23_6.2 as %.loc23_16 {
+// CHECK:STDOUT: impl @impl.13: %.loc23_6.2 as %.loc23_16 {
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   witness = <error>
 // CHECK:STDOUT: }

+ 3 - 3
toolchain/check/testdata/interface/fail_assoc_const_bad_default.carbon

@@ -24,8 +24,8 @@ interface I {
 // CHECK:STDOUT:   %I.type: type = facet_type <@I> [template]
 // CHECK:STDOUT:   %Self.1: %I.type = bind_symbolic_name Self, 0 [symbolic]
 // CHECK:STDOUT:   %.1: i32 = int_value 42 [template]
-// CHECK:STDOUT:   %.7: type = assoc_entity_type %I.type, type [template]
-// CHECK:STDOUT:   %.8: %.7 = assoc_entity element0, @I.%T [template]
+// CHECK:STDOUT:   %.27: type = assoc_entity_type %I.type, type [template]
+// CHECK:STDOUT:   %.28: %.27 = assoc_entity element0, @I.%T [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -50,7 +50,7 @@ interface I {
 // CHECK:STDOUT:   %.loc18_18: i32 = int_value 42 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc18_20.1: type = converted %.loc18_18, <error> [template = <error>]
 // CHECK:STDOUT:   %T: type = assoc_const_decl T [template]
-// CHECK:STDOUT:   %.loc18_20.2: %.7 = assoc_entity element0, %T [template = constants.%.8]
+// CHECK:STDOUT:   %.loc18_20.2: %.27 = assoc_entity element0, %T [template = constants.%.28]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .Self = %Self

+ 3 - 3
toolchain/check/testdata/let/compile_time_bindings.carbon

@@ -639,8 +639,8 @@ impl i32 as Empty {
 // CHECK:STDOUT:   %.2: %.1 = assoc_entity element0, @I.%T [template]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [template]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [template]
-// CHECK:STDOUT:   %.8: type = assoc_entity_type %I.type, %F.type [template]
-// CHECK:STDOUT:   %.9: %.8 = assoc_entity element1, @I.%F.decl [template]
+// CHECK:STDOUT:   %.28: type = assoc_entity_type %I.type, %F.type [template]
+// CHECK:STDOUT:   %.29: %.28 = assoc_entity element1, @I.%F.decl [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -677,7 +677,7 @@ impl i32 as Empty {
 // CHECK:STDOUT:     %return.param: ref <error> = out_param runtime_param0
 // CHECK:STDOUT:     %return: ref <error> = return_slot %return.param
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.loc13: %.8 = assoc_entity element1, %F.decl [template = constants.%.9]
+// CHECK:STDOUT:   %.loc13: %.28 = assoc_entity element1, %F.decl [template = constants.%.29]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .Self = %Self

+ 2 - 2
toolchain/check/testdata/operators/overloaded/eq.carbon

@@ -393,7 +393,7 @@ fn TestLhsBad(a: D, b: C) -> bool {
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {} {}
 // CHECK:STDOUT:   %D.decl: type = class_decl @D [template = constants.%D] {} {}
-// CHECK:STDOUT:   impl_decl @impl [template] {} {
+// CHECK:STDOUT:   impl_decl @impl.1 [template] {} {
 // CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [template = constants.%C]
 // CHECK:STDOUT:     %Core.ref: <namespace> = name_ref Core, imports.%Core [template = imports.%Core]
 // CHECK:STDOUT:     %Eq.ref: type = name_ref Eq, imports.%import_ref.1 [template = constants.%Eq.type]
@@ -440,7 +440,7 @@ fn TestLhsBad(a: D, b: C) -> bool {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: impl @impl: %C.ref as %Eq.ref {
+// CHECK:STDOUT: impl @impl.1: %C.ref as %Eq.ref {
 // CHECK:STDOUT:   %Equal.decl: %Equal.type.1 = fn_decl @Equal.1 [template = constants.%Equal.1] {
 // CHECK:STDOUT:     %self.patt: %C = binding_pattern self
 // CHECK:STDOUT:     %self.param_patt: %C = value_param_pattern %self.patt, runtime_param0

+ 4 - 4
toolchain/check/testdata/operators/overloaded/implicit_as.carbon

@@ -65,7 +65,7 @@ fn Test() {
 // CHECK:STDOUT:   %Test.type: type = fn_type @Test [template]
 // CHECK:STDOUT:   %Test: %Test.type = struct_value () [template]
 // CHECK:STDOUT:   %.14: <specific function> = specific_function %Source, @Source(%X) [template]
-// CHECK:STDOUT:   %.16: <specific function> = specific_function %Source, @Source(i32) [template]
+// CHECK:STDOUT:   %.34: <specific function> = specific_function %Source, @Source(i32) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -75,7 +75,7 @@ fn Test() {
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.2: %ImplicitAs.type.1 = import_ref Core//prelude/operators/as, inst+48, loaded [template = constants.%ImplicitAs]
+// CHECK:STDOUT:   %import_ref.2: %ImplicitAs.type.1 = import_ref Core//prelude/operators/as, inst+55, loaded [template = constants.%ImplicitAs]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -262,7 +262,7 @@ fn Test() {
 // CHECK:STDOUT:   %int.make_type_32: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc31_16.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:   %.loc31_16.2: type = converted %int.make_type_32, %.loc31_16.1 [template = i32]
-// CHECK:STDOUT:   %.loc31_10: <specific function> = specific_function %Source.ref.loc31, @Source(i32) [template = constants.%.16]
+// CHECK:STDOUT:   %.loc31_10: <specific function> = specific_function %Source.ref.loc31, @Source(i32) [template = constants.%.34]
 // CHECK:STDOUT:   %Source.call.loc31: init i32 = call %.loc31_10()
 // CHECK:STDOUT:   %.loc31_16.3: %Convert.type.3 = interface_witness_access constants.%.8, element0 [template = constants.%Convert.2]
 // CHECK:STDOUT:   %.loc31_16.4: <bound method> = bound_method %Source.call.loc31, %.loc31_16.3
@@ -303,6 +303,6 @@ fn Test() {
 // CHECK:STDOUT:   %T.patt.loc27_11.2 => i32
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %.loc27_35.2 => constants.%.16
+// CHECK:STDOUT:   %.loc27_35.2 => constants.%.34
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 3 - 3
toolchain/check/testdata/operators/overloaded/index.carbon

@@ -384,7 +384,7 @@ let x: i32 = c[0];
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {} {}
 // CHECK:STDOUT:   %ElementType.decl: type = class_decl @ElementType [template = constants.%ElementType.1] {} {}
 // CHECK:STDOUT:   %SubscriptType.decl: type = class_decl @SubscriptType [template = constants.%SubscriptType.1] {} {}
-// CHECK:STDOUT:   impl_decl @impl [template] {} {
+// CHECK:STDOUT:   impl_decl @impl.1 [template] {} {
 // CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [template = constants.%C]
 // CHECK:STDOUT:     %Core.ref: <namespace> = name_ref Core, imports.%Core [template = imports.%Core]
 // CHECK:STDOUT:     %IndexWith.ref: %IndexWith.type.1 = name_ref IndexWith, imports.%import_ref.1 [template = constants.%IndexWith]
@@ -396,7 +396,7 @@ let x: i32 = c[0];
 // CHECK:STDOUT:   %ElementType.ref: type = name_ref ElementType, %ElementType.decl [template = constants.%ElementType.1]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: impl @impl: %C.ref as %IndexWith.type {
+// CHECK:STDOUT: impl @impl.1: %C.ref as %IndexWith.type {
 // CHECK:STDOUT:   %At.decl: %At.type.2 = fn_decl @At.2 [template = constants.%At.2] {
 // CHECK:STDOUT:     %self.patt: %C = binding_pattern self
 // CHECK:STDOUT:     %self.param_patt: %C = value_param_pattern %self.patt, runtime_param0
@@ -405,7 +405,7 @@ let x: i32 = c[0];
 // CHECK:STDOUT:     %return.patt: %ElementType.1 = return_slot_pattern
 // CHECK:STDOUT:     %return.param_patt: %ElementType.1 = out_param_pattern %return.patt, runtime_param2
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %Self.ref: type = name_ref Self, @impl.%C.ref [template = constants.%C]
+// CHECK:STDOUT:     %Self.ref: type = name_ref Self, @impl.1.%C.ref [template = constants.%C]
 // CHECK:STDOUT:     %SubscriptType.ref: type = name_ref SubscriptType, file.%SubscriptType.decl [template = constants.%SubscriptType.1]
 // CHECK:STDOUT:     %ElementType.ref: type = name_ref ElementType, file.%ElementType.decl [template = constants.%ElementType.1]
 // CHECK:STDOUT:     %self.param: %C = value_param runtime_param0

+ 4 - 4
toolchain/check/testdata/where_expr/constraints.carbon

@@ -806,7 +806,7 @@ let B: type where .Self impls A = D;
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %default.import = import <invalid>
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {} {}
-// CHECK:STDOUT:   impl_decl @impl [template] {} {
+// CHECK:STDOUT:   impl_decl @impl.1 [template] {} {
 // CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [template = constants.%C]
 // CHECK:STDOUT:     %J.ref: type = name_ref J, imports.%import_ref.1 [template = constants.%J.type.1]
 // CHECK:STDOUT:   }
@@ -834,7 +834,7 @@ let B: type where .Self impls A = D;
 // CHECK:STDOUT:   witness = ()
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: impl @impl: %C.ref as %J.ref {
+// CHECK:STDOUT: impl @impl.1: %C.ref as %J.ref {
 // CHECK:STDOUT:   %.loc8: <witness> = interface_witness () [template = constants.%.3]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
@@ -919,7 +919,7 @@ let B: type where .Self impls A = D;
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %A.decl: type = interface_decl @A [template = constants.%A.type] {} {}
 // CHECK:STDOUT:   %D.decl: type = class_decl @D [template = constants.%D] {} {}
-// CHECK:STDOUT:   impl_decl @impl [template] {} {
+// CHECK:STDOUT:   impl_decl @impl.1 [template] {} {
 // CHECK:STDOUT:     %D.ref: type = name_ref D, file.%D.decl [template = constants.%D]
 // CHECK:STDOUT:     %A.ref: type = name_ref A, file.%A.decl [template = constants.%A.type]
 // CHECK:STDOUT:   }
@@ -939,7 +939,7 @@ let B: type where .Self impls A = D;
 // CHECK:STDOUT:   witness = ()
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: impl @impl: %D.ref as %A.ref {
+// CHECK:STDOUT: impl @impl.1: %D.ref as %A.ref {
 // CHECK:STDOUT:   %.loc6: <witness> = interface_witness () [template = constants.%.3]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members: