فهرست منبع

Remove the SemIRLoc typedef (#5299)

Replace SemIRLoc typedef uses with explicitly SemIR::LocId, loc ->
loc_id for consistency.
Jon Ross-Perkins 1 سال پیش
والد
کامیت
55da026a46

+ 5 - 4
toolchain/check/context.cpp

@@ -25,17 +25,18 @@ Context::Context(DiagnosticEmitterBase* emitter,
       scope_stack_(sem_ir_),
       vtable_stack_("vtable_stack_", *sem_ir, vlog_stream),
       global_init_(this),
-      region_stack_(
-          [this](SemIRLoc loc, std::string label) { TODO(loc, label); }) {
+      region_stack_([this](SemIR::LocId loc_id, std::string label) {
+        TODO(loc_id, label);
+      }) {
   // Prepare fields which relate to the number of IRs available for import.
   import_irs().Reserve(imported_ir_count);
   import_ir_constant_values_.reserve(imported_ir_count);
   check_ir_map_.resize(total_ir_count, SemIR::ImportIRId::None);
 }
 
-auto Context::TODO(SemIRLoc loc, std::string label) -> bool {
+auto Context::TODO(SemIR::LocId loc_id, std::string label) -> bool {
   CARBON_DIAGNOSTIC(SemanticsTodo, Error, "semantics TODO: `{0}`", std::string);
-  emitter_->Emit(loc, SemanticsTodo, std::move(label));
+  emitter_->Emit(loc_id, SemanticsTodo, std::move(label));
   return false;
 }
 

+ 3 - 3
toolchain/check/context.h

@@ -57,7 +57,7 @@ class Context {
                    int total_ir_count, llvm::raw_ostream* vlog_stream);
 
   // Marks an implementation TODO. Always returns false.
-  auto TODO(SemIRLoc loc, std::string label) -> bool;
+  auto TODO(SemIR::LocId loc_id, std::string label) -> bool;
 
   // Runs verification that the processing cleanly finished.
   auto VerifyOnFinish() const -> void;
@@ -152,7 +152,7 @@ class Context {
   }
 
   auto definitions_required_by_use()
-      -> llvm::SmallVector<std::pair<SemIRLoc, SemIR::SpecificId>>& {
+      -> llvm::SmallVector<std::pair<SemIR::LocId, SemIR::SpecificId>>& {
     return definitions_required_by_use_;
   }
 
@@ -350,7 +350,7 @@ class Context {
   // Entities that should have definitions by the end of the current source
   // file, because of a generic was used a concrete specific. This is currently
   // only tracking specific functions that should have a definition emitted.
-  llvm::SmallVector<std::pair<SemIRLoc, SemIR::SpecificId>>
+  llvm::SmallVector<std::pair<SemIR::LocId, SemIR::SpecificId>>
       definitions_required_by_use_;
 
   // State for global initialization.

+ 2 - 2
toolchain/check/convert.cpp

@@ -609,14 +609,14 @@ using InheritancePath =
 
 // Computes the inheritance path from class `derived_id` to class `base_id`.
 // Returns nullopt if `derived_id` is not a class derived from `base_id`.
-static auto ComputeInheritancePath(Context& context, SemIRLoc loc,
+static auto ComputeInheritancePath(Context& context, SemIR::LocId loc_id,
                                    SemIR::TypeId derived_id,
                                    SemIR::TypeId base_id)
     -> std::optional<InheritancePath> {
   // We intend for NRVO to be applied to `result`. All `return` statements in
   // this function should `return result;`.
   std::optional<InheritancePath> result(std::in_place);
-  if (!TryToCompleteType(context, derived_id, loc)) {
+  if (!TryToCompleteType(context, derived_id, loc_id)) {
     // TODO: Should we give an error here? If we don't, and there is an
     // inheritance path when the class is defined, we may have a coherence
     // problem.

+ 15 - 15
toolchain/check/decl_name_stack.cpp

@@ -206,7 +206,7 @@ auto DeclNameStack::LookupOrAddName(NameContext name_context,
 // `fn Class(T:! type).F(n: i32)` we will push the scope for `Class(T:! type)`
 // between the scope containing the declaration of `T` and the scope
 // containing the declaration of `n`.
-static auto PushNameQualifierScope(Context& context, SemIRLoc loc,
+static auto PushNameQualifierScope(Context& context, SemIR::LocId loc_id,
                                    SemIR::InstId scope_inst_id,
                                    SemIR::NameScopeId scope_id,
                                    SemIR::GenericId generic_id,
@@ -219,7 +219,7 @@ static auto PushNameQualifierScope(Context& context, SemIRLoc loc,
   if (generic_id.has_value()) {
     self_specific_id = context.generics().GetSelfSpecific(generic_id);
     // When declaring a member of a generic, resolve the self specific.
-    ResolveSpecificDefinition(context, loc, self_specific_id);
+    ResolveSpecificDefinition(context, loc_id, self_specific_id);
   }
 
   // Close the generic stack scope and open a new one for whatever comes after
@@ -325,14 +325,14 @@ static auto CheckQualifierIsResolved(
 // Diagnose that a qualified declaration name specifies an incomplete class as
 // its scope.
 static auto DiagnoseQualifiedDeclInIncompleteClassScope(Context& context,
-                                                        SemIRLoc loc,
+                                                        SemIR::LocId loc_id,
                                                         SemIR::ClassId class_id)
     -> void {
   CARBON_DIAGNOSTIC(QualifiedDeclInIncompleteClassScope, Error,
                     "cannot declare a member of incomplete class {0}",
                     SemIR::TypeId);
   auto builder =
-      context.emitter().Build(loc, QualifiedDeclInIncompleteClassScope,
+      context.emitter().Build(loc_id, QualifiedDeclInIncompleteClassScope,
                               context.classes().Get(class_id).self_type_id);
   NoteIncompleteClass(context, class_id, builder);
   builder.Emit();
@@ -341,13 +341,13 @@ static auto DiagnoseQualifiedDeclInIncompleteClassScope(Context& context,
 // Diagnose that a qualified declaration name specifies an undefined interface
 // as its scope.
 static auto DiagnoseQualifiedDeclInUndefinedInterfaceScope(
-    Context& context, SemIRLoc loc, SemIR::InterfaceId interface_id,
+    Context& context, SemIR::LocId loc_id, SemIR::InterfaceId interface_id,
     SemIR::InstId interface_inst_id) -> void {
   CARBON_DIAGNOSTIC(QualifiedDeclInUndefinedInterfaceScope, Error,
                     "cannot declare a member of undefined interface {0}",
                     InstIdAsType);
   auto builder = context.emitter().Build(
-      loc, QualifiedDeclInUndefinedInterfaceScope, interface_inst_id);
+      loc_id, QualifiedDeclInUndefinedInterfaceScope, interface_inst_id);
   NoteIncompleteInterface(context, interface_id, builder);
   builder.Emit();
 }
@@ -355,32 +355,32 @@ static auto DiagnoseQualifiedDeclInUndefinedInterfaceScope(
 // Diagnose that a qualified declaration name specifies a different package as
 // its scope.
 static auto DiagnoseQualifiedDeclInImportedPackage(Context& context,
-                                                   SemIRLoc use_loc,
-                                                   SemIRLoc import_loc)
+                                                   SemIR::LocId use_loc_id,
+                                                   SemIR::LocId import_loc_id)
     -> void {
   CARBON_DIAGNOSTIC(QualifiedDeclOutsidePackage, Error,
                     "imported packages cannot be used for declarations");
   CARBON_DIAGNOSTIC(QualifiedDeclOutsidePackageSource, Note,
                     "package imported here");
   context.emitter()
-      .Build(use_loc, QualifiedDeclOutsidePackage)
-      .Note(import_loc, QualifiedDeclOutsidePackageSource)
+      .Build(use_loc_id, QualifiedDeclOutsidePackage)
+      .Note(import_loc_id, QualifiedDeclOutsidePackageSource)
       .Emit();
 }
 
 // Diagnose that a qualified declaration name specifies a non-scope entity as
 // its scope.
-static auto DiagnoseQualifiedDeclInNonScope(Context& context, SemIRLoc use_loc,
-                                            SemIRLoc non_scope_entity_loc)
-    -> void {
+static auto DiagnoseQualifiedDeclInNonScope(
+    Context& context, SemIR::LocId use_loc_id,
+    SemIR::LocId non_scope_entity_loc_id) -> void {
   CARBON_DIAGNOSTIC(QualifiedNameInNonScope, Error,
                     "name qualifiers are only allowed for entities that "
                     "provide a scope");
   CARBON_DIAGNOSTIC(QualifiedNameNonScopeEntity, Note,
                     "referenced non-scope entity declared here");
   context.emitter()
-      .Build(use_loc, QualifiedNameInNonScope)
-      .Note(non_scope_entity_loc, QualifiedNameNonScopeEntity)
+      .Build(use_loc_id, QualifiedNameInNonScope)
+      .Note(non_scope_entity_loc_id, QualifiedNameNonScopeEntity)
       .Emit();
 }
 

+ 1 - 1
toolchain/check/diagnostic_emitter.h

@@ -16,7 +16,7 @@
 
 namespace Carbon::Check {
 
-// Handles the transformation of a SemIRLoc to a DiagnosticLoc.
+// Handles the transformation of a SemIR::LocId to a DiagnosticLoc.
 class DiagnosticEmitter : public DiagnosticEmitterBase {
  public:
   explicit DiagnosticEmitter(

+ 2 - 5
toolchain/check/diagnostic_helpers.h

@@ -11,17 +11,14 @@
 
 namespace Carbon::Check {
 
-// TODO: Update code to use LocId directly.
-using SemIRLoc = SemIR::LocId;
-
 // TODO: Consider instead changing calls to `SemIR::LocId::TokenOnly(...)`.
-inline auto TokenOnly(SemIR::LocId loc_id) -> SemIRLoc {
+inline auto TokenOnly(SemIR::LocId loc_id) -> SemIR::LocId {
   return loc_id.ToTokenOnly();
 }
 
 // We define the emitter separately for dependencies, so only provide a base
 // here.
-using DiagnosticEmitterBase = Diagnostics::Emitter<SemIRLoc>;
+using DiagnosticEmitterBase = Diagnostics::Emitter<SemIR::LocId>;
 
 using DiagnosticBuilder = DiagnosticEmitterBase::Builder;
 

+ 47 - 42
toolchain/check/eval.cpp

@@ -39,31 +39,32 @@ struct SpecificEvalInfo {
 class EvalContext {
  public:
   explicit EvalContext(
-      Context* context, SemIRLoc fallback_loc,
+      Context* context, SemIR::LocId fallback_loc_id,
       SemIR::SpecificId specific_id = SemIR::SpecificId::None,
       std::optional<SpecificEvalInfo> specific_eval_info = std::nullopt)
       : context_(context),
-        fallback_loc_(fallback_loc),
+        fallback_loc_id_(fallback_loc_id),
         specific_id_(specific_id),
         specific_eval_info_(specific_eval_info) {}
 
   // Gets the location to use for diagnostics if a better location is
   // unavailable.
   // TODO: This is also sometimes unavailable.
-  auto fallback_loc() const -> SemIRLoc { return fallback_loc_; }
+  auto fallback_loc_id() const -> SemIR::LocId { return fallback_loc_id_; }
 
   // Returns a location to use to point at an instruction in a diagnostic, given
   // a list of instructions that might have an attached location. This is the
   // location of the first instruction in the list that has a location if there
   // is one, and otherwise the fallback location.
-  auto GetDiagnosticLoc(llvm::ArrayRef<SemIR::InstId> inst_ids) -> SemIRLoc {
+  auto GetDiagnosticLoc(llvm::ArrayRef<SemIR::InstId> inst_ids)
+      -> SemIR::LocId {
     for (auto inst_id : inst_ids) {
       if (inst_id.has_value() &&
           context_->insts().GetLocId(inst_id).has_value()) {
         return inst_id;
       }
     }
-    return fallback_loc_;
+    return fallback_loc_id_;
   }
 
   // Gets the value of the specified compile-time binding in this context.
@@ -199,7 +200,7 @@ class EvalContext {
   // The type-checking context in which we're performing evaluation.
   Context* context_;
   // The location to use for diagnostics when a better location isn't available.
-  SemIRLoc fallback_loc_;
+  SemIR::LocId fallback_loc_id_;
   // The specific that we are evaluating within.
   SemIR::SpecificId specific_id_;
   // If we are currently evaluating an eval block for `specific_id_`,
@@ -549,11 +550,11 @@ static auto GetConstantValue(EvalContext& eval_context,
                                                    .Get(specific.generic_id)
                                                    .decl_block_id.has_value()) {
       ResolveSpecificDeclaration(eval_context.context(),
-                                 eval_context.fallback_loc(), specific_id);
+                                 eval_context.fallback_loc_id(), specific_id);
     }
     return specific_id;
   }
-  return MakeSpecific(eval_context.context(), eval_context.fallback_loc(),
+  return MakeSpecific(eval_context.context(), eval_context.fallback_loc_id(),
                       specific.generic_id, args_id);
 }
 
@@ -819,14 +820,14 @@ static auto PerformArrayIndex(EvalContext& eval_context, SemIR::ArrayIndex inst)
 
 // Forms a constant int type as an evaluation result. Requires that width_id is
 // constant.
-static auto MakeIntTypeResult(Context& context, SemIRLoc loc,
+static auto MakeIntTypeResult(Context& context, SemIR::LocId loc_id,
                               SemIR::IntKind int_kind, SemIR::InstId width_id,
                               Phase phase) -> SemIR::ConstantId {
   auto result = SemIR::IntType{
       .type_id = GetSingletonType(context, SemIR::TypeType::SingletonInstId),
       .int_kind = int_kind,
       .bit_width_id = width_id};
-  if (!ValidateIntType(context, loc, result)) {
+  if (!ValidateIntType(context, loc_id, result)) {
     return SemIR::ErrorInst::SingletonConstantId;
   }
   return MakeConstantResult(context, result, phase);
@@ -854,7 +855,7 @@ static auto PerformIntConvert(Context& context, SemIR::InstId arg_id,
 
 // Performs a conversion between integer types, diagnosing if the value doesn't
 // fit in the destination type.
-static auto PerformCheckedIntConvert(Context& context, SemIRLoc loc,
+static auto PerformCheckedIntConvert(Context& context, SemIR::LocId loc_id,
                                      SemIR::InstId arg_id,
                                      SemIR::TypeId dest_type_id)
     -> SemIR::ConstantId {
@@ -872,7 +873,7 @@ static auto PerformCheckedIntConvert(Context& context, SemIRLoc loc,
         NegativeIntInUnsignedType, Error,
         "negative integer value {0} converted to unsigned type {1}", TypedInt,
         SemIR::TypeId);
-    context.emitter().Emit(loc, NegativeIntInUnsignedType,
+    context.emitter().Emit(loc_id, NegativeIntInUnsignedType,
                            {.type = arg.type_id, .value = arg_val},
                            dest_type_id);
   }
@@ -882,7 +883,7 @@ static auto PerformCheckedIntConvert(Context& context, SemIRLoc loc,
     CARBON_DIAGNOSTIC(IntTooLargeForType, Error,
                       "integer value {0} too large for type {1}", TypedInt,
                       SemIR::TypeId);
-    context.emitter().Emit(loc, IntTooLargeForType,
+    context.emitter().Emit(loc_id, IntTooLargeForType,
                            {.type = arg.type_id, .value = arg_val},
                            dest_type_id);
   }
@@ -893,9 +894,10 @@ static auto PerformCheckedIntConvert(Context& context, SemIRLoc loc,
 }
 
 // Issues a diagnostic for a compile-time division by zero.
-static auto DiagnoseDivisionByZero(Context& context, SemIRLoc loc) -> void {
+static auto DiagnoseDivisionByZero(Context& context, SemIR::LocId loc_id)
+    -> void {
   CARBON_DIAGNOSTIC(CompileTimeDivisionByZero, Error, "division by zero");
-  context.emitter().Emit(loc, CompileTimeDivisionByZero);
+  context.emitter().Emit(loc_id, CompileTimeDivisionByZero);
 }
 
 // Get an integer at a suitable bit-width: either `bit_width_id` if it has a
@@ -908,7 +910,7 @@ static auto GetIntAtSuitableWidth(Context& context, IntId int_id,
 }
 
 // Performs a builtin unary integer -> integer operation.
-static auto PerformBuiltinUnaryIntOp(Context& context, SemIRLoc loc,
+static auto PerformBuiltinUnaryIntOp(Context& context, SemIR::LocId loc_id,
                                      SemIR::BuiltinFunctionKind builtin_kind,
                                      SemIR::InstId arg_id)
     -> SemIR::ConstantId {
@@ -923,7 +925,7 @@ static auto PerformBuiltinUnaryIntOp(Context& context, SemIRLoc loc,
         if (bit_width_id.has_value()) {
           CARBON_DIAGNOSTIC(CompileTimeIntegerNegateOverflow, Error,
                             "integer overflow in negation of {0}", TypedInt);
-          context.emitter().Emit(loc, CompileTimeIntegerNegateOverflow,
+          context.emitter().Emit(loc_id, CompileTimeIntegerNegateOverflow,
                                  {.type = op.type_id, .value = op_val});
         } else {
           // Widen the integer so we don't overflow into the sign bit.
@@ -1075,7 +1077,7 @@ static auto ComputeBinaryIntOpResult(SemIR::BuiltinFunctionKind builtin_kind,
 }
 
 // Performs a builtin integer bit shift operation.
-static auto PerformBuiltinIntShiftOp(Context& context, SemIRLoc loc,
+static auto PerformBuiltinIntShiftOp(Context& context, SemIR::LocId loc_id,
                                      SemIR::BuiltinFunctionKind builtin_kind,
                                      SemIR::InstId lhs_id, SemIR::InstId rhs_id)
     -> SemIR::ConstantId {
@@ -1094,7 +1096,7 @@ static auto PerformBuiltinIntShiftOp(Context& context, SemIRLoc loc,
         "shift distance >= type width of {0} in `{1} {2:<<|>>} {3}`", unsigned,
         TypedInt, Diagnostics::BoolAsSelect, TypedInt);
     context.emitter().Emit(
-        loc, CompileTimeShiftOutOfRange, lhs_val.getBitWidth(),
+        loc_id, CompileTimeShiftOutOfRange, lhs_val.getBitWidth(),
         {.type = lhs.type_id, .value = lhs_val},
         builtin_kind == SemIR::BuiltinFunctionKind::IntLeftShift,
         {.type = rhs.type_id, .value = rhs_orig_val});
@@ -1108,7 +1110,8 @@ static auto PerformBuiltinIntShiftOp(Context& context, SemIRLoc loc,
                       "shift distance negative in `{0} {1:<<|>>} {2}`",
                       TypedInt, Diagnostics::BoolAsSelect, TypedInt);
     context.emitter().Emit(
-        loc, CompileTimeShiftNegative, {.type = lhs.type_id, .value = lhs_val},
+        loc_id, CompileTimeShiftNegative,
+        {.type = lhs.type_id, .value = lhs_val},
         builtin_kind == SemIR::BuiltinFunctionKind::IntLeftShift,
         {.type = rhs.type_id, .value = rhs_orig_val});
     // TODO: Is it useful to recover by returning 0 or -1?
@@ -1128,7 +1131,7 @@ static auto PerformBuiltinIntShiftOp(Context& context, SemIRLoc loc,
                           "integer whose width is greater than the "
                           "maximum supported width of {1}",
                           TypedInt, int);
-        context.emitter().Emit(loc, CompileTimeUnsizedShiftOutOfRange,
+        context.emitter().Emit(loc_id, CompileTimeUnsizedShiftOutOfRange,
                                {.type = rhs.type_id, .value = rhs_orig_val},
                                IntStore::MaxIntWidth);
         return SemIR::ErrorInst::SingletonConstantId;
@@ -1152,7 +1155,7 @@ static auto PerformBuiltinIntShiftOp(Context& context, SemIRLoc loc,
 }
 
 // Performs a homogeneous builtin binary integer -> integer operation.
-static auto PerformBuiltinBinaryIntOp(Context& context, SemIRLoc loc,
+static auto PerformBuiltinBinaryIntOp(Context& context, SemIR::LocId loc_id,
                                       SemIR::BuiltinFunctionKind builtin_kind,
                                       SemIR::InstId lhs_id,
                                       SemIR::InstId rhs_id)
@@ -1174,7 +1177,7 @@ static auto PerformBuiltinBinaryIntOp(Context& context, SemIRLoc loc,
     case SemIR::BuiltinFunctionKind::IntUDiv:
     case SemIR::BuiltinFunctionKind::IntUMod:
       if (rhs_val.isZero()) {
-        DiagnoseDivisionByZero(context, loc);
+        DiagnoseDivisionByZero(context, loc_id);
         return SemIR::ErrorInst::SingletonConstantId;
       }
       break;
@@ -1216,7 +1219,7 @@ static auto PerformBuiltinBinaryIntOp(Context& context, SemIRLoc loc,
     CARBON_DIAGNOSTIC(CompileTimeIntegerOverflow, Error,
                       "integer overflow in calculation `{0} {1} {2}`", TypedInt,
                       Lex::TokenKind, TypedInt);
-    context.emitter().Emit(loc, CompileTimeIntegerOverflow,
+    context.emitter().Emit(loc_id, CompileTimeIntegerOverflow,
                            {.type = type_id, .value = lhs_val}, result.op_token,
                            {.type = type_id, .value = rhs_val});
   }
@@ -1366,8 +1369,8 @@ static auto PerformBuiltinBoolComparison(
 }
 
 // Returns a constant for a call to a builtin function.
-static auto MakeConstantForBuiltinCall(EvalContext& eval_context, SemIRLoc loc,
-                                       SemIR::Call call,
+static auto MakeConstantForBuiltinCall(EvalContext& eval_context,
+                                       SemIR::LocId loc_id, SemIR::Call call,
                                        SemIR::BuiltinFunctionKind builtin_kind,
                                        llvm::ArrayRef<SemIR::InstId> arg_ids,
                                        Phase phase) -> SemIR::ConstantId {
@@ -1403,7 +1406,7 @@ static auto MakeConstantForBuiltinCall(EvalContext& eval_context, SemIRLoc loc,
           // say if it's referring to the left or the right side for the error.
           // The `arg_id` instruction has no location in it for some reason.
           context.emitter().Emit(
-              loc, FacetTypeRequiredForTypeAndOperator,
+              loc_id, FacetTypeRequiredForTypeAndOperator,
               context.types().GetTypeIdForTypeInstId(type_arg_id));
         }
       }
@@ -1430,12 +1433,12 @@ static auto MakeConstantForBuiltinCall(EvalContext& eval_context, SemIRLoc loc,
     }
 
     case SemIR::BuiltinFunctionKind::IntMakeTypeSigned: {
-      return MakeIntTypeResult(context, loc, SemIR::IntKind::Signed, arg_ids[0],
-                               phase);
+      return MakeIntTypeResult(context, loc_id, SemIR::IntKind::Signed,
+                               arg_ids[0], phase);
     }
 
     case SemIR::BuiltinFunctionKind::IntMakeTypeUnsigned: {
-      return MakeIntTypeResult(context, loc, SemIR::IntKind::Unsigned,
+      return MakeIntTypeResult(context, loc_id, SemIR::IntKind::Unsigned,
                                arg_ids[0], phase);
     }
 
@@ -1444,7 +1447,7 @@ static auto MakeConstantForBuiltinCall(EvalContext& eval_context, SemIRLoc loc,
       if (phase != Phase::Concrete) {
         break;
       }
-      if (!ValidateFloatBitWidth(context, loc, arg_ids[0])) {
+      if (!ValidateFloatBitWidth(context, loc_id, arg_ids[0])) {
         return SemIR::ErrorInst::SingletonConstantId;
       }
       return context.constant_values().Get(
@@ -1466,7 +1469,8 @@ static auto MakeConstantForBuiltinCall(EvalContext& eval_context, SemIRLoc loc,
       if (phase != Phase::Concrete) {
         return MakeConstantResult(context, call, phase);
       }
-      return PerformCheckedIntConvert(context, loc, arg_ids[0], call.type_id);
+      return PerformCheckedIntConvert(context, loc_id, arg_ids[0],
+                                      call.type_id);
     }
 
     // Unary integer -> integer operations.
@@ -1476,7 +1480,8 @@ static auto MakeConstantForBuiltinCall(EvalContext& eval_context, SemIRLoc loc,
       if (phase != Phase::Concrete) {
         break;
       }
-      return PerformBuiltinUnaryIntOp(context, loc, builtin_kind, arg_ids[0]);
+      return PerformBuiltinUnaryIntOp(context, loc_id, builtin_kind,
+                                      arg_ids[0]);
     }
 
     // Homogeneous binary integer -> integer operations.
@@ -1496,8 +1501,8 @@ static auto MakeConstantForBuiltinCall(EvalContext& eval_context, SemIRLoc loc,
       if (phase != Phase::Concrete) {
         break;
       }
-      return PerformBuiltinBinaryIntOp(context, loc, builtin_kind, arg_ids[0],
-                                       arg_ids[1]);
+      return PerformBuiltinBinaryIntOp(context, loc_id, builtin_kind,
+                                       arg_ids[0], arg_ids[1]);
     }
 
     // Bit shift operations.
@@ -1506,7 +1511,7 @@ static auto MakeConstantForBuiltinCall(EvalContext& eval_context, SemIRLoc loc,
       if (phase != Phase::Concrete) {
         break;
       }
-      return PerformBuiltinIntShiftOp(context, loc, builtin_kind, arg_ids[0],
+      return PerformBuiltinIntShiftOp(context, loc_id, builtin_kind, arg_ids[0],
                                       arg_ids[1]);
     }
 
@@ -1574,7 +1579,7 @@ static auto MakeConstantForBuiltinCall(EvalContext& eval_context, SemIRLoc loc,
 }
 
 // Makes a constant for a call instruction.
-static auto MakeConstantForCall(EvalContext& eval_context, SemIRLoc loc,
+static auto MakeConstantForCall(EvalContext& eval_context, SemIR::LocId loc_id,
                                 SemIR::Call call) -> SemIR::ConstantId {
   Phase phase = Phase::Concrete;
 
@@ -1630,7 +1635,7 @@ static auto MakeConstantForCall(EvalContext& eval_context, SemIRLoc loc,
       CARBON_DIAGNOSTIC(CompTimeOnlyFunctionHere, Note,
                         "compile-time-only function declared here");
       eval_context.emitter()
-          .Build(loc, NonConstantCallToCompTimeOnlyFunction)
+          .Build(loc_id, NonConstantCallToCompTimeOnlyFunction)
           .Note(eval_context.functions()
                     .Get(callee_function.function_id)
                     .latest_decl_id(),
@@ -1643,7 +1648,7 @@ static auto MakeConstantForCall(EvalContext& eval_context, SemIRLoc loc,
   // Handle calls to builtins.
   if (builtin_kind != SemIR::BuiltinFunctionKind::None) {
     return MakeConstantForBuiltinCall(
-        eval_context, loc, call, builtin_kind,
+        eval_context, loc_id, call, builtin_kind,
         eval_context.inst_blocks().Get(call.args_id), phase);
   }
 
@@ -1948,7 +1953,7 @@ auto TryEvalInstUnsafe(Context& context, SemIR::InstId inst_id,
   return TryEvalInstInContext(eval_context, inst_id, inst);
 }
 
-auto TryEvalBlockForSpecific(Context& context, SemIRLoc loc,
+auto TryEvalBlockForSpecific(Context& context, SemIR::LocId loc_id,
                              SemIR::SpecificId specific_id,
                              SemIR::GenericInstIndex::Region region)
     -> SemIR::InstBlockId {
@@ -1959,7 +1964,7 @@ auto TryEvalBlockForSpecific(Context& context, SemIRLoc loc,
   llvm::SmallVector<SemIR::InstId> result;
   result.resize(eval_block.size(), SemIR::InstId::None);
 
-  EvalContext eval_context(&context, loc, specific_id,
+  EvalContext eval_context(&context, loc_id, specific_id,
                            SpecificEvalInfo{
                                .region = region,
                                .values = result,
@@ -1969,7 +1974,7 @@ auto TryEvalBlockForSpecific(Context& context, SemIRLoc loc,
       &context.emitter(), [&](auto& builder) {
         CARBON_DIAGNOSTIC(ResolvingSpecificHere, Note, "in {0} used here",
                           SemIR::SpecificId);
-        builder.Note(loc, ResolvingSpecificHere, specific_id);
+        builder.Note(loc_id, ResolvingSpecificHere, specific_id);
       });
 
   for (auto [i, inst_id] : llvm::enumerate(eval_block)) {

+ 1 - 1
toolchain/check/eval.h

@@ -52,7 +52,7 @@ auto TryEvalInst(Context& context, InstT inst) -> SemIR::ConstantId {
 // Evaluates the eval block for a region of a specific. Produces a block
 // containing the evaluated constant values of the instructions in the eval
 // block.
-auto TryEvalBlockForSpecific(Context& context, SemIRLoc loc,
+auto TryEvalBlockForSpecific(Context& context, SemIR::LocId loc_id,
                              SemIR::SpecificId specific_id,
                              SemIR::GenericInstIndex::Region region)
     -> SemIR::InstBlockId;

+ 5 - 5
toolchain/check/facet_type.cpp

@@ -39,20 +39,20 @@ static auto WitnessAccessMatchesInterface(
 }
 
 static auto IncompleteFacetTypeDiagnosticBuilder(
-    Context& context, SemIRLoc loc, SemIR::TypeInstId facet_type_inst_id,
+    Context& context, SemIR::LocId loc_id, SemIR::TypeInstId facet_type_inst_id,
     bool is_definition) -> DiagnosticBuilder {
   if (is_definition) {
     CARBON_DIAGNOSTIC(ImplAsIncompleteFacetTypeDefinition, Error,
                       "definition of impl as incomplete facet type {0}",
                       InstIdAsType);
-    return context.emitter().Build(loc, ImplAsIncompleteFacetTypeDefinition,
+    return context.emitter().Build(loc_id, ImplAsIncompleteFacetTypeDefinition,
                                    facet_type_inst_id);
   } else {
     CARBON_DIAGNOSTIC(
         ImplAsIncompleteFacetTypeRewrites, Error,
         "declaration of impl as incomplete facet type {0} with rewrites",
         InstIdAsType);
-    return context.emitter().Build(loc, ImplAsIncompleteFacetTypeRewrites,
+    return context.emitter().Build(loc_id, ImplAsIncompleteFacetTypeRewrites,
                                    facet_type_inst_id);
   }
 }
@@ -244,14 +244,14 @@ auto InitialFacetTypeImplWitness(
 }
 
 auto RequireCompleteFacetTypeForImplDefinition(
-    Context& context, SemIRLoc loc, SemIR::TypeInstId facet_type_inst_id)
+    Context& context, SemIR::LocId loc_id, SemIR::TypeInstId facet_type_inst_id)
     -> bool {
   auto facet_type_id =
       context.types().GetTypeIdForTypeInstId(facet_type_inst_id);
   return RequireCompleteType(context, facet_type_id,
                              context.insts().GetLocId(facet_type_inst_id), [&] {
                                return IncompleteFacetTypeDiagnosticBuilder(
-                                   context, loc, facet_type_inst_id,
+                                   context, loc_id, facet_type_inst_id,
                                    /*is_definition=*/true);
                              });
 }

+ 1 - 1
toolchain/check/facet_type.h

@@ -48,7 +48,7 @@ auto InitialFacetTypeImplWitness(
 // Returns `true` if the facet type is complete. Otherwise issues a diagnostic
 // and returns `false`.
 auto RequireCompleteFacetTypeForImplDefinition(
-    Context& context, SemIRLoc loc, SemIR::TypeInstId facet_type_inst_id)
+    Context& context, SemIR::LocId loc_id, SemIR::TypeInstId facet_type_inst_id)
     -> bool;
 
 // Replaces the placeholder created by `InitialFacetTypeImplWitness` with an

+ 17 - 14
toolchain/check/generic.cpp

@@ -466,7 +466,7 @@ auto BuildGeneric(Context& context, SemIR::InstId decl_id) -> SemIR::GenericId {
   return generic_id;
 }
 
-auto FinishGenericDecl(Context& context, SemIRLoc loc,
+auto FinishGenericDecl(Context& context, SemIR::LocId loc_id,
                        SemIR::GenericId generic_id) -> void {
   if (!generic_id.has_value()) {
     return;
@@ -477,7 +477,7 @@ auto FinishGenericDecl(Context& context, SemIRLoc loc,
   context.generic_region_stack().Pop();
   context.generics().Get(generic_id).decl_block_id = decl_block_id;
 
-  ResolveSpecificDeclaration(context, loc,
+  ResolveSpecificDeclaration(context, loc_id,
                              context.generics().GetSelfSpecific(generic_id));
 }
 
@@ -524,7 +524,7 @@ auto FinishGenericDefinition(Context& context, SemIR::GenericId generic_id)
   context.generic_region_stack().Pop();
 }
 
-auto ResolveSpecificDeclaration(Context& context, SemIRLoc loc,
+auto ResolveSpecificDeclaration(Context& context, SemIR::LocId loc_id,
                                 SemIR::SpecificId specific_id) -> void {
   // If this is the first time we've formed this specific, evaluate its decl
   // block to form information about the specific.
@@ -535,7 +535,7 @@ auto ResolveSpecificDeclaration(Context& context, SemIRLoc loc,
         SemIR::InstBlockId::Empty;
 
     auto decl_block_id =
-        TryEvalBlockForSpecific(context, loc, specific_id,
+        TryEvalBlockForSpecific(context, loc_id, specific_id,
                                 SemIR::GenericInstIndex::Region::Declaration);
     // Note that TryEvalBlockForSpecific may reallocate the list of specifics,
     // so re-lookup the specific here.
@@ -543,17 +543,19 @@ auto ResolveSpecificDeclaration(Context& context, SemIRLoc loc,
   }
 }
 
-auto MakeSpecific(Context& context, SemIRLoc loc, SemIR::GenericId generic_id,
-                  SemIR::InstBlockId args_id) -> SemIR::SpecificId {
+auto MakeSpecific(Context& context, SemIR::LocId loc_id,
+                  SemIR::GenericId generic_id, SemIR::InstBlockId args_id)
+    -> SemIR::SpecificId {
   auto specific_id = context.specifics().GetOrAdd(generic_id, args_id);
-  ResolveSpecificDeclaration(context, loc, specific_id);
+  ResolveSpecificDeclaration(context, loc_id, specific_id);
   return specific_id;
 }
 
-auto MakeSpecific(Context& context, SemIRLoc loc, SemIR::GenericId generic_id,
+auto MakeSpecific(Context& context, SemIR::LocId loc_id,
+                  SemIR::GenericId generic_id,
                   llvm::ArrayRef<SemIR::InstId> args) -> SemIR::SpecificId {
   auto args_id = context.inst_blocks().AddCanonical(args);
-  return MakeSpecific(context, loc, generic_id, args_id);
+  return MakeSpecific(context, loc_id, generic_id, args_id);
 }
 
 static auto MakeSelfSpecificId(Context& context, SemIR::GenericId generic_id)
@@ -575,18 +577,18 @@ static auto MakeSelfSpecificId(Context& context, SemIR::GenericId generic_id)
   return context.specifics().GetOrAdd(generic_id, args_id);
 }
 
-auto MakeSelfSpecific(Context& context, SemIRLoc loc,
+auto MakeSelfSpecific(Context& context, SemIR::LocId loc_id,
                       SemIR::GenericId generic_id) -> SemIR::SpecificId {
   // Build a corresponding specific.
   SemIR::SpecificId specific_id = MakeSelfSpecificId(context, generic_id);
   // TODO: This could be made more efficient. We don't need to perform
   // substitution here; we know we want identity mappings for all constants and
   // types. We could also consider not storing the mapping at all in this case.
-  ResolveSpecificDeclaration(context, loc, specific_id);
+  ResolveSpecificDeclaration(context, loc_id, specific_id);
   return specific_id;
 }
 
-auto ResolveSpecificDefinition(Context& context, SemIRLoc loc,
+auto ResolveSpecificDefinition(Context& context, SemIR::LocId loc_id,
                                SemIR::SpecificId specific_id) -> bool {
   // TODO: Handle recursive resolution of the same generic definition.
   auto& specific = context.specifics().Get(specific_id);
@@ -600,8 +602,9 @@ auto ResolveSpecificDefinition(Context& context, SemIRLoc loc,
       // The generic is not defined yet.
       return false;
     }
-    auto definition_block_id = TryEvalBlockForSpecific(
-        context, loc, specific_id, SemIR::GenericInstIndex::Region::Definition);
+    auto definition_block_id =
+        TryEvalBlockForSpecific(context, loc_id, specific_id,
+                                SemIR::GenericInstIndex::Region::Definition);
     // Note that TryEvalBlockForSpecific may reallocate the list of specifics,
     // so re-lookup the specific here.
     context.specifics().Get(specific_id).definition_block_id =

+ 9 - 7
toolchain/check/generic.h

@@ -28,7 +28,7 @@ auto DiscardGenericDecl(Context& context) -> void;
 auto BuildGeneric(Context& context, SemIR::InstId decl_id) -> SemIR::GenericId;
 
 // Builds eval block for the declaration.
-auto FinishGenericDecl(Context& context, SemIRLoc loc,
+auto FinishGenericDecl(Context& context, SemIR::LocId loc_id,
                        SemIR::GenericId generic_id) -> void;
 
 // BuildGeneric() and FinishGenericDecl() combined. Normally you would call this
@@ -55,31 +55,33 @@ auto RebuildGenericEvalBlock(Context& context, SemIR::GenericId generic_id,
 // Builds a new specific with a given argument list, or finds an existing one if
 // this generic has already been referenced with these arguments. Performs
 // substitution into the declaration, but not the definition, of the generic.
-auto MakeSpecific(Context& context, SemIRLoc loc, SemIR::GenericId generic_id,
+auto MakeSpecific(Context& context, SemIR::LocId loc_id,
+                  SemIR::GenericId generic_id,
                   llvm::ArrayRef<SemIR::InstId> args) -> SemIR::SpecificId;
 
 // Builds a new specific or finds an existing one in the case where the argument
 // list has already been converted into an instruction block. `args_id` should
 // be a canonical instruction block referring to constants.
-auto MakeSpecific(Context& context, SemIRLoc loc, SemIR::GenericId generic_id,
-                  SemIR::InstBlockId args_id) -> SemIR::SpecificId;
+auto MakeSpecific(Context& context, SemIR::LocId loc_id,
+                  SemIR::GenericId generic_id, SemIR::InstBlockId args_id)
+    -> SemIR::SpecificId;
 
 // Builds the specific that describes how the generic should refer to itself.
 // For example, for a generic `G(T:! type)`, this is the specific `G(T)`. If
 // `generic_id` is `None`, returns `None`.
-auto MakeSelfSpecific(Context& context, SemIRLoc loc,
+auto MakeSelfSpecific(Context& context, SemIR::LocId loc_id,
                       SemIR::GenericId generic_id) -> SemIR::SpecificId;
 
 // Resolve the declaration of the given specific, by evaluating the eval block
 // of the corresponding generic and storing a corresponding value block in the
 // specific.
-auto ResolveSpecificDeclaration(Context& context, SemIRLoc loc,
+auto ResolveSpecificDeclaration(Context& context, SemIR::LocId loc_id,
                                 SemIR::SpecificId specific_id) -> void;
 
 // Attempts to resolve the definition of the given specific, by evaluating the
 // eval block of the corresponding generic and storing a corresponding value
 // block in the specific. Returns false if a definition is not available.
-auto ResolveSpecificDefinition(Context& context, SemIRLoc loc,
+auto ResolveSpecificDefinition(Context& context, SemIR::LocId loc_id,
                                SemIR::SpecificId specific_id) -> bool;
 
 // Diagnoses if an entity has implicit parameters, indicating it's generic, but

+ 12 - 11
toolchain/check/handle_class.cpp

@@ -54,7 +54,7 @@ static auto MergeClassRedecl(Context& context, Parse::AnyClassDeclId node_id,
                              SemIR::ClassId prev_class_id,
                              SemIR::ImportIRId prev_import_ir_id) -> bool {
   auto& prev_class = context.classes().Get(prev_class_id);
-  SemIRLoc prev_loc = prev_class.latest_decl_id();
+  SemIR::LocId prev_loc_id = prev_class.latest_decl_id();
 
   // Check the generic parameters match, if they were specified.
   if (!CheckRedeclParamsMatch(context, DeclParams(new_class),
@@ -65,7 +65,7 @@ static auto MergeClassRedecl(Context& context, Parse::AnyClassDeclId node_id,
   DiagnoseIfInvalidRedecl(
       context, Lex::TokenKind::Class, prev_class.name_id,
       RedeclInfo(new_class, node_id, new_is_definition),
-      RedeclInfo(prev_class, prev_loc, prev_class.has_definition_started()),
+      RedeclInfo(prev_class, prev_loc_id, prev_class.has_definition_started()),
       prev_import_ir_id);
 
   if (new_is_definition && prev_class.has_definition_started()) {
@@ -301,22 +301,23 @@ auto HandleParseNode(Context& context, Parse::ClassDefinitionStartId node_id)
 
 // Diagnoses a class-specific declaration appearing outside a class.
 static auto DiagnoseClassSpecificDeclOutsideClass(Context& context,
-                                                  SemIRLoc loc,
+                                                  SemIR::LocId loc_id,
                                                   Lex::TokenKind tok) -> void {
   CARBON_DIAGNOSTIC(ClassSpecificDeclOutsideClass, Error,
                     "`{0}` declaration outside class", Lex::TokenKind);
-  context.emitter().Emit(loc, ClassSpecificDeclOutsideClass, tok);
+  context.emitter().Emit(loc_id, ClassSpecificDeclOutsideClass, tok);
 }
 
 // Returns the current scope's class declaration, or diagnoses if it isn't a
 // class.
-static auto GetCurrentScopeAsClassOrDiagnose(Context& context, SemIRLoc loc,
+static auto GetCurrentScopeAsClassOrDiagnose(Context& context,
+                                             SemIR::LocId loc_id,
                                              Lex::TokenKind tok)
     -> std::optional<SemIR::ClassDecl> {
   auto class_scope =
       context.scope_stack().GetCurrentScopeAs<SemIR::ClassDecl>();
   if (!class_scope) {
-    DiagnoseClassSpecificDeclOutsideClass(context, loc, tok);
+    DiagnoseClassSpecificDeclOutsideClass(context, loc_id, tok);
   }
   return class_scope;
 }
@@ -324,8 +325,8 @@ static auto GetCurrentScopeAsClassOrDiagnose(Context& context, SemIRLoc loc,
 // Diagnoses a class-specific declaration that is repeated within a class, but
 // is not permitted to be repeated.
 static auto DiagnoseClassSpecificDeclRepeated(Context& context,
-                                              SemIRLoc new_loc,
-                                              SemIRLoc prev_loc,
+                                              SemIR::LocId new_loc_id,
+                                              SemIR::LocId prev_loc_id,
                                               Lex::TokenKind tok) -> void {
   CARBON_DIAGNOSTIC(AdaptDeclRepeated, Error,
                     "multiple `adapt` declarations in class");
@@ -336,9 +337,9 @@ static auto DiagnoseClassSpecificDeclRepeated(Context& context,
                     "previous `{0}` declaration is here", Lex::TokenKind);
   CARBON_CHECK(tok == Lex::TokenKind::Adapt || tok == Lex::TokenKind::Base);
   context.emitter()
-      .Build(new_loc, tok == Lex::TokenKind::Adapt ? AdaptDeclRepeated
-                                                   : BaseDeclRepeated)
-      .Note(prev_loc, ClassSpecificDeclPrevious, tok)
+      .Build(new_loc_id, tok == Lex::TokenKind::Adapt ? AdaptDeclRepeated
+                                                      : BaseDeclRepeated)
+      .Note(prev_loc_id, ClassSpecificDeclPrevious, tok)
       .Emit();
 }
 

+ 2 - 2
toolchain/check/import.cpp

@@ -608,7 +608,7 @@ static auto AddNamespaceFromOtherPackage(Context& context,
 }
 
 auto ImportNameFromOtherPackage(
-    Context& context, SemIRLoc loc, SemIR::NameScopeId scope_id,
+    Context& context, SemIR::LocId loc_id, SemIR::NameScopeId scope_id,
     llvm::ArrayRef<std::pair<SemIR::ImportIRId, SemIR::NameScopeId>>
         import_ir_scopes,
     SemIR::NameId name_id) -> SemIR::InstId {
@@ -626,7 +626,7 @@ auto ImportNameFromOtherPackage(
       &context.emitter(), [&](auto& builder) {
         CARBON_DIAGNOSTIC(InNameLookup, Note, "in name lookup for `{0}`",
                           SemIR::NameId);
-        builder.Note(loc, InNameLookup, name_id);
+        builder.Note(loc_id, InNameLookup, name_id);
       });
 
   // Although we track the result here and look in each IR, we pretty much use

+ 1 - 1
toolchain/check/import.h

@@ -88,7 +88,7 @@ auto ImportLibrariesFromOtherPackage(Context& context,
 // Arguments are all in the context of the current IR. Scope lookup is expected
 // to be resolved first.
 auto ImportNameFromOtherPackage(
-    Context& context, SemIRLoc loc, SemIR::NameScopeId scope_id,
+    Context& context, SemIR::LocId loc_id, SemIR::NameScopeId scope_id,
     llvm::ArrayRef<std::pair<SemIR::ImportIRId, SemIR::NameScopeId>>
         import_ir_scopes,
     SemIR::NameId name_id) -> SemIR::InstId;

+ 11 - 10
toolchain/check/import_cpp.cpp

@@ -55,8 +55,8 @@ class CarbonClangDiagnosticConsumer : public clang::DiagnosticConsumer {
  public:
   // Creates an instance with the location that triggers calling Clang.
   // `context` must not be null.
-  explicit CarbonClangDiagnosticConsumer(Context* context, SemIRLoc loc)
-      : context_(context), loc_(loc) {}
+  explicit CarbonClangDiagnosticConsumer(Context* context, SemIR::LocId loc_id)
+      : context_(context), loc_id_(loc_id) {}
 
   // Generates a Carbon warning for each Clang warning and a Carbon error for
   // each Clang error or fatal.
@@ -87,9 +87,10 @@ class CarbonClangDiagnosticConsumer : public clang::DiagnosticConsumer {
       case clang::DiagnosticsEngine::Note:
       case clang::DiagnosticsEngine::Remark: {
         context_->TODO(
-            loc_, llvm::formatv(
-                      "Unsupported: C++ diagnostic level for diagnostic\n{0}",
-                      diagnostics_str));
+            loc_id_,
+            llvm::formatv(
+                "Unsupported: C++ diagnostic level for diagnostic\n{0}",
+                diagnostics_str));
         return;
       }
       case clang::DiagnosticsEngine::Warning:
@@ -112,7 +113,7 @@ class CarbonClangDiagnosticConsumer : public clang::DiagnosticConsumer {
                        ? CppInteropParseWarning
                        : CppInteropParseError,
                    diagnostics_str)
-            .Note(loc_, InCppImport)
+            .Note(loc_id_, InCppImport)
             .Emit();
         return;
       }
@@ -124,7 +125,7 @@ class CarbonClangDiagnosticConsumer : public clang::DiagnosticConsumer {
   Context* context_;
 
   // The location that triggered calling Clang.
-  SemIRLoc loc_;
+  SemIR::LocId loc_id_;
 };
 
 }  // namespace
@@ -139,9 +140,9 @@ static auto GenerateAst(Context& context, llvm::StringRef importing_file_path,
     -> std::pair<std::unique_ptr<clang::ASTUnit>, bool> {
   // TODO: Use all import locations by referring each Clang diagnostic to the
   // relevant import.
-  SemIRLoc loc = imports.back().node_id;
+  SemIR::LocId loc_id = imports.back().node_id;
 
-  CarbonClangDiagnosticConsumer diagnostics_consumer(&context, loc);
+  CarbonClangDiagnosticConsumer diagnostics_consumer(&context, loc_id);
 
   // TODO: Share compilation flags with ClangRunner.
   auto ast = clang::tooling::buildASTFromCodeWithArgs(
@@ -327,7 +328,7 @@ static auto MakeParamPatternsBlockId(Context& context, SemIR::LocId loc_id,
 // Returns the return type of the given function declaration.
 // Currently only void and 32-bit int are supported.
 // TODO: Support more return types.
-static auto GetReturnType(Context& context, SemIRLoc loc_id,
+static auto GetReturnType(Context& context, SemIR::LocId loc_id,
                           const clang::FunctionDecl* clang_decl)
     -> SemIR::InstId {
   clang::QualType ret_type = clang_decl->getReturnType().getCanonicalType();

+ 7 - 7
toolchain/check/interface.cpp

@@ -125,10 +125,10 @@ static auto GetGenericArgsWithSelfType(Context& context,
 }
 
 auto GetSelfSpecificForInterfaceMemberWithSelfType(
-    Context& context, SemIRLoc loc, SemIR::SpecificId interface_specific_id,
-    SemIR::GenericId generic_id, SemIR::SpecificId enclosing_specific_id,
-    SemIR::TypeId self_type_id, SemIR::InstId witness_inst_id)
-    -> SemIR::SpecificId {
+    Context& context, SemIR::LocId loc_id,
+    SemIR::SpecificId interface_specific_id, SemIR::GenericId generic_id,
+    SemIR::SpecificId enclosing_specific_id, SemIR::TypeId self_type_id,
+    SemIR::InstId witness_inst_id) -> SemIR::SpecificId {
   const auto& generic = context.generics().Get(generic_id);
   auto self_specific_args = context.inst_blocks().Get(
       context.specifics().Get(generic.self_specific_id).args_id);
@@ -169,10 +169,10 @@ auto GetSelfSpecificForInterfaceMemberWithSelfType(
     arg_ids.push_back(new_arg_id);
   }
 
-  return MakeSpecific(context, loc, generic_id, arg_ids);
+  return MakeSpecific(context, loc_id, generic_id, arg_ids);
 }
 
-auto GetTypeForSpecificAssociatedEntity(Context& context, SemIRLoc loc,
+auto GetTypeForSpecificAssociatedEntity(Context& context, SemIR::LocId loc_id,
                                         SemIR::SpecificId interface_specific_id,
                                         SemIR::InstId decl_id,
                                         SemIR::TypeId self_type_id,
@@ -189,7 +189,7 @@ auto GetTypeForSpecificAssociatedEntity(Context& context, SemIRLoc loc,
     auto arg_ids =
         GetGenericArgsWithSelfType(context, interface_specific_id, generic_id,
                                    self_type_id, self_witness_id);
-    auto const_specific_id = MakeSpecific(context, loc, generic_id, arg_ids);
+    auto const_specific_id = MakeSpecific(context, loc_id, generic_id, arg_ids);
     return SemIR::GetTypeOfInstInSpecific(context.sem_ir(), const_specific_id,
                                           decl_id);
   } else if (auto fn = context.types().TryGetAs<SemIR::FunctionType>(

+ 5 - 5
toolchain/check/interface.h

@@ -20,14 +20,14 @@ auto BuildAssociatedEntity(Context& context, SemIR::InterfaceId interface_id,
 // Gets the self specific of a generic declaration that is an interface member,
 // given a specific for the interface plus a type to use as `Self`.
 auto GetSelfSpecificForInterfaceMemberWithSelfType(
-    Context& context, SemIRLoc loc, SemIR::SpecificId interface_specific_id,
-    SemIR::GenericId generic_id, SemIR::SpecificId enclosing_specific_id,
-    SemIR::TypeId self_type_id, SemIR::InstId witness_inst_id)
-    -> SemIR::SpecificId;
+    Context& context, SemIR::LocId loc_id,
+    SemIR::SpecificId interface_specific_id, SemIR::GenericId generic_id,
+    SemIR::SpecificId enclosing_specific_id, SemIR::TypeId self_type_id,
+    SemIR::InstId witness_inst_id) -> SemIR::SpecificId;
 
 // Gets the type of the specified associated entity, given the specific for the
 // interface and the type of `Self`.
-auto GetTypeForSpecificAssociatedEntity(Context& context, SemIRLoc loc,
+auto GetTypeForSpecificAssociatedEntity(Context& context, SemIR::LocId loc_id,
                                         SemIR::SpecificId interface_specific_id,
                                         SemIR::InstId decl_id,
                                         SemIR::TypeId self_type_id,

+ 55 - 50
toolchain/check/merge.cpp

@@ -17,40 +17,41 @@ CARBON_DIAGNOSTIC(RedeclPrevDecl, Note, "previously declared here");
 
 // Diagnoses a redeclaration which is redundant.
 static auto DiagnoseRedundant(Context& context, Lex::TokenKind decl_kind,
-                              SemIR::NameId name_id, SemIRLoc new_loc,
-                              SemIRLoc prev_loc) -> void {
+                              SemIR::NameId name_id, SemIR::LocId new_loc_id,
+                              SemIR::LocId prev_loc_id) -> void {
   CARBON_DIAGNOSTIC(RedeclRedundant, Error,
                     "redeclaration of `{0} {1}` is redundant", Lex::TokenKind,
                     SemIR::NameId);
   context.emitter()
-      .Build(new_loc, RedeclRedundant, decl_kind, name_id)
-      .Note(prev_loc, RedeclPrevDecl)
+      .Build(new_loc_id, RedeclRedundant, decl_kind, name_id)
+      .Note(prev_loc_id, RedeclPrevDecl)
       .Emit();
 }
 
 // Diagnoses a redefinition.
 static auto DiagnoseRedef(Context& context, Lex::TokenKind decl_kind,
-                          SemIR::NameId name_id, SemIRLoc new_loc,
-                          SemIRLoc prev_loc) -> void {
+                          SemIR::NameId name_id, SemIR::LocId new_loc_id,
+                          SemIR::LocId prev_loc_id) -> void {
   CARBON_DIAGNOSTIC(RedeclRedef, Error, "redefinition of `{0} {1}`",
                     Lex::TokenKind, SemIR::NameId);
   CARBON_DIAGNOSTIC(RedeclPrevDef, Note, "previously defined here");
   context.emitter()
-      .Build(new_loc, RedeclRedef, decl_kind, name_id)
-      .Note(prev_loc, RedeclPrevDef)
+      .Build(new_loc_id, RedeclRedef, decl_kind, name_id)
+      .Note(prev_loc_id, RedeclPrevDef)
       .Emit();
 }
 
 // Diagnoses an `extern` versus non-`extern` mismatch.
 static auto DiagnoseExternMismatch(Context& context, Lex::TokenKind decl_kind,
-                                   SemIR::NameId name_id, SemIRLoc new_loc,
-                                   SemIRLoc prev_loc) -> void {
+                                   SemIR::NameId name_id,
+                                   SemIR::LocId new_loc_id,
+                                   SemIR::LocId prev_loc_id) -> void {
   CARBON_DIAGNOSTIC(RedeclExternMismatch, Error,
                     "redeclarations of `{0} {1}` must match use of `extern`",
                     Lex::TokenKind, SemIR::NameId);
   context.emitter()
-      .Build(new_loc, RedeclExternMismatch, decl_kind, name_id)
-      .Note(prev_loc, RedeclPrevDecl)
+      .Build(new_loc_id, RedeclExternMismatch, decl_kind, name_id)
+      .Note(prev_loc_id, RedeclPrevDecl)
       .Emit();
 }
 
@@ -58,20 +59,21 @@ static auto DiagnoseExternMismatch(Context& context, Lex::TokenKind decl_kind,
 static auto DiagnoseExternLibraryInImporter(Context& context,
                                             Lex::TokenKind decl_kind,
                                             SemIR::NameId name_id,
-                                            SemIRLoc new_loc, SemIRLoc prev_loc)
-    -> void {
+                                            SemIR::LocId new_loc_id,
+                                            SemIR::LocId prev_loc_id) -> void {
   CARBON_DIAGNOSTIC(ExternLibraryInImporter, Error,
                     "cannot declare imported `{0} {1}` as `extern library`",
                     Lex::TokenKind, SemIR::NameId);
   context.emitter()
-      .Build(new_loc, ExternLibraryInImporter, decl_kind, name_id)
-      .Note(prev_loc, RedeclPrevDecl)
+      .Build(new_loc_id, ExternLibraryInImporter, decl_kind, name_id)
+      .Note(prev_loc_id, RedeclPrevDecl)
       .Emit();
 }
 
 // Diagnoses `extern library` pointing to the wrong library.
-static auto DiagnoseExternLibraryIncorrect(Context& context, SemIRLoc new_loc,
-                                           SemIRLoc prev_loc) -> void {
+static auto DiagnoseExternLibraryIncorrect(Context& context,
+                                           SemIR::LocId new_loc_id,
+                                           SemIR::LocId prev_loc_id) -> void {
   CARBON_DIAGNOSTIC(
       ExternLibraryIncorrect, Error,
       "declaration in {0} doesn't match `extern library` declaration",
@@ -79,17 +81,17 @@ static auto DiagnoseExternLibraryIncorrect(Context& context, SemIRLoc new_loc,
   CARBON_DIAGNOSTIC(ExternLibraryExpected, Note,
                     "previously declared with `extern library` here");
   context.emitter()
-      .Build(new_loc, ExternLibraryIncorrect, context.sem_ir().library_id())
-      .Note(prev_loc, ExternLibraryExpected)
+      .Build(new_loc_id, ExternLibraryIncorrect, context.sem_ir().library_id())
+      .Note(prev_loc_id, ExternLibraryExpected)
       .Emit();
 }
 
-auto DiagnoseExternRequiresDeclInApiFile(Context& context, SemIRLoc loc)
+auto DiagnoseExternRequiresDeclInApiFile(Context& context, SemIR::LocId loc_id)
     -> void {
   CARBON_DIAGNOSTIC(
       ExternRequiresDeclInApiFile, Error,
       "`extern` entities must have a declaration in the API file");
-  context.emitter().Emit(loc, ExternRequiresDeclInApiFile);
+  context.emitter().Emit(loc_id, ExternRequiresDeclInApiFile);
 }
 
 auto DiagnoseIfInvalidRedecl(Context& context, Lex::TokenKind decl_kind,
@@ -99,17 +101,18 @@ auto DiagnoseIfInvalidRedecl(Context& context, Lex::TokenKind decl_kind,
   if (!import_ir_id.has_value()) {
     // Check for disallowed redeclarations in the same file.
     if (!new_decl.is_definition) {
-      DiagnoseRedundant(context, decl_kind, name_id, new_decl.loc,
-                        prev_decl.loc);
+      DiagnoseRedundant(context, decl_kind, name_id, new_decl.loc_id,
+                        prev_decl.loc_id);
       return;
     }
     if (prev_decl.is_definition) {
-      DiagnoseRedef(context, decl_kind, name_id, new_decl.loc, prev_decl.loc);
+      DiagnoseRedef(context, decl_kind, name_id, new_decl.loc_id,
+                    prev_decl.loc_id);
       return;
     }
     if (prev_decl.is_extern != new_decl.is_extern) {
-      DiagnoseExternMismatch(context, decl_kind, name_id, new_decl.loc,
-                             prev_decl.loc);
+      DiagnoseExternMismatch(context, decl_kind, name_id, new_decl.loc_id,
+                             prev_decl.loc_id);
       return;
     }
     return;
@@ -120,16 +123,17 @@ auto DiagnoseIfInvalidRedecl(Context& context, Lex::TokenKind decl_kind,
     // forward declaration in the impl is allowed.
     if (prev_decl.is_definition) {
       if (new_decl.is_definition) {
-        DiagnoseRedef(context, decl_kind, name_id, new_decl.loc, prev_decl.loc);
+        DiagnoseRedef(context, decl_kind, name_id, new_decl.loc_id,
+                      prev_decl.loc_id);
       } else {
-        DiagnoseRedundant(context, decl_kind, name_id, new_decl.loc,
-                          prev_decl.loc);
+        DiagnoseRedundant(context, decl_kind, name_id, new_decl.loc_id,
+                          prev_decl.loc_id);
       }
       return;
     }
     if (prev_decl.is_extern != new_decl.is_extern) {
-      DiagnoseExternMismatch(context, decl_kind, name_id, new_decl.loc,
-                             prev_decl.loc);
+      DiagnoseExternMismatch(context, decl_kind, name_id, new_decl.loc_id,
+                             prev_decl.loc_id);
       return;
     }
     return;
@@ -140,26 +144,26 @@ auto DiagnoseIfInvalidRedecl(Context& context, Lex::TokenKind decl_kind,
     // We continue after issuing the "missing API declaration" diagnostic,
     // because it may still be helpful to note other issues with the
     // declarations.
-    DiagnoseExternRequiresDeclInApiFile(context, new_decl.loc);
+    DiagnoseExternRequiresDeclInApiFile(context, new_decl.loc_id);
   }
   if (prev_decl.is_extern != new_decl.is_extern) {
-    DiagnoseExternMismatch(context, decl_kind, name_id, new_decl.loc,
-                           prev_decl.loc);
+    DiagnoseExternMismatch(context, decl_kind, name_id, new_decl.loc_id,
+                           prev_decl.loc_id);
     return;
   }
   if (!prev_decl.extern_library_id.has_value()) {
     if (new_decl.extern_library_id.has_value()) {
-      DiagnoseExternLibraryInImporter(context, decl_kind, name_id, new_decl.loc,
-                                      prev_decl.loc);
+      DiagnoseExternLibraryInImporter(context, decl_kind, name_id,
+                                      new_decl.loc_id, prev_decl.loc_id);
     } else {
-      DiagnoseRedundant(context, decl_kind, name_id, new_decl.loc,
-                        prev_decl.loc);
+      DiagnoseRedundant(context, decl_kind, name_id, new_decl.loc_id,
+                        prev_decl.loc_id);
     }
     return;
   }
   if (prev_decl.extern_library_id != SemIR::LibraryNameId::Error &&
       prev_decl.extern_library_id != context.sem_ir().library_id()) {
-    DiagnoseExternLibraryIncorrect(context, new_decl.loc, prev_decl.loc);
+    DiagnoseExternLibraryIncorrect(context, new_decl.loc_id, prev_decl.loc_id);
     return;
   }
 }
@@ -305,9 +309,9 @@ static auto CheckRedeclParam(Context& context, bool is_implicit_param,
 }
 
 // Returns false if the param refs differ for a redeclaration.
-static auto CheckRedeclParams(Context& context, SemIRLoc new_decl_loc,
+static auto CheckRedeclParams(Context& context, SemIR::LocId new_decl_loc_id,
                               SemIR::InstBlockId new_param_patterns_id,
-                              SemIRLoc prev_decl_loc,
+                              SemIR::LocId prev_decl_loc_id,
                               SemIR::InstBlockId prev_param_patterns_id,
                               bool is_implicit_param,
                               SemIR::SpecificId prev_specific_id, bool diagnose,
@@ -331,9 +335,9 @@ static auto CheckRedeclParams(Context& context, SemIRLoc new_decl_loc,
                       "{1:with|without} {0:implicit |}parameter list",
                       Diagnostics::BoolAsSelect, Diagnostics::BoolAsSelect);
     context.emitter()
-        .Build(new_decl_loc, RedeclParamListDiffers, is_implicit_param,
+        .Build(new_decl_loc_id, RedeclParamListDiffers, is_implicit_param,
                new_param_patterns_id.has_value())
-        .Note(prev_decl_loc, RedeclParamListPrevious, is_implicit_param,
+        .Note(prev_decl_loc_id, RedeclParamListPrevious, is_implicit_param,
               prev_param_patterns_id.has_value())
         .Emit();
     return false;
@@ -358,9 +362,9 @@ static auto CheckRedeclParams(Context& context, SemIRLoc new_decl_loc,
         "previously declared with {0:implicit |}parameter count of {1}",
         Diagnostics::BoolAsSelect, int32_t);
     context.emitter()
-        .Build(new_decl_loc, RedeclParamCountDiffers, is_implicit_param,
+        .Build(new_decl_loc_id, RedeclParamCountDiffers, is_implicit_param,
                new_param_pattern_ids.size())
-        .Note(prev_decl_loc, RedeclParamCountPrevious, is_implicit_param,
+        .Note(prev_decl_loc_id, RedeclParamCountPrevious, is_implicit_param,
               prev_param_pattern_ids.size())
         .Emit();
     return false;
@@ -487,15 +491,16 @@ auto CheckRedeclParamsMatch(Context& context, const DeclParams& new_entity,
     return false;
   }
   if (!CheckRedeclParams(
-          context, new_entity.loc, new_entity.implicit_param_patterns_id,
-          prev_entity.loc, prev_entity.implicit_param_patterns_id,
+          context, new_entity.loc_id, new_entity.implicit_param_patterns_id,
+          prev_entity.loc_id, prev_entity.implicit_param_patterns_id,
           /*is_implicit_param=*/true, prev_specific_id, diagnose, check_self)) {
     return false;
   }
   // Don't forward `check_self` here because it's extra cost, and `self` is only
   // allowed in implicit params.
-  if (!CheckRedeclParams(context, new_entity.loc, new_entity.param_patterns_id,
-                         prev_entity.loc, prev_entity.param_patterns_id,
+  if (!CheckRedeclParams(context, new_entity.loc_id,
+                         new_entity.param_patterns_id, prev_entity.loc_id,
+                         prev_entity.param_patterns_id,
                          /*is_implicit_param=*/false, prev_specific_id,
                          diagnose, /*check_self=*/true)) {
     return false;

+ 8 - 8
toolchain/check/merge.h

@@ -13,20 +13,20 @@ namespace Carbon::Check {
 
 // Diagnoses an `extern` declaration that was not preceded by a declaration in
 // the API file.
-auto DiagnoseExternRequiresDeclInApiFile(Context& context, SemIRLoc loc)
+auto DiagnoseExternRequiresDeclInApiFile(Context& context, SemIR::LocId loc_id)
     -> void;
 
 // Information on new and previous declarations for DiagnoseIfInvalidRedecl.
 struct RedeclInfo {
-  explicit RedeclInfo(SemIR::EntityWithParamsBase params, SemIRLoc loc,
+  explicit RedeclInfo(SemIR::EntityWithParamsBase params, SemIR::LocId loc_id,
                       bool is_definition)
-      : loc(loc),
+      : loc_id(loc_id),
         is_definition(is_definition),
         is_extern(params.is_extern),
         extern_library_id(params.extern_library_id) {}
 
   // The associated diagnostic location.
-  SemIRLoc loc;
+  SemIR::LocId loc_id;
   // True if a definition.
   bool is_definition;
   // True if an `extern` declaration.
@@ -60,24 +60,24 @@ auto ReplacePrevInstForMerge(Context& context, SemIR::NameScopeId scope_id,
 // different kinds of entity such as classes and functions.
 struct DeclParams {
   explicit DeclParams(const SemIR::EntityWithParamsBase& base)
-      : loc(base.latest_decl_id()),
+      : loc_id(base.latest_decl_id()),
         first_param_node_id(base.first_param_node_id),
         last_param_node_id(base.last_param_node_id),
         implicit_param_patterns_id(base.implicit_param_patterns_id),
         param_patterns_id(base.param_patterns_id) {}
 
-  DeclParams(SemIRLoc loc, Parse::NodeId first_param_node_id,
+  DeclParams(SemIR::LocId loc_id, Parse::NodeId first_param_node_id,
              Parse::NodeId last_param_node_id,
              SemIR::InstBlockId implicit_param_patterns_id,
              SemIR::InstBlockId param_patterns_id)
-      : loc(loc),
+      : loc_id(loc_id),
         first_param_node_id(first_param_node_id),
         last_param_node_id(last_param_node_id),
         implicit_param_patterns_id(implicit_param_patterns_id),
         param_patterns_id(param_patterns_id) {}
 
   // The location of the declaration of the entity.
-  SemIRLoc loc;
+  SemIR::LocId loc_id;
 
   // Parse tree bounds for the parameters, including both implicit and explicit
   // parameters. These will be compared to match between declaration and

+ 14 - 15
toolchain/check/name_lookup.cpp

@@ -191,12 +191,10 @@ auto LookupNameInExactScope(Context& context, SemIR::LocId loc_id,
 }
 
 // Prints diagnostics on invalid qualified name access.
-static auto DiagnoseInvalidQualifiedNameAccess(Context& context, SemIRLoc loc,
-                                               SemIR::InstId scope_result_id,
-                                               SemIR::NameId name_id,
-                                               SemIR::AccessKind access_kind,
-                                               bool is_parent_access,
-                                               AccessInfo access_info) -> void {
+static auto DiagnoseInvalidQualifiedNameAccess(
+    Context& context, SemIR::LocId loc_id, SemIR::InstId scope_result_id,
+    SemIR::NameId name_id, SemIR::AccessKind access_kind, bool is_parent_access,
+    AccessInfo access_info) -> void {
   auto class_type = context.insts().TryGetAs<SemIR::ClassType>(
       context.constant_values().GetInstId(access_info.constant_id));
   if (!class_type) {
@@ -228,7 +226,7 @@ static auto DiagnoseInvalidQualifiedNameAccess(Context& context, SemIRLoc loc,
       Diagnostics::BoolAsSelect, SemIR::NameId, SemIR::TypeId);
   CARBON_DIAGNOSTIC(ClassMemberDeclaration, Note, "declared here");
   context.emitter()
-      .Build(loc, ClassInvalidMemberAccess,
+      .Build(loc_id, ClassInvalidMemberAccess,
              access_kind == SemIR::AccessKind::Private, name_id, parent_type_id)
       .Note(scope_result_id, ClassMemberDeclaration)
       .Emit();
@@ -351,7 +349,7 @@ auto AppendLookupScopesForConstant(Context& context, SemIR::LocId loc_id,
 
 // Prints a diagnostic for a missing qualified name.
 static auto DiagnoseMemberNameNotFound(
-    Context& context, SemIRLoc loc, SemIR::NameId name_id,
+    Context& context, SemIR::LocId loc_id, SemIR::NameId name_id,
     llvm::ArrayRef<LookupScope> lookup_scopes) -> void {
   if (lookup_scopes.size() == 1 &&
       lookup_scopes.front().name_scope_id.has_value()) {
@@ -360,7 +358,7 @@ static auto DiagnoseMemberNameNotFound(
       CARBON_DIAGNOSTIC(MemberNameNotFoundInSpecificScope, Error,
                         "member name `{0}` not found in {1}", SemIR::NameId,
                         SemIR::SpecificId);
-      context.emitter().Emit(loc, MemberNameNotFoundInSpecificScope, name_id,
+      context.emitter().Emit(loc_id, MemberNameNotFoundInSpecificScope, name_id,
                              specific_id);
     } else {
       auto scope_inst_id = context.name_scopes()
@@ -369,7 +367,7 @@ static auto DiagnoseMemberNameNotFound(
       CARBON_DIAGNOSTIC(MemberNameNotFoundInInstScope, Error,
                         "member name `{0}` not found in {1}", SemIR::NameId,
                         InstIdAsType);
-      context.emitter().Emit(loc, MemberNameNotFoundInInstScope, name_id,
+      context.emitter().Emit(loc_id, MemberNameNotFoundInInstScope, name_id,
                              scope_inst_id);
     }
     return;
@@ -377,7 +375,7 @@ static auto DiagnoseMemberNameNotFound(
 
   CARBON_DIAGNOSTIC(MemberNameNotFound, Error, "member name `{0}` not found",
                     SemIR::NameId);
-  context.emitter().Emit(loc, MemberNameNotFound, name_id);
+  context.emitter().Emit(loc_id, MemberNameNotFound, name_id);
 }
 
 auto LookupQualifiedName(Context& context, SemIR::LocId loc_id,
@@ -547,7 +545,8 @@ auto LookupNameInCore(Context& context, SemIR::LocId loc_id,
 }
 
 auto DiagnoseDuplicateName(Context& context, SemIR::NameId name_id,
-                           SemIRLoc dup_def, SemIRLoc prev_def) -> void {
+                           SemIR::LocId dup_def, SemIR::LocId prev_def)
+    -> void {
   CARBON_DIAGNOSTIC(NameDeclDuplicate, Error,
                     "duplicate name `{0}` being declared in the same scope",
                     SemIR::NameId);
@@ -572,10 +571,10 @@ auto DiagnosePoisonedName(Context& context, SemIR::NameId name_id,
       .Emit();
 }
 
-auto DiagnoseNameNotFound(Context& context, SemIRLoc loc, SemIR::NameId name_id)
-    -> void {
+auto DiagnoseNameNotFound(Context& context, SemIR::LocId loc_id,
+                          SemIR::NameId name_id) -> void {
   CARBON_DIAGNOSTIC(NameNotFound, Error, "name `{0}` not found", SemIR::NameId);
-  context.emitter().Emit(loc, NameNotFound, name_id);
+  context.emitter().Emit(loc_id, NameNotFound, name_id);
 }
 
 }  // namespace Carbon::Check

+ 3 - 3
toolchain/check/name_lookup.h

@@ -101,7 +101,7 @@ auto LookupNameInCore(Context& context, SemIR::LocId loc_id,
 
 // Prints a diagnostic for a duplicate name.
 auto DiagnoseDuplicateName(Context& context, SemIR::NameId name_id,
-                           SemIRLoc dup_def, SemIRLoc prev_def) -> void;
+                           SemIR::LocId dup_def, SemIR::LocId prev_def) -> void;
 
 // Prints a diagnostic for a poisoned name when it's later declared.
 auto DiagnosePoisonedName(Context& context, SemIR::NameId name_id,
@@ -109,8 +109,8 @@ auto DiagnosePoisonedName(Context& context, SemIR::NameId name_id,
                           SemIR::LocId decl_name_loc_id) -> void;
 
 // Prints a diagnostic for a missing name.
-auto DiagnoseNameNotFound(Context& context, SemIRLoc loc, SemIR::NameId name_id)
-    -> void;
+auto DiagnoseNameNotFound(Context& context, SemIR::LocId loc_id,
+                          SemIR::NameId name_id) -> void;
 
 }  // namespace Carbon::Check
 

+ 1 - 1
toolchain/check/region_stack.h

@@ -17,7 +17,7 @@ namespace Carbon::Check {
 class RegionStack {
  public:
   // A callback for Context::TODO.
-  using TodoFn = std::function<auto(SemIRLoc, std::string)->void>;
+  using TodoFn = std::function<auto(SemIR::LocId, std::string)->void>;
 
   explicit RegionStack(TodoFn todo_fn) : todo_fn_(std::move(todo_fn)) {}
 

+ 9 - 9
toolchain/check/type.cpp

@@ -11,8 +11,8 @@
 namespace Carbon::Check {
 
 // Enforces that an integer type has a valid bit width.
-auto ValidateIntType(Context& context, SemIRLoc loc, SemIR::IntType result)
-    -> bool {
+auto ValidateIntType(Context& context, SemIR::LocId loc_id,
+                     SemIR::IntType result) -> bool {
   auto bit_width =
       context.insts().TryGetAs<SemIR::IntValue>(result.bit_width_id);
   if (!bit_width) {
@@ -26,7 +26,7 @@ auto ValidateIntType(Context& context, SemIRLoc loc, SemIR::IntType result)
     CARBON_DIAGNOSTIC(IntWidthNotPositive, Error,
                       "integer type width of {0} is not positive", TypedInt);
     context.emitter().Emit(
-        loc, IntWidthNotPositive,
+        loc_id, IntWidthNotPositive,
         {.type = bit_width->type_id, .value = bit_width_val});
     return false;
   }
@@ -35,7 +35,7 @@ auto ValidateIntType(Context& context, SemIRLoc loc, SemIR::IntType result)
                       "integer type width of {0} is greater than the "
                       "maximum supported width of {1}",
                       TypedInt, int);
-    context.emitter().Emit(loc, IntWidthTooLarge,
+    context.emitter().Emit(loc_id, IntWidthTooLarge,
                            {.type = bit_width->type_id, .value = bit_width_val},
                            IntStore::MaxIntWidth);
     return false;
@@ -44,7 +44,7 @@ auto ValidateIntType(Context& context, SemIRLoc loc, SemIR::IntType result)
 }
 
 // Enforces that the bit width is 64 for a float.
-auto ValidateFloatBitWidth(Context& context, SemIRLoc loc,
+auto ValidateFloatBitWidth(Context& context, SemIR::LocId loc_id,
                            SemIR::InstId inst_id) -> bool {
   auto inst = context.insts().GetAs<SemIR::IntValue>(inst_id);
   if (context.ints().Get(inst.int_id) == 64) {
@@ -52,20 +52,20 @@ auto ValidateFloatBitWidth(Context& context, SemIRLoc loc,
   }
 
   CARBON_DIAGNOSTIC(CompileTimeFloatBitWidth, Error, "bit width must be 64");
-  context.emitter().Emit(loc, CompileTimeFloatBitWidth);
+  context.emitter().Emit(loc_id, CompileTimeFloatBitWidth);
   return false;
 }
 
 // Enforces that a float type has a valid bit width.
-auto ValidateFloatType(Context& context, SemIRLoc loc, SemIR::FloatType result)
-    -> bool {
+auto ValidateFloatType(Context& context, SemIR::LocId loc_id,
+                       SemIR::FloatType result) -> bool {
   auto bit_width =
       context.insts().TryGetAs<SemIR::IntValue>(result.bit_width_id);
   if (!bit_width) {
     // Symbolic bit width.
     return true;
   }
-  return ValidateFloatBitWidth(context, loc, result.bit_width_id);
+  return ValidateFloatBitWidth(context, loc_id, result.bit_width_id);
 }
 
 // Gets or forms a type_id for a type, given the instruction kind and arguments.

+ 5 - 5
toolchain/check/type.h

@@ -12,16 +12,16 @@
 namespace Carbon::Check {
 
 // Enforces that an integer type has a valid bit width.
-auto ValidateIntType(Context& context, SemIRLoc loc, SemIR::IntType result)
-    -> bool;
+auto ValidateIntType(Context& context, SemIR::LocId loc_id,
+                     SemIR::IntType result) -> bool;
 
 // Enforces that the bit width is 64 for a float.
-auto ValidateFloatBitWidth(Context& context, SemIRLoc loc,
+auto ValidateFloatBitWidth(Context& context, SemIR::LocId loc_id,
                            SemIR::InstId inst_id) -> bool;
 
 // Enforces that a float type has a valid bit width.
-auto ValidateFloatType(Context& context, SemIRLoc loc, SemIR::FloatType result)
-    -> bool;
+auto ValidateFloatType(Context& context, SemIR::LocId loc_id,
+                       SemIR::FloatType result) -> bool;
 
 // Gets the type to use for an unbound associated entity declared in this
 // interface. For example, this is the type of `I.T` after

+ 10 - 8
toolchain/check/type_completion.cpp

@@ -30,9 +30,9 @@ namespace {
 class TypeCompleter {
  public:
   // `context` mut not be null.
-  TypeCompleter(Context* context, SemIRLoc loc,
+  TypeCompleter(Context* context, SemIR::LocId loc_id,
                 MakeDiagnosticBuilderFn diagnoser)
-      : context_(context), loc_(loc), diagnoser_(diagnoser) {}
+      : context_(context), loc_id_(loc_id), diagnoser_(diagnoser) {}
 
   // Attempts to complete the given type. Returns true if it is now complete,
   // false if it could not be completed.
@@ -165,7 +165,7 @@ class TypeCompleter {
 
   Context* context_;
   llvm::SmallVector<WorkItem> work_list_;
-  SemIRLoc loc_;
+  SemIR::LocId loc_id_;
   MakeDiagnosticBuilderFn diagnoser_;
 };
 }  // namespace
@@ -274,7 +274,7 @@ auto TypeCompleter::AddNestedIncompleteTypes(SemIR::Inst type_inst) -> bool {
         return false;
       }
       if (inst.specific_id.has_value()) {
-        ResolveSpecificDefinition(*context_, loc_, inst.specific_id);
+        ResolveSpecificDefinition(*context_, loc_id_, inst.specific_id);
       }
       if (auto adapted_type_id =
               class_info.GetAdaptedType(context_->sem_ir(), inst.specific_id);
@@ -307,7 +307,8 @@ auto TypeCompleter::AddNestedIncompleteTypes(SemIR::Inst type_inst) -> bool {
         }
 
         if (req_interface.specific_id.has_value()) {
-          ResolveSpecificDefinition(*context_, loc_, req_interface.specific_id);
+          ResolveSpecificDefinition(*context_, loc_id_,
+                                    req_interface.specific_id);
         }
       }
       break;
@@ -531,9 +532,10 @@ auto TypeCompleter::BuildInfo(SemIR::TypeId type_id, SemIR::Inst inst) const
   }
 }
 
-auto TryToCompleteType(Context& context, SemIR::TypeId type_id, SemIRLoc loc,
-                       MakeDiagnosticBuilderFn diagnoser) -> bool {
-  return TypeCompleter(&context, loc, diagnoser).Complete(type_id);
+auto TryToCompleteType(Context& context, SemIR::TypeId type_id,
+                       SemIR::LocId loc_id, MakeDiagnosticBuilderFn diagnoser)
+    -> bool {
+  return TypeCompleter(&context, loc_id, diagnoser).Complete(type_id);
 }
 
 auto CompleteTypeOrCheckFail(Context& context, SemIR::TypeId type_id) -> void {

+ 2 - 1
toolchain/check/type_completion.h

@@ -20,7 +20,8 @@ namespace Carbon::Check {
 // However, it's important that we use it during monomorphization, where we
 // don't want to trigger a request for more monomorphization.
 // TODO: Remove the other call to this function.
-auto TryToCompleteType(Context& context, SemIR::TypeId type_id, SemIRLoc loc,
+auto TryToCompleteType(Context& context, SemIR::TypeId type_id,
+                       SemIR::LocId loc_id,
                        MakeDiagnosticBuilderFn diagnoser = nullptr) -> bool;
 
 // Completes the type `type_id`. CHECK-fails if it can't be completed.