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

Make representation of call to a generic class / interface more uniform. (#4050)

Model such calls as call operations, and compute the resulting type in
constant evaluation rather than in type-checking. This means we no
longer form non-constant `ClassType` or `InterfaceType` values, and that
we produce an `<error>` type in the case of bad argument lists rather
than a broken / meaningless `ClassType` / `InterfaceType` that doesn't
actually represent a type. This in turn suppresses some follow-on
diagnostics.
Richard Smith 1 год назад
Родитель
Сommit
d18584c6c2

+ 14 - 11
toolchain/check/call.cpp

@@ -16,6 +16,7 @@ namespace Carbon::Check {
 // Performs a call where the callee is the name of a generic class, such as
 // `Vector(i32)`.
 static auto PerformCallToGenericClass(Context& context, Parse::NodeId node_id,
+                                      SemIR::InstId callee_id,
                                       SemIR::ClassId class_id,
                                       llvm::ArrayRef<SemIR::InstId> arg_ids)
     -> SemIR::InstId {
@@ -26,10 +27,10 @@ static auto PerformCallToGenericClass(Context& context, Parse::NodeId node_id,
       context, node_id, /*self_id=*/SemIR::InstId::Invalid, arg_ids,
       /*return_storage_id=*/SemIR::InstId::Invalid, class_info.decl_id,
       class_info.implicit_param_refs_id, class_info.param_refs_id);
-  return context.AddInst<SemIR::ClassType>(node_id,
-                                           {.type_id = SemIR::TypeId::TypeType,
-                                            .class_id = class_id,
-                                            .args_id = converted_args_id});
+  return context.AddInst<SemIR::Call>(node_id,
+                                      {.type_id = SemIR::TypeId::TypeType,
+                                       .callee_id = callee_id,
+                                       .args_id = converted_args_id});
 }
 
 // Performs a call where the callee is the name of a generic interface, such as
@@ -37,6 +38,7 @@ static auto PerformCallToGenericClass(Context& context, Parse::NodeId node_id,
 // TODO: Refactor with PerformCallToGenericClass.
 static auto PerformCallToGenericInterface(Context& context,
                                           Parse::NodeId node_id,
+                                          SemIR::InstId callee_id,
                                           SemIR::InterfaceId interface_id,
                                           llvm::ArrayRef<SemIR::InstId> arg_ids)
     -> SemIR::InstId {
@@ -47,10 +49,10 @@ static auto PerformCallToGenericInterface(Context& context,
       context, node_id, /*self_id=*/SemIR::InstId::Invalid, arg_ids,
       /*return_storage_id=*/SemIR::InstId::Invalid, interface_info.decl_id,
       interface_info.implicit_param_refs_id, interface_info.param_refs_id);
-  return context.AddInst<SemIR::InterfaceType>(
-      node_id, {.type_id = SemIR::TypeId::TypeType,
-                .interface_id = interface_id,
-                .args_id = converted_args_id});
+  return context.AddInst<SemIR::Call>(node_id,
+                                      {.type_id = SemIR::TypeId::TypeType,
+                                       .callee_id = callee_id,
+                                       .args_id = converted_args_id});
 }
 
 auto PerformCall(Context& context, Parse::NodeId node_id,
@@ -63,12 +65,13 @@ auto PerformCall(Context& context, Parse::NodeId node_id,
         context.types().GetAsInst(context.insts().Get(callee_id).type_id());
     CARBON_KIND_SWITCH(type_inst) {
       case CARBON_KIND(SemIR::GenericClassType generic_class): {
-        return PerformCallToGenericClass(context, node_id,
+        return PerformCallToGenericClass(context, node_id, callee_id,
                                          generic_class.class_id, arg_ids);
       }
       case CARBON_KIND(SemIR::GenericInterfaceType generic_interface): {
-        return PerformCallToGenericInterface(
-            context, node_id, generic_interface.interface_id, arg_ids);
+        return PerformCallToGenericInterface(context, node_id, callee_id,
+                                             generic_interface.interface_id,
+                                             arg_ids);
       }
       default: {
         if (!callee_function.is_error) {

+ 46 - 12
toolchain/check/eval.cpp

@@ -845,25 +845,59 @@ static auto MakeConstantForCall(Context& context, SemIRLoc loc,
 
   auto callee_function =
       SemIR::GetCalleeFunction(context.sem_ir(), call.callee_id);
-  if (!callee_function.function_id.is_valid()) {
+  auto builtin_kind = SemIR::BuiltinFunctionKind::None;
+  if (callee_function.function_id.is_valid()) {
+    // Calls to builtins might be constant.
+    builtin_kind =
+        context.functions().Get(callee_function.function_id).builtin_kind;
+    if (builtin_kind == SemIR::BuiltinFunctionKind::None) {
+      // TODO: Eventually we'll want to treat some kinds of non-builtin
+      // functions as producing constants.
+      return SemIR::ConstantId::NotConstant;
+    }
+  } else {
+    // Calls to non-functions, such as calls to generic entity names, might be
+    // constant.
+  }
+
+  // If the arguments aren't constant, this is not a constant call.
+  if (!ReplaceFieldWithConstantValue(context, &call, &SemIR::Call::args_id,
+                                     &phase)) {
+    return SemIR::ConstantId::NotConstant;
+  }
+  if (phase == Phase::UnknownDueToError) {
     return SemIR::ConstantId::Error;
   }
-  const auto& function = context.functions().Get(callee_function.function_id);
 
   // Handle calls to builtins.
-  if (function.builtin_kind != SemIR::BuiltinFunctionKind::None) {
-    if (!ReplaceFieldWithConstantValue(context, &call, &SemIR::Call::args_id,
-                                       &phase)) {
-      return SemIR::ConstantId::NotConstant;
-    }
-    if (phase == Phase::UnknownDueToError) {
-      return SemIR::ConstantId::Error;
-    }
-    return MakeConstantForBuiltinCall(context, loc, call, function.builtin_kind,
+  if (builtin_kind != SemIR::BuiltinFunctionKind::None) {
+    return MakeConstantForBuiltinCall(context, loc, call, builtin_kind,
                                       context.inst_blocks().Get(call.args_id),
                                       phase);
   }
-  return SemIR::ConstantId::NotConstant;
+
+  // Look at the type of the callee for special cases: calls to generic class
+  // and generic interface types.
+  auto type_inst =
+      context.types().GetAsInst(context.insts().Get(call.callee_id).type_id());
+  CARBON_KIND_SWITCH(type_inst) {
+    case CARBON_KIND(SemIR::GenericClassType generic_class):
+      return MakeConstantResult(
+          context,
+          SemIR::ClassType{.type_id = call.type_id,
+                           .class_id = generic_class.class_id,
+                           .args_id = call.args_id},
+          phase);
+    case CARBON_KIND(SemIR::GenericInterfaceType generic_interface):
+      return MakeConstantResult(
+          context,
+          SemIR::InterfaceType{.type_id = call.type_id,
+                               .interface_id = generic_interface.interface_id,
+                               .args_id = call.args_id},
+          phase);
+    default:
+      return SemIR::ConstantId::NotConstant;
+  }
 }
 
 auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)

+ 22 - 15
toolchain/check/testdata/class/generic/call.carbon

@@ -108,14 +108,18 @@ var a: Class(5, i32*);
 // CHECK:STDOUT:   %.loc6_17.2: type = converted %int.make_type_32.loc6, %.loc6_17.1 [template = i32]
 // CHECK:STDOUT:   %.loc6_17.3: type = ptr_type i32 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc6_20: i32 = int_literal 5 [template = constants.%.4]
-// CHECK:STDOUT:   %Class.loc6: type = class_type @Class, (%.loc6_17.3, %.loc6_20) [template = constants.%Class.3]
+// CHECK:STDOUT:   %.loc6_13: init type = call %Class.ref.loc6(%.loc6_17.3, %.loc6_20) [template = constants.%Class.3]
+// CHECK:STDOUT:   %.loc6_21.1: type = value_of_initializer %.loc6_13 [template = constants.%Class.3]
+// CHECK:STDOUT:   %.loc6_21.2: type = converted %.loc6_13, %.loc6_21.1 [template = constants.%Class.3]
 // CHECK:STDOUT:   %a.var: ref %Class.3 = var a
 // CHECK:STDOUT:   %a: ref %Class.3 = bind_name a, %a.var
 // CHECK:STDOUT:   %Class.ref.loc9: %Class.type = name_ref Class, %Class.decl [template = constants.%Class.1]
 // CHECK:STDOUT:   %.loc9_15: %.1 = tuple_literal ()
 // CHECK:STDOUT:   %.loc9_18: i32 = int_literal 0 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc9_13: type = converted %.loc9_15, constants.%.1 [template = constants.%.1]
-// CHECK:STDOUT:   %Class.loc9: type = class_type @Class, (%.loc9_13, %.loc9_18) [template = constants.%Class.4]
+// CHECK:STDOUT:   %.loc9_13.1: type = converted %.loc9_15, constants.%.1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc9_13.2: init type = call %Class.ref.loc9(%.loc9_13.1, %.loc9_18) [template = constants.%Class.4]
+// CHECK:STDOUT:   %.loc9_19.1: type = value_of_initializer %.loc9_13.2 [template = constants.%Class.4]
+// CHECK:STDOUT:   %.loc9_19.2: type = converted %.loc9_13.2, %.loc9_19.1 [template = constants.%Class.4]
 // CHECK:STDOUT:   %b.var: ref %Class.4 = var b
 // CHECK:STDOUT:   %b: ref %Class.4 = bind_name b, %b.var
 // CHECK:STDOUT: }
@@ -140,7 +144,6 @@ var a: Class(5, i32*);
 // CHECK:STDOUT:   %Class.2: type = class_type @Class [template]
 // CHECK:STDOUT:   %.2: type = struct_type {} [template]
 // CHECK:STDOUT:   %.3: type = ptr_type i32 [template]
-// CHECK:STDOUT:   %.4: type = ptr_type %.2 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -166,9 +169,11 @@ var a: Class(5, i32*);
 // CHECK:STDOUT:   %.loc13_17.1: type = value_of_initializer %int.make_type_32.loc13 [template = i32]
 // CHECK:STDOUT:   %.loc13_17.2: type = converted %int.make_type_32.loc13, %.loc13_17.1 [template = i32]
 // CHECK:STDOUT:   %.loc13_17.3: type = ptr_type i32 [template = constants.%.3]
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class.2]
-// CHECK:STDOUT:   %a.var: ref %Class.2 = var a
-// CHECK:STDOUT:   %a: ref %Class.2 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc13_13: init type = call %Class.ref(<invalid>) [template = <error>]
+// CHECK:STDOUT:   %.loc13_18.1: type = value_of_initializer %.loc13_13 [template = <error>]
+// CHECK:STDOUT:   %.loc13_18.2: type = converted %.loc13_13, %.loc13_18.1 [template = <error>]
+// CHECK:STDOUT:   %a.var: ref <error> = var a
+// CHECK:STDOUT:   %a: ref <error> = bind_name a, %a.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
@@ -193,7 +198,6 @@ var a: Class(5, i32*);
 // CHECK:STDOUT:   %.3: type = ptr_type i32 [template]
 // CHECK:STDOUT:   %.4: i32 = int_literal 1 [template]
 // CHECK:STDOUT:   %.5: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.6: type = ptr_type %.2 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -221,9 +225,11 @@ var a: Class(5, i32*);
 // CHECK:STDOUT:   %.loc13_17.3: type = ptr_type i32 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc13_20: i32 = int_literal 1 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc13_23: i32 = int_literal 2 [template = constants.%.5]
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class.2]
-// CHECK:STDOUT:   %a.var: ref %Class.2 = var a
-// CHECK:STDOUT:   %a: ref %Class.2 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc13_13: init type = call %Class.ref(<invalid>) [template = <error>]
+// CHECK:STDOUT:   %.loc13_24.1: type = value_of_initializer %.loc13_13 [template = <error>]
+// CHECK:STDOUT:   %.loc13_24.2: type = converted %.loc13_13, %.loc13_24.1 [template = <error>]
+// CHECK:STDOUT:   %a.var: ref <error> = var a
+// CHECK:STDOUT:   %a: ref <error> = bind_name a, %a.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
@@ -247,7 +253,6 @@ var a: Class(5, i32*);
 // CHECK:STDOUT:   %.2: type = struct_type {} [template]
 // CHECK:STDOUT:   %.3: i32 = int_literal 5 [template]
 // CHECK:STDOUT:   %.4: type = ptr_type i32 [template]
-// CHECK:STDOUT:   %.5: type = ptr_type %.2 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -274,9 +279,11 @@ var a: Class(5, i32*);
 // CHECK:STDOUT:   %.loc12_20.1: type = value_of_initializer %int.make_type_32.loc12 [template = i32]
 // CHECK:STDOUT:   %.loc12_20.2: type = converted %int.make_type_32.loc12, %.loc12_20.1 [template = i32]
 // CHECK:STDOUT:   %.loc12_20.3: type = ptr_type i32 [template = constants.%.4]
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class.2]
-// CHECK:STDOUT:   %a.var: ref %Class.2 = var a
-// CHECK:STDOUT:   %a: ref %Class.2 = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc12_13: init type = call %Class.ref(<invalid>) [template = <error>]
+// CHECK:STDOUT:   %.loc12_21.1: type = value_of_initializer %.loc12_13 [template = <error>]
+// CHECK:STDOUT:   %.loc12_21.2: type = converted %.loc12_13, %.loc12_21.1 [template = <error>]
+// CHECK:STDOUT:   %a.var: ref <error> = var a
+// CHECK:STDOUT:   %a: ref <error> = bind_name a, %a.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {

+ 3 - 1
toolchain/check/testdata/class/generic/fail_todo_use.carbon

@@ -120,7 +120,9 @@ fn Run() -> i32 {
 // CHECK:STDOUT:   %int.make_type_32: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc25_15.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:   %.loc25_15.2: type = converted %int.make_type_32, %.loc25_15.1 [template = i32]
-// CHECK:STDOUT:   %Class: type = class_type @Class, (%.loc25_15.2) [template = constants.%Class.3]
+// CHECK:STDOUT:   %.loc25_15.3: init type = call %Class.ref(%.loc25_15.2) [template = constants.%Class.3]
+// CHECK:STDOUT:   %.loc25_19.1: type = value_of_initializer %.loc25_15.3 [template = constants.%Class.3]
+// CHECK:STDOUT:   %.loc25_19.2: type = converted %.loc25_15.3, %.loc25_19.1 [template = constants.%Class.3]
 // CHECK:STDOUT:   %v.var: ref %Class.3 = var v
 // CHECK:STDOUT:   %v: ref %Class.3 = bind_name v, %v.var
 // CHECK:STDOUT:   %.loc25_29: i32 = int_literal 0 [template = constants.%.7]

+ 20 - 10
toolchain/check/testdata/class/generic/import.carbon

@@ -135,7 +135,9 @@ class Class(U:! type) {
 // CHECK:STDOUT:     %int.make_type_32: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:     %.loc11_24.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:     %.loc11_24.2: type = converted %int.make_type_32, %.loc11_24.1 [template = i32]
-// CHECK:STDOUT:     %CompleteClass: type = class_type @CompleteClass, (%.loc11_24.2) [template = constants.%CompleteClass.3]
+// CHECK:STDOUT:     %.loc11_24.3: init type = call %CompleteClass.ref(%.loc11_24.2) [template = constants.%CompleteClass.3]
+// CHECK:STDOUT:     %.loc11_28.1: type = value_of_initializer %.loc11_24.3 [template = constants.%CompleteClass.3]
+// CHECK:STDOUT:     %.loc11_28.2: type = converted %.loc11_24.3, %.loc11_28.1 [template = constants.%CompleteClass.3]
 // CHECK:STDOUT:     @F.2.%return: ref %CompleteClass.3 = var <return slot>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -203,7 +205,7 @@ class Class(U:! type) {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %import_ref.1: %Class.type = import_ref ir0, inst+5, loaded [template = constants.%Class.1]
 // CHECK:STDOUT:   %import_ref.2: %CompleteClass.type = import_ref ir0, inst+12, loaded [template = constants.%CompleteClass.1]
-// CHECK:STDOUT:   %import_ref.3: %F.type = import_ref ir0, inst+48, loaded [template = constants.%F]
+// CHECK:STDOUT:   %import_ref.3: %F.type = import_ref ir0, inst+50, loaded [template = constants.%F]
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %Class.decl: %Class.type = class_decl @Class [template = constants.%Class.1] {
 // CHECK:STDOUT:     %T.loc4_13.1: type = param T
@@ -218,7 +220,9 @@ class Class(U:! type) {
 // CHECK:STDOUT:     %int.make_type_32: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:     %.loc8_24.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:     %.loc8_24.2: type = converted %int.make_type_32, %.loc8_24.1 [template = i32]
-// CHECK:STDOUT:     %CompleteClass: type = class_type @CompleteClass, (%.loc8_24.2) [template = constants.%CompleteClass.3]
+// CHECK:STDOUT:     %.loc8_24.3: init type = call %CompleteClass.ref(%.loc8_24.2) [template = constants.%CompleteClass.3]
+// CHECK:STDOUT:     %.loc8_28.1: type = value_of_initializer %.loc8_24.3 [template = constants.%CompleteClass.3]
+// CHECK:STDOUT:     %.loc8_28.2: type = converted %.loc8_24.3, %.loc8_28.1 [template = constants.%CompleteClass.3]
 // CHECK:STDOUT:     @F.%return: ref %CompleteClass.3 = var <return slot>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -283,7 +287,7 @@ class Class(U:! type) {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %import_ref.1 = import_ref ir1, inst+5, unloaded
 // CHECK:STDOUT:   %import_ref.2: %CompleteClass.type = import_ref ir1, inst+12, loaded [template = constants.%CompleteClass.1]
-// CHECK:STDOUT:   %import_ref.3: %F.type.1 = import_ref ir1, inst+48, loaded [template = constants.%F.1]
+// CHECK:STDOUT:   %import_ref.3: %F.type.1 = import_ref ir1, inst+50, loaded [template = constants.%F.1]
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %import_ref.4: %Int32.type = import_ref ir4, inst+3, loaded [template = constants.%Int32]
 // CHECK:STDOUT:   %Use.decl: %Use.type = fn_decl @Use [template = constants.%Use] {
@@ -313,7 +317,9 @@ class Class(U:! type) {
 // CHECK:STDOUT:   %int.make_type_32: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc6_23.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:   %.loc6_23.2: type = converted %int.make_type_32, %.loc6_23.1 [template = i32]
-// CHECK:STDOUT:   %CompleteClass: type = class_type @CompleteClass, (%.loc6_23.2) [template = constants.%CompleteClass.3]
+// CHECK:STDOUT:   %.loc6_23.3: init type = call %CompleteClass.ref(%.loc6_23.2) [template = constants.%CompleteClass.3]
+// CHECK:STDOUT:   %.loc6_27.1: type = value_of_initializer %.loc6_23.3 [template = constants.%CompleteClass.3]
+// CHECK:STDOUT:   %.loc6_27.2: type = converted %.loc6_23.3, %.loc6_27.1 [template = constants.%CompleteClass.3]
 // CHECK:STDOUT:   %v.var: ref %CompleteClass.3 = var v
 // CHECK:STDOUT:   %v: ref %CompleteClass.3 = bind_name v, %v.var
 // CHECK:STDOUT:   %F.ref.loc6: %F.type.1 = name_ref F, file.%import_ref.3 [template = constants.%F.1]
@@ -362,7 +368,7 @@ class Class(U:! type) {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %import_ref.1 = import_ref ir1, inst+5, unloaded
 // CHECK:STDOUT:   %import_ref.2: %CompleteClass.type = import_ref ir1, inst+12, loaded [template = constants.%CompleteClass.1]
-// CHECK:STDOUT:   %import_ref.3: %F.type = import_ref ir1, inst+48, loaded [template = constants.%F]
+// CHECK:STDOUT:   %import_ref.3: %F.type = import_ref ir1, inst+50, loaded [template = constants.%F]
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %import_ref.4: %Int32.type = import_ref ir4, inst+3, loaded [template = constants.%Int32]
 // CHECK:STDOUT:   %Use.decl: %Use.type = fn_decl @Use [template = constants.%Use] {
@@ -392,7 +398,9 @@ class Class(U:! type) {
 // CHECK:STDOUT:   %int.make_type_32: init type = call constants.%Int32() [template = i32]
 // CHECK:STDOUT:   %.loc6_23.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:   %.loc6_23.2: type = converted %int.make_type_32, %.loc6_23.1 [template = i32]
-// CHECK:STDOUT:   %CompleteClass: type = class_type @CompleteClass, (%.loc6_23.2) [template = constants.%CompleteClass.3]
+// CHECK:STDOUT:   %.loc6_23.3: init type = call %CompleteClass.ref(%.loc6_23.2) [template = constants.%CompleteClass.3]
+// CHECK:STDOUT:   %.loc6_27.1: type = value_of_initializer %.loc6_23.3 [template = constants.%CompleteClass.3]
+// CHECK:STDOUT:   %.loc6_27.2: type = converted %.loc6_23.3, %.loc6_27.1 [template = constants.%CompleteClass.3]
 // CHECK:STDOUT:   %v.var: ref %CompleteClass.3 = var v
 // CHECK:STDOUT:   %v: ref %CompleteClass.3 = bind_name v, %v.var
 // CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%import_ref.3 [template = constants.%F]
@@ -438,7 +446,7 @@ class Class(U:! type) {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %import_ref.1 = import_ref ir1, inst+5, unloaded
 // CHECK:STDOUT:   %import_ref.2: %CompleteClass.type = import_ref ir1, inst+12, loaded [template = constants.%CompleteClass.1]
-// CHECK:STDOUT:   %import_ref.3: %F.type = import_ref ir1, inst+48, loaded [template = constants.%F]
+// CHECK:STDOUT:   %import_ref.3: %F.type = import_ref ir1, inst+50, loaded [template = constants.%F]
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %Use.decl: %Use.type = fn_decl @Use [template = constants.%Use] {}
 // CHECK:STDOUT:   %import_ref.4 = import_ref ir1, inst+15, unloaded
@@ -461,7 +469,9 @@ class Class(U:! type) {
 // CHECK:STDOUT:   %.loc11_27.1: type = value_of_initializer %int.make_type_32 [template = i32]
 // CHECK:STDOUT:   %.loc11_27.2: type = converted %int.make_type_32, %.loc11_27.1 [template = i32]
 // CHECK:STDOUT:   %.loc11_27.3: type = ptr_type i32 [template = constants.%.3]
-// CHECK:STDOUT:   %CompleteClass: type = class_type @CompleteClass, (%.loc11_27.3) [template = constants.%CompleteClass.3]
+// CHECK:STDOUT:   %.loc11_23: init type = call %CompleteClass.ref(%.loc11_27.3) [template = constants.%CompleteClass.3]
+// CHECK:STDOUT:   %.loc11_28.1: type = value_of_initializer %.loc11_23 [template = constants.%CompleteClass.3]
+// CHECK:STDOUT:   %.loc11_28.2: type = converted %.loc11_23, %.loc11_28.1 [template = constants.%CompleteClass.3]
 // CHECK:STDOUT:   %v.var: ref %CompleteClass.3 = var v
 // CHECK:STDOUT:   %v: ref %CompleteClass.3 = bind_name v, %v.var
 // CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%import_ref.3 [template = constants.%F]
@@ -498,7 +508,7 @@ class Class(U:! type) {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %import_ref.1: %Class.type = import_ref ir0, inst+5, loaded [template = constants.%Class.1]
 // CHECK:STDOUT:   %import_ref.2 = import_ref ir0, inst+12, unloaded
-// CHECK:STDOUT:   %import_ref.3 = import_ref ir0, inst+48, unloaded
+// CHECK:STDOUT:   %import_ref.3 = import_ref ir0, inst+50, unloaded
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %.decl: %.type = class_decl @.1 [template = constants.%.2] {
 // CHECK:STDOUT:     %U.loc9_13.1: type = param U

+ 3 - 1
toolchain/check/testdata/impl/fail_extend_impl_forall.carbon

@@ -84,12 +84,14 @@ class C {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
+// CHECK:STDOUT:   %.loc19_54.1: type = value_of_initializer %.loc19_52 [symbolic = constants.%.4]
+// CHECK:STDOUT:   %.loc19_54.2: type = converted %.loc19_52, %.loc19_54.1 [symbolic = constants.%.4]
 // CHECK:STDOUT:   impl_decl @impl {
 // CHECK:STDOUT:     %T.loc19_23.1: type = param T
 // CHECK:STDOUT:     %T.loc19_23.2: type = bind_symbolic_name T 0, %T.loc19_23.1 [symbolic = constants.%T]
 // CHECK:STDOUT:     %GenericInterface.ref: %GenericInterface.type = name_ref GenericInterface, file.%GenericInterface.decl [template = constants.%GenericInterface]
 // CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc19_23.2 [symbolic = constants.%T]
-// CHECK:STDOUT:     %.loc19: type = interface_type @GenericInterface, (%T.ref) [symbolic = constants.%.4]
+// CHECK:STDOUT:     %.loc19_52: init type = call %GenericInterface.ref(%T.ref) [symbolic = constants.%.4]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:

+ 18 - 6
toolchain/check/testdata/interface/no_prelude/generic.carbon

@@ -124,14 +124,18 @@ fn G(T:! Generic(B)) {
 // CHECK:STDOUT:   %Receive.decl: %Receive.type = fn_decl @Receive [template = constants.%Receive] {
 // CHECK:STDOUT:     %Simple.ref.loc24: %Simple.type = name_ref Simple, %Simple.decl [template = constants.%Simple]
 // CHECK:STDOUT:     %C.ref.loc24: type = name_ref C, %C.decl [template = constants.%C]
-// CHECK:STDOUT:     %.loc24: type = interface_type @Simple, (%C.ref.loc24) [template = constants.%.5]
+// CHECK:STDOUT:     %.loc24_22: init type = call %Simple.ref.loc24(%C.ref.loc24) [template = constants.%.5]
+// CHECK:STDOUT:     %.loc24_24.1: type = value_of_initializer %.loc24_22 [template = constants.%.5]
+// CHECK:STDOUT:     %.loc24_24.2: type = converted %.loc24_22, %.loc24_24.1 [template = constants.%.5]
 // CHECK:STDOUT:     %T.loc24_12.1: %.5 = param T
 // CHECK:STDOUT:     @Receive.%T: %.5 = bind_symbolic_name T 0, %T.loc24_12.1 [symbolic = constants.%T.2]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Pass.decl: %Pass.type = fn_decl @Pass [template = constants.%Pass] {
 // CHECK:STDOUT:     %Simple.ref.loc25: %Simple.type = name_ref Simple, %Simple.decl [template = constants.%Simple]
 // CHECK:STDOUT:     %C.ref.loc25: type = name_ref C, %C.decl [template = constants.%C]
-// CHECK:STDOUT:     %.loc25: type = interface_type @Simple, (%C.ref.loc25) [template = constants.%.5]
+// CHECK:STDOUT:     %.loc25_19: init type = call %Simple.ref.loc25(%C.ref.loc25) [template = constants.%.5]
+// CHECK:STDOUT:     %.loc25_21.1: type = value_of_initializer %.loc25_19 [template = constants.%.5]
+// CHECK:STDOUT:     %.loc25_21.2: type = converted %.loc25_19, %.loc25_21.1 [template = constants.%.5]
 // CHECK:STDOUT:     %T.loc25_9.1: %.5 = param T
 // CHECK:STDOUT:     @Pass.%T: %.5 = bind_symbolic_name T 0, %T.loc25_9.1 [symbolic = constants.%T.2]
 // CHECK:STDOUT:   }
@@ -186,15 +190,19 @@ fn G(T:! Generic(B)) {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
+// CHECK:STDOUT:   %.loc14_19.1: type = value_of_initializer %.loc14_17 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc14_19.2: type = converted %.loc14_17, %.loc14_19.1 [template = constants.%.5]
 // CHECK:STDOUT:   impl_decl @impl.1 {
 // CHECK:STDOUT:     %Simple.ref: %Simple.type = name_ref Simple, file.%Simple.decl [template = constants.%Simple]
 // CHECK:STDOUT:     %C.ref.loc14: type = name_ref C, file.%C.decl [template = constants.%C]
-// CHECK:STDOUT:     %.loc14: type = interface_type @Simple, (%C.ref.loc14) [template = constants.%.5]
+// CHECK:STDOUT:     %.loc14_17: init type = call %Simple.ref(%C.ref.loc14) [template = constants.%.5]
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc15_24.1: type = value_of_initializer %.loc15_22 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc15_24.2: type = converted %.loc15_22, %.loc15_24.1 [template = constants.%.7]
 // CHECK:STDOUT:   impl_decl @impl.2 {
 // CHECK:STDOUT:     %WithAssocFn.ref: %WithAssocFn.type = name_ref WithAssocFn, file.%WithAssocFn.decl [template = constants.%WithAssocFn]
 // CHECK:STDOUT:     %C.ref.loc15: type = name_ref C, file.%C.decl [template = constants.%C]
-// CHECK:STDOUT:     %.loc15: type = interface_type @WithAssocFn, (%C.ref.loc15) [template = constants.%.7]
+// CHECK:STDOUT:     %.loc15_22: init type = call %WithAssocFn.ref(%C.ref.loc15) [template = constants.%.7]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
@@ -259,14 +267,18 @@ fn G(T:! Generic(B)) {
 // CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [template = constants.%F] {
 // CHECK:STDOUT:     %Generic.ref.loc9: %Generic.type = name_ref Generic, %Generic.decl [template = constants.%Generic]
 // CHECK:STDOUT:     %A.ref: type = name_ref A, %A.decl [template = constants.%A]
-// CHECK:STDOUT:     %.loc9: type = interface_type @Generic, (%A.ref) [template = constants.%.3]
+// CHECK:STDOUT:     %.loc9_17: init type = call %Generic.ref.loc9(%A.ref) [template = constants.%.3]
+// CHECK:STDOUT:     %.loc9_19.1: type = value_of_initializer %.loc9_17 [template = constants.%.3]
+// CHECK:STDOUT:     %.loc9_19.2: type = converted %.loc9_17, %.loc9_19.1 [template = constants.%.3]
 // CHECK:STDOUT:     %T.loc9_6.1: %.3 = param T
 // CHECK:STDOUT:     @F.%T: %.3 = bind_symbolic_name T 0, %T.loc9_6.1 [symbolic = constants.%T.2]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [template = constants.%G] {
 // CHECK:STDOUT:     %Generic.ref.loc10: %Generic.type = name_ref Generic, %Generic.decl [template = constants.%Generic]
 // CHECK:STDOUT:     %B.ref: type = name_ref B, %B.decl [template = constants.%B]
-// CHECK:STDOUT:     %.loc10: type = interface_type @Generic, (%B.ref) [template = constants.%.4]
+// CHECK:STDOUT:     %.loc10_17: init type = call %Generic.ref.loc10(%B.ref) [template = constants.%.4]
+// CHECK:STDOUT:     %.loc10_19.1: type = value_of_initializer %.loc10_17 [template = constants.%.4]
+// CHECK:STDOUT:     %.loc10_19.2: type = converted %.loc10_17, %.loc10_19.1 [template = constants.%.4]
 // CHECK:STDOUT:     %T.loc10_6.1: %.4 = param T
 // CHECK:STDOUT:     @G.%T: %.4 = bind_symbolic_name T 0, %T.loc10_6.1 [symbolic = constants.%T.3]
 // CHECK:STDOUT:   }

+ 3 - 1
toolchain/check/testdata/interface/no_prelude/generic_import.carbon

@@ -93,11 +93,13 @@ impl C as AddWith(C) {
 // CHECK:STDOUT:   %import_ref.2 = import_ref ir1, inst+8, unloaded
 // CHECK:STDOUT:   %import_ref.3 = import_ref ir1, inst+14, unloaded
 // CHECK:STDOUT:   %import_ref.4: %F.type.2 = import_ref ir1, inst+10, loaded [template = constants.%F.2]
+// CHECK:STDOUT:   %.loc7_20.1: type = value_of_initializer %.loc7_18 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc7_20.2: type = converted %.loc7_18, %.loc7_20.1 [template = constants.%.3]
 // CHECK:STDOUT:   impl_decl @impl {
 // CHECK:STDOUT:     %C.ref.loc7_6: type = name_ref C, %C.decl [template = constants.%C]
 // CHECK:STDOUT:     %AddWith.ref: %AddWith.type = name_ref AddWith, %import_ref.1 [template = constants.%AddWith.1]
 // CHECK:STDOUT:     %C.ref.loc7_19: type = name_ref C, %C.decl [template = constants.%C]
-// CHECK:STDOUT:     %.loc7: type = interface_type @AddWith, (%C.ref.loc7_19) [template = constants.%.3]
+// CHECK:STDOUT:     %.loc7_18: init type = call %AddWith.ref(%C.ref.loc7_19) [template = constants.%.3]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 27 - 23
toolchain/check/testdata/struct/import.carbon

@@ -30,14 +30,10 @@ var c: C({.a = 1, .b = 2}) = F();
 // --- fail_bad_type.impl.carbon
 
 impl package Implicit;
-// CHECK:STDERR: fail_bad_type.impl.carbon:[[@LINE+14]]:1: ERROR: Cannot implicitly convert from `C` to `C`.
-// CHECK:STDERR: var c_bad: C({.c = 1, .d = 2}) = F();
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// CHECK:STDERR:
 // CHECK:STDERR: fail_bad_type.impl.carbon:[[@LINE+10]]:14: ERROR: Missing value for field `a` in struct initialization.
 // CHECK:STDERR: var c_bad: C({.c = 1, .d = 2}) = F();
 // CHECK:STDERR:              ^~~~~~~~~~~~~~~~
-// CHECK:STDERR: fail_bad_type.impl.carbon:[[@LINE-8]]:6: In import.
+// CHECK:STDERR: fail_bad_type.impl.carbon:[[@LINE-4]]:6: In import.
 // CHECK:STDERR: impl package Implicit;
 // CHECK:STDERR:      ^~~~~~~
 // CHECK:STDERR: implicit.carbon:8:1: Initializing parameter 1 of function declared here.
@@ -141,8 +137,10 @@ var c_bad: C({.a = 3, .b = 4}) = F();
 // CHECK:STDOUT:     %.loc9_27: i32 = int_literal 2 [template = constants.%.14]
 // CHECK:STDOUT:     %.loc9_28: %.11 = struct_literal (%.loc9_19, %.loc9_27)
 // CHECK:STDOUT:     %struct: %.11 = struct_value (%.loc9_19, %.loc9_27) [template = constants.%struct.4]
-// CHECK:STDOUT:     %.loc9_12: %.11 = converted %.loc9_28, %struct [template = constants.%struct.4]
-// CHECK:STDOUT:     %C: type = class_type @C, (%.loc9_12) [template = constants.%C.3]
+// CHECK:STDOUT:     %.loc9_12.1: %.11 = converted %.loc9_28, %struct [template = constants.%struct.4]
+// CHECK:STDOUT:     %.loc9_12.2: init type = call %C.ref(%.loc9_12.1) [template = constants.%C.3]
+// CHECK:STDOUT:     %.loc9_29.1: type = value_of_initializer %.loc9_12.2 [template = constants.%C.3]
+// CHECK:STDOUT:     %.loc9_29.2: type = converted %.loc9_12.2, %.loc9_29.1 [template = constants.%C.3]
 // CHECK:STDOUT:     @F.%return: ref %C.3 = var <return slot>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -230,7 +228,7 @@ var c_bad: C({.a = 3, .b = 4}) = F();
 // CHECK:STDOUT:   %import_ref.1: ref %.2 = import_ref ir0, inst+16, loaded
 // CHECK:STDOUT:   %import_ref.2: ref %.6 = import_ref ir0, inst+59, loaded
 // CHECK:STDOUT:   %import_ref.3: %C.type = import_ref ir0, inst+103, loaded [template = constants.%C.1]
-// CHECK:STDOUT:   %import_ref.4: %F.type = import_ref ir0, inst+123, loaded [template = constants.%F]
+// CHECK:STDOUT:   %import_ref.4: %F.type = import_ref ir0, inst+125, loaded [template = constants.%F]
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %import_ref.5: %Int32.type = import_ref ir3, inst+3, loaded [template = constants.%Int32]
 // CHECK:STDOUT:   %int.make_type_32.loc4: init type = call constants.%Int32() [template = i32]
@@ -263,8 +261,10 @@ var c_bad: C({.a = 3, .b = 4}) = F();
 // CHECK:STDOUT:   %.loc6_24: i32 = int_literal 2 [template = constants.%.13]
 // CHECK:STDOUT:   %.loc6_25: %.11 = struct_literal (%.loc6_16, %.loc6_24)
 // CHECK:STDOUT:   %struct: %.11 = struct_value (%.loc6_16, %.loc6_24) [template = constants.%struct]
-// CHECK:STDOUT:   %.loc6_9: %.11 = converted %.loc6_25, %struct [template = constants.%struct]
-// CHECK:STDOUT:   %C: type = class_type @C, (%.loc6_9) [template = constants.%C.3]
+// CHECK:STDOUT:   %.loc6_9.1: %.11 = converted %.loc6_25, %struct [template = constants.%struct]
+// CHECK:STDOUT:   %.loc6_9.2: init type = call %C.ref(%.loc6_9.1) [template = constants.%C.3]
+// CHECK:STDOUT:   %.loc6_26.1: type = value_of_initializer %.loc6_9.2 [template = constants.%C.3]
+// CHECK:STDOUT:   %.loc6_26.2: type = converted %.loc6_9.2, %.loc6_26.1 [template = constants.%C.3]
 // CHECK:STDOUT:   %c.var: ref %C.3 = var c
 // CHECK:STDOUT:   %c: ref %C.3 = bind_name c, %c.var
 // CHECK:STDOUT: }
@@ -330,11 +330,11 @@ var c_bad: C({.a = 3, .b = 4}) = F();
 // CHECK:STDOUT:   %.5: i32 = int_literal 2 [template]
 // CHECK:STDOUT:   %.6: type = struct_type {.c: i32, .d: i32} [template]
 // CHECK:STDOUT:   %.7: type = ptr_type %.3 [template]
-// CHECK:STDOUT:   %.8: type = ptr_type %.2 [template]
 // CHECK:STDOUT:   %struct: %.3 = struct_value (%.4, %.5) [template]
 // CHECK:STDOUT:   %C.3: type = class_type @C, (%struct) [template]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [template]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [template]
+// CHECK:STDOUT:   %.8: type = ptr_type %.2 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -349,16 +349,18 @@ var c_bad: C({.a = 3, .b = 4}) = F();
 // CHECK:STDOUT:   %import_ref.1 = import_ref ir0, inst+16, unloaded
 // CHECK:STDOUT:   %import_ref.2 = import_ref ir0, inst+59, unloaded
 // CHECK:STDOUT:   %import_ref.3: %C.type = import_ref ir0, inst+103, loaded [template = constants.%C.1]
-// CHECK:STDOUT:   %import_ref.4: %F.type = import_ref ir0, inst+123, loaded [template = constants.%F]
+// CHECK:STDOUT:   %import_ref.4: %F.type = import_ref ir0, inst+125, loaded [template = constants.%F]
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %import_ref.5 = import_ref ir0, inst+106, unloaded
 // CHECK:STDOUT:   %C.ref: %C.type = name_ref C, %import_ref.3 [template = constants.%C.1]
-// CHECK:STDOUT:   %.loc17_20: i32 = int_literal 1 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc17_28: i32 = int_literal 2 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc17_29: %.6 = struct_literal (%.loc17_20, %.loc17_28)
-// CHECK:STDOUT:   %C: type = class_type @C [template = constants.%C.2]
-// CHECK:STDOUT:   %c_bad.var: ref %C.2 = var c_bad
-// CHECK:STDOUT:   %c_bad: ref %C.2 = bind_name c_bad, %c_bad.var
+// CHECK:STDOUT:   %.loc13_20: i32 = int_literal 1 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc13_28: i32 = int_literal 2 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc13_29: %.6 = struct_literal (%.loc13_20, %.loc13_28)
+// CHECK:STDOUT:   %.loc13_13: init type = call %C.ref(<invalid>) [template = <error>]
+// CHECK:STDOUT:   %.loc13_30.1: type = value_of_initializer %.loc13_13 [template = <error>]
+// CHECK:STDOUT:   %.loc13_30.2: type = converted %.loc13_13, %.loc13_30.1 [template = <error>]
+// CHECK:STDOUT:   %c_bad.var: ref <error> = var c_bad
+// CHECK:STDOUT:   %c_bad: ref <error> = bind_name c_bad, %c_bad.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
@@ -371,8 +373,8 @@ var c_bad: C({.a = 3, .b = 4}) = F();
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%import_ref.4 [template = constants.%F]
-// CHECK:STDOUT:   %.loc17: ref %C.3 = temporary_storage
-// CHECK:STDOUT:   %F.call: init %C.3 = call %F.ref() to %.loc17
+// CHECK:STDOUT:   %.loc13: ref %C.3 = temporary_storage
+// CHECK:STDOUT:   %F.call: init %C.3 = call %F.ref() to %.loc13
 // CHECK:STDOUT:   assign file.%c_bad.var, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
@@ -413,7 +415,7 @@ var c_bad: C({.a = 3, .b = 4}) = F();
 // CHECK:STDOUT:   %import_ref.1 = import_ref ir0, inst+16, unloaded
 // CHECK:STDOUT:   %import_ref.2 = import_ref ir0, inst+59, unloaded
 // CHECK:STDOUT:   %import_ref.3: %C.type = import_ref ir0, inst+103, loaded [template = constants.%C.1]
-// CHECK:STDOUT:   %import_ref.4: %F.type = import_ref ir0, inst+123, loaded [template = constants.%F]
+// CHECK:STDOUT:   %import_ref.4: %F.type = import_ref ir0, inst+125, loaded [template = constants.%F]
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %import_ref.5 = import_ref ir0, inst+106, unloaded
 // CHECK:STDOUT:   %C.ref: %C.type = name_ref C, %import_ref.3 [template = constants.%C.1]
@@ -421,8 +423,10 @@ var c_bad: C({.a = 3, .b = 4}) = F();
 // CHECK:STDOUT:   %.loc6_28: i32 = int_literal 4 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc6_29: %.3 = struct_literal (%.loc6_20, %.loc6_28)
 // CHECK:STDOUT:   %struct: %.3 = struct_value (%.loc6_20, %.loc6_28) [template = constants.%struct.1]
-// CHECK:STDOUT:   %.loc6_13: %.3 = converted %.loc6_29, %struct [template = constants.%struct.1]
-// CHECK:STDOUT:   %C: type = class_type @C, (%.loc6_13) [template = constants.%C.3]
+// CHECK:STDOUT:   %.loc6_13.1: %.3 = converted %.loc6_29, %struct [template = constants.%struct.1]
+// CHECK:STDOUT:   %.loc6_13.2: init type = call %C.ref(%.loc6_13.1) [template = constants.%C.3]
+// CHECK:STDOUT:   %.loc6_30.1: type = value_of_initializer %.loc6_13.2 [template = constants.%C.3]
+// CHECK:STDOUT:   %.loc6_30.2: type = converted %.loc6_13.2, %.loc6_30.1 [template = constants.%C.3]
 // CHECK:STDOUT:   %c_bad.var: ref %C.3 = var c_bad
 // CHECK:STDOUT:   %c_bad: ref %C.3 = bind_name c_bad, %c_bad.var
 // CHECK:STDOUT: }

+ 28 - 24
toolchain/check/testdata/tuples/import.carbon

@@ -31,14 +31,10 @@ var c: C((1, 2)) = F();
 
 impl package Implicit;
 
-// CHECK:STDERR: fail_bad_type.impl.carbon:[[@LINE+14]]:1: ERROR: Cannot implicitly convert from `C` to `C`.
-// CHECK:STDERR: var c_bad: C((1, 2, 3)) = F();
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// CHECK:STDERR:
 // CHECK:STDERR: fail_bad_type.impl.carbon:[[@LINE+10]]:14: ERROR: Cannot initialize tuple of 2 element(s) from tuple with 3 element(s).
 // CHECK:STDERR: var c_bad: C((1, 2, 3)) = F();
 // CHECK:STDERR:              ^~~~~~~~~
-// CHECK:STDERR: fail_bad_type.impl.carbon:[[@LINE-9]]:6: In import.
+// CHECK:STDERR: fail_bad_type.impl.carbon:[[@LINE-5]]:6: In import.
 // CHECK:STDERR: impl package Implicit;
 // CHECK:STDERR:      ^~~~~~~
 // CHECK:STDERR: implicit.carbon:7:1: Initializing parameter 1 of function declared here.
@@ -156,8 +152,10 @@ var c_bad: C((3, 4)) = F();
 // CHECK:STDOUT:     %.loc9_17: i32 = int_literal 2 [template = constants.%.16]
 // CHECK:STDOUT:     %.loc9_18: %.9 = tuple_literal (%.loc9_14, %.loc9_17)
 // CHECK:STDOUT:     %tuple: %.9 = tuple_value (%.loc9_14, %.loc9_17) [template = constants.%tuple.5]
-// CHECK:STDOUT:     %.loc9_12: %.9 = converted %.loc9_18, %tuple [template = constants.%tuple.5]
-// CHECK:STDOUT:     %C: type = class_type @C, (%.loc9_12) [template = constants.%C.3]
+// CHECK:STDOUT:     %.loc9_12.1: %.9 = converted %.loc9_18, %tuple [template = constants.%tuple.5]
+// CHECK:STDOUT:     %.loc9_12.2: init type = call %C.ref(%.loc9_12.1) [template = constants.%C.3]
+// CHECK:STDOUT:     %.loc9_19.1: type = value_of_initializer %.loc9_12.2 [template = constants.%C.3]
+// CHECK:STDOUT:     %.loc9_19.2: type = converted %.loc9_12.2, %.loc9_19.1 [template = constants.%C.3]
 // CHECK:STDOUT:     @F.%return: ref %C.3 = var <return slot>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -254,7 +252,7 @@ var c_bad: C((3, 4)) = F();
 // CHECK:STDOUT:   %import_ref.1: ref %.3 = import_ref ir0, inst+16, loaded
 // CHECK:STDOUT:   %import_ref.2: ref %.9 = import_ref ir0, inst+60, loaded
 // CHECK:STDOUT:   %import_ref.3: %C.type = import_ref ir0, inst+108, loaded [template = constants.%C.1]
-// CHECK:STDOUT:   %import_ref.4: %F.type = import_ref ir0, inst+123, loaded [template = constants.%F]
+// CHECK:STDOUT:   %import_ref.4: %F.type = import_ref ir0, inst+125, loaded [template = constants.%F]
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %import_ref.5: %Int32.type = import_ref ir3, inst+3, loaded [template = constants.%Int32]
 // CHECK:STDOUT:   %int.make_type_32.loc4: init type = call constants.%Int32() [template = i32]
@@ -296,8 +294,10 @@ var c_bad: C((3, 4)) = F();
 // CHECK:STDOUT:   %.loc6_14: i32 = int_literal 2 [template = constants.%.16]
 // CHECK:STDOUT:   %.loc6_15: %.8 = tuple_literal (%.loc6_11, %.loc6_14)
 // CHECK:STDOUT:   %tuple: %.8 = tuple_value (%.loc6_11, %.loc6_14) [template = constants.%tuple]
-// CHECK:STDOUT:   %.loc6_9: %.8 = converted %.loc6_15, %tuple [template = constants.%tuple]
-// CHECK:STDOUT:   %C: type = class_type @C, (%.loc6_9) [template = constants.%C.3]
+// CHECK:STDOUT:   %.loc6_9.1: %.8 = converted %.loc6_15, %tuple [template = constants.%tuple]
+// CHECK:STDOUT:   %.loc6_9.2: init type = call %C.ref(%.loc6_9.1) [template = constants.%C.3]
+// CHECK:STDOUT:   %.loc6_16.1: type = value_of_initializer %.loc6_9.2 [template = constants.%C.3]
+// CHECK:STDOUT:   %.loc6_16.2: type = converted %.loc6_9.2, %.loc6_16.1 [template = constants.%C.3]
 // CHECK:STDOUT:   %c.var: ref %C.3 = var c
 // CHECK:STDOUT:   %c: ref %C.3 = bind_name c, %c.var
 // CHECK:STDOUT: }
@@ -372,11 +372,11 @@ var c_bad: C((3, 4)) = F();
 // CHECK:STDOUT:   %.6: i32 = int_literal 3 [template]
 // CHECK:STDOUT:   %.7: type = tuple_type (i32, i32, i32) [template]
 // CHECK:STDOUT:   %.8: type = ptr_type %.3 [template]
-// CHECK:STDOUT:   %.9: type = ptr_type %.2 [template]
 // CHECK:STDOUT:   %tuple: %.3 = tuple_value (%.4, %.5) [template]
 // CHECK:STDOUT:   %C.3: type = class_type @C, (%tuple) [template]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [template]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [template]
+// CHECK:STDOUT:   %.9: type = ptr_type %.2 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -391,17 +391,19 @@ var c_bad: C((3, 4)) = F();
 // CHECK:STDOUT:   %import_ref.1 = import_ref ir0, inst+16, unloaded
 // CHECK:STDOUT:   %import_ref.2 = import_ref ir0, inst+60, unloaded
 // CHECK:STDOUT:   %import_ref.3: %C.type = import_ref ir0, inst+108, loaded [template = constants.%C.1]
-// CHECK:STDOUT:   %import_ref.4: %F.type = import_ref ir0, inst+123, loaded [template = constants.%F]
+// CHECK:STDOUT:   %import_ref.4: %F.type = import_ref ir0, inst+125, loaded [template = constants.%F]
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %import_ref.5 = import_ref ir0, inst+111, unloaded
 // CHECK:STDOUT:   %C.ref: %C.type = name_ref C, %import_ref.3 [template = constants.%C.1]
-// CHECK:STDOUT:   %.loc18_15: i32 = int_literal 1 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc18_18: i32 = int_literal 2 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc18_21: i32 = int_literal 3 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc18_22: %.7 = tuple_literal (%.loc18_15, %.loc18_18, %.loc18_21)
-// CHECK:STDOUT:   %C: type = class_type @C [template = constants.%C.2]
-// CHECK:STDOUT:   %c_bad.var: ref %C.2 = var c_bad
-// CHECK:STDOUT:   %c_bad: ref %C.2 = bind_name c_bad, %c_bad.var
+// CHECK:STDOUT:   %.loc14_15: i32 = int_literal 1 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc14_18: i32 = int_literal 2 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc14_21: i32 = int_literal 3 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc14_22: %.7 = tuple_literal (%.loc14_15, %.loc14_18, %.loc14_21)
+// CHECK:STDOUT:   %.loc14_13: init type = call %C.ref(<invalid>) [template = <error>]
+// CHECK:STDOUT:   %.loc14_23.1: type = value_of_initializer %.loc14_13 [template = <error>]
+// CHECK:STDOUT:   %.loc14_23.2: type = converted %.loc14_13, %.loc14_23.1 [template = <error>]
+// CHECK:STDOUT:   %c_bad.var: ref <error> = var c_bad
+// CHECK:STDOUT:   %c_bad: ref <error> = bind_name c_bad, %c_bad.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
@@ -414,8 +416,8 @@ var c_bad: C((3, 4)) = F();
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%import_ref.4 [template = constants.%F]
-// CHECK:STDOUT:   %.loc18: ref %C.3 = temporary_storage
-// CHECK:STDOUT:   %F.call: init %C.3 = call %F.ref() to %.loc18
+// CHECK:STDOUT:   %.loc14: ref %C.3 = temporary_storage
+// CHECK:STDOUT:   %F.call: init %C.3 = call %F.ref() to %.loc14
 // CHECK:STDOUT:   assign file.%c_bad.var, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
@@ -456,7 +458,7 @@ var c_bad: C((3, 4)) = F();
 // CHECK:STDOUT:   %import_ref.1 = import_ref ir0, inst+16, unloaded
 // CHECK:STDOUT:   %import_ref.2 = import_ref ir0, inst+60, unloaded
 // CHECK:STDOUT:   %import_ref.3: %C.type = import_ref ir0, inst+108, loaded [template = constants.%C.1]
-// CHECK:STDOUT:   %import_ref.4: %F.type = import_ref ir0, inst+123, loaded [template = constants.%F]
+// CHECK:STDOUT:   %import_ref.4: %F.type = import_ref ir0, inst+125, loaded [template = constants.%F]
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %import_ref.5 = import_ref ir0, inst+111, unloaded
 // CHECK:STDOUT:   %C.ref: %C.type = name_ref C, %import_ref.3 [template = constants.%C.1]
@@ -464,8 +466,10 @@ var c_bad: C((3, 4)) = F();
 // CHECK:STDOUT:   %.loc7_18: i32 = int_literal 4 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc7_19: %.3 = tuple_literal (%.loc7_15, %.loc7_18)
 // CHECK:STDOUT:   %tuple: %.3 = tuple_value (%.loc7_15, %.loc7_18) [template = constants.%tuple.1]
-// CHECK:STDOUT:   %.loc7_13: %.3 = converted %.loc7_19, %tuple [template = constants.%tuple.1]
-// CHECK:STDOUT:   %C: type = class_type @C, (%.loc7_13) [template = constants.%C.3]
+// CHECK:STDOUT:   %.loc7_13.1: %.3 = converted %.loc7_19, %tuple [template = constants.%tuple.1]
+// CHECK:STDOUT:   %.loc7_13.2: init type = call %C.ref(%.loc7_13.1) [template = constants.%C.3]
+// CHECK:STDOUT:   %.loc7_20.1: type = value_of_initializer %.loc7_13.2 [template = constants.%C.3]
+// CHECK:STDOUT:   %.loc7_20.2: type = converted %.loc7_13.2, %.loc7_20.1 [template = constants.%C.3]
 // CHECK:STDOUT:   %c_bad.var: ref %C.3 = var c_bad
 // CHECK:STDOUT:   %c_bad: ref %C.3 = bind_name c_bad, %c_bad.var
 // CHECK:STDOUT: }

+ 2 - 2
toolchain/sem_ir/inst_kind.def

@@ -101,7 +101,7 @@ CARBON_SEM_IR_INST_KIND_IMPL(Call, TYPE_NEVER, CONSTANT_NEVER)
 CARBON_SEM_IR_INST_KIND_IMPL(ClassDecl, TYPE_NEVER, CONSTANT_NEVER)
 CARBON_SEM_IR_INST_KIND_IMPL(ClassElementAccess, TYPE_NEVER, CONSTANT_NEVER)
 CARBON_SEM_IR_INST_KIND_IMPL(ClassInit, TYPE_NEVER, CONSTANT_NEVER)
-CARBON_SEM_IR_INST_KIND_IMPL(ClassType, TYPE_ALWAYS, CONSTANT_CONDITIONAL)
+CARBON_SEM_IR_INST_KIND_IMPL(ClassType, TYPE_ALWAYS, CONSTANT_ALWAYS)
 CARBON_SEM_IR_INST_KIND_IMPL(ConstType, TYPE_ALWAYS, CONSTANT_CONDITIONAL)
 CARBON_SEM_IR_INST_KIND_IMPL(Converted, TYPE_NEVER, CONSTANT_NEVER)
 CARBON_SEM_IR_INST_KIND_IMPL(Deref, TYPE_NEVER, CONSTANT_NEVER)
@@ -120,7 +120,7 @@ CARBON_SEM_IR_INST_KIND_IMPL(ImportRefUnloaded, TYPE_NEVER, CONSTANT_NEVER)
 CARBON_SEM_IR_INST_KIND_IMPL(ImportRefLoaded, TYPE_NEVER, CONSTANT_NEVER)
 CARBON_SEM_IR_INST_KIND_IMPL(InitializeFrom, TYPE_NEVER, CONSTANT_NEVER)
 CARBON_SEM_IR_INST_KIND_IMPL(InterfaceDecl, TYPE_NEVER, CONSTANT_NEVER)
-CARBON_SEM_IR_INST_KIND_IMPL(InterfaceType, TYPE_ALWAYS, CONSTANT_CONDITIONAL)
+CARBON_SEM_IR_INST_KIND_IMPL(InterfaceType, TYPE_ALWAYS, CONSTANT_ALWAYS)
 CARBON_SEM_IR_INST_KIND_IMPL(InterfaceWitness, TYPE_NEVER, CONSTANT_CONDITIONAL)
 CARBON_SEM_IR_INST_KIND_IMPL(InterfaceWitnessAccess, TYPE_MAYBE,
                              CONSTANT_SYMBOLIC_ONLY)