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

Move diagnostics into a namespace (#5173)

What this really does is avoids shadowing names, so that we can
comfortable have things like `Check::DiagnosticEmitter` or
`Check::DiagnosticLoc` without shadowing being a concern.

Note, down this path I'm also thinking about:

- Renaming misc DiagnosticConsumer/DiagnosticEmitter classes, possibly
just to DiagnosticConsumer/DiagnosticEmitter (so
`Check::DiagnosticEmitter` instead of `SemIRLocDiagnosticEmitter`).
- Dropping `Diagnostic` from `Emitter::DiagnosticBuilder`.
- But not for `Check::DiagnosticBuilder`, because `Check::Builder` would
be ambiguous.
- Renaming diagnostics/diagnostic_* to drop "diagnostic".

[Discussion about SemIRLoc ->
DiagnosticLoc](https://discord.com/channels/655572317891461132/655578254970716160/1353771570463768698)
reminded me of this (in particular the older [Check::DiagnosticBuilder
discussion](https://discord.com/channels/655572317891461132/655578254970716160/1344363562608627763)),
but I'd only do that rename if there's matching consensus about a path
forward where we keep SemIRLoc, and in a way that it's only ever used
for diagnostics (the divergence from which is at the root of current
LocId discussion).

I'm trying to keep that separate from a namespace addition for clarity.
Jon Ross-Perkins 1 год назад
Родитель
Сommit
acbe6530c3
83 измененных файлов с 561 добавлено и 527 удалено
  1. 4 3
      toolchain/check/call.cpp
  2. 1 1
      toolchain/check/check.cpp
  3. 1 1
      toolchain/check/check.h
  4. 7 7
      toolchain/check/check_unit.h
  5. 1 1
      toolchain/check/context.cpp
  6. 3 3
      toolchain/check/context.h
  7. 12 9
      toolchain/check/convert.cpp
  8. 2 2
      toolchain/check/deduce.cpp
  9. 6 6
      toolchain/check/diagnostic_helpers.h
  10. 6 4
      toolchain/check/eval.cpp
  11. 1 1
      toolchain/check/handle_literal.cpp
  12. 1 1
      toolchain/check/handle_name.cpp
  13. 1 1
      toolchain/check/handle_struct.cpp
  14. 1 1
      toolchain/check/import.cpp
  15. 5 3
      toolchain/check/import_cpp.cpp
  16. 8 7
      toolchain/check/merge.cpp
  17. 5 3
      toolchain/check/modifiers.cpp
  18. 2 2
      toolchain/check/name_lookup.cpp
  19. 2 2
      toolchain/check/pattern_match.cpp
  20. 4 4
      toolchain/check/sem_ir_loc_diagnostic_emitter.cpp
  21. 7 6
      toolchain/check/sem_ir_loc_diagnostic_emitter.h
  22. 1 1
      toolchain/check/type_completion.cpp
  23. 20 20
      toolchain/diagnostics/coverage_test.cpp
  24. 4 5
      toolchain/diagnostics/diagnostic.cpp
  25. 24 24
      toolchain/diagnostics/diagnostic.h
  26. 10 10
      toolchain/diagnostics/diagnostic_consumer.cpp
  27. 14 15
      toolchain/diagnostics/diagnostic_consumer.h
  28. 79 80
      toolchain/diagnostics/diagnostic_emitter.h
  29. 23 25
      toolchain/diagnostics/diagnostic_emitter_test.cpp
  30. 3 3
      toolchain/diagnostics/diagnostic_kind.cpp
  31. 7 8
      toolchain/diagnostics/diagnostic_kind.h
  32. 6 6
      toolchain/diagnostics/file_diagnostics.h
  33. 6 6
      toolchain/diagnostics/format_providers.cpp
  34. 10 10
      toolchain/diagnostics/format_providers.h
  35. 46 24
      toolchain/diagnostics/format_providers_test.cpp
  36. 7 7
      toolchain/diagnostics/mocks.cpp
  37. 28 26
      toolchain/diagnostics/mocks.h
  38. 11 11
      toolchain/diagnostics/null_diagnostics.h
  39. 6 6
      toolchain/diagnostics/sorting_diagnostic_consumer.h
  40. 14 20
      toolchain/diagnostics/sorting_diagnostic_consumer_test.cpp
  41. 7 7
      toolchain/driver/compile_subcommand.cpp
  42. 1 1
      toolchain/driver/compile_subcommand.h
  43. 2 2
      toolchain/driver/driver_env.h
  44. 7 7
      toolchain/language_server/context.cpp
  45. 8 5
      toolchain/language_server/context.h
  46. 2 2
      toolchain/language_server/language_server.cpp
  47. 1 1
      toolchain/language_server/language_server.h
  48. 1 1
      toolchain/lex/helpers.cpp
  49. 1 1
      toolchain/lex/helpers.h
  50. 4 4
      toolchain/lex/lex.cpp
  51. 1 1
      toolchain/lex/lex.h
  52. 6 6
      toolchain/lex/numeric_literal.cpp
  53. 1 1
      toolchain/lex/numeric_literal.h
  54. 2 2
      toolchain/lex/numeric_literal_benchmark.cpp
  55. 1 1
      toolchain/lex/numeric_literal_fuzzer.cpp
  56. 2 2
      toolchain/lex/numeric_literal_test.cpp
  57. 1 1
      toolchain/lex/string_literal.cpp
  58. 1 1
      toolchain/lex/string_literal.h
  59. 2 2
      toolchain/lex/string_literal_benchmark.cpp
  60. 1 1
      toolchain/lex/string_literal_fuzzer.cpp
  61. 2 2
      toolchain/lex/string_literal_test.cpp
  62. 4 4
      toolchain/lex/test_helpers.h
  63. 2 2
      toolchain/lex/tokenized_buffer.cpp
  64. 12 10
      toolchain/lex/tokenized_buffer.h
  65. 4 4
      toolchain/lex/tokenized_buffer_benchmark.cpp
  66. 2 2
      toolchain/lex/tokenized_buffer_fuzzer.cpp
  67. 31 28
      toolchain/lex/tokenized_buffer_test.cpp
  68. 6 5
      toolchain/parse/context.cpp
  69. 8 8
      toolchain/parse/context.h
  70. 1 1
      toolchain/parse/handle_binding_pattern.cpp
  71. 2 2
      toolchain/parse/handle_brace_expr.cpp
  72. 2 1
      toolchain/parse/handle_period.cpp
  73. 1 1
      toolchain/parse/parse.cpp
  74. 1 1
      toolchain/parse/parse.h
  75. 3 3
      toolchain/parse/parse_fuzzer.cpp
  76. 1 1
      toolchain/parse/tree_and_subtrees.cpp
  77. 1 1
      toolchain/parse/tree_and_subtrees.h
  78. 3 3
      toolchain/sem_ir/ids.h
  79. 6 6
      toolchain/source/source_buffer.cpp
  80. 5 5
      toolchain/source/source_buffer.h
  81. 8 8
      toolchain/source/source_buffer_test.cpp
  82. 2 2
      toolchain/testing/compile_helper.cpp
  83. 3 3
      toolchain/testing/compile_helper.h

+ 4 - 3
toolchain/check/call.cpp

@@ -55,12 +55,13 @@ static auto ResolveCalleeInCall(Context& context, SemIR::LocId loc_id,
                       "{0} argument{0:s} passed to "
                       "{1:=0:function|=1:generic class|=2:generic interface}"
                       " expecting {2} argument{2:s}",
-                      IntAsSelect, IntAsSelect, IntAsSelect);
+                      Diagnostics::IntAsSelect, Diagnostics::IntAsSelect,
+                      Diagnostics::IntAsSelect);
     CARBON_DIAGNOSTIC(
         InCallToEntity, Note,
         "calling {0:=0:function|=1:generic class|=2:generic interface}"
         " declared here",
-        IntAsSelect);
+        Diagnostics::IntAsSelect);
     context.emitter()
         .Build(loc_id, CallArgCountMismatch, arg_ids.size(),
                static_cast<int>(entity_kind_for_diagnostic), params.size())
@@ -218,7 +219,7 @@ auto PerformCall(Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id,
   SemIR::InstId return_slot_arg_id = SemIR::InstId::None;
   SemIR::ReturnTypeInfo return_info = [&] {
     auto& function = context.functions().Get(callee_function.function_id);
-    DiagnosticAnnotationScope annotate_diagnostics(
+    Diagnostics::AnnotationScope annotate_diagnostics(
         &context.emitter(), [&](auto& builder) {
           CARBON_DIAGNOSTIC(IncompleteReturnTypeHere, Note,
                             "return type declared here");

+ 1 - 1
toolchain/check/check.cpp

@@ -302,7 +302,7 @@ static auto BuildApiMapAndDiagnosePackaging(
         CARBON_DIAGNOSTIC(
             IncorrectExtension, Error,
             "file extension of `{0:.impl|}.carbon` required for {0:`impl`|api}",
-            BoolAsSelect);
+            Diagnostics::BoolAsSelect);
         auto diag = unit_info.emitter.Build(
             packaging ? packaging->names.node_id : Parse::NodeId::None,
             IncorrectExtension, is_impl);

+ 1 - 1
toolchain/check/check.h

@@ -17,7 +17,7 @@ namespace Carbon::Check {
 
 // Checking information that's tracked per file.
 struct Unit {
-  DiagnosticConsumer* consumer;
+  Diagnostics::Consumer* consumer;
   SharedValueStores* value_stores;
   // The `timings` may be null if nothing is to be recorded.
   Timings* timings;

+ 7 - 7
toolchain/check/check_unit.h

@@ -50,16 +50,16 @@ struct PackageImports {
 // information), in addition to the `Unit` itself.
 struct UnitAndImports {
   // Converts a `NodeId` to a diagnostic location for `UnitAndImports`.
-  class Emitter : public DiagnosticEmitter<Parse::NodeId> {
+  class NodeEmitter : public Diagnostics::Emitter<Parse::NodeId> {
    public:
-    explicit Emitter(DiagnosticConsumer* consumer,
-                     Parse::GetTreeAndSubtreesFn tree_and_subtrees_getter)
-        : DiagnosticEmitter(consumer),
+    explicit NodeEmitter(Diagnostics::Consumer* consumer,
+                         Parse::GetTreeAndSubtreesFn tree_and_subtrees_getter)
+        : Emitter(consumer),
           tree_and_subtrees_getter_(tree_and_subtrees_getter) {}
 
    protected:
     auto ConvertLoc(Parse::NodeId node_id, ContextFnT /*context_fn*/) const
-        -> ConvertedDiagnosticLoc override {
+        -> Diagnostics::ConvertedLoc override {
       return tree_and_subtrees_getter_().NodeToDiagnosticLoc(
           node_id, /*token_only=*/false);
     }
@@ -83,8 +83,8 @@ struct UnitAndImports {
   Unit* unit;
 
   // Emitter information.
-  ErrorTrackingDiagnosticConsumer err_tracker;
-  Emitter emitter;
+  Diagnostics::ErrorTrackingConsumer err_tracker;
+  NodeEmitter emitter;
 
   // List of the outgoing imports. If a package includes unavailable library
   // imports, it has an entry with has_load_error set. Invalid imports (for

+ 1 - 1
toolchain/check/context.cpp

@@ -8,7 +8,7 @@
 
 namespace Carbon::Check {
 
-Context::Context(DiagnosticEmitter<SemIRLoc>* emitter,
+Context::Context(Diagnostics::Emitter<SemIRLoc>* emitter,
                  Parse::GetTreeAndSubtreesFn tree_and_subtrees_getter,
                  SemIR::File* sem_ir, int imported_ir_count, int total_ir_count,
                  llvm::raw_ostream* vlog_stream)

+ 3 - 3
toolchain/check/context.h

@@ -50,7 +50,7 @@ namespace Carbon::Check {
 class Context {
  public:
   // Stores references for work.
-  explicit Context(DiagnosticEmitter<SemIRLoc>* emitter,
+  explicit Context(Diagnostics::Emitter<SemIRLoc>* emitter,
                    Parse::GetTreeAndSubtreesFn tree_and_subtrees_getter,
                    SemIR::File* sem_ir, int imported_ir_count,
                    int total_ir_count, llvm::raw_ostream* vlog_stream);
@@ -69,7 +69,7 @@ class Context {
     return tokens().GetKind(parse_tree().node_token(node_id));
   }
 
-  auto emitter() -> DiagnosticEmitter<SemIRLoc>& { return *emitter_; }
+  auto emitter() -> Diagnostics::Emitter<SemIRLoc>& { return *emitter_; }
 
   auto parse_tree_and_subtrees() -> const Parse::TreeAndSubtrees& {
     return tree_and_subtrees_getter_();
@@ -276,7 +276,7 @@ class Context {
 
  private:
   // Handles diagnostics.
-  DiagnosticEmitter<SemIRLoc>* emitter_;
+  Diagnostics::Emitter<SemIRLoc>* emitter_;
 
   // Returns a lazily constructed TreeAndSubtrees.
   Parse::GetTreeAndSubtreesFn tree_and_subtrees_getter_;

+ 12 - 9
toolchain/check/convert.cpp

@@ -270,12 +270,12 @@ static auto ConvertTupleToArray(Context& context, SemIR::TupleType tuple_type,
       CARBON_DIAGNOSTIC(ArrayInitFromLiteralArgCountMismatch, Error,
                         "cannot initialize array of {0} element{0:s} from {1} "
                         "initializer{1:s}",
-                        IntAsSelect, IntAsSelect);
+                        Diagnostics::IntAsSelect, Diagnostics::IntAsSelect);
       CARBON_DIAGNOSTIC(
           ArrayInitFromExprArgCountMismatch, Error,
           "cannot initialize array of {0} element{0:s} from tuple "
           "with {1} element{1:s}",
-          IntAsSelect, IntAsSelect);
+          Diagnostics::IntAsSelect, Diagnostics::IntAsSelect);
       context.emitter().Emit(value_loc_id,
                              literal_elems.empty()
                                  ? ArrayInitFromExprArgCountMismatch
@@ -359,7 +359,7 @@ static auto ConvertTupleToTuple(Context& context, SemIR::TupleType src_type,
           TupleInitElementCountMismatch, Error,
           "cannot initialize tuple of {0} element{0:s} from tuple "
           "with {1} element{1:s}",
-          IntAsSelect, IntAsSelect);
+          Diagnostics::IntAsSelect, Diagnostics::IntAsSelect);
       context.emitter().Emit(value_loc_id, TupleInitElementCountMismatch,
                              dest_elem_types.size(), src_elem_types.size());
     }
@@ -459,7 +459,8 @@ static auto ConvertStructToStructOrClass(Context& context,
           StructInitElementCountMismatch, Error,
           "cannot initialize {0:class|struct} with {1} field{1:s} from struct "
           "with {2} field{2:s}",
-          BoolAsSelect, IntAsSelect, IntAsSelect);
+          Diagnostics::BoolAsSelect, Diagnostics::IntAsSelect,
+          Diagnostics::IntAsSelect);
       context.emitter().Emit(value_loc_id, StructInitElementCountMismatch,
                              ToClass, dest_elem_fields_size,
                              src_elem_fields.size());
@@ -869,7 +870,7 @@ static auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id,
         // While the types are the same, the conversion can still fail if it
         // performs a copy while converting the value to another category, and
         // the type (or some part of it) is not copyable.
-        DiagnosticAnnotationScope annotate_diagnostics(
+        Diagnostics::AnnotationScope annotate_diagnostics(
             &context.emitter(), [&](auto& builder) {
               CARBON_DIAGNOSTIC(InCopy, Note, "in copy of {0}", TypeOfInstId);
               builder.Note(value_id, InCopy, value_id);
@@ -1135,7 +1136,7 @@ static auto DiagnoseConversionFailureToConstraintValue(Context& context,
           ConversionFailureFacetToFacet, Error,
           "cannot{0:| implicitly} convert type {1} that implements {2} "
           "into type implementing {3}{0: with `as`|}",
-          BoolAsSelect, InstIdAsType, TypeOfInstId, SemIR::TypeId);
+          Diagnostics::BoolAsSelect, InstIdAsType, TypeOfInstId, SemIR::TypeId);
       return context.emitter().Build(
           loc_id, ConversionFailureFacetToFacet,
           target.kind == ConversionTarget::ExplicitAs, expr_id,
@@ -1144,7 +1145,7 @@ static auto DiagnoseConversionFailureToConstraintValue(Context& context,
       CARBON_DIAGNOSTIC(ConversionFailureTypeToFacet, Error,
                         "cannot{0:| implicitly} convert type {1} "
                         "into type implementing {2}{0: with `as`|}",
-                        BoolAsSelect, InstIdAsType, SemIR::TypeId);
+                        Diagnostics::BoolAsSelect, InstIdAsType, SemIR::TypeId);
       return context.emitter().Build(
           loc_id, ConversionFailureTypeToFacet,
           target.kind == ConversionTarget::ExplicitAs, expr_id, target.type_id);
@@ -1154,7 +1155,8 @@ static auto DiagnoseConversionFailureToConstraintValue(Context& context,
         ConversionFailureNonTypeToFacet, Error,
         "cannot{0:| implicitly} convert non-type value of type {1} "
         "{2:to|into type implementing} {3}{0: with `as`|}",
-        BoolAsSelect, TypeOfInstId, BoolAsSelect, SemIR::TypeId);
+        Diagnostics::BoolAsSelect, TypeOfInstId, Diagnostics::BoolAsSelect,
+        SemIR::TypeId);
     return context.emitter().Build(
         loc_id, ConversionFailureNonTypeToFacet,
         target.kind == ConversionTarget::ExplicitAs, expr_id,
@@ -1286,7 +1288,8 @@ auto Convert(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id,
         CARBON_DIAGNOSTIC(ConversionFailure, Error,
                           "cannot{0:| implicitly} convert value of type {1} to "
                           "{2}{0: with `as`|}",
-                          BoolAsSelect, TypeOfInstId, SemIR::TypeId);
+                          Diagnostics::BoolAsSelect, TypeOfInstId,
+                          SemIR::TypeId);
         return context.emitter().Build(
             loc_id, ConversionFailure,
             target.kind == ConversionTarget::ExplicitAs, expr_id,

+ 2 - 2
toolchain/check/deduce.cpp

@@ -332,7 +332,7 @@ auto DeductionContext::Deduce() -> bool {
       // compile-time value (e.g. TupleType) that we can decompose further.
       // So we do this conversion here, even though we will later try convert
       // again when we have deduced all of the bindings.
-      DiagnosticAnnotationScope annotate_diagnostics(
+      Diagnostics::AnnotationScope annotate_diagnostics(
           &context().emitter(), [&](auto& builder) {
             if (diagnose_) {
               NoteInitializingParam(param_id, builder);
@@ -573,7 +573,7 @@ auto DeductionContext::CheckDeductionIsComplete() -> bool {
       binding_type_id =
           context().types().GetTypeIdForTypeConstantId(param_type_const_id);
 
-      DiagnosticAnnotationScope annotate_diagnostics(
+      Diagnostics::AnnotationScope annotate_diagnostics(
           &context().emitter(), [&](auto& builder) {
             if (diagnose_) {
               NoteInitializingParam(binding_id, builder);

+ 6 - 6
toolchain/check/diagnostic_helpers.h

@@ -46,7 +46,7 @@ class SemIRLoc {
   bool token_only_;
 };
 
-using DiagnosticBuilder = DiagnosticEmitter<SemIRLoc>::DiagnosticBuilder;
+using DiagnosticBuilder = Diagnostics::Emitter<SemIRLoc>::DiagnosticBuilder;
 
 // A function that forms a diagnostic for some kind of problem. The
 // DiagnosticBuilder is returned rather than emitted so that the caller
@@ -69,7 +69,7 @@ inline auto TokenOnly(SemIR::LocId loc_id) -> SemIRLoc {
 // possible, because we should eventually be able to produce a sugared type name
 // in this case, whereas a `TypeId` will render as a canonical type.
 struct TypeOfInstId {
-  using DiagnosticType = DiagnosticTypeInfo<std::string>;
+  using DiagnosticType = Diagnostics::TypeInfo<std::string>;
 
   // NOLINTNEXTLINE(google-explicit-constructor)
   TypeOfInstId(SemIR::InstId inst_id) : inst_id(inst_id) {}
@@ -86,7 +86,7 @@ struct TypeOfInstId {
 // This should be used when the source expression used to construct a type is
 // available.
 struct InstIdAsType {
-  using DiagnosticType = DiagnosticTypeInfo<std::string>;
+  using DiagnosticType = Diagnostics::TypeInfo<std::string>;
 
   // NOLINTNEXTLINE(google-explicit-constructor)
   InstIdAsType(SemIR::InstId inst_id) : inst_id(inst_id) {}
@@ -103,7 +103,7 @@ struct InstIdAsType {
 // This is intended for cases where the type is part of a larger syntactic
 // construct in a diagnostic, such as "redefinition of `impl {0} as {1}`".
 struct InstIdAsRawType {
-  using DiagnosticType = DiagnosticTypeInfo<std::string>;
+  using DiagnosticType = Diagnostics::TypeInfo<std::string>;
 
   // NOLINTNEXTLINE(google-explicit-constructor)
   InstIdAsRawType(SemIR::InstId inst_id) : inst_id(inst_id) {}
@@ -118,7 +118,7 @@ struct InstIdAsRawType {
 // possible, because it can't be formatted with syntactic sugar such as aliases
 // that describe how the type was written.
 struct TypeIdAsRawType {
-  using DiagnosticType = DiagnosticTypeInfo<std::string>;
+  using DiagnosticType = Diagnostics::TypeInfo<std::string>;
 
   // NOLINTNEXTLINE(google-explicit-constructor)
   TypeIdAsRawType(SemIR::TypeId type_id) : type_id(type_id) {}
@@ -129,7 +129,7 @@ struct TypeIdAsRawType {
 // An integer value together with its type. The type is used to determine how to
 // format the value in diagnostics.
 struct TypedInt {
-  using DiagnosticType = DiagnosticTypeInfo<llvm::APSInt>;
+  using DiagnosticType = Diagnostics::TypeInfo<llvm::APSInt>;
 
   SemIR::TypeId type;
   llvm::APInt value;

+ 6 - 4
toolchain/check/eval.cpp

@@ -187,7 +187,9 @@ class EvalContext {
 
   auto sem_ir() -> SemIR::File& { return context().sem_ir(); }
 
-  auto emitter() -> DiagnosticEmitter<SemIRLoc>& { return context().emitter(); }
+  auto emitter() -> Diagnostics::Emitter<SemIRLoc>& {
+    return context().emitter();
+  }
 
  private:
   // The type-checking context in which we're performing evaluation.
@@ -1036,7 +1038,7 @@ static auto PerformBuiltinIntShiftOp(Context& context, SemIRLoc loc,
     CARBON_DIAGNOSTIC(
         CompileTimeShiftOutOfRange, Error,
         "shift distance >= type width of {0} in `{1} {2:<<|>>} {3}`", unsigned,
-        TypedInt, BoolAsSelect, TypedInt);
+        TypedInt, Diagnostics::BoolAsSelect, TypedInt);
     context.emitter().Emit(
         loc, CompileTimeShiftOutOfRange, lhs_val.getBitWidth(),
         {.type = lhs.type_id, .value = lhs_val},
@@ -1050,7 +1052,7 @@ static auto PerformBuiltinIntShiftOp(Context& context, SemIRLoc loc,
       context.sem_ir().types().IsSignedInt(rhs.type_id)) {
     CARBON_DIAGNOSTIC(CompileTimeShiftNegative, Error,
                       "shift distance negative in `{0} {1:<<|>>} {2}`",
-                      TypedInt, BoolAsSelect, TypedInt);
+                      TypedInt, Diagnostics::BoolAsSelect, TypedInt);
     context.emitter().Emit(
         loc, CompileTimeShiftNegative, {.type = lhs.type_id, .value = lhs_val},
         builtin_kind == SemIR::BuiltinFunctionKind::IntLeftShift,
@@ -1888,7 +1890,7 @@ auto TryEvalBlockForSpecific(Context& context, SemIRLoc loc,
                                .values = result,
                            });
 
-  DiagnosticAnnotationScope annotate_diagnostics(
+  Diagnostics::AnnotationScope annotate_diagnostics(
       &context.emitter(), [&](auto& builder) {
         CARBON_DIAGNOSTIC(ResolvingSpecificHere, Note, "in {0} used here",
                           InstIdAsType);

+ 1 - 1
toolchain/check/handle_literal.cpp

@@ -111,7 +111,7 @@ static auto HandleIntOrUnsignedIntTypeLiteral(Context& context,
     CARBON_DIAGNOSTIC(IntWidthNotMultipleOf8, Error,
                       "bit width of integer type literal must be a multiple of "
                       "8; use `Core.{0:Int|UInt}({1})` instead",
-                      BoolAsSelect, llvm::APSInt);
+                      Diagnostics::BoolAsSelect, llvm::APSInt);
     context.emitter().Emit(
         node_id, IntWidthNotMultipleOf8, int_kind.is_signed(),
         llvm::APSInt(context.ints().Get(size_id), /*isUnsigned=*/true));

+ 1 - 1
toolchain/check/handle_name.cpp

@@ -266,7 +266,7 @@ auto HandleParseNode(Context& context, Parse::DesignatorExprId node_id)
       // instead so we can generate a "name `.Self` implicitly referenced by
       // designated expression, but not found" diagnostic instead of adding a
       // note to the current "name `.Self` not found" message.
-      DiagnosticAnnotationScope annotate_diagnostics(
+      Diagnostics::AnnotationScope annotate_diagnostics(
           &context.emitter(), [&](auto& builder) {
             CARBON_DIAGNOSTIC(
                 NoPeriodSelfForDesignator, Note,

+ 1 - 1
toolchain/check/handle_struct.cpp

@@ -87,7 +87,7 @@ static auto DiagnoseDuplicateNames(
       CARBON_DIAGNOSTIC(StructNameDuplicate, Error,
                         "duplicated field name `{1}` in "
                         "{0:struct type literal|struct literal}",
-                        BoolAsSelect, SemIR::NameId);
+                        Diagnostics::BoolAsSelect, SemIR::NameId);
       CARBON_DIAGNOSTIC(StructNamePrevious, Note,
                         "field with the same name here");
       context.emitter()

+ 1 - 1
toolchain/check/import.cpp

@@ -617,7 +617,7 @@ auto ImportNameFromOtherPackage(
   }
 
   // Annotate diagnostics as occurring during this name lookup.
-  DiagnosticAnnotationScope annotate_diagnostics(
+  Diagnostics::AnnotationScope annotate_diagnostics(
       &context.emitter(), [&](auto& builder) {
         CARBON_DIAGNOSTIC(InNameLookup, Note, "in name lookup for `{0}`",
                           SemIR::NameId);

+ 5 - 3
toolchain/check/import_cpp.cpp

@@ -83,13 +83,15 @@ static auto GenerateAst(Context& context, llvm::StringRef importing_file_path,
     CARBON_DIAGNOSTIC(
         CppInteropParseError, Error,
         "{0} error{0:s} and {1} warning{1:s} in {2} `Cpp` import{2:s}:\n{3}",
-        IntAsSelect, IntAsSelect, IntAsSelect, std::string);
+        Diagnostics::IntAsSelect, Diagnostics::IntAsSelect,
+        Diagnostics::IntAsSelect, std::string);
     context.emitter().Emit(loc, CppInteropParseError, num_errors, num_warnings,
                            num_imports, diagnostics_str);
   } else if (num_warnings > 0) {
     CARBON_DIAGNOSTIC(CppInteropParseWarning, Warning,
                       "{0} warning{0:s} in `Cpp` {1} import{1:s}:\n{2}",
-                      IntAsSelect, IntAsSelect, std::string);
+                      Diagnostics::IntAsSelect, Diagnostics::IntAsSelect,
+                      std::string);
     context.emitter().Emit(loc, CppInteropParseWarning, num_warnings,
                            num_imports, diagnostics_str);
   }
@@ -348,7 +350,7 @@ static auto ImportNameDecl(Context& context, SemIR::LocId loc_id,
 auto ImportNameFromCpp(Context& context, SemIR::LocId loc_id,
                        SemIR::NameScopeId scope_id, SemIR::NameId name_id)
     -> SemIR::InstId {
-  DiagnosticAnnotationScope annotate_diagnostics(
+  Diagnostics::AnnotationScope annotate_diagnostics(
       &context.emitter(), [&](auto& builder) {
         CARBON_DIAGNOSTIC(InCppNameLookup, Note,
                           "in `Cpp` name lookup for `{0}`", SemIR::NameId);

+ 8 - 7
toolchain/check/merge.cpp

@@ -209,14 +209,14 @@ static auto CheckRedeclParam(Context& context, bool is_implicit_param,
   CARBON_DIAGNOSTIC(
       RedeclParamPrevious, Note,
       "previous declaration's corresponding {0:implicit |}parameter here",
-      BoolAsSelect);
+      Diagnostics::BoolAsSelect);
   auto emit_diagnostic = [&]() {
     if (!diagnose) {
       return;
     }
     CARBON_DIAGNOSTIC(RedeclParamDiffers, Error,
                       "redeclaration differs at {0:implicit |}parameter {1}",
-                      BoolAsSelect, int32_t);
+                      Diagnostics::BoolAsSelect, int32_t);
     context.emitter()
         .Build(new_param_pattern_id, RedeclParamDiffers, is_implicit_param,
                param_index + 1)
@@ -277,7 +277,8 @@ static auto CheckRedeclParam(Context& context, bool is_implicit_param,
     CARBON_DIAGNOSTIC(RedeclParamDiffersType, Error,
                       "type {3} of {0:implicit |}parameter {1} in "
                       "redeclaration differs from previous parameter type {2}",
-                      BoolAsSelect, int32_t, SemIR::TypeId, SemIR::TypeId);
+                      Diagnostics::BoolAsSelect, int32_t, SemIR::TypeId,
+                      SemIR::TypeId);
     context.emitter()
         .Build(new_param_pattern_id, RedeclParamDiffersType, is_implicit_param,
                param_index + 1, prev_param_type_id, new_param_pattern.type_id())
@@ -315,11 +316,11 @@ static auto CheckRedeclParams(Context& context, SemIRLoc new_decl_loc,
     CARBON_DIAGNOSTIC(RedeclParamListDiffers, Error,
                       "redeclaration differs because of "
                       "{1:|missing }{0:implicit |}parameter list",
-                      BoolAsSelect, BoolAsSelect);
+                      Diagnostics::BoolAsSelect, Diagnostics::BoolAsSelect);
     CARBON_DIAGNOSTIC(RedeclParamListPrevious, Note,
                       "previously declared "
                       "{1:with|without} {0:implicit |}parameter list",
-                      BoolAsSelect, BoolAsSelect);
+                      Diagnostics::BoolAsSelect, Diagnostics::BoolAsSelect);
     context.emitter()
         .Build(new_decl_loc, RedeclParamListDiffers, is_implicit_param,
                new_param_patterns_id.has_value())
@@ -342,11 +343,11 @@ static auto CheckRedeclParams(Context& context, SemIRLoc new_decl_loc,
     CARBON_DIAGNOSTIC(
         RedeclParamCountDiffers, Error,
         "redeclaration differs because of {0:implicit |}parameter count of {1}",
-        BoolAsSelect, int32_t);
+        Diagnostics::BoolAsSelect, int32_t);
     CARBON_DIAGNOSTIC(
         RedeclParamCountPrevious, Note,
         "previously declared with {0:implicit |}parameter count of {1}",
-        BoolAsSelect, int32_t);
+        Diagnostics::BoolAsSelect, int32_t);
     context.emitter()
         .Build(new_decl_loc, RedeclParamCountDiffers, is_implicit_param,
                new_param_pattern_ids.size())

+ 5 - 3
toolchain/check/modifiers.cpp

@@ -11,9 +11,10 @@ namespace Carbon::Check {
 // Builds the diagnostic for DiagnoseNotAllowed.
 template <typename... TokenKinds>
 static auto StartDiagnoseNotAllowed(
-    Context& context, const DiagnosticBase<TokenKinds...>& diagnostic_base,
+    Context& context,
+    const Diagnostics::DiagnosticBase<TokenKinds...>& diagnostic_base,
     Parse::NodeId modifier_node, Lex::TokenKind declaration_kind)
-    -> DiagnosticEmitter<SemIRLoc>::DiagnosticBuilder {
+    -> Diagnostics::Emitter<SemIRLoc>::DiagnosticBuilder {
   if constexpr (sizeof...(TokenKinds) == 0) {
     return context.emitter().Build(modifier_node, diagnostic_base);
   } else if constexpr (sizeof...(TokenKinds) == 1) {
@@ -34,7 +35,8 @@ static auto StartDiagnoseNotAllowed(
 // declaration kind.
 template <typename... TokenKinds>
 static auto DiagnoseNotAllowed(
-    Context& context, const DiagnosticBase<TokenKinds...>& diagnostic_base,
+    Context& context,
+    const Diagnostics::DiagnosticBase<TokenKinds...>& diagnostic_base,
     Parse::NodeId modifier_node, Lex::TokenKind decl_kind,
     SemIR::LocId context_loc_id) -> void {
   auto diag = StartDiagnoseNotAllowed(context, diagnostic_base, modifier_node,

+ 2 - 2
toolchain/check/name_lookup.cpp

@@ -225,7 +225,7 @@ static auto DiagnoseInvalidQualifiedNameAccess(Context& context, SemIRLoc loc,
   CARBON_DIAGNOSTIC(
       ClassInvalidMemberAccess, Error,
       "cannot access {0:private|protected} member `{1}` of type {2}",
-      BoolAsSelect, SemIR::NameId, SemIR::TypeId);
+      Diagnostics::BoolAsSelect, SemIR::NameId, SemIR::TypeId);
   CARBON_DIAGNOSTIC(ClassMemberDeclaration, Note, "declared here");
   context.emitter()
       .Build(loc, ClassInvalidMemberAccess,
@@ -424,7 +424,7 @@ auto LookupQualifiedName(Context& context, SemIR::LocId loc_id,
         SemIR::ConstantId const_id = GetConstantValueInSpecific(
             context.sem_ir(), specific_id, extended_id);
 
-        DiagnosticAnnotationScope annotate_diagnostics(
+        Diagnostics::AnnotationScope annotate_diagnostics(
             &context.emitter(), [&](auto& builder) {
               CARBON_DIAGNOSTIC(FromExtendHere, Note,
                                 "declared as an extended scope here");

+ 2 - 2
toolchain/check/pattern_match.cpp

@@ -493,7 +493,7 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
       CARBON_DIAGNOSTIC(TuplePatternSizeDoesntMatchLiteral, Error,
                         "tuple pattern expects {0} element{0:s}, but tuple "
                         "literal has {1}",
-                        IntAsSelect, IntAsSelect);
+                        Diagnostics::IntAsSelect, Diagnostics::IntAsSelect);
       context.emitter().Emit(pattern_loc_id, TuplePatternSizeDoesntMatchLiteral,
                              subpattern_ids.size(), subscrutinee_ids.size());
       return;
@@ -531,7 +531,7 @@ auto MatchContext::EmitPatternMatch(Context& context,
   if (entry.pattern_id == SemIR::ErrorInst::SingletonInstId) {
     return;
   }
-  DiagnosticAnnotationScope annotate_diagnostics(
+  Diagnostics::AnnotationScope annotate_diagnostics(
       &context.emitter(), [&](auto& builder) {
         if (kind_ == MatchKind::Caller) {
           CARBON_DIAGNOSTIC(InCallToFunctionParam, Note,

+ 4 - 4
toolchain/check/sem_ir_loc_diagnostic_emitter.cpp

@@ -12,7 +12,7 @@ namespace Carbon::Check {
 
 auto SemIRLocDiagnosticEmitter::ConvertLoc(SemIRLoc loc,
                                            ContextFnT context_fn) const
-    -> ConvertedDiagnosticLoc {
+    -> Diagnostics::ConvertedLoc {
   auto converted = ConvertLocImpl(loc, context_fn);
 
   // Use the token when possible, but -1 is the default value.
@@ -35,7 +35,7 @@ auto SemIRLocDiagnosticEmitter::ConvertLoc(SemIRLoc loc,
 
 auto SemIRLocDiagnosticEmitter::ConvertLocImpl(SemIRLoc loc,
                                                ContextFnT context_fn) const
-    -> ConvertedDiagnosticLoc {
+    -> Diagnostics::ConvertedLoc {
   llvm::SmallVector<SemIR::AbsoluteNodeId> absolute_node_ids =
       loc.is_inst_id_ ? SemIR::GetAbsoluteNodeId(sem_ir_, loc.inst_id_)
                       : SemIR::GetAbsoluteNodeId(sem_ir_, loc.loc_id_);
@@ -59,7 +59,7 @@ auto SemIRLocDiagnosticEmitter::ConvertLocImpl(SemIRLoc loc,
 
 auto SemIRLocDiagnosticEmitter::ConvertLocInFile(
     SemIR::AbsoluteNodeId absolute_node_id, bool token_only,
-    ContextFnT /*context_fn*/) const -> ConvertedDiagnosticLoc {
+    ContextFnT /*context_fn*/) const -> Diagnostics::ConvertedLoc {
   const auto& tree_and_subtrees =
       tree_and_subtrees_getters_[absolute_node_id.check_ir_id.index]();
   return tree_and_subtrees.NodeToDiagnosticLoc(absolute_node_id.node_id,
@@ -118,7 +118,7 @@ auto SemIRLocDiagnosticEmitter::ConvertArg(llvm::Any arg) const -> llvm::Any {
     return llvm::APSInt(typed_int->value,
                         !sem_ir_->types().IsSignedInt(typed_int->type));
   }
-  return DiagnosticEmitter<SemIRLoc>::ConvertArg(arg);
+  return Diagnostics::Emitter<SemIRLoc>::ConvertArg(arg);
 }
 
 }  // namespace Carbon::Check

+ 7 - 6
toolchain/check/sem_ir_loc_diagnostic_emitter.h

@@ -17,13 +17,13 @@
 namespace Carbon::Check {
 
 // Handles the transformation of a SemIRLoc to a DiagnosticLoc.
-class SemIRLocDiagnosticEmitter : public DiagnosticEmitter<SemIRLoc> {
+class SemIRLocDiagnosticEmitter : public Diagnostics::Emitter<SemIRLoc> {
  public:
   explicit SemIRLocDiagnosticEmitter(
-      DiagnosticConsumer* consumer,
+      Diagnostics::Consumer* consumer,
       llvm::ArrayRef<Parse::GetTreeAndSubtreesFn> tree_and_subtrees_getters,
       const SemIR::File* sem_ir)
-      : DiagnosticEmitter(consumer),
+      : Emitter(consumer),
         tree_and_subtrees_getters_(tree_and_subtrees_getters),
         sem_ir_(sem_ir) {}
 
@@ -44,17 +44,18 @@ class SemIRLocDiagnosticEmitter : public DiagnosticEmitter<SemIRLoc> {
   // locations, or `loc` if it's in the same file and (for whatever reason)
   // later.
   auto ConvertLoc(SemIRLoc loc, ContextFnT context_fn) const
-      -> ConvertedDiagnosticLoc override;
+      -> Diagnostics::ConvertedLoc override;
 
  private:
   // Implements `ConvertLoc`, but without `last_token_` applied.
   auto ConvertLocImpl(SemIRLoc loc, ContextFnT context_fn) const
-      -> ConvertedDiagnosticLoc;
+      -> Diagnostics::ConvertedLoc;
 
   // Converts a node_id corresponding to a specific sem_ir to a diagnostic
   // location.
   auto ConvertLocInFile(SemIR::AbsoluteNodeId absolute_node_id, bool token_only,
-                        ContextFnT context_fn) const -> ConvertedDiagnosticLoc;
+                        ContextFnT context_fn) const
+      -> Diagnostics::ConvertedLoc;
 
   // Converters for each SemIR.
   llvm::ArrayRef<Parse::GetTreeAndSubtreesFn> tree_and_subtrees_getters_;

+ 1 - 1
toolchain/check/type_completion.cpp

@@ -579,7 +579,7 @@ static auto NoteAbstractClass(Context& context, SemIR::ClassId class_id,
   CARBON_DIAGNOSTIC(
       ClassAbstractHere, Note,
       "{0:=0:uses class that|=1:class} was declared abstract here",
-      IntAsSelect);
+      Diagnostics::IntAsSelect);
   builder.Note(class_info.definition_id, ClassAbstractHere,
                static_cast<int>(direct_use));
 }

+ 20 - 20
toolchain/diagnostics/coverage_test.cpp

@@ -11,37 +11,37 @@
 ABSL_FLAG(std::string, testdata_manifest, "",
           "A path to a file containing repo-relative names of test files.");
 
-namespace Carbon {
+namespace Carbon::Diagnostics {
 namespace {
 
-constexpr DiagnosticKind DiagnosticKinds[] = {
-#define CARBON_DIAGNOSTIC_KIND(Name) DiagnosticKind::Name,
+constexpr Kind Kinds[] = {
+#define CARBON_DIAGNOSTIC_KIND(Name) Kind::Name,
 #include "toolchain/diagnostics/diagnostic_kind.def"
 };
 
-constexpr DiagnosticKind UntestedDiagnosticKinds[] = {
+constexpr Kind UntestedKinds[] = {
     // These exist only for unit tests.
-    DiagnosticKind::TestDiagnostic,
-    DiagnosticKind::TestDiagnosticNote,
+    Kind::TestDiagnostic,
+    Kind::TestDiagnosticNote,
 
     // Diagnosing erroneous install conditions, but test environments are
     // typically correct.
-    DiagnosticKind::CompilePreludeManifestError,
-    DiagnosticKind::DriverInstallInvalid,
+    Kind::CompilePreludeManifestError,
+    Kind::DriverInstallInvalid,
 
     // These diagnose filesystem issues that are hard to unit test.
-    DiagnosticKind::ErrorReadingFile,
-    DiagnosticKind::ErrorStattingFile,
-    DiagnosticKind::FileTooLarge,
+    Kind::ErrorReadingFile,
+    Kind::ErrorStattingFile,
+    Kind::FileTooLarge,
 
     // These aren't feasible to test with a normal testcase, but are tested in
     // lex/tokenized_buffer_test.cpp.
-    DiagnosticKind::TooManyTokens,
-    DiagnosticKind::UnsupportedCrLineEnding,
-    DiagnosticKind::UnsupportedLfCrLineEnding,
+    Kind::TooManyTokens,
+    Kind::UnsupportedCrLineEnding,
+    Kind::UnsupportedLfCrLineEnding,
 
     // This is a little long but is tested in lex/numeric_literal_test.cpp.
-    DiagnosticKind::TooManyDigits,
+    Kind::TooManyDigits,
 
     // TODO: This can only fire if the first message in a diagnostic is rooted
     // in a file other than the file being compiled. The language server
@@ -50,16 +50,16 @@ constexpr DiagnosticKind UntestedDiagnosticKinds[] = {
     //   in the current file.
     // - Require all diagnostics produced by compiling have their first location
     //   be in the file being compiled, never an import.
-    DiagnosticKind::LanguageServerDiagnosticInWrongFile,
+    Kind::LanguageServerDiagnosticInWrongFile,
 };
 
 // Looks for diagnostic kinds that aren't covered by a file_test.
-TEST(Coverage, DiagnosticKind) {
+TEST(Coverage, Kind) {
   Testing::TestKindCoverage(absl::GetFlag(FLAGS_testdata_manifest),
                             R"(^ *// CHECK:STDERR: .* \[(\w+)\]$)",
-                            llvm::ArrayRef(DiagnosticKinds),
-                            llvm::ArrayRef(UntestedDiagnosticKinds));
+                            llvm::ArrayRef(Kinds),
+                            llvm::ArrayRef(UntestedKinds));
 }
 
 }  // namespace
-}  // namespace Carbon
+}  // namespace Carbon::Diagnostics

+ 4 - 5
toolchain/diagnostics/diagnostic.cpp

@@ -7,9 +7,9 @@
 #include <algorithm>
 #include <cstdint>
 
-namespace Carbon {
+namespace Carbon::Diagnostics {
 
-auto DiagnosticLoc::FormatLocation(llvm::raw_ostream& out) const -> void {
+auto Loc::FormatLocation(llvm::raw_ostream& out) const -> void {
   if (filename.empty()) {
     return;
   }
@@ -23,8 +23,7 @@ auto DiagnosticLoc::FormatLocation(llvm::raw_ostream& out) const -> void {
   out << ": ";
 }
 
-auto DiagnosticLoc::FormatSnippet(llvm::raw_ostream& out, int indent) const
-    -> void {
+auto Loc::FormatSnippet(llvm::raw_ostream& out, int indent) const -> void {
   if (column_number == -1) {
     return;
   }
@@ -48,4 +47,4 @@ auto DiagnosticLoc::FormatSnippet(llvm::raw_ostream& out, int indent) const
   out << '\n';
 }
 
-}  // namespace Carbon
+}  // namespace Carbon::Diagnostics

+ 24 - 24
toolchain/diagnostics/diagnostic.h

@@ -15,9 +15,9 @@
 #include "llvm/ADT/StringRef.h"
 #include "toolchain/diagnostics/diagnostic_kind.h"
 
-namespace Carbon {
+namespace Carbon::Diagnostics {
 
-enum class DiagnosticLevel : int8_t {
+enum class Level : int8_t {
   // Information about the location of another diagnostic, showing how we
   // reached that location. This is currently only used for the "in import"
   // message.
@@ -39,17 +39,17 @@ enum class DiagnosticLevel : int8_t {
 // Arguments are passed to llvm::formatv; see:
 // https://llvm.org/doxygen/FormatVariadic_8h_source.html
 //
-// See `DiagnosticEmitter::Emit` for comments about argument lifetimes.
-#define CARBON_DIAGNOSTIC(DiagnosticName, Level, Format, ...) \
-  static constexpr auto DiagnosticName =                      \
-      ::Carbon::DiagnosticBase<__VA_ARGS__>(                  \
-          ::Carbon::DiagnosticKind::DiagnosticName,           \
-          ::Carbon::DiagnosticLevel::Level, Format)
-
-// A location for a diagnostic in a file. The lifetime of a DiagnosticLoc
+// See `Diagnostics::Emitter::Emit` for comments about argument lifetimes.
+#define CARBON_DIAGNOSTIC(DiagnosticName, LevelValue, Format, ...) \
+  static constexpr auto DiagnosticName =                           \
+      ::Carbon::Diagnostics::DiagnosticBase<__VA_ARGS__>(          \
+          ::Carbon::Diagnostics::Kind::DiagnosticName,             \
+          ::Carbon::Diagnostics::Level::LevelValue, Format)
+
+// A location for a diagnostic in a file. The lifetime of a Loc
 // is required to be less than SourceBuffer that it refers to due to the
 // contained filename and line references.
-struct DiagnosticLoc {
+struct Loc {
   // Writes the location to the given stream. It will be formatted as
   // `<filename>:<line_number>:<column_number>: ` with parts dropped when
   // unknown.
@@ -78,18 +78,18 @@ struct DiagnosticLoc {
 
 // A message composing a diagnostic. This may be the main message, but can also
 // be notes providing more information.
-struct DiagnosticMessage {
+struct Message {
   // Helper for calling `format_fn`.
   auto Format() const -> std::string { return format_fn(*this); }
 
   // The diagnostic's kind.
-  DiagnosticKind kind;
+  Kind kind;
 
   // The diagnostic's level.
-  DiagnosticLevel level;
+  Level level;
 
   // The calculated location of the diagnostic.
-  DiagnosticLoc loc;
+  Loc loc;
 
   // The diagnostic's format string. This, along with format_args, will be
   // passed to format_fn.
@@ -104,18 +104,18 @@ struct DiagnosticMessage {
   llvm::SmallVector<llvm::Any> format_args;
 
   // Returns the formatted string. By default, this uses llvm::formatv.
-  std::function<auto(const DiagnosticMessage&)->std::string> format_fn;
+  std::function<auto(const Message&)->std::string> format_fn;
 };
 
 // An instance of a single error or warning.  Information about the diagnostic
 // can be recorded into it for more complex consumers.
 struct Diagnostic {
   // The diagnostic's level.
-  DiagnosticLevel level;
+  Level level;
 
   // The byte offset of the final token which is associated with the diagnostic.
-  // This is used by `SortingDiagnosticConsumer`. This is separate from the
-  // `DiagnosticLoc` because it must refer to a position in the primary file
+  // This is used by `SortingConsumer`. This is separate from the
+  // `Loc` because it must refer to a position in the primary file
   // being processed by a consumer, and has no use cross-file or in notes.
   //
   // This will usually be the start position (not end) of the last lexed token
@@ -127,14 +127,14 @@ struct Diagnostic {
 
   // Messages related to the diagnostic. Only one should be a warning or error;
   // other messages provide context.
-  llvm::SmallVector<DiagnosticMessage> messages;
+  llvm::SmallVector<Message> messages;
 };
 
 // Use the DIAGNOSTIC macro to instantiate this.
 // This stores static information about a diagnostic category.
 template <typename... Args>
 struct DiagnosticBase {
-  explicit constexpr DiagnosticBase(DiagnosticKind kind, DiagnosticLevel level,
+  explicit constexpr DiagnosticBase(Kind kind, Level level,
                                     llvm::StringLiteral format)
       : Kind(kind), Level(level), Format(format) {
     static_assert((... && !(std::is_same_v<Args, llvm::StringRef> ||
@@ -145,13 +145,13 @@ struct DiagnosticBase {
   }
 
   // The diagnostic's kind.
-  DiagnosticKind Kind;
+  Kind Kind;
   // The diagnostic's level.
-  DiagnosticLevel Level;
+  Level Level;
   // The diagnostic's format for llvm::formatv.
   llvm::StringLiteral Format;
 };
 
-}  // namespace Carbon
+}  // namespace Carbon::Diagnostics
 
 #endif  // CARBON_TOOLCHAIN_DIAGNOSTICS_DIAGNOSTIC_H_

+ 10 - 10
toolchain/diagnostics/diagnostic_consumer.cpp

@@ -7,9 +7,9 @@
 #include <algorithm>
 #include <cstdint>
 
-namespace Carbon {
+namespace Carbon::Diagnostics {
 
-auto StreamDiagnosticConsumer::HandleDiagnostic(Diagnostic diagnostic) -> void {
+auto StreamConsumer::HandleDiagnostic(Diagnostic diagnostic) -> void {
   if (printed_diagnostic_) {
     *stream_ << "\n";
   } else {
@@ -19,16 +19,16 @@ auto StreamDiagnosticConsumer::HandleDiagnostic(Diagnostic diagnostic) -> void {
   for (const auto& message : diagnostic.messages) {
     message.loc.FormatLocation(*stream_);
     switch (message.level) {
-      case DiagnosticLevel::Error:
+      case Level::Error:
         *stream_ << "error: ";
         break;
-      case DiagnosticLevel::Warning:
+      case Level::Warning:
         *stream_ << "warning: ";
         break;
-      case DiagnosticLevel::Note:
+      case Level::Note:
         *stream_ << "note: ";
         break;
-      case DiagnosticLevel::LocationInfo:
+      case Level::LocationInfo:
         break;
     }
     *stream_ << message.Format();
@@ -39,15 +39,15 @@ auto StreamDiagnosticConsumer::HandleDiagnostic(Diagnostic diagnostic) -> void {
     // Don't include a snippet for location information to keep this diagnostic
     // more visually associated with the following diagnostic that it describes
     // and to better match C++ compilers.
-    if (message.level != DiagnosticLevel::LocationInfo) {
+    if (message.level != Level::LocationInfo) {
       message.loc.FormatSnippet(*stream_);
     }
   }
 }
 
-auto ConsoleDiagnosticConsumer() -> DiagnosticConsumer& {
-  static auto* consumer = new StreamDiagnosticConsumer(&llvm::errs());
+auto ConsoleConsumer() -> Consumer& {
+  static auto* consumer = new StreamConsumer(&llvm::errs());
   return *consumer;
 }
 
-}  // namespace Carbon
+}  // namespace Carbon::Diagnostics

+ 14 - 15
toolchain/diagnostics/diagnostic_consumer.h

@@ -9,25 +9,25 @@
 #include "llvm/ADT/StringRef.h"
 #include "toolchain/diagnostics/diagnostic.h"
 
-namespace Carbon {
+namespace Carbon::Diagnostics {
 
 // Receives diagnostics as they are emitted.
-class DiagnosticConsumer {
+class Consumer {
  public:
-  virtual ~DiagnosticConsumer() = default;
+  virtual ~Consumer() = default;
 
   // Handle a diagnostic.
   //
   // This relies on moves of the Diagnostic. At present, diagnostics are
   // allocated on the stack, so their lifetime is that of HandleDiagnostic.
-  // However, SortingDiagnosticConsumer needs a longer lifetime, until all
+  // However, SortingConsumer needs a longer lifetime, until all
   // diagnostics have been produced. As a consequence, it needs to either copy
   // or move the Diagnostic, and right now we're moving due to the overhead of
   // notes.
   //
   // At present, there is no persistent storage of diagnostics because IDEs
   // would be fine with diagnostics being printed immediately and discarded,
-  // without SortingDiagnosticConsumer. If this becomes a performance issue, we
+  // without SortingConsumer. If this becomes a performance issue, we
   // may want to investigate alternative ownership models that address both IDE
   // and CLI user needs.
   virtual auto HandleDiagnostic(Diagnostic diagnostic) -> void = 0;
@@ -37,10 +37,9 @@ class DiagnosticConsumer {
 };
 
 // A diagnostic consumer that prints to a stream.
-class StreamDiagnosticConsumer : public DiagnosticConsumer {
+class StreamConsumer : public Consumer {
  public:
-  explicit StreamDiagnosticConsumer(llvm::raw_ostream* stream)
-      : stream_(stream) {}
+  explicit StreamConsumer(llvm::raw_ostream* stream) : stream_(stream) {}
 
   auto HandleDiagnostic(Diagnostic diagnostic) -> void override;
   auto Flush() -> void override { stream_->flush(); }
@@ -51,7 +50,7 @@ class StreamDiagnosticConsumer : public DiagnosticConsumer {
   }
 
  private:
-  auto Print(const DiagnosticMessage& message, llvm::StringRef prefix) -> void;
+  auto Print(const Message& message, llvm::StringRef prefix) -> void;
 
   llvm::raw_ostream* stream_;
 
@@ -63,17 +62,17 @@ class StreamDiagnosticConsumer : public DiagnosticConsumer {
 };
 
 // Returns a diagnostic consumer instance that prints to stderr.
-auto ConsoleDiagnosticConsumer() -> DiagnosticConsumer&;
+auto ConsoleConsumer() -> Consumer&;
 
 // Diagnostic consumer adaptor that tracks whether any errors have been
 // produced.
-class ErrorTrackingDiagnosticConsumer : public DiagnosticConsumer {
+class ErrorTrackingConsumer : public Consumer {
  public:
-  explicit ErrorTrackingDiagnosticConsumer(DiagnosticConsumer& next_consumer)
+  explicit ErrorTrackingConsumer(Consumer& next_consumer)
       : next_consumer_(&next_consumer) {}
 
   auto HandleDiagnostic(Diagnostic diagnostic) -> void override {
-    seen_error_ |= diagnostic.level == DiagnosticLevel::Error;
+    seen_error_ |= diagnostic.level == Level::Error;
     next_consumer_->HandleDiagnostic(std::move(diagnostic));
   }
 
@@ -84,10 +83,10 @@ class ErrorTrackingDiagnosticConsumer : public DiagnosticConsumer {
   auto seen_error() const -> bool { return seen_error_; }
 
  private:
-  DiagnosticConsumer* next_consumer_;
+  Consumer* next_consumer_;
   bool seen_error_ = false;
 };
 
-}  // namespace Carbon
+}  // namespace Carbon::Diagnostics
 
 #endif  // CARBON_TOOLCHAIN_DIAGNOSTICS_DIAGNOSTIC_CONSUMER_H_

+ 79 - 80
toolchain/diagnostics/diagnostic_emitter.h

@@ -18,7 +18,7 @@
 #include "toolchain/diagnostics/diagnostic_consumer.h"
 #include "toolchain/diagnostics/diagnostic_kind.h"
 
-namespace Carbon {
+namespace Carbon::Diagnostics {
 
 namespace Internal {
 
@@ -30,13 +30,13 @@ using NoTypeDeduction = std::type_identity_t<Arg>;
 }  // namespace Internal
 
 template <typename LocT, typename AnnotateFn>
-class DiagnosticAnnotationScope;
+class AnnotationScope;
 
 // The result of `DiagnosticConvert::ConvertLoc`. This is non-templated to allow
 // sharing across converters.
-struct ConvertedDiagnosticLoc {
-  // Becomes DiagnosticMessage::loc.
-  DiagnosticLoc loc;
+struct ConvertedLoc {
+  // Becomes Message::loc.
+  Loc loc;
   // Becomes Diagnostic::last_byte_offset.
   int32_t last_byte_offset;
 };
@@ -46,10 +46,10 @@ struct ConvertedDiagnosticLoc {
 // write:
 //
 // struct NameId {
-//   using DiagnosticType = DiagnosticTypeInfo<std::string>;
+//   using DiagnosticType = Diagnostics::TypeInfo<std::string>;
 // };
 template <typename StorageTypeT>
-struct DiagnosticTypeInfo {
+struct TypeInfo {
   using StorageType = StorageTypeT;
 };
 
@@ -62,10 +62,10 @@ struct DiagnosticTypeInfo {
 // when parsing, or a parse tree node when type-checking, and to allow unit
 // tests to be decoupled from any concrete location representation.
 template <typename LocT>
-class DiagnosticEmitter {
+class Emitter {
  public:
   // A builder-pattern type to provide a fluent interface for constructing
-  // a more complex diagnostic. See `DiagnosticEmitter::Build` for the
+  // a more complex diagnostic. See `Emitter::Build` for the
   // expected usage.
   // This is nodiscard to protect against accidentally building a diagnostic
   // without emitting it.
@@ -77,14 +77,14 @@ class DiagnosticEmitter {
         -> DiagnosticBuilder& = default;
 
     // Adds a note diagnostic attached to the main diagnostic being built.
-    // The API mirrors the main emission API: `DiagnosticEmitter::Emit`.
-    // For the expected usage see the builder API: `DiagnosticEmitter::Build`.
+    // The API mirrors the main emission API: `Emitter::Emit`.
+    // For the expected usage see the builder API: `Emitter::Build`.
     template <typename... Args>
     auto Note(LocT loc, const DiagnosticBase<Args...>& diagnostic_base,
               Internal::NoTypeDeduction<Args>... args) -> DiagnosticBuilder&;
 
     // Emits the built diagnostic and its attached notes.
-    // For the expected usage see the builder API: `DiagnosticEmitter::Build`.
+    // For the expected usage see the builder API: `Emitter::Build`.
     template <typename... Args>
     auto Emit() & -> void;
 
@@ -98,10 +98,10 @@ class DiagnosticEmitter {
     explicit operator bool() { return emitter_; }
 
    private:
-    friend class DiagnosticEmitter<LocT>;
+    friend class Emitter<LocT>;
 
     template <typename... Args>
-    explicit DiagnosticBuilder(DiagnosticEmitter<LocT>* emitter, LocT loc,
+    explicit DiagnosticBuilder(Emitter<LocT>* emitter, LocT loc,
                                const DiagnosticBase<Args...>& diagnostic_base,
                                llvm::SmallVector<llvm::Any> args);
 
@@ -116,30 +116,29 @@ class DiagnosticEmitter {
                     llvm::SmallVector<llvm::Any> args) -> void;
 
     // Adds a message to the diagnostic, handling conversion of the arguments. A
-    // DiagnosticLoc must be provided instead of a LocT in order to
+    // Loc must be provided instead of a LocT in order to
     // avoid potential recursion.
     template <typename... Args>
-    auto AddMessageWithDiagnosticLoc(
-        DiagnosticLoc loc, const DiagnosticBase<Args...>& diagnostic_base,
-        llvm::SmallVector<llvm::Any> args) -> void;
+    auto AddMessageWithLoc(Loc loc,
+                           const DiagnosticBase<Args...>& diagnostic_base,
+                           llvm::SmallVector<llvm::Any> args) -> void;
 
     // Handles the cast of llvm::Any to Args types for formatv.
     // TODO: Custom formatting can be provided with an format_provider, but that
     // affects all formatv calls. Consider replacing formatv with a custom call
     // that allows diagnostic-specific formatting.
     template <typename... Args, size_t... N>
-    static auto FormatFn(const DiagnosticMessage& message,
+    static auto FormatFn(const Message& message,
                          std::index_sequence<N...> /*indices*/) -> std::string;
 
-    DiagnosticEmitter<LocT>* emitter_;
+    Emitter<LocT>* emitter_;
     Diagnostic diagnostic_;
   };
 
   // `consumer` is required to outlive the diagnostic emitter.
-  explicit DiagnosticEmitter(DiagnosticConsumer* consumer)
-      : consumer_(consumer) {}
+  explicit Emitter(Consumer* consumer) : consumer_(consumer) {}
 
-  virtual ~DiagnosticEmitter() = default;
+  virtual ~Emitter() = default;
 
   // Emits an error.
   //
@@ -165,16 +164,16 @@ class DiagnosticEmitter {
 
  protected:
   // Callback type used to report context messages from ConvertLoc.
-  // Note that the first parameter type is DiagnosticLoc rather than
+  // Note that the first parameter type is Loc rather than
   // LocT, because ConvertLoc must not recurse.
   using ContextFnT =
-      llvm::function_ref<auto(DiagnosticLoc, const DiagnosticBase<>&)->void>;
+      llvm::function_ref<auto(Loc, const DiagnosticBase<>&)->void>;
 
-  // Converts a LocT to a DiagnosticLoc and its `last_byte_offset` (see
-  // `DiagnosticMessage`). ConvertLoc may invoke context_fn to provide context
+  // Converts a LocT to a Loc and its `last_byte_offset` (see
+  // `Message`). ConvertLoc may invoke context_fn to provide context
   // messages.
   virtual auto ConvertLoc(LocT loc, ContextFnT context_fn) const
-      -> ConvertedDiagnosticLoc = 0;
+      -> ConvertedLoc = 0;
 
   // Converts arg types as needed. Most children don't customize conversion, so
   // the default returns the argument unchanged.
@@ -187,35 +186,35 @@ class DiagnosticEmitter {
   auto MakeAny(Arg arg) -> llvm::Any;
 
   template <typename OtherLocT, typename AnnotateFn>
-  friend class DiagnosticAnnotationScope;
+  friend class AnnotationScope;
 
-  DiagnosticConsumer* consumer_;
+  Consumer* consumer_;
   llvm::SmallVector<llvm::function_ref<auto(DiagnosticBuilder& builder)->void>>
       annotate_fns_;
 };
 
-// This relies on `void*` location handling on `DiagnosticEmitter`.
+// This relies on `void*` location handling on `Emitter`.
 //
 // TODO: Based on how this ends up used or if we get more distinct emitters, it
 // might be worth considering having diagnostics specify that they don't apply
 // to source-location carrying emitters. For example, this might look like a
 // `CARBON_NO_LOC_DIAGNOSTIC` macro, or some other factoring. But it might end
 // up being more noise than it is worth.
-class NoLocDiagnosticEmitter : public DiagnosticEmitter<void*> {
+class NoLocEmitter : public Emitter<void*> {
  public:
-  using DiagnosticEmitter::DiagnosticEmitter;
+  using Emitter::Emitter;
 
   // Emits an error. This specialization only applies to
-  // `NoLocDiagnosticEmitter`.
+  // `NoLocEmitter`.
   template <typename... Args>
   auto Emit(const DiagnosticBase<Args...>& diagnostic_base,
             Internal::NoTypeDeduction<Args>... args) -> void {
-    DiagnosticEmitter::Emit(nullptr, diagnostic_base, args...);
+    Emitter::Emit(nullptr, diagnostic_base, args...);
   }
 
  protected:
   auto ConvertLoc(void* /*loc*/, ContextFnT /*context_fn*/) const
-      -> ConvertedDiagnosticLoc override {
+      -> ConvertedLoc override {
     return {.loc = {.filename = ""}, .last_byte_offset = -1};
   }
 };
@@ -228,24 +227,23 @@ class NoLocDiagnosticEmitter : public DiagnosticEmitter<void*> {
 // given emitter. That function can annotate the diagnostic by calling
 // `builder.Note` to add notes.
 template <typename LocT, typename AnnotateFn>
-class DiagnosticAnnotationScope {
+class AnnotationScope {
  public:
-  DiagnosticAnnotationScope(DiagnosticEmitter<LocT>* emitter,
-                            AnnotateFn annotate)
+  AnnotationScope(Emitter<LocT>* emitter, AnnotateFn annotate)
       : emitter_(emitter), annotate_(std::move(annotate)) {
     emitter_->annotate_fns_.push_back(annotate_);
   }
-  ~DiagnosticAnnotationScope() { emitter_->annotate_fns_.pop_back(); }
+  ~AnnotationScope() { emitter_->annotate_fns_.pop_back(); }
 
  private:
-  DiagnosticEmitter<LocT>* emitter_;
+  Emitter<LocT>* emitter_;
   // Make a copy of the annotation function to ensure that it lives long enough.
   AnnotateFn annotate_;
 };
 
 template <typename LocT, typename AnnotateFn>
-DiagnosticAnnotationScope(DiagnosticEmitter<LocT>* emitter, AnnotateFn annotate)
-    -> DiagnosticAnnotationScope<LocT, AnnotateFn>;
+AnnotationScope(Emitter<LocT>* emitter, AnnotateFn annotate)
+    -> AnnotationScope<LocT, AnnotateFn>;
 
 // ============================================================================
 // Only internal implementation details below this point.
@@ -254,13 +252,13 @@ DiagnosticAnnotationScope(DiagnosticEmitter<LocT>* emitter, AnnotateFn annotate)
 namespace Internal {
 
 // Determines whether there's a DiagnosticType member on Arg.
-// Used by DiagnosticEmitter.
+// Used by Emitter.
 template <typename Arg>
 concept HasDiagnosticType = requires { typename Arg::DiagnosticType; };
 
 // The default implementation with no conversion.
 template <typename Arg>
-struct DiagnosticTypeForArg : public DiagnosticTypeInfo<Arg> {};
+struct DiagnosticTypeForArg : public TypeInfo<Arg> {};
 
 // Exposes a custom conversion for an argument type.
 template <typename Arg>
@@ -271,14 +269,14 @@ struct DiagnosticTypeForArg<Arg> : public Arg::DiagnosticType {};
 
 template <typename LocT>
 template <typename... Args>
-auto DiagnosticEmitter<LocT>::DiagnosticBuilder::Note(
+auto Emitter<LocT>::DiagnosticBuilder::Note(
     LocT loc, const DiagnosticBase<Args...>& diagnostic_base,
     Internal::NoTypeDeduction<Args>... args) -> DiagnosticBuilder& {
   if (!emitter_) {
     return *this;
   }
-  CARBON_CHECK(diagnostic_base.Level == DiagnosticLevel::Note ||
-                   diagnostic_base.Level == DiagnosticLevel::LocationInfo,
+  CARBON_CHECK(diagnostic_base.Level == Level::Note ||
+                   diagnostic_base.Level == Level::LocationInfo,
                "{0}", static_cast<int>(diagnostic_base.Level));
   AddMessage(loc, diagnostic_base, {emitter_->MakeAny<Args>(args)...});
   return *this;
@@ -286,7 +284,7 @@ auto DiagnosticEmitter<LocT>::DiagnosticBuilder::Note(
 
 template <typename LocT>
 template <typename... Args>
-auto DiagnosticEmitter<LocT>::DiagnosticBuilder::Emit() & -> void {
+auto Emitter<LocT>::DiagnosticBuilder::Emit() & -> void {
   if (!emitter_) {
     return;
   }
@@ -303,7 +301,7 @@ concept AlwaysFalse = false;
 
 template <typename LocT>
 template <typename... Args>
-auto DiagnosticEmitter<LocT>::DiagnosticBuilder::Emit() && -> void {
+auto Emitter<LocT>::DiagnosticBuilder::Emit() && -> void {
   // TODO: This is required by clang-16, but `false` may work in newer clang
   // versions. Replace when possible.
   static_assert(Internal::AlwaysFalse<LocT>,
@@ -314,59 +312,59 @@ auto DiagnosticEmitter<LocT>::DiagnosticBuilder::Emit() && -> void {
 
 template <typename LocT>
 template <typename... Args>
-DiagnosticEmitter<LocT>::DiagnosticBuilder::DiagnosticBuilder(
-    DiagnosticEmitter<LocT>* emitter, LocT loc,
+Emitter<LocT>::DiagnosticBuilder::DiagnosticBuilder(
+    Emitter<LocT>* emitter, LocT loc,
     const DiagnosticBase<Args...>& diagnostic_base,
     llvm::SmallVector<llvm::Any> args)
     : emitter_(emitter), diagnostic_({.level = diagnostic_base.Level}) {
   AddMessage(loc, diagnostic_base, std::move(args));
-  CARBON_CHECK(diagnostic_base.Level != DiagnosticLevel::Note);
+  CARBON_CHECK(diagnostic_base.Level != Level::Note);
 }
 
 template <typename LocT>
 template <typename... Args>
-auto DiagnosticEmitter<LocT>::DiagnosticBuilder::AddMessage(
+auto Emitter<LocT>::DiagnosticBuilder::AddMessage(
     LocT loc, const DiagnosticBase<Args...>& diagnostic_base,
     llvm::SmallVector<llvm::Any> args) -> void {
   if (!emitter_) {
     return;
   }
   auto converted = emitter_->ConvertLoc(
-      loc, [&](DiagnosticLoc context_loc,
-               const DiagnosticBase<>& context_diagnostic_base) {
-        AddMessageWithDiagnosticLoc(context_loc, context_diagnostic_base, {});
+      loc,
+      [&](Loc context_loc, const DiagnosticBase<>& context_diagnostic_base) {
+        AddMessageWithLoc(context_loc, context_diagnostic_base, {});
       });
   // Use the last byte offset from the first message.
   if (diagnostic_.messages.empty()) {
     diagnostic_.last_byte_offset = converted.last_byte_offset;
   }
-  AddMessageWithDiagnosticLoc(converted.loc, diagnostic_base, args);
+  AddMessageWithLoc(converted.loc, diagnostic_base, args);
 }
 
 template <typename LocT>
 template <typename... Args>
-auto DiagnosticEmitter<LocT>::DiagnosticBuilder::AddMessageWithDiagnosticLoc(
-    DiagnosticLoc loc, const DiagnosticBase<Args...>& diagnostic_base,
+auto Emitter<LocT>::DiagnosticBuilder::AddMessageWithLoc(
+    Loc loc, const DiagnosticBase<Args...>& diagnostic_base,
     llvm::SmallVector<llvm::Any> args) -> void {
   if (!emitter_) {
     return;
   }
-  diagnostic_.messages.emplace_back(DiagnosticMessage{
-      .kind = diagnostic_base.Kind,
-      .level = diagnostic_base.Level,
-      .loc = loc,
-      .format = diagnostic_base.Format,
-      .format_args = std::move(args),
-      .format_fn = [](const DiagnosticMessage& message) -> std::string {
-        return FormatFn<Args...>(message,
-                                 std::make_index_sequence<sizeof...(Args)>());
-      }});
+  diagnostic_.messages.emplace_back(
+      Message{.kind = diagnostic_base.Kind,
+              .level = diagnostic_base.Level,
+              .loc = loc,
+              .format = diagnostic_base.Format,
+              .format_args = std::move(args),
+              .format_fn = [](const Message& message) -> std::string {
+                return FormatFn<Args...>(
+                    message, std::make_index_sequence<sizeof...(Args)>());
+              }});
 }
 
 template <typename LocT>
 template <typename... Args, size_t... N>
-auto DiagnosticEmitter<LocT>::DiagnosticBuilder::FormatFn(
-    const DiagnosticMessage& message, std::index_sequence<N...> /*indices*/)
+auto Emitter<LocT>::DiagnosticBuilder::FormatFn(
+    const Message& message, std::index_sequence<N...> /*indices*/)
     -> std::string {
   static_assert(sizeof...(Args) == sizeof...(N), "Invalid template args");
   CARBON_CHECK(message.format_args.size() == sizeof...(Args),
@@ -381,9 +379,9 @@ auto DiagnosticEmitter<LocT>::DiagnosticBuilder::FormatFn(
 
 template <typename LocT>
 template <typename... Args>
-auto DiagnosticEmitter<LocT>::Emit(
-    LocT loc, const DiagnosticBase<Args...>& diagnostic_base,
-    Internal::NoTypeDeduction<Args>... args) -> void {
+auto Emitter<LocT>::Emit(LocT loc,
+                         const DiagnosticBase<Args...>& diagnostic_base,
+                         Internal::NoTypeDeduction<Args>... args) -> void {
   DiagnosticBuilder builder(this, loc, diagnostic_base,
                             {MakeAny<Args>(args)...});
   builder.Emit();
@@ -391,16 +389,17 @@ auto DiagnosticEmitter<LocT>::Emit(
 
 template <typename LocT>
 template <typename... Args>
-auto DiagnosticEmitter<LocT>::Build(
-    LocT loc, const DiagnosticBase<Args...>& diagnostic_base,
-    Internal::NoTypeDeduction<Args>... args) -> DiagnosticBuilder {
+auto Emitter<LocT>::Build(LocT loc,
+                          const DiagnosticBase<Args...>& diagnostic_base,
+                          Internal::NoTypeDeduction<Args>... args)
+    -> DiagnosticBuilder {
   return DiagnosticBuilder(this, loc, diagnostic_base,
                            {MakeAny<Args>(args)...});
 }
 
 template <typename LocT>
 template <typename Arg>
-auto DiagnosticEmitter<LocT>::MakeAny(Arg arg) -> llvm::Any {
+auto Emitter<LocT>::MakeAny(Arg arg) -> llvm::Any {
   llvm::Any converted = ConvertArg(arg);
   using Storage = Internal::DiagnosticTypeForArg<Arg>::StorageType;
   CARBON_CHECK(llvm::any_cast<Storage>(&converted),
@@ -409,6 +408,6 @@ auto DiagnosticEmitter<LocT>::MakeAny(Arg arg) -> llvm::Any {
   return converted;
 }
 
-}  // namespace Carbon
+}  // namespace Carbon::Diagnostics
 
 #endif  // CARBON_TOOLCHAIN_DIAGNOSTICS_DIAGNOSTIC_EMITTER_H_

+ 23 - 25
toolchain/diagnostics/diagnostic_emitter_test.cpp

@@ -13,72 +13,70 @@
 namespace Carbon::Testing {
 namespace {
 
-using ::Carbon::Testing::IsDiagnostic;
-using ::Carbon::Testing::IsSingleDiagnostic;
 using testing::ElementsAre;
 
-class FakeDiagnosticEmitter : public DiagnosticEmitter<int> {
+class FakeEmitter : public Diagnostics::Emitter<int> {
  public:
-  using DiagnosticEmitter::DiagnosticEmitter;
+  using Emitter::Emitter;
 
  protected:
   auto ConvertLoc(int n, ContextFnT /*context_fn*/) const
-      -> ConvertedDiagnosticLoc override {
+      -> Diagnostics::ConvertedLoc override {
     return {.loc = {.line_number = 1, .column_number = n},
             .last_byte_offset = -1};
   }
 };
 
-class DiagnosticEmitterTest : public ::testing::Test {
+class EmitterTest : public ::testing::Test {
  public:
-  DiagnosticEmitterTest() : emitter_(&consumer_) {}
+  EmitterTest() : emitter_(&consumer_) {}
 
   Testing::MockDiagnosticConsumer consumer_;
-  FakeDiagnosticEmitter emitter_;
+  FakeEmitter emitter_;
 };
 
-TEST_F(DiagnosticEmitterTest, EmitSimpleError) {
+TEST_F(EmitterTest, EmitSimpleError) {
   CARBON_DIAGNOSTIC(TestDiagnostic, Error, "simple error");
   EXPECT_CALL(consumer_, HandleDiagnostic(IsSingleDiagnostic(
-                             DiagnosticKind::TestDiagnostic,
-                             DiagnosticLevel::Error, 1, 1, "simple error")));
+                             Diagnostics::Kind::TestDiagnostic,
+                             Diagnostics::Level::Error, 1, 1, "simple error")));
   EXPECT_CALL(consumer_, HandleDiagnostic(IsSingleDiagnostic(
-                             DiagnosticKind::TestDiagnostic,
-                             DiagnosticLevel::Error, 1, 2, "simple error")));
+                             Diagnostics::Kind::TestDiagnostic,
+                             Diagnostics::Level::Error, 1, 2, "simple error")));
   emitter_.Emit(1, TestDiagnostic);
   emitter_.Emit(2, TestDiagnostic);
 }
 
-TEST_F(DiagnosticEmitterTest, EmitSimpleWarning) {
+TEST_F(EmitterTest, EmitSimpleWarning) {
   CARBON_DIAGNOSTIC(TestDiagnostic, Warning, "simple warning");
   EXPECT_CALL(consumer_,
               HandleDiagnostic(IsSingleDiagnostic(
-                  DiagnosticKind::TestDiagnostic, DiagnosticLevel::Warning, 1,
-                  1, "simple warning")));
+                  Diagnostics::Kind::TestDiagnostic,
+                  Diagnostics::Level::Warning, 1, 1, "simple warning")));
   emitter_.Emit(1, TestDiagnostic);
 }
 
-TEST_F(DiagnosticEmitterTest, EmitOneArgDiagnostic) {
+TEST_F(EmitterTest, EmitOneArgDiagnostic) {
   CARBON_DIAGNOSTIC(TestDiagnostic, Error, "arg: `{0}`", std::string);
   EXPECT_CALL(consumer_, HandleDiagnostic(IsSingleDiagnostic(
-                             DiagnosticKind::TestDiagnostic,
-                             DiagnosticLevel::Error, 1, 1, "arg: `str`")));
+                             Diagnostics::Kind::TestDiagnostic,
+                             Diagnostics::Level::Error, 1, 1, "arg: `str`")));
   emitter_.Emit(1, TestDiagnostic, "str");
 }
 
-TEST_F(DiagnosticEmitterTest, EmitNote) {
+TEST_F(EmitterTest, EmitNote) {
   CARBON_DIAGNOSTIC(TestDiagnostic, Warning, "simple warning");
   CARBON_DIAGNOSTIC(TestDiagnosticNote, Note, "note");
   EXPECT_CALL(
       consumer_,
       HandleDiagnostic(IsDiagnostic(
-          DiagnosticLevel::Warning,
+          Diagnostics::Level::Warning,
           ElementsAre(
-              IsDiagnosticMessage(DiagnosticKind::TestDiagnostic,
-                                  DiagnosticLevel::Warning, 1, 1,
+              IsDiagnosticMessage(Diagnostics::Kind::TestDiagnostic,
+                                  Diagnostics::Level::Warning, 1, 1,
                                   "simple warning"),
-              IsDiagnosticMessage(DiagnosticKind::TestDiagnosticNote,
-                                  DiagnosticLevel::Note, 1, 2, "note")))));
+              IsDiagnosticMessage(Diagnostics::Kind::TestDiagnosticNote,
+                                  Diagnostics::Level::Note, 1, 2, "note")))));
   emitter_.Build(1, TestDiagnostic).Note(2, TestDiagnosticNote).Emit();
 }
 

+ 3 - 3
toolchain/diagnostics/diagnostic_kind.cpp

@@ -4,11 +4,11 @@
 
 #include "toolchain/diagnostics/diagnostic_kind.h"  // IWYU pragma: keep
 
-namespace Carbon {
+namespace Carbon::Diagnostics {
 
-CARBON_DEFINE_ENUM_CLASS_NAMES(DiagnosticKind) = {
+CARBON_DEFINE_ENUM_CLASS_NAMES(Kind) = {
 #define CARBON_DIAGNOSTIC_KIND(Name) CARBON_ENUM_CLASS_NAME_STRING(Name)
 #include "toolchain/diagnostics/diagnostic_kind.def"
 };
 
-}  // namespace Carbon
+}  // namespace Carbon::Diagnostics

+ 7 - 8
toolchain/diagnostics/diagnostic_kind.h

@@ -9,12 +9,12 @@
 
 #include "common/enum_base.h"
 
-namespace Carbon {
+namespace Carbon::Diagnostics {
 
 // Although this currently fits into int8_t, it shouldn't be expected to
 // long-term.
 // NOLINTNEXTLINE(performance-enum-size)
-CARBON_DEFINE_RAW_ENUM_CLASS(DiagnosticKind, uint16_t) {
+CARBON_DEFINE_RAW_ENUM_CLASS(Kind, uint16_t) {
 #define CARBON_DIAGNOSTIC_KIND(Name) CARBON_RAW_ENUM_ENUMERATOR(Name)
 #include "toolchain/diagnostics/diagnostic_kind.def"
 };
@@ -27,19 +27,18 @@ CARBON_DEFINE_RAW_ENUM_CLASS(DiagnosticKind, uint16_t) {
 // definitions centrally is expected to create a compilation bottleneck
 // long-term, and we also see value to keeping diagnostic format strings close
 // to the consuming code.
-class DiagnosticKind : public CARBON_ENUM_BASE(DiagnosticKind) {
+class Kind : public CARBON_ENUM_BASE(Kind) {
  public:
 #define CARBON_DIAGNOSTIC_KIND(Name) CARBON_ENUM_CONSTANT_DECL(Name)
 #include "toolchain/diagnostics/diagnostic_kind.def"
 };
 
-#define CARBON_DIAGNOSTIC_KIND(Name) \
-  CARBON_ENUM_CONSTANT_DEFINITION(DiagnosticKind, Name)
+#define CARBON_DIAGNOSTIC_KIND(Name) CARBON_ENUM_CONSTANT_DEFINITION(Kind, Name)
 #include "toolchain/diagnostics/diagnostic_kind.def"
 
-// We expect DiagnosticKind to fit into 2 bits.
-static_assert(sizeof(DiagnosticKind) == 2, "DiagnosticKind includes padding!");
+// We expect Kind to fit into 2 bits.
+static_assert(sizeof(Kind) == 2, "Kind includes padding!");
 
-}  // namespace Carbon
+}  // namespace Carbon::Diagnostics
 
 #endif  // CARBON_TOOLCHAIN_DIAGNOSTICS_DIAGNOSTIC_KIND_H_

+ 6 - 6
toolchain/diagnostics/file_diagnostics.h

@@ -7,26 +7,26 @@
 
 #include "toolchain/diagnostics/diagnostic_emitter.h"
 
-namespace Carbon {
+namespace Carbon::Diagnostics {
 
-// We frequently want a `DiagnosticEmitter` that directly uses a filename. Note
+// We frequently want a `Emitter` that directly uses a filename. Note
 // that an empty string can be used for a diagnostic that has no particular
 // location.
 //
 // Note this provides no way to set a line or column on diagnostics. More
 // specific emitters must be used for that.
-class FileDiagnosticEmitter : public DiagnosticEmitter<llvm::StringRef> {
+class FileEmitter : public Emitter<llvm::StringRef> {
  public:
-  using DiagnosticEmitter::DiagnosticEmitter;
+  using Emitter::Emitter;
 
  protected:
   // Converts a filename directly to the diagnostic location.
   auto ConvertLoc(llvm::StringRef filename, ContextFnT /*context_fn*/) const
-      -> ConvertedDiagnosticLoc override {
+      -> ConvertedLoc override {
     return {.loc = {.filename = filename}, .last_byte_offset = -1};
   }
 };
 
-}  // namespace Carbon
+}  // namespace Carbon::Diagnostics
 
 #endif  // CARBON_TOOLCHAIN_DIAGNOSTICS_FILE_DIAGNOSTICS_H_

+ 6 - 6
toolchain/diagnostics/format_providers.cpp

@@ -7,9 +7,9 @@
 #include "common/check.h"
 #include "llvm/ADT/StringExtras.h"
 
-auto llvm::format_provider<Carbon::BoolAsSelect>::format(
-    const Carbon::BoolAsSelect& wrapper, raw_ostream& out, StringRef style)
-    -> void {
+auto llvm::format_provider<Carbon::Diagnostics::BoolAsSelect>::format(
+    const Carbon::Diagnostics::BoolAsSelect& wrapper, raw_ostream& out,
+    StringRef style) -> void {
   if (style.empty()) {
     llvm::format_provider<bool>::format(wrapper.value, out, style);
     return;
@@ -30,9 +30,9 @@ auto llvm::format_provider<Carbon::BoolAsSelect>::format(
   }
 }
 
-auto llvm::format_provider<Carbon::IntAsSelect>::format(
-    const Carbon::IntAsSelect& wrapper, raw_ostream& out, StringRef style)
-    -> void {
+auto llvm::format_provider<Carbon::Diagnostics::IntAsSelect>::format(
+    const Carbon::Diagnostics::IntAsSelect& wrapper, raw_ostream& out,
+    StringRef style) -> void {
   if (style == "s") {
     if (wrapper.value != 1) {
       out << "s";

+ 10 - 10
toolchain/diagnostics/format_providers.h

@@ -8,7 +8,7 @@
 #include "common/ostream.h"
 #include "llvm/Support/FormatVariadicDetails.h"
 
-namespace Carbon {
+namespace Carbon::Diagnostics {
 
 // Selects a formatv string based on the value.
 //
@@ -53,20 +53,20 @@ struct IntAsSelect {
   int value;
 };
 
-}  // namespace Carbon
+}  // namespace Carbon::Diagnostics
 
-// See BoolAsSelect.
+// See Diagnostics::BoolAsSelect.
 template <>
-struct llvm::format_provider<Carbon::BoolAsSelect> {
-  static auto format(const Carbon::BoolAsSelect& wrapper, raw_ostream& out,
-                     StringRef style) -> void;
+struct llvm::format_provider<Carbon::Diagnostics::BoolAsSelect> {
+  static auto format(const Carbon::Diagnostics::BoolAsSelect& wrapper,
+                     raw_ostream& out, StringRef style) -> void;
 };
 
-// See IntAsSelect.
+// See Diagnostics::IntAsSelect.
 template <>
-struct llvm::format_provider<Carbon::IntAsSelect> {
-  static auto format(const Carbon::IntAsSelect& wrapper, raw_ostream& out,
-                     StringRef style) -> void;
+struct llvm::format_provider<Carbon::Diagnostics::IntAsSelect> {
+  static auto format(const Carbon::Diagnostics::IntAsSelect& wrapper,
+                     raw_ostream& out, StringRef style) -> void;
 };
 
 #endif  // CARBON_TOOLCHAIN_DIAGNOSTICS_FORMAT_PROVIDERS_H_

+ 46 - 24
toolchain/diagnostics/format_providers_test.cpp

@@ -9,72 +9,94 @@
 
 #include "llvm/Support/FormatVariadic.h"
 
-namespace Carbon {
+namespace Carbon::Diagnostics {
 namespace {
 
 using ::testing::Eq;
 
 TEST(BoolAsSelect, Cases) {
   constexpr char Format[] = "{0:a|b}";
-  EXPECT_THAT(llvm::formatv(Format, BoolAsSelect(true)).str(), Eq("a"));
-  EXPECT_THAT(llvm::formatv(Format, BoolAsSelect(false)).str(), Eq("b"));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::BoolAsSelect(true)).str(),
+              Eq("a"));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::BoolAsSelect(false)).str(),
+              Eq("b"));
 }
 
 TEST(BoolAsSelect, CasesWithNormalFormat) {
   constexpr char Format[] = "{0} {0:a|b}";
-  EXPECT_THAT(llvm::formatv(Format, BoolAsSelect(true)).str(), Eq("true a"));
-  EXPECT_THAT(llvm::formatv(Format, BoolAsSelect(false)).str(), Eq("false b"));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::BoolAsSelect(true)).str(),
+              Eq("true a"));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::BoolAsSelect(false)).str(),
+              Eq("false b"));
 }
 
 TEST(BoolAsSelect, Spaces) {
   constexpr char Format[] = "{0: a | b }";
-  EXPECT_THAT(llvm::formatv(Format, BoolAsSelect(true)).str(), Eq(" a "));
-  EXPECT_THAT(llvm::formatv(Format, BoolAsSelect(false)).str(), Eq(" b "));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::BoolAsSelect(true)).str(),
+              Eq(" a "));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::BoolAsSelect(false)).str(),
+              Eq(" b "));
 }
 
 TEST(IntAsSelect, OnlyDefault) {
   constexpr char Format[] = "{0::default}";
-  EXPECT_THAT(llvm::formatv(Format, IntAsSelect(0)).str(), Eq("default"));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::IntAsSelect(0)).str(),
+              Eq("default"));
 }
 
 TEST(IntAsSelect, OneEquals) {
   constexpr char Format[] = "{0:=0:zero}";
-  EXPECT_THAT(llvm::formatv(Format, IntAsSelect(0)).str(), Eq("zero"));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::IntAsSelect(0)).str(),
+              Eq("zero"));
 }
 
 TEST(IntAsSelect, TwoEquals) {
   constexpr char Format[] = "{0:=0:zero|=1:one}";
-  EXPECT_THAT(llvm::formatv(Format, IntAsSelect(0)).str(), Eq("zero"));
-  EXPECT_THAT(llvm::formatv(Format, IntAsSelect(1)).str(), Eq("one"));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::IntAsSelect(0)).str(),
+              Eq("zero"));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::IntAsSelect(1)).str(),
+              Eq("one"));
 }
 
 TEST(IntAsSelect, TwoEqualsAndDefault) {
   constexpr char Format[] = "{0:=0:zero|=1:one|:default}";
-  EXPECT_THAT(llvm::formatv(Format, IntAsSelect(0)).str(), Eq("zero"));
-  EXPECT_THAT(llvm::formatv(Format, IntAsSelect(1)).str(), Eq("one"));
-  EXPECT_THAT(llvm::formatv(Format, IntAsSelect(2)).str(), Eq("default"));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::IntAsSelect(0)).str(),
+              Eq("zero"));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::IntAsSelect(1)).str(),
+              Eq("one"));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::IntAsSelect(2)).str(),
+              Eq("default"));
 }
 
 TEST(IntAsSelect, Spaces) {
   constexpr char Format[] = "{0:=0: zero |=1: one |: default }";
-  EXPECT_THAT(llvm::formatv(Format, IntAsSelect(0)).str(), Eq(" zero "));
-  EXPECT_THAT(llvm::formatv(Format, IntAsSelect(1)).str(), Eq(" one "));
-  EXPECT_THAT(llvm::formatv(Format, IntAsSelect(2)).str(), Eq(" default "));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::IntAsSelect(0)).str(),
+              Eq(" zero "));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::IntAsSelect(1)).str(),
+              Eq(" one "));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::IntAsSelect(2)).str(),
+              Eq(" default "));
 }
 
 TEST(IntAsSelect, CasesWithNormalFormat) {
   constexpr char Format[] = "{0} argument{0:=1:|:s}";
-  EXPECT_THAT(llvm::formatv(Format, IntAsSelect(0)).str(), Eq("0 arguments"));
-  EXPECT_THAT(llvm::formatv(Format, IntAsSelect(1)).str(), Eq("1 argument"));
-  EXPECT_THAT(llvm::formatv(Format, IntAsSelect(2)).str(), Eq("2 arguments"));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::IntAsSelect(0)).str(),
+              Eq("0 arguments"));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::IntAsSelect(1)).str(),
+              Eq("1 argument"));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::IntAsSelect(2)).str(),
+              Eq("2 arguments"));
 }
 
 TEST(IntAsSelect, PluralS) {
   constexpr char Format[] = "{0} argument{0:s}";
-  EXPECT_THAT(llvm::formatv(Format, IntAsSelect(0)).str(), Eq("0 arguments"));
-  EXPECT_THAT(llvm::formatv(Format, IntAsSelect(1)).str(), Eq("1 argument"));
-  EXPECT_THAT(llvm::formatv(Format, IntAsSelect(2)).str(), Eq("2 arguments"));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::IntAsSelect(0)).str(),
+              Eq("0 arguments"));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::IntAsSelect(1)).str(),
+              Eq("1 argument"));
+  EXPECT_THAT(llvm::formatv(Format, Diagnostics::IntAsSelect(2)).str(),
+              Eq("2 arguments"));
 }
 
 }  // namespace
-}  // namespace Carbon
+}  // namespace Carbon::Diagnostics

+ 7 - 7
toolchain/diagnostics/mocks.cpp

@@ -4,7 +4,7 @@
 
 #include "toolchain/diagnostics/mocks.h"
 
-namespace Carbon {
+namespace Carbon::Diagnostics {
 
 auto PrintTo(const Diagnostic& diagnostic, std::ostream* os) -> void {
   *os << "Diagnostic{";
@@ -17,21 +17,21 @@ auto PrintTo(const Diagnostic& diagnostic, std::ostream* os) -> void {
   *os << "\"}";
 }
 
-auto PrintTo(DiagnosticLevel level, std::ostream* os) -> void {
+auto PrintTo(Level level, std::ostream* os) -> void {
   switch (level) {
-    case DiagnosticLevel::LocationInfo:
+    case Level::LocationInfo:
       *os << "LocationInfo";
       break;
-    case DiagnosticLevel::Note:
+    case Level::Note:
       *os << "Note";
       break;
-    case DiagnosticLevel::Warning:
+    case Level::Warning:
       *os << "Warning";
       break;
-    case DiagnosticLevel::Error:
+    case Level::Error:
       *os << "Error";
       break;
   }
 }
 
-}  // namespace Carbon
+}  // namespace Carbon::Diagnostics

+ 28 - 26
toolchain/diagnostics/mocks.h

@@ -11,51 +11,53 @@
 
 namespace Carbon::Testing {
 
-class MockDiagnosticConsumer : public DiagnosticConsumer {
+class MockDiagnosticConsumer : public Diagnostics::Consumer {
  public:
-  MOCK_METHOD(void, HandleDiagnostic, (Diagnostic diagnostic), (override));
+  MOCK_METHOD(void, HandleDiagnostic, (Diagnostics::Diagnostic diagnostic),
+              (override));
 };
 
 // NOLINTNEXTLINE(modernize-use-trailing-return-type): From the macro.
-MATCHER_P(IsDiagnosticMessageString, matcher, "") {
-  const DiagnosticMessage& message = arg;
+MATCHER_P(IsDiagnosticsMessageString, matcher, "") {
+  const Diagnostics::Message& message = arg;
   return testing::ExplainMatchResult(matcher, message.Format(),
                                      result_listener);
 }
 
-inline auto IsDiagnosticMessage(testing::Matcher<DiagnosticKind> kind,
-                                testing::Matcher<DiagnosticLevel> level,
+inline auto IsDiagnosticMessage(testing::Matcher<Diagnostics::Kind> kind,
+                                testing::Matcher<Diagnostics::Level> level,
                                 testing::Matcher<int> line_number,
                                 testing::Matcher<int> column_number,
                                 testing::Matcher<std::string> message)
-    -> testing::Matcher<DiagnosticMessage> {
+    -> testing::Matcher<Diagnostics::Message> {
   using testing::AllOf;
   using testing::Field;
-  return AllOf(Field("kind", &DiagnosticMessage::kind, kind),
-               Field("level", &DiagnosticMessage::level, level),
-               Field(&DiagnosticMessage::loc,
-                     AllOf(Field("line_number", &DiagnosticLoc::line_number,
-                                 line_number),
-                           Field("column_number", &DiagnosticLoc::column_number,
-                                 column_number))),
-               IsDiagnosticMessageString(message));
+  return AllOf(
+      Field("kind", &Diagnostics::Message::kind, kind),
+      Field("level", &Diagnostics::Message::level, level),
+      Field(&Diagnostics::Message::loc,
+            AllOf(Field("line_number", &Diagnostics::Loc::line_number,
+                        line_number),
+                  Field("column_number", &Diagnostics::Loc::column_number,
+                        column_number))),
+      IsDiagnosticsMessageString(message));
 }
 
 inline auto IsDiagnostic(
-    testing::Matcher<DiagnosticLevel> level,
-    testing::Matcher<llvm::SmallVector<DiagnosticMessage>> elements)
-    -> testing::Matcher<Diagnostic> {
+    testing::Matcher<Diagnostics::Level> level,
+    testing::Matcher<llvm::SmallVector<Diagnostics::Message>> elements)
+    -> testing::Matcher<Diagnostics::Diagnostic> {
   return testing::AllOf(
-      testing::Field("level", &Diagnostic::level, level),
-      testing::Field("messages", &Diagnostic::messages, elements));
+      testing::Field("level", &Diagnostics::Diagnostic::level, level),
+      testing::Field("messages", &Diagnostics::Diagnostic::messages, elements));
 }
 
-inline auto IsSingleDiagnostic(testing::Matcher<DiagnosticKind> kind,
-                               testing::Matcher<DiagnosticLevel> level,
+inline auto IsSingleDiagnostic(testing::Matcher<Diagnostics::Kind> kind,
+                               testing::Matcher<Diagnostics::Level> level,
                                testing::Matcher<int> line_number,
                                testing::Matcher<int> column_number,
                                testing::Matcher<std::string> message)
-    -> testing::Matcher<Diagnostic> {
+    -> testing::Matcher<Diagnostics::Diagnostic> {
   return IsDiagnostic(
       level, testing::ElementsAre(IsDiagnosticMessage(kind, level, line_number,
                                                       column_number, message)));
@@ -63,12 +65,12 @@ inline auto IsSingleDiagnostic(testing::Matcher<DiagnosticKind> kind,
 
 }  // namespace Carbon::Testing
 
-namespace Carbon {
+namespace Carbon::Diagnostics {
 
 // Printing helpers for tests.
 auto PrintTo(const Diagnostic& diagnostic, std::ostream* os) -> void;
-auto PrintTo(DiagnosticLevel level, std::ostream* os) -> void;
+auto PrintTo(Level level, std::ostream* os) -> void;
 
-}  // namespace Carbon
+}  // namespace Carbon::Diagnostics
 
 #endif  // CARBON_TOOLCHAIN_DIAGNOSTICS_MOCKS_H_

+ 11 - 11
toolchain/diagnostics/null_diagnostics.h

@@ -7,37 +7,37 @@
 
 #include "toolchain/diagnostics/diagnostic_emitter.h"
 
-namespace Carbon {
+namespace Carbon::Diagnostics {
 
 // Returns a singleton consumer that doesn't print its diagnostics.
-inline auto NullDiagnosticConsumer() -> DiagnosticConsumer& {
-  struct Consumer : DiagnosticConsumer {
+inline auto NullConsumer() -> Consumer& {
+  struct SingletonConsumer : Consumer {
     auto HandleDiagnostic(Diagnostic /*d*/) -> void override {}
   };
-  static auto* consumer = new Consumer;
+  static auto* consumer = new SingletonConsumer;
   return *consumer;
 }
 
 // Returns a singleton emitter that doesn't print its diagnostics.
 template <typename LocT>
-inline auto NullDiagnosticEmitter() -> DiagnosticEmitter<LocT>& {
-  class Emitter : public DiagnosticEmitter<LocT> {
+inline auto NullEmitter() -> Emitter<LocT>& {
+  class SingletonEmitter : public Emitter<LocT> {
    public:
-    using DiagnosticEmitter<LocT>::DiagnosticEmitter;
+    using Emitter<LocT>::Emitter;
 
    protected:
     // Converts a filename directly to the diagnostic location.
     auto ConvertLoc(LocT /*loc*/,
-                    DiagnosticEmitter<LocT>::ContextFnT /*context_fn*/) const
-        -> ConvertedDiagnosticLoc override {
+                    Emitter<LocT>::ContextFnT /*context_fn*/) const
+        -> ConvertedLoc override {
       return {.loc = {}, .last_byte_offset = -1};
     }
   };
 
-  static auto* emitter = new Emitter(&NullDiagnosticConsumer());
+  static auto* emitter = new SingletonEmitter(&NullConsumer());
   return *emitter;
 }
 
-}  // namespace Carbon
+}  // namespace Carbon::Diagnostics
 
 #endif  // CARBON_TOOLCHAIN_DIAGNOSTICS_NULL_DIAGNOSTICS_H_

+ 6 - 6
toolchain/diagnostics/sorting_diagnostic_consumer.h

@@ -9,7 +9,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "toolchain/diagnostics/diagnostic_emitter.h"
 
-namespace Carbon {
+namespace Carbon::Diagnostics {
 
 // Buffers incoming diagnostics for printing and sorting.
 //
@@ -19,12 +19,12 @@ namespace Carbon {
 // `Diagnostic::messages[0]` will always be a location in the consumer's primary
 // file, but if it needs to correspond to a different file, the
 // `last_byte_offset` must still indicate an offset within the primary file.
-class SortingDiagnosticConsumer : public DiagnosticConsumer {
+class SortingConsumer : public Consumer {
  public:
-  explicit SortingDiagnosticConsumer(DiagnosticConsumer& next_consumer)
+  explicit SortingConsumer(Consumer& next_consumer)
       : next_consumer_(&next_consumer) {}
 
-  ~SortingDiagnosticConsumer() override {
+  ~SortingConsumer() override {
     // We choose not to automatically flush diagnostics here, because they are
     // likely to refer to data that gets destroyed before the diagnostics
     // consumer is destroyed, because the diagnostics consumer is typically
@@ -55,9 +55,9 @@ class SortingDiagnosticConsumer : public DiagnosticConsumer {
   // specify 0.
   llvm::SmallVector<Diagnostic, 0> diagnostics_;
 
-  DiagnosticConsumer* next_consumer_;
+  Consumer* next_consumer_;
 };
 
-}  // namespace Carbon
+}  // namespace Carbon::Diagnostics
 
 #endif  // CARBON_TOOLCHAIN_DIAGNOSTICS_SORTING_DIAGNOSTIC_CONSUMER_H_

+ 14 - 20
toolchain/diagnostics/sorting_diagnostic_consumer_test.cpp

@@ -11,7 +11,7 @@
 #include "toolchain/diagnostics/diagnostic_emitter.h"
 #include "toolchain/diagnostics/mocks.h"
 
-namespace Carbon {
+namespace Carbon::Diagnostics {
 namespace {
 
 using ::Carbon::Testing::IsSingleDiagnostic;
@@ -20,21 +20,21 @@ using ::testing::InSequence;
 
 CARBON_DIAGNOSTIC(TestDiagnostic, Error, "M{0}", int);
 
-class FakeDiagnosticEmitter : public DiagnosticEmitter<int32_t> {
+class FakeEmitter : public Emitter<int32_t> {
  public:
-  using DiagnosticEmitter::DiagnosticEmitter;
+  using Emitter::Emitter;
 
  protected:
   auto ConvertLoc(int32_t last_byte_offset, ContextFnT /*context_fn*/) const
-      -> ConvertedDiagnosticLoc override {
+      -> ConvertedLoc override {
     return {.loc = {}, .last_byte_offset = last_byte_offset};
   }
 };
 
-TEST(SortedDiagnosticEmitterTest, SortErrors) {
+TEST(SortedEmitterTest, SortErrors) {
   Testing::MockDiagnosticConsumer consumer;
-  SortingDiagnosticConsumer sorting_consumer(consumer);
-  FakeDiagnosticEmitter emitter(&sorting_consumer);
+  SortingConsumer sorting_consumer(consumer);
+  FakeEmitter emitter(&sorting_consumer);
 
   emitter.Emit(1, TestDiagnostic, 1);
   emitter.Emit(-1, TestDiagnostic, 2);
@@ -45,25 +45,19 @@ TEST(SortedDiagnosticEmitterTest, SortErrors) {
 
   InSequence s;
   EXPECT_CALL(consumer, HandleDiagnostic(IsSingleDiagnostic(
-                            DiagnosticKind::TestDiagnostic,
-                            DiagnosticLevel::Error, _, _, "M2")));
+                            Kind::TestDiagnostic, Level::Error, _, _, "M2")));
   EXPECT_CALL(consumer, HandleDiagnostic(IsSingleDiagnostic(
-                            DiagnosticKind::TestDiagnostic,
-                            DiagnosticLevel::Error, _, _, "M3")));
+                            Kind::TestDiagnostic, Level::Error, _, _, "M3")));
   EXPECT_CALL(consumer, HandleDiagnostic(IsSingleDiagnostic(
-                            DiagnosticKind::TestDiagnostic,
-                            DiagnosticLevel::Error, _, _, "M1")));
+                            Kind::TestDiagnostic, Level::Error, _, _, "M1")));
   EXPECT_CALL(consumer, HandleDiagnostic(IsSingleDiagnostic(
-                            DiagnosticKind::TestDiagnostic,
-                            DiagnosticLevel::Error, _, _, "M5")));
+                            Kind::TestDiagnostic, Level::Error, _, _, "M5")));
   EXPECT_CALL(consumer, HandleDiagnostic(IsSingleDiagnostic(
-                            DiagnosticKind::TestDiagnostic,
-                            DiagnosticLevel::Error, _, _, "M6")));
+                            Kind::TestDiagnostic, Level::Error, _, _, "M6")));
   EXPECT_CALL(consumer, HandleDiagnostic(IsSingleDiagnostic(
-                            DiagnosticKind::TestDiagnostic,
-                            DiagnosticLevel::Error, _, _, "M4")));
+                            Kind::TestDiagnostic, Level::Error, _, _, "M4")));
   sorting_consumer.Flush();
 }
 
 }  // namespace
-}  // namespace Carbon
+}  // namespace Carbon::Diagnostics

+ 7 - 7
toolchain/driver/compile_subcommand.cpp

@@ -299,8 +299,8 @@ static auto PhaseToString(CompileOptions::Phase phase) -> std::string {
   }
 }
 
-auto CompileSubcommand::ValidateOptions(NoLocDiagnosticEmitter& emitter) const
-    -> bool {
+auto CompileSubcommand::ValidateOptions(
+    Diagnostics::NoLocEmitter& emitter) const -> bool {
   CARBON_DIAGNOSTIC(
       CompilePhaseFlagConflict, Error,
       "requested dumping {0} but compile phase is limited to `{1}`",
@@ -341,7 +341,7 @@ namespace {
 class CompilationUnit {
  public:
   explicit CompilationUnit(DriverEnv& driver_env, const CompileOptions& options,
-                           DiagnosticConsumer* consumer,
+                           Diagnostics::Consumer* consumer,
                            llvm::StringRef input_filename);
 
   // Loads source and lexes it. Returns true on success.
@@ -411,8 +411,8 @@ class CompilationUnit {
   llvm::raw_pwrite_stream* vlog_stream_;
 
   // Diagnostics are sent to consumer_, with optional sorting.
-  std::optional<SortingDiagnosticConsumer> sorting_consumer_;
-  DiagnosticConsumer* consumer_;
+  std::optional<Diagnostics::SortingConsumer> sorting_consumer_;
+  Diagnostics::Consumer* consumer_;
 
   bool success_ = true;
 
@@ -436,7 +436,7 @@ class CompilationUnit {
 
 CompilationUnit::CompilationUnit(DriverEnv& driver_env,
                                  const CompileOptions& options,
-                                 DiagnosticConsumer* consumer,
+                                 Diagnostics::Consumer* consumer,
                                  llvm::StringRef input_filename)
     : driver_env_(&driver_env),
       options_(options),
@@ -445,7 +445,7 @@ CompilationUnit::CompilationUnit(DriverEnv& driver_env,
   if (vlog_stream_ != nullptr || options_.stream_errors) {
     consumer_ = consumer;
   } else {
-    sorting_consumer_ = SortingDiagnosticConsumer(*consumer);
+    sorting_consumer_ = Diagnostics::SortingConsumer(*consumer);
     consumer_ = &*sorting_consumer_;
   }
   if (options_.dump_mem_usage && IncludeInDumps()) {

+ 1 - 1
toolchain/driver/compile_subcommand.h

@@ -77,7 +77,7 @@ class CompileSubcommand : public DriverSubcommand {
   // Does custom validation of the compile-subcommand options structure beyond
   // what the command line parsing library supports. Diagnoses and returns false
   // on failure.
-  auto ValidateOptions(NoLocDiagnosticEmitter& emitter) const -> bool;
+  auto ValidateOptions(Diagnostics::NoLocEmitter& emitter) const -> bool;
 
   CompileOptions options_;
 };

+ 2 - 2
toolchain/driver/driver_env.h

@@ -56,10 +56,10 @@ struct DriverEnv {
   bool enable_leaking = false;
 
   // A diagnostic consumer, to be able to connect output.
-  StreamDiagnosticConsumer consumer;
+  Diagnostics::StreamConsumer consumer;
 
   // A diagnostic emitter that has no locations.
-  NoLocDiagnosticEmitter emitter;
+  Diagnostics::NoLocEmitter emitter;
 
   // For CARBON_VLOG.
   llvm::raw_pwrite_stream* vlog_stream = nullptr;

+ 7 - 7
toolchain/language_server/context.cpp

@@ -22,7 +22,7 @@ namespace Carbon::LanguageServer {
 // A consumer for turning diagnostics into a `textDocument/publishDiagnostics`
 // notification.
 // https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_publishDiagnostics
-class PublishDiagnosticConsumer : public DiagnosticConsumer {
+class PublishDiagnosticConsumer : public Diagnostics::Consumer {
  public:
   // Initializes params with the target file information.
   explicit PublishDiagnosticConsumer(Context* context,
@@ -31,14 +31,14 @@ class PublishDiagnosticConsumer : public DiagnosticConsumer {
       : context_(context), params_{.uri = uri, .version = version} {}
 
   // Turns a diagnostic into an LSP diagnostic.
-  auto HandleDiagnostic(Diagnostic diagnostic) -> void override {
+  auto HandleDiagnostic(Diagnostics::Diagnostic diagnostic) -> void override {
     const auto& message = diagnostic.messages[0];
     if (message.loc.filename != params_.uri.file()) {
       // `pushDiagnostic` requires diagnostics to be associated with a location
       // in the current file. Suppress diagnostics rooted in other files.
       // TODO: Consider if there's a better way to handle this.
       RawStringOstream stream;
-      StreamDiagnosticConsumer consumer(&stream);
+      Diagnostics::StreamConsumer consumer(&stream);
       consumer.HandleDiagnostic(diagnostic);
 
       CARBON_DIAGNOSTIC(LanguageServerDiagnosticInWrongFile, Warning,
@@ -68,7 +68,7 @@ class PublishDiagnosticConsumer : public DiagnosticConsumer {
  private:
   // Returns the LSP range for a diagnostic. Note that Carbon uses 1-based
   // numbers while LSP uses 0-based.
-  auto GetRange(const DiagnosticLoc& loc) -> clang::clangd::Range {
+  auto GetRange(const Diagnostics::Loc& loc) -> clang::clangd::Range {
     return {.start = {.line = loc.line_number - 1,
                       .character = loc.column_number - 1},
             .end = {.line = loc.line_number,
@@ -76,7 +76,7 @@ class PublishDiagnosticConsumer : public DiagnosticConsumer {
   }
 
   // Converts a diagnostic level to an LSP severity.
-  auto GetSeverity(DiagnosticLevel level) -> int {
+  auto GetSeverity(Diagnostics::Level level) -> int {
     // https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#diagnosticSeverity
     enum class DiagnosticSeverity {
       Error = 1,
@@ -86,9 +86,9 @@ class PublishDiagnosticConsumer : public DiagnosticConsumer {
     };
 
     switch (level) {
-      case DiagnosticLevel::Error:
+      case Diagnostics::Level::Error:
         return static_cast<int>(DiagnosticSeverity::Error);
-      case DiagnosticLevel::Warning:
+      case Diagnostics::Level::Warning:
         return static_cast<int>(DiagnosticSeverity::Warning);
       default:
         CARBON_FATAL("Unexpected diagnostic level: {0}", level);

+ 8 - 5
toolchain/language_server/context.h

@@ -52,7 +52,8 @@ class Context {
   };
 
   // `vlog_stream` is optional; other parameters are required.
-  explicit Context(llvm::raw_ostream* vlog_stream, DiagnosticConsumer* consumer,
+  explicit Context(llvm::raw_ostream* vlog_stream,
+                   Diagnostics::Consumer* consumer,
                    clang::clangd::LSPBinder::RawOutgoing* outgoing)
       : vlog_stream_(vlog_stream),
         file_emitter_(consumer),
@@ -70,16 +71,18 @@ class Context {
   }
 
   auto vlog_stream() -> llvm::raw_ostream* { return vlog_stream_; }
-  auto file_emitter() -> FileDiagnosticEmitter& { return file_emitter_; }
-  auto no_loc_emitter() -> NoLocDiagnosticEmitter& { return no_loc_emitter_; }
+  auto file_emitter() -> Diagnostics::FileEmitter& { return file_emitter_; }
+  auto no_loc_emitter() -> Diagnostics::NoLocEmitter& {
+    return no_loc_emitter_;
+  }
 
   auto files() -> Map<std::string, File>& { return files_; }
 
  private:
   // Diagnostic and output streams.
   llvm::raw_ostream* vlog_stream_;
-  FileDiagnosticEmitter file_emitter_;
-  NoLocDiagnosticEmitter no_loc_emitter_;
+  Diagnostics::FileEmitter file_emitter_;
+  Diagnostics::NoLocEmitter no_loc_emitter_;
   clang::clangd::LSPBinder::RawOutgoing* outgoing_;
 
   // Content of files managed by the language client.

+ 2 - 2
toolchain/language_server/language_server.cpp

@@ -44,7 +44,7 @@ class Logger : public clang::clangd::Logger {
 
 auto Run(FILE* input_stream, llvm::raw_ostream& output_stream,
          llvm::raw_ostream& error_stream, llvm::raw_ostream* vlog_stream,
-         DiagnosticConsumer& consumer) -> bool {
+         Diagnostics::Consumer& consumer) -> bool {
   // The language server internally uses diagnostics for logging issues, but the
   // clangd parts have their own logging system. We intercept that here.
   Logger logger(&error_stream, vlog_stream);
@@ -65,7 +65,7 @@ auto Run(FILE* input_stream, llvm::raw_ostream& output_stream,
     RawStringOstream out;
     out << err;
     CARBON_DIAGNOSTIC(LanguageServerTransportError, Error, "{0}", std::string);
-    NoLocDiagnosticEmitter emitter(&consumer);
+    Diagnostics::NoLocEmitter emitter(&consumer);
     emitter.Emit(LanguageServerTransportError, out.TakeStr());
     return false;
   }

+ 1 - 1
toolchain/language_server/language_server.h

@@ -17,7 +17,7 @@ namespace Carbon::LanguageServer {
 // This is thread-hostile because `clangd::LoggingSession` relies on a global.
 auto Run(FILE* input_stream, llvm::raw_ostream& output_stream,
          llvm::raw_ostream& error_stream, llvm::raw_ostream* vlog_stream,
-         DiagnosticConsumer& consumer) -> bool;
+         Diagnostics::Consumer& consumer) -> bool;
 
 }  // namespace Carbon::LanguageServer
 

+ 1 - 1
toolchain/lex/helpers.cpp

@@ -6,7 +6,7 @@
 
 namespace Carbon::Lex {
 
-auto CanLexInt(DiagnosticEmitter<const char*>& emitter, llvm::StringRef text)
+auto CanLexInt(Diagnostics::Emitter<const char*>& emitter, llvm::StringRef text)
     -> bool {
   // llvm::getAsInteger is used for parsing, but it's quadratic and visibly slow
   // on large integer values. This limit exists to avoid hitting those limits.

+ 1 - 1
toolchain/lex/helpers.h

@@ -11,7 +11,7 @@ namespace Carbon::Lex {
 
 // Should guard calls to getAsInteger due to performance issues with large
 // integers. Emits an error if the text cannot be lexed.
-auto CanLexInt(DiagnosticEmitter<const char*>& emitter, llvm::StringRef text)
+auto CanLexInt(Diagnostics::Emitter<const char*>& emitter, llvm::StringRef text)
     -> bool;
 
 }  // namespace Carbon::Lex

+ 4 - 4
toolchain/lex/lex.cpp

@@ -81,7 +81,7 @@ class [[clang::internal_linkage]] Lexer {
   };
 
   Lexer(SharedValueStores& value_stores, SourceBuffer& source,
-        DiagnosticConsumer& consumer)
+        Diagnostics::Consumer& consumer)
       : buffer_(value_stores, source),
         consumer_(consumer),
         emitter_(&consumer_, &buffer_),
@@ -220,7 +220,7 @@ class [[clang::internal_linkage]] Lexer {
   llvm::SmallVector<TokenIndex> open_groups_;
   bool has_mismatched_brackets_ = false;
 
-  ErrorTrackingDiagnosticConsumer consumer_;
+  Diagnostics::ErrorTrackingConsumer consumer_;
 
   TokenizedBuffer::SourcePointerDiagnosticEmitter emitter_;
 
@@ -1526,7 +1526,7 @@ class Lexer::ErrorRecoveryBuffer {
 };
 
 // Issue an UnmatchedOpening diagnostic.
-static auto DiagnoseUnmatchedOpening(DiagnosticEmitter<TokenIndex>& emitter,
+static auto DiagnoseUnmatchedOpening(Diagnostics::Emitter<TokenIndex>& emitter,
                                      TokenIndex opening_token) -> void {
   CARBON_DIAGNOSTIC(UnmatchedOpening, Error,
                     "opening symbol without a corresponding closing symbol");
@@ -1610,7 +1610,7 @@ auto Lexer::DiagnoseAndFixMismatchedBrackets() -> void {
 }
 
 auto Lex(SharedValueStores& value_stores, SourceBuffer& source,
-         DiagnosticConsumer& consumer) -> TokenizedBuffer {
+         Diagnostics::Consumer& consumer) -> TokenizedBuffer {
   return Lexer(value_stores, source, consumer).Lex();
 }
 

+ 1 - 1
toolchain/lex/lex.h

@@ -18,7 +18,7 @@ namespace Carbon::Lex {
 // which will refer into the source.
 auto Lex(SharedValueStores& value_stores,
          SourceBuffer& source [[clang::lifetimebound]],
-         DiagnosticConsumer& consumer) -> TokenizedBuffer;
+         Diagnostics::Consumer& consumer) -> TokenizedBuffer;
 
 }  // namespace Carbon::Lex
 

+ 6 - 6
toolchain/lex/numeric_literal.cpp

@@ -88,7 +88,7 @@ auto NumericLiteral::Lex(llvm::StringRef source_text,
 // either diagnosing or extracting its meaning.
 class NumericLiteral::Parser {
  public:
-  Parser(DiagnosticEmitter<const char*>& emitter, NumericLiteral literal);
+  Parser(Diagnostics::Emitter<const char*>& emitter, NumericLiteral literal);
 
   auto IsInt() -> bool {
     return literal_.radix_point_ == static_cast<int>(literal_.text_.size());
@@ -124,7 +124,7 @@ class NumericLiteral::Parser {
   auto CheckFractionalPart() -> bool;
   auto CheckExponentPart() -> bool;
 
-  DiagnosticEmitter<const char*>& emitter_;
+  Diagnostics::Emitter<const char*>& emitter_;
   NumericLiteral literal_;
 
   // The radix of the literal: 2, 10, or 16, for a prefix of '0b', no prefix,
@@ -147,7 +147,7 @@ class NumericLiteral::Parser {
   bool exponent_is_negative_ = false;
 };
 
-NumericLiteral::Parser::Parser(DiagnosticEmitter<const char*>& emitter,
+NumericLiteral::Parser::Parser(Diagnostics::Emitter<const char*>& emitter,
                                NumericLiteral literal)
     : emitter_(emitter), literal_(literal) {
   int_part_ = literal.text_.substr(0, literal.radix_point_);
@@ -292,7 +292,7 @@ auto NumericLiteral::Parser::CheckDigitSequence(llvm::StringRef text,
         InvalidDigit, Error,
         "invalid digit '{0}' in {1:=2:binary|=10:decimal|=16:hexadecimal} "
         "numeric literal",
-        char, IntAsSelect);
+        char, Diagnostics::IntAsSelect);
     emitter_.Emit(text.begin() + i, InvalidDigit, c, static_cast<int>(radix));
     return {.ok = false};
   }
@@ -374,8 +374,8 @@ auto NumericLiteral::Parser::CheckExponentPart() -> bool {
 }
 
 // Parse the token and compute its value.
-auto NumericLiteral::ComputeValue(DiagnosticEmitter<const char*>& emitter) const
-    -> Value {
+auto NumericLiteral::ComputeValue(
+    Diagnostics::Emitter<const char*>& emitter) const -> Value {
   Parser parser(emitter, *this);
 
   if (!parser.Check()) {

+ 1 - 1
toolchain/lex/numeric_literal.h

@@ -47,7 +47,7 @@ class NumericLiteral {
 
   // Compute the value of the token, if possible. Emit diagnostics to the given
   // emitter if the token is not valid.
-  auto ComputeValue(DiagnosticEmitter<const char*>& emitter) const -> Value;
+  auto ComputeValue(Diagnostics::Emitter<const char*>& emitter) const -> Value;
 
   // Get the text corresponding to this literal.
   auto text() const -> llvm::StringRef { return text_; }

+ 2 - 2
toolchain/lex/numeric_literal_benchmark.cpp

@@ -26,7 +26,7 @@ static void BM_Lex_Int(benchmark::State& state) {
 static void BM_ComputeValue_Float(benchmark::State& state) {
   auto val = NumericLiteral::Lex("0.000001", true);
   CARBON_CHECK(val);
-  auto& emitter = NullDiagnosticEmitter<const char*>();
+  auto& emitter = Diagnostics::NullEmitter<const char*>();
   for (auto _ : state) {
     val->ComputeValue(emitter);
   }
@@ -34,7 +34,7 @@ static void BM_ComputeValue_Float(benchmark::State& state) {
 
 static void BM_ComputeValue_Int(benchmark::State& state) {
   auto val = NumericLiteral::Lex("1_234_567_890", true);
-  auto& emitter = NullDiagnosticEmitter<const char*>();
+  auto& emitter = Diagnostics::NullEmitter<const char*>();
   CARBON_CHECK(val);
   for (auto _ : state) {
     val->ComputeValue(emitter);

+ 1 - 1
toolchain/lex/numeric_literal_fuzzer.cpp

@@ -21,7 +21,7 @@ extern "C" int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size) {
   }
 
   volatile auto value =
-      token->ComputeValue(NullDiagnosticEmitter<const char*>());
+      token->ComputeValue(Diagnostics::NullEmitter<const char*>());
   (void)value;
   return 0;
 }

+ 2 - 2
toolchain/lex/numeric_literal_test.cpp

@@ -23,7 +23,7 @@ using ::testing::VariantWith;
 
 class NumericLiteralTest : public ::testing::Test {
  public:
-  NumericLiteralTest() : error_tracker(ConsoleDiagnosticConsumer()) {}
+  NumericLiteralTest() : error_tracker(Diagnostics::ConsoleConsumer()) {}
 
   auto Lex(llvm::StringRef text, bool can_form_real_literal) -> NumericLiteral {
     std::optional<NumericLiteral> result =
@@ -41,7 +41,7 @@ class NumericLiteralTest : public ::testing::Test {
     return Lex(text, can_form_real_literal).ComputeValue(emitter);
   }
 
-  ErrorTrackingDiagnosticConsumer error_tracker;
+  Diagnostics::ErrorTrackingConsumer error_tracker;
 };
 
 // Matcher for signed llvm::APInt.

+ 1 - 1
toolchain/lex/string_literal.cpp

@@ -14,7 +14,7 @@
 
 namespace Carbon::Lex {
 
-using LexerDiagnosticEmitter = DiagnosticEmitter<const char*>;
+using LexerDiagnosticEmitter = Diagnostics::Emitter<const char*>;
 
 static constexpr char MultiLineIndicator[] = R"(''')";
 static constexpr char DoubleQuotedMultiLineIndicator[] = R"(""")";

+ 1 - 1
toolchain/lex/string_literal.h

@@ -29,7 +29,7 @@ class StringLiteral {
   // deal with, this can return the content directly. Otherwise, the allocator
   // will be used for the StringRef.
   auto ComputeValue(llvm::BumpPtrAllocator& allocator,
-                    DiagnosticEmitter<const char*>& emitter) const
+                    Diagnostics::Emitter<const char*>& emitter) const
       -> llvm::StringRef;
 
   // Get the text corresponding to this literal.

+ 2 - 2
toolchain/lex/string_literal_benchmark.cpp

@@ -94,8 +94,8 @@ static void BM_SimpleStringValue(benchmark::State& state, int size,
   }
   x.append(terminator);
   for (auto _ : state) {
-    StringLiteral::Lex(x)->ComputeValue(allocator,
-                                        NullDiagnosticEmitter<const char*>());
+    StringLiteral::Lex(x)->ComputeValue(
+        allocator, Diagnostics::NullEmitter<const char*>());
   }
 }
 

+ 1 - 1
toolchain/lex/string_literal_fuzzer.cpp

@@ -35,7 +35,7 @@ extern "C" int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size) {
 
   llvm::BumpPtrAllocator allocator;
   volatile auto value =
-      token->ComputeValue(allocator, NullDiagnosticEmitter<const char*>());
+      token->ComputeValue(allocator, Diagnostics::NullEmitter<const char*>());
   (void)value;
 
   return 0;

+ 2 - 2
toolchain/lex/string_literal_test.cpp

@@ -16,7 +16,7 @@ namespace {
 
 class StringLiteralTest : public ::testing::Test {
  public:
-  StringLiteralTest() : error_tracker_(ConsoleDiagnosticConsumer()) {}
+  StringLiteralTest() : error_tracker_(Diagnostics::ConsoleConsumer()) {}
 
   auto Lex(llvm::StringRef text) -> StringLiteral {
     std::optional<StringLiteral> result = StringLiteral::Lex(text);
@@ -32,7 +32,7 @@ class StringLiteralTest : public ::testing::Test {
   }
 
   llvm::BumpPtrAllocator allocator_;
-  ErrorTrackingDiagnosticConsumer error_tracker_;
+  Diagnostics::ErrorTrackingConsumer error_tracker_;
 };
 
 TEST_F(StringLiteralTest, StringLiteralBounds) {

+ 4 - 4
toolchain/lex/test_helpers.h

@@ -17,18 +17,18 @@ namespace Carbon::Testing {
 
 // A diagnostic converter for tests that lex a single token. Produces
 // locations such as "`12.5`:1:3" to refer to the third character in the token.
-class SingleTokenDiagnosticEmitter : public DiagnosticEmitter<const char*> {
+class SingleTokenDiagnosticEmitter : public Diagnostics::Emitter<const char*> {
  public:
   // Form a converter for a given token. The string provided here must refer
   // to the same character array that we are going to lex.
-  explicit SingleTokenDiagnosticEmitter(DiagnosticConsumer* consumer,
+  explicit SingleTokenDiagnosticEmitter(Diagnostics::Consumer* consumer,
                                         llvm::StringRef token)
-      : DiagnosticEmitter(consumer), token_(token) {}
+      : Emitter(consumer), token_(token) {}
 
  protected:
   // Implements `DiagnosticConverter::ConvertLoc`.
   auto ConvertLoc(const char* pos, ContextFnT /*context_fn*/) const
-      -> ConvertedDiagnosticLoc override {
+      -> Diagnostics::ConvertedLoc override {
     CARBON_CHECK(StringRefContainsPointer(token_, pos),
                  "invalid diagnostic location");
     llvm::StringRef prefix = token_.take_front(pos - token_.begin());

+ 2 - 2
toolchain/lex/tokenized_buffer.cpp

@@ -378,7 +378,7 @@ auto TokenizedBuffer::CollectMemUsage(MemUsage& mem_usage,
 }
 
 auto TokenizedBuffer::SourcePointerToDiagnosticLoc(const char* loc) const
-    -> ConvertedDiagnosticLoc {
+    -> Diagnostics::ConvertedLoc {
   CARBON_CHECK(StringRefContainsPointer(source_->text(), loc),
                "location not within buffer");
   int32_t offset = loc - source_->text().begin();
@@ -416,7 +416,7 @@ auto TokenizedBuffer::SourcePointerToDiagnosticLoc(const char* loc) const
 }
 
 auto TokenizedBuffer::TokenToDiagnosticLoc(TokenIndex token) const
-    -> ConvertedDiagnosticLoc {
+    -> Diagnostics::ConvertedLoc {
   // Map the token location into a position within the source buffer.
   const char* token_start =
       source_->text().begin() + GetTokenInfo(token).byte_offset();

+ 12 - 10
toolchain/lex/tokenized_buffer.h

@@ -177,7 +177,8 @@ class TokenizedBuffer : public Printable<TokenizedBuffer> {
       -> void;
 
   // Converts a token to a diagnostic location.
-  auto TokenToDiagnosticLoc(TokenIndex token) const -> ConvertedDiagnosticLoc;
+  auto TokenToDiagnosticLoc(TokenIndex token) const
+      -> Diagnostics::ConvertedLoc;
 
   // Returns true if the buffer has errors that were detected at lexing time.
   auto has_errors() const -> bool { return has_errors_; }
@@ -207,15 +208,16 @@ class TokenizedBuffer : public Printable<TokenizedBuffer> {
  private:
   friend class Lexer;
 
-  class SourcePointerDiagnosticEmitter : public DiagnosticEmitter<const char*> {
+  class SourcePointerDiagnosticEmitter
+      : public Diagnostics::Emitter<const char*> {
    public:
-    explicit SourcePointerDiagnosticEmitter(DiagnosticConsumer* consumer,
+    explicit SourcePointerDiagnosticEmitter(Diagnostics::Consumer* consumer,
                                             const TokenizedBuffer* tokens)
-        : DiagnosticEmitter(consumer), tokens_(tokens) {}
+        : Emitter(consumer), tokens_(tokens) {}
 
    protected:
     auto ConvertLoc(const char* loc, ContextFnT /*context_fn*/) const
-        -> ConvertedDiagnosticLoc override {
+        -> Diagnostics::ConvertedLoc override {
       return tokens_->SourcePointerToDiagnosticLoc(loc);
     }
 
@@ -223,15 +225,15 @@ class TokenizedBuffer : public Printable<TokenizedBuffer> {
     const TokenizedBuffer* tokens_;
   };
 
-  class TokenDiagnosticEmitter : public DiagnosticEmitter<TokenIndex> {
+  class TokenDiagnosticEmitter : public Diagnostics::Emitter<TokenIndex> {
    public:
-    explicit TokenDiagnosticEmitter(DiagnosticConsumer* consumer,
+    explicit TokenDiagnosticEmitter(Diagnostics::Consumer* consumer,
                                     const TokenizedBuffer* tokens)
-        : DiagnosticEmitter(consumer), tokens_(tokens) {}
+        : Emitter(consumer), tokens_(tokens) {}
 
    protected:
     auto ConvertLoc(TokenIndex token, ContextFnT /*context_fn*/) const
-        -> ConvertedDiagnosticLoc override {
+        -> Diagnostics::ConvertedLoc override {
       return tokens_->TokenToDiagnosticLoc(token);
     }
 
@@ -241,7 +243,7 @@ class TokenizedBuffer : public Printable<TokenizedBuffer> {
 
   // Converts a pointer into the source to a diagnostic location.
   auto SourcePointerToDiagnosticLoc(const char* loc) const
-      -> ConvertedDiagnosticLoc;
+      -> Diagnostics::ConvertedLoc;
 
   // Specifies minimum widths to use when printing a token's fields via
   // `printToken`.

+ 4 - 4
toolchain/lex/tokenized_buffer_benchmark.cpp

@@ -214,13 +214,13 @@ class LexerBenchHelper {
       : source_(MakeSourceBuffer(text)) {}
 
   auto Lex() -> TokenizedBuffer {
-    DiagnosticConsumer& consumer = NullDiagnosticConsumer();
+    Diagnostics::Consumer& consumer = Diagnostics::NullConsumer();
     return Lex::Lex(value_stores_, source_, consumer);
   }
 
   auto DiagnoseErrors() -> std::string {
     RawStringOstream result;
-    StreamDiagnosticConsumer consumer(&result);
+    Diagnostics::StreamConsumer consumer(&result);
     auto buffer = Lex::Lex(value_stores_, source_, consumer);
     consumer.Flush();
     CARBON_CHECK(buffer.has_errors(),
@@ -234,8 +234,8 @@ class LexerBenchHelper {
   auto MakeSourceBuffer(llvm::StringRef text) -> SourceBuffer {
     CARBON_CHECK(fs_.addFile(filename_, /*ModificationTime=*/0,
                              llvm::MemoryBuffer::getMemBuffer(text)));
-    return std::move(*SourceBuffer::MakeFromFile(fs_, filename_,
-                                                 ConsoleDiagnosticConsumer()));
+    return std::move(*SourceBuffer::MakeFromFile(
+        fs_, filename_, Diagnostics::ConsoleConsumer()));
   }
 
   SharedValueStores value_stores_;

+ 2 - 2
toolchain/lex/tokenized_buffer_fuzzer.cpp

@@ -32,10 +32,10 @@ extern "C" int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size) {
       llvm::MemoryBuffer::getMemBuffer(data_ref, /*BufferName=*/TestFileName,
                                        /*RequiresNullTerminator=*/false)));
   auto source =
-      SourceBuffer::MakeFromFile(fs, TestFileName, NullDiagnosticConsumer());
+      SourceBuffer::MakeFromFile(fs, TestFileName, Diagnostics::NullConsumer());
 
   SharedValueStores value_stores;
-  auto buffer = Lex::Lex(value_stores, *source, NullDiagnosticConsumer());
+  auto buffer = Lex::Lex(value_stores, *source, Diagnostics::NullConsumer());
   if (buffer.has_errors()) {
     return 0;
   }

+ 31 - 28
toolchain/lex/tokenized_buffer_test.cpp

@@ -1028,8 +1028,8 @@ TEST_F(LexerTest, TypeLiteralTooManyDigits) {
   // We increase the number of digits until the first one that is to large.
   Testing::MockDiagnosticConsumer consumer;
   EXPECT_CALL(consumer, HandleDiagnostic(IsSingleDiagnostic(
-                            DiagnosticKind::TooManyTypeBitWidthDigits,
-                            DiagnosticLevel::Error, 1, 2, _)));
+                            Diagnostics::Kind::TooManyTypeBitWidthDigits,
+                            Diagnostics::Level::Error, 1, 2, _)));
   std::string code = "i";
   // A 128-bit APInt should be plenty large, but if needed in the future it can
   // be widened without issue.
@@ -1061,8 +1061,8 @@ TEST_F(LexerTest, TypeLiteralTooManyDigits) {
   // crashing or hanging, and show the correct number.
   constexpr int Count = 10000;
   EXPECT_CALL(consumer, HandleDiagnostic(IsSingleDiagnostic(
-                            DiagnosticKind::TooManyTypeBitWidthDigits,
-                            DiagnosticLevel::Error, 1, 2,
+                            Diagnostics::Kind::TooManyTypeBitWidthDigits,
+                            Diagnostics::Level::Error, 1, 2,
                             HasSubstr(llvm::formatv(" {0} ", Count)))));
   code = "i";
   code.append(Count, '9');
@@ -1083,72 +1083,75 @@ TEST_F(LexerTest, DiagnosticTrailingComment) {
 
   Testing::MockDiagnosticConsumer consumer;
   EXPECT_CALL(consumer, HandleDiagnostic(IsSingleDiagnostic(
-                            DiagnosticKind::TrailingComment,
-                            DiagnosticLevel::Error, 3, 19, _)));
+                            Diagnostics::Kind::TrailingComment,
+                            Diagnostics::Level::Error, 3, 19, _)));
   compile_helper_.GetTokenizedBuffer(testcase, &consumer);
 }
 
 TEST_F(LexerTest, DiagnosticWhitespace) {
   Testing::MockDiagnosticConsumer consumer;
-  EXPECT_CALL(consumer, HandleDiagnostic(IsSingleDiagnostic(
-                            DiagnosticKind::NoWhitespaceAfterCommentIntroducer,
-                            DiagnosticLevel::Error, 1, 3, _)));
+  EXPECT_CALL(consumer,
+              HandleDiagnostic(IsSingleDiagnostic(
+                  Diagnostics::Kind::NoWhitespaceAfterCommentIntroducer,
+                  Diagnostics::Level::Error, 1, 3, _)));
   compile_helper_.GetTokenizedBuffer("//no space after comment", &consumer);
 }
 
 TEST_F(LexerTest, DiagnosticUnrecognizedEscape) {
   Testing::MockDiagnosticConsumer consumer;
-  EXPECT_CALL(consumer, HandleDiagnostic(IsSingleDiagnostic(
-                            DiagnosticKind::UnknownEscapeSequence,
-                            DiagnosticLevel::Error, 1, 8, HasSubstr("`b`"))));
+  EXPECT_CALL(consumer,
+              HandleDiagnostic(IsSingleDiagnostic(
+                  Diagnostics::Kind::UnknownEscapeSequence,
+                  Diagnostics::Level::Error, 1, 8, HasSubstr("`b`"))));
   compile_helper_.GetTokenizedBuffer(R"("hello\bworld")", &consumer);
 }
 
 TEST_F(LexerTest, DiagnosticBadHex) {
   Testing::MockDiagnosticConsumer consumer;
   EXPECT_CALL(consumer, HandleDiagnostic(IsSingleDiagnostic(
-                            DiagnosticKind::HexadecimalEscapeMissingDigits,
-                            DiagnosticLevel::Error, 1, 9, _)));
+                            Diagnostics::Kind::HexadecimalEscapeMissingDigits,
+                            Diagnostics::Level::Error, 1, 9, _)));
   compile_helper_.GetTokenizedBuffer(R"("hello\xabworld")", &consumer);
 }
 
 TEST_F(LexerTest, DiagnosticInvalidDigit) {
   Testing::MockDiagnosticConsumer consumer;
-  EXPECT_CALL(consumer, HandleDiagnostic(IsSingleDiagnostic(
-                            DiagnosticKind::InvalidDigit,
-                            DiagnosticLevel::Error, 1, 6, HasSubstr("'a'"))));
+  EXPECT_CALL(consumer,
+              HandleDiagnostic(IsSingleDiagnostic(
+                  Diagnostics::Kind::InvalidDigit, Diagnostics::Level::Error, 1,
+                  6, HasSubstr("'a'"))));
   compile_helper_.GetTokenizedBuffer("0x123abc", &consumer);
 }
 
 TEST_F(LexerTest, DiagnosticCR) {
   Testing::MockDiagnosticConsumer consumer;
   EXPECT_CALL(consumer, HandleDiagnostic(IsSingleDiagnostic(
-                            DiagnosticKind::UnsupportedCrLineEnding,
-                            DiagnosticLevel::Error, 1, 1, _)));
+                            Diagnostics::Kind::UnsupportedCrLineEnding,
+                            Diagnostics::Level::Error, 1, 1, _)));
   compile_helper_.GetTokenizedBuffer("\r", &consumer);
 }
 
 TEST_F(LexerTest, DiagnosticLfCr) {
   Testing::MockDiagnosticConsumer consumer;
   EXPECT_CALL(consumer, HandleDiagnostic(IsSingleDiagnostic(
-                            DiagnosticKind::UnsupportedLfCrLineEnding,
-                            DiagnosticLevel::Error, 2, 1, _)));
+                            Diagnostics::Kind::UnsupportedLfCrLineEnding,
+                            Diagnostics::Level::Error, 2, 1, _)));
   compile_helper_.GetTokenizedBuffer("\n\r", &consumer);
 }
 
 TEST_F(LexerTest, DiagnosticMissingTerminator) {
   Testing::MockDiagnosticConsumer consumer;
   EXPECT_CALL(consumer, HandleDiagnostic(IsSingleDiagnostic(
-                            DiagnosticKind::UnterminatedString,
-                            DiagnosticLevel::Error, 1, 1, _)));
+                            Diagnostics::Kind::UnterminatedString,
+                            Diagnostics::Level::Error, 1, 1, _)));
   compile_helper_.GetTokenizedBuffer(R"(#" ")", &consumer);
 }
 
 TEST_F(LexerTest, DiagnosticUnrecognizedChar) {
   Testing::MockDiagnosticConsumer consumer;
   EXPECT_CALL(consumer, HandleDiagnostic(IsSingleDiagnostic(
-                            DiagnosticKind::UnrecognizedCharacters,
-                            DiagnosticLevel::Error, 1, 1, _)));
+                            Diagnostics::Kind::UnrecognizedCharacters,
+                            Diagnostics::Level::Error, 1, 1, _)));
   compile_helper_.GetTokenizedBuffer("\b", &consumer);
 }
 
@@ -1161,9 +1164,9 @@ TEST_F(LexerTest, DiagnosticFileTooLarge) {
     input += "{}\n";
   }
   EXPECT_CALL(consumer,
-              HandleDiagnostic(IsSingleDiagnostic(DiagnosticKind::TooManyTokens,
-                                                  DiagnosticLevel::Error,
-                                                  TokenIndex::Max / 2, 1, _)));
+              HandleDiagnostic(IsSingleDiagnostic(
+                  Diagnostics::Kind::TooManyTokens, Diagnostics::Level::Error,
+                  TokenIndex::Max / 2, 1, _)));
   compile_helper_.GetTokenizedBuffer(input, &consumer);
 }
 

+ 6 - 5
toolchain/parse/context.cpp

@@ -22,7 +22,8 @@
 namespace Carbon::Parse {
 
 Context::Context(Tree* tree, Lex::TokenizedBuffer* tokens,
-                 DiagnosticConsumer* consumer, llvm::raw_ostream* vlog_stream)
+                 Diagnostics::Consumer* consumer,
+                 llvm::raw_ostream* vlog_stream)
     : tree_(tree),
       tokens_(tokens),
       err_tracker_(*consumer),
@@ -283,8 +284,8 @@ auto Context::DiagnoseOperatorFixity(OperatorFixity fixity) -> void {
       CARBON_DIAGNOSTIC(BinaryOperatorRequiresWhitespace, Error,
                         "whitespace missing {0:=-1:before|=0:around|=1:after} "
                         "binary operator",
-                        IntAsSelect);
-      IntAsSelect pos(0);
+                        Diagnostics::IntAsSelect);
+      Diagnostics::IntAsSelect pos(0);
       if (tokens().HasLeadingWhitespace(*position_)) {
         pos.value = 1;
       } else if (tokens().HasTrailingWhitespace(*position_)) {
@@ -302,14 +303,14 @@ auto Context::DiagnoseOperatorFixity(OperatorFixity fixity) -> void {
       CARBON_DIAGNOSTIC(
           UnaryOperatorHasWhitespace, Error,
           "whitespace is not allowed {0:after|before} this unary operator",
-          BoolAsSelect);
+          Diagnostics::BoolAsSelect);
       emitter_.Emit(*position_, UnaryOperatorHasWhitespace, prefix);
     } else if (IsLexicallyValidInfixOperator()) {
       // Pre/postfix operators must not satisfy the infix operator rules.
       CARBON_DIAGNOSTIC(
           UnaryOperatorRequiresWhitespace, Error,
           "whitespace is required {0:before|after} this unary operator",
-          BoolAsSelect);
+          Diagnostics::BoolAsSelect);
       emitter_.Emit(*position_, UnaryOperatorRequiresWhitespace, prefix);
     }
   }

+ 8 - 8
toolchain/parse/context.h

@@ -35,16 +35,16 @@ enum class Lookahead : int32_t {
 class Context {
  public:
   // A token-based emitter for use during parse.
-  class Emitter : public DiagnosticEmitter<Lex::TokenIndex> {
+  class TokenEmitter : public Diagnostics::Emitter<Lex::TokenIndex> {
    public:
-    explicit Emitter(DiagnosticConsumer* consumer, Context* context)
-        : DiagnosticEmitter(consumer), context_(context) {}
+    explicit TokenEmitter(Diagnostics::Consumer* consumer, Context* context)
+        : Emitter(consumer), context_(context) {}
 
    protected:
     // Applies the `position_` to the `last_byte_offset` returned by
     // `TokenToDiagnosticLoc`.
     auto ConvertLoc(Lex::TokenIndex token, ContextFnT /*context_fn*/) const
-        -> ConvertedDiagnosticLoc override {
+        -> Diagnostics::ConvertedLoc override {
       auto converted = context_->tokens().TokenToDiagnosticLoc(token);
       converted.last_byte_offset =
           std::max(converted.last_byte_offset,
@@ -122,7 +122,7 @@ class Context {
                 "StateStackEntry has unexpected size!");
 
   explicit Context(Tree* tree, Lex::TokenizedBuffer* tokens,
-                   DiagnosticConsumer* consumer,
+                   Diagnostics::Consumer* consumer,
                    llvm::raw_ostream* vlog_stream);
 
   // Adds a node to the parse tree that has no children (a leaf).
@@ -407,7 +407,7 @@ class Context {
 
   auto has_errors() const -> bool { return err_tracker_.seen_error(); }
 
-  auto emitter() -> Emitter& { return emitter_; }
+  auto emitter() -> TokenEmitter& { return emitter_; }
 
   auto position() -> Lex::TokenIterator& { return position_; }
   auto position() const -> Lex::TokenIterator { return position_; }
@@ -440,8 +440,8 @@ class Context {
   Tree* tree_;
   Lex::TokenizedBuffer* tokens_;
 
-  ErrorTrackingDiagnosticConsumer err_tracker_;
-  Emitter emitter_;
+  Diagnostics::ErrorTrackingConsumer err_tracker_;
+  TokenEmitter emitter_;
 
   // Whether to print verbose output.
   llvm::raw_ostream* vlog_stream_;

+ 1 - 1
toolchain/parse/handle_binding_pattern.cpp

@@ -25,7 +25,7 @@ auto HandleBindingPattern(Context& context) -> void {
     if (!state.has_error) {
       CARBON_DIAGNOSTIC(ExpectedBindingPattern, Error,
                         "expected {0:name|`:` or `:!`} in binding pattern",
-                        BoolAsSelect);
+                        Diagnostics::BoolAsSelect);
       context.emitter().Emit(*context.position(), ExpectedBindingPattern,
                              expected_name);
       state.has_error = true;

+ 2 - 2
toolchain/parse/handle_brace_expr.cpp

@@ -23,7 +23,7 @@ auto HandleBraceExpr(Context& context) -> void {
 static auto HandleBraceExprParamError(Context& context,
                                       Context::StateStackEntry state,
                                       State param_finish_state) -> void {
-  IntAsSelect mode(0);
+  Diagnostics::IntAsSelect mode(0);
   switch (param_finish_state) {
     case State::BraceExprParamFinishAsType:
       mode.value = 0;
@@ -41,7 +41,7 @@ static auto HandleBraceExprParamError(Context& context,
       ExpectedStructLiteralField, Error,
       "expected {0:=0:`.field: field_type`|"
       "=1:`.field = value`|=2:`.field: field_type` or `.field = value`}",
-      IntAsSelect);
+      Diagnostics::IntAsSelect);
   context.emitter().Emit(*context.position(), ExpectedStructLiteralField, mode);
 
   state.has_error = true;

+ 2 - 1
toolchain/parse/handle_period.cpp

@@ -38,7 +38,8 @@ static auto HandlePeriodOrArrow(Context& context, NodeKind node_kind,
     return;
   } else {
     CARBON_DIAGNOSTIC(ExpectedIdentifierAfterPeriodOrArrow, Error,
-                      "expected identifier after `{0:->|.}`", BoolAsSelect);
+                      "expected identifier after `{0:->|.}`",
+                      Diagnostics::BoolAsSelect);
     context.emitter().Emit(*context.position(),
                            ExpectedIdentifierAfterPeriodOrArrow, is_arrow);
     // If we see a keyword, assume it was intended to be a name.

+ 1 - 1
toolchain/parse/parse.cpp

@@ -17,7 +17,7 @@ auto HandleInvalid(Context& context) -> void {
                context.PopState());
 }
 
-auto Parse(Lex::TokenizedBuffer& tokens, DiagnosticConsumer& consumer,
+auto Parse(Lex::TokenizedBuffer& tokens, Diagnostics::Consumer& consumer,
            llvm::raw_ostream* vlog_stream) -> Tree {
   // Delegate to the parser.
   Tree tree(tokens);

+ 1 - 1
toolchain/parse/parse.h

@@ -15,7 +15,7 @@ namespace Carbon::Parse {
 // Parses the token buffer into a `Tree`.
 //
 // This is the factory function which is used to build parse trees.
-auto Parse(Lex::TokenizedBuffer& tokens, DiagnosticConsumer& consumer,
+auto Parse(Lex::TokenizedBuffer& tokens, Diagnostics::Consumer& consumer,
            llvm::raw_ostream* vlog_stream) -> Tree;
 
 }  // namespace Carbon::Parse

+ 3 - 3
toolchain/parse/parse_fuzzer.cpp

@@ -29,18 +29,18 @@ extern "C" int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size) {
       llvm::MemoryBuffer::getMemBuffer(data_ref, /*BufferName=*/TestFileName,
                                        /*RequiresNullTerminator=*/false)));
   auto source =
-      SourceBuffer::MakeFromFile(fs, TestFileName, NullDiagnosticConsumer());
+      SourceBuffer::MakeFromFile(fs, TestFileName, Diagnostics::NullConsumer());
 
   // Lex the input.
   SharedValueStores value_stores;
-  auto tokens = Lex::Lex(value_stores, *source, NullDiagnosticConsumer());
+  auto tokens = Lex::Lex(value_stores, *source, Diagnostics::NullConsumer());
   if (tokens.has_errors()) {
     return 0;
   }
 
   // Now parse it into a tree. Note that parsing will (when asserts are enabled)
   // walk the entire tree to verify it so we don't have to do that here.
-  Parse::Parse(tokens, NullDiagnosticConsumer(), /*vlog_stream=*/nullptr);
+  Parse::Parse(tokens, Diagnostics::NullConsumer(), /*vlog_stream=*/nullptr);
   return 0;
 }
 

+ 1 - 1
toolchain/parse/tree_and_subtrees.cpp

@@ -260,7 +260,7 @@ auto TreeAndSubtrees::GetSubtreeTokenRange(NodeId node_id) const -> TokenRange {
 }
 
 auto TreeAndSubtrees::NodeToDiagnosticLoc(NodeId node_id, bool token_only) const
-    -> ConvertedDiagnosticLoc {
+    -> Diagnostics::ConvertedLoc {
   // Support the invalid token as a way to emit only the filename, when there
   // is no line association.
   if (!node_id.has_value()) {

+ 1 - 1
toolchain/parse/tree_and_subtrees.h

@@ -120,7 +120,7 @@ class TreeAndSubtrees {
   // Converts the node to a diagnostic location, covering either the full
   // subtree or only the token.
   auto NodeToDiagnosticLoc(NodeId node_id, bool token_only) const
-      -> ConvertedDiagnosticLoc;
+      -> Diagnostics::ConvertedLoc;
 
   // Returns an iterable range over the parse tree node and all of its
   // descendants in depth-first postorder.

+ 3 - 3
toolchain/sem_ir/ids.h

@@ -479,7 +479,7 @@ struct NameId : public IdBase<NameId> {
   static constexpr llvm::StringLiteral Label = "name";
 
   // names().GetFormatted() is used for diagnostics.
-  using DiagnosticType = DiagnosticTypeInfo<std::string>;
+  using DiagnosticType = Diagnostics::TypeInfo<std::string>;
 
   // An enum of special names.
   enum class SpecialNameId : uint8_t {
@@ -708,7 +708,7 @@ struct TypeId : public IdBase<TypeId> {
   // `StringifyTypeExpr` is used for diagnostics. However, where possible, an
   // `InstId` describing how the type was written should be preferred, using
   // `InstIdAsType` or `TypeOfInstId` as the diagnostic argument type.
-  using DiagnosticType = DiagnosticTypeInfo<std::string>;
+  using DiagnosticType = Diagnostics::TypeInfo<std::string>;
 
   using IdBase::IdBase;
 
@@ -755,7 +755,7 @@ struct ElementIndex : public IndexBase<ElementIndex> {
 // The ID of a library name. This is either a string literal or `default`.
 struct LibraryNameId : public IdBase<LibraryNameId> {
   static constexpr llvm::StringLiteral Label = "library_name";
-  using DiagnosticType = DiagnosticTypeInfo<std::string>;
+  using DiagnosticType = Diagnostics::TypeInfo<std::string>;
 
   // The name of `default`.
   static const LibraryNameId Default;

+ 6 - 6
toolchain/source/source_buffer.cpp

@@ -11,7 +11,7 @@
 
 namespace Carbon {
 
-auto SourceBuffer::MakeFromStdin(DiagnosticConsumer& consumer)
+auto SourceBuffer::MakeFromStdin(Diagnostics::Consumer& consumer)
     -> std::optional<SourceBuffer> {
   return MakeFromMemoryBuffer(llvm::MemoryBuffer::getSTDIN(), "<stdin>",
                               /*is_regular_file=*/false, consumer);
@@ -19,9 +19,9 @@ auto SourceBuffer::MakeFromStdin(DiagnosticConsumer& consumer)
 
 auto SourceBuffer::MakeFromFile(llvm::vfs::FileSystem& fs,
                                 llvm::StringRef filename,
-                                DiagnosticConsumer& consumer)
+                                Diagnostics::Consumer& consumer)
     -> std::optional<SourceBuffer> {
-  FileDiagnosticEmitter emitter(&consumer);
+  Diagnostics::FileEmitter emitter(&consumer);
 
   llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>> file =
       fs.openFileForRead(filename);
@@ -53,7 +53,7 @@ auto SourceBuffer::MakeFromFile(llvm::vfs::FileSystem& fs,
 
 auto SourceBuffer::MakeFromStringCopy(llvm::StringRef filename,
                                       llvm::StringRef text,
-                                      DiagnosticConsumer& consumer)
+                                      Diagnostics::Consumer& consumer)
     -> std::optional<SourceBuffer> {
   return MakeFromMemoryBuffer(
       llvm::MemoryBuffer::getMemBufferCopy(text, filename), filename,
@@ -63,8 +63,8 @@ auto SourceBuffer::MakeFromStringCopy(llvm::StringRef filename,
 auto SourceBuffer::MakeFromMemoryBuffer(
     llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer,
     llvm::StringRef filename, bool is_regular_file,
-    DiagnosticConsumer& consumer) -> std::optional<SourceBuffer> {
-  FileDiagnosticEmitter emitter(&consumer);
+    Diagnostics::Consumer& consumer) -> std::optional<SourceBuffer> {
+  Diagnostics::FileEmitter emitter(&consumer);
 
   if (buffer.getError()) {
     CARBON_DIAGNOSTIC(ErrorReadingFile, Error, "error reading file: {0}",

+ 5 - 5
toolchain/source/source_buffer.h

@@ -36,19 +36,19 @@ class SourceBuffer {
  public:
   // Opens and reads the contents of stdin. Returns a SourceBuffer on success.
   // Prints an error and returns nullopt on failure.
-  static auto MakeFromStdin(DiagnosticConsumer& consumer)
+  static auto MakeFromStdin(Diagnostics::Consumer& consumer)
       -> std::optional<SourceBuffer>;
 
   // Opens the requested file. Returns a SourceBuffer on success. Prints an
   // error and returns nullopt on failure.
   static auto MakeFromFile(llvm::vfs::FileSystem& fs, llvm::StringRef filename,
-                           DiagnosticConsumer& consumer)
+                           Diagnostics::Consumer& consumer)
       -> std::optional<SourceBuffer>;
 
   // Handles conditional use of stdin based on the filename being "-".
   static auto MakeFromFileOrStdin(llvm::vfs::FileSystem& fs,
                                   llvm::StringRef filename,
-                                  DiagnosticConsumer& consumer)
+                                  Diagnostics::Consumer& consumer)
       -> std::optional<SourceBuffer> {
     if (filename == "-") {
       return MakeFromStdin(consumer);
@@ -60,7 +60,7 @@ class SourceBuffer {
   // Returns a source buffer with the provided text content. Copies `filename`
   // and `text` to take ownership.
   static auto MakeFromStringCopy(llvm::StringRef filename, llvm::StringRef text,
-                                 DiagnosticConsumer& consumer)
+                                 Diagnostics::Consumer& consumer)
       -> std::optional<SourceBuffer>;
 
   // Use one of the factory functions above to create a source buffer.
@@ -80,7 +80,7 @@ class SourceBuffer {
   static auto MakeFromMemoryBuffer(
       llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer,
       llvm::StringRef filename, bool is_regular_file,
-      DiagnosticConsumer& consumer) -> std::optional<SourceBuffer>;
+      Diagnostics::Consumer& consumer) -> std::optional<SourceBuffer>;
 
   explicit SourceBuffer(std::string filename,
                         std::unique_ptr<llvm::MemoryBuffer> text,

+ 8 - 8
toolchain/source/source_buffer_test.cpp

@@ -17,8 +17,8 @@ static constexpr llvm::StringLiteral TestFileName = "test.carbon";
 
 TEST(SourceBufferTest, MissingFile) {
   llvm::vfs::InMemoryFileSystem fs;
-  auto buffer =
-      SourceBuffer::MakeFromFile(fs, TestFileName, ConsoleDiagnosticConsumer());
+  auto buffer = SourceBuffer::MakeFromFile(fs, TestFileName,
+                                           Diagnostics::ConsoleConsumer());
   EXPECT_FALSE(buffer);
 }
 
@@ -27,8 +27,8 @@ TEST(SourceBufferTest, SimpleFile) {
   CARBON_CHECK(fs.addFile(TestFileName, /*ModificationTime=*/0,
                           llvm::MemoryBuffer::getMemBuffer("Hello World")));
 
-  auto buffer =
-      SourceBuffer::MakeFromFile(fs, TestFileName, ConsoleDiagnosticConsumer());
+  auto buffer = SourceBuffer::MakeFromFile(fs, TestFileName,
+                                           Diagnostics::ConsoleConsumer());
   ASSERT_TRUE(buffer);
 
   EXPECT_EQ(TestFileName, buffer->filename());
@@ -44,8 +44,8 @@ TEST(SourceBufferTest, NoNull) {
                                        /*BufferName=*/"",
                                        /*RequiresNullTerminator=*/false)));
 
-  auto buffer =
-      SourceBuffer::MakeFromFile(fs, TestFileName, ConsoleDiagnosticConsumer());
+  auto buffer = SourceBuffer::MakeFromFile(fs, TestFileName,
+                                           Diagnostics::ConsoleConsumer());
   ASSERT_TRUE(buffer);
 
   EXPECT_EQ(TestFileName, buffer->filename());
@@ -57,8 +57,8 @@ TEST(SourceBufferTest, EmptyFile) {
   CARBON_CHECK(fs.addFile(TestFileName, /*ModificationTime=*/0,
                           llvm::MemoryBuffer::getMemBuffer("")));
 
-  auto buffer =
-      SourceBuffer::MakeFromFile(fs, TestFileName, ConsoleDiagnosticConsumer());
+  auto buffer = SourceBuffer::MakeFromFile(fs, TestFileName,
+                                           Diagnostics::ConsoleConsumer());
   ASSERT_TRUE(buffer);
 
   EXPECT_EQ(TestFileName, buffer->filename());

+ 2 - 2
toolchain/testing/compile_helper.cpp

@@ -7,7 +7,7 @@
 namespace Carbon::Testing {
 
 auto CompileHelper::GetTokenizedBuffer(llvm::StringRef text,
-                                       DiagnosticConsumer* consumer)
+                                       Diagnostics::Consumer* consumer)
     -> Lex::TokenizedBuffer& {
   auto& source = GetSourceBuffer(text);
 
@@ -18,7 +18,7 @@ auto CompileHelper::GetTokenizedBuffer(llvm::StringRef text,
 }
 
 auto CompileHelper::GetTokenizedBufferWithSharedValueStore(
-    llvm::StringRef text, DiagnosticConsumer* consumer)
+    llvm::StringRef text, Diagnostics::Consumer* consumer)
     -> std::pair<Lex::TokenizedBuffer&, SharedValueStores&> {
   auto& tokens = GetTokenizedBuffer(text, consumer);
   return {tokens, value_store_storage_.front()};

+ 3 - 3
toolchain/testing/compile_helper.h

@@ -21,12 +21,12 @@ class CompileHelper {
  public:
   // Returns the result of lex.
   auto GetTokenizedBuffer(llvm::StringRef text,
-                          DiagnosticConsumer* consumer = nullptr)
+                          Diagnostics::Consumer* consumer = nullptr)
       -> Lex::TokenizedBuffer&;
 
   // Returns the result of lex along with shared values.
   auto GetTokenizedBufferWithSharedValueStore(
-      llvm::StringRef text, DiagnosticConsumer* consumer = nullptr)
+      llvm::StringRef text, Diagnostics::Consumer* consumer = nullptr)
       -> std::pair<Lex::TokenizedBuffer&, SharedValueStores&>;
 
   // Returns the result of parse.
@@ -44,7 +44,7 @@ class CompileHelper {
   auto GetSourceBuffer(llvm::StringRef text) -> SourceBuffer&;
 
   // Diagnostics will be printed to console.
-  DiagnosticConsumer& consumer_ = ConsoleDiagnosticConsumer();
+  Diagnostics::Consumer& consumer_ = Diagnostics::ConsoleConsumer();
 
   // An index to generate unique filenames.
   int file_index_ = 0;