tint/writer/spirv: Use Diagnostics() for errors

Brings the SPIR-V writer in line with other writers.

Change-Id: Iaa261150de953b414f966dd004bd48f7315ceb0c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/131221
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: James Price <jrprice@google.com>
diff --git a/src/tint/writer/spirv/builder.cc b/src/tint/writer/spirv/builder.cc
index 40ab2a4..add10aa 100644
--- a/src/tint/writer/spirv/builder.cc
+++ b/src/tint/writer/spirv/builder.cc
@@ -261,7 +261,6 @@
                                       builtin::Extension::kChromiumExperimentalPushConstant,
                                       builtin::Extension::kF16,
                                   })) {
-        error_ = builder_.Diagnostics().str();
         return false;
     }
 
@@ -300,7 +299,8 @@
 uint32_t Builder::LookupVariableID(const sem::Variable* var) {
     auto it = var_to_id_.find(var);
     if (it == var_to_id_.end()) {
-        error_ = "unable to find ID for variable: " + var->Declaration()->name->symbol.Name();
+        TINT_ICE(Writer, builder_.Diagnostics())
+            << "unable to find ID for variable: " + var->Declaration()->name->symbol.Name();
         return 0;
     }
     return it->second;
@@ -374,7 +374,7 @@
 
 bool Builder::GenerateBreakStatement(const ast::BreakStatement*) {
     if (merge_stack_.empty()) {
-        error_ = "Attempted to break without a merge block";
+        TINT_ICE(Writer, builder_.Diagnostics()) << "Attempted to break without a merge block";
         return false;
     }
     if (!push_function_inst(spv::Op::OpBranch, {Operand(merge_stack_.back())})) {
@@ -398,7 +398,8 @@
 
 bool Builder::GenerateContinueStatement(const ast::ContinueStatement*) {
     if (continue_stack_.empty()) {
-        error_ = "Attempted to continue without a continue block";
+        TINT_ICE(Writer, builder_.Diagnostics())
+            << "Attempted to continue without a continue block";
         return false;
     }
     if (!push_function_inst(spv::Op::OpBranch, {Operand(continue_stack_.back())})) {
@@ -420,7 +421,7 @@
 bool Builder::GenerateEntryPoint(const ast::Function* func, uint32_t id) {
     auto stage = pipeline_stage_to_execution_model(func->PipelineStage());
     if (stage == SpvExecutionModelMax) {
-        error_ = "Unknown pipeline stage provided";
+        TINT_ICE(Writer, builder_.Diagnostics()) << "Unknown pipeline stage provided";
         return false;
     }
 
@@ -437,8 +438,8 @@
 
         uint32_t var_id = LookupVariableID(var);
         if (var_id == 0) {
-            error_ =
-                "unable to find ID for global variable: " + var->Declaration()->name->symbol.Name();
+            TINT_ICE(Writer, builder_.Diagnostics()) << "unable to find ID for global variable: " +
+                                                            var->Declaration()->name->symbol.Name();
             return false;
         }
 
@@ -461,9 +462,9 @@
 
         // Check if the workgroup_size uses pipeline-overridable constants.
         if (!wgsize[0].has_value() || !wgsize[1].has_value() || !wgsize[2].has_value()) {
-            error_ =
-                "override-expressions should have been removed with the SubstituteOverride "
-                "transform";
+            TINT_ICE(Writer, builder_.Diagnostics())
+                << "override-expressions should have been removed with the SubstituteOverride "
+                   "transform";
             return false;
         }
         module_.PushExecutionMode(
@@ -506,7 +507,8 @@
         [&](const ast::LiteralExpression* l) { return GenerateLiteralIfNeeded(l); },
         [&](const ast::UnaryOpExpression* u) { return GenerateUnaryOpExpression(u); },
         [&](Default) {
-            error_ = "unknown expression type: " + std::string(expr->TypeInfo().name);
+            TINT_ICE(Writer, builder_.Diagnostics())
+                << "unknown expression type: " + std::string(expr->TypeInfo().name);
             return 0;
         });
 }
@@ -638,7 +640,7 @@
 
     if (v->Is<ast::Let>()) {
         if (!v->initializer) {
-            error_ = "missing initializer for let";
+            TINT_ICE(Writer, builder_.Diagnostics()) << "missing initializer for let";
             return false;
         }
         RegisterVariable(sem, init_id);
@@ -819,7 +821,7 @@
                 return true;  // ignored
             },
             [&](Default) {
-                error_ = "unknown attribute";
+                TINT_ICE(Writer, builder_.Diagnostics()) << "unknown attribute";
                 return false;
             });
         if (!ok) {
@@ -1054,7 +1056,8 @@
                 return GenerateMemberAccessor(member, &info);
             },
             [&](Default) {
-                error_ = "invalid accessor in list: " + std::string(accessor->TypeInfo().name);
+                TINT_ICE(Writer, builder_.Diagnostics())
+                    << "invalid accessor in list: " + std::string(accessor->TypeInfo().name);
                 return false;
             });
         if (!ok) {
@@ -1092,7 +1095,8 @@
             return LookupVariableID(user->Variable());
         }
     }
-    error_ = "identifier '" + expr->identifier->symbol.Name() + "' does not resolve to a variable";
+    TINT_ICE(Writer, builder_.Diagnostics())
+        << "identifier '" + expr->identifier->symbol.Name() + "' does not resolve to a variable";
     return 0;
 }
 
@@ -1186,7 +1190,7 @@
             return GenerateValueConstructorOrConversion(call, var);
         }
     }
-    error_ = "unknown constructor expression";
+    TINT_ICE(Writer, builder_.Diagnostics()) << "unknown constructor expression";
     return 0;
 }
 
@@ -1349,7 +1353,7 @@
                 ops.push_back(Operand(extract_id));
             }
         } else {
-            error_ = "Unhandled type cast value type";
+            TINT_ICE(Writer, builder_.Diagnostics()) << "Unhandled type cast value type";
             return 0;
         }
     }
@@ -1489,7 +1493,8 @@
             zero_id = GenerateConstantIfNeeded(ScalarConstant::I32(0));
             one_id = GenerateConstantIfNeeded(ScalarConstant::I32(1));
         } else {
-            error_ = "invalid destination type for bool conversion";
+            TINT_ICE(Writer, builder_.Diagnostics())
+                << "invalid destination type for bool conversion";
             return false;
         }
         if (auto* to_vec = to_type->As<type::Vector>()) {
@@ -1525,9 +1530,9 @@
     }
 
     if (op == spv::Op::OpNop) {
-        error_ =
-            "unable to determine conversion type for cast, from: " + from_type->FriendlyName() +
-            " to: " + to_type->FriendlyName();
+        TINT_ICE(Writer, builder_.Diagnostics())
+            << "unable to determine conversion type for cast, from: " + from_type->FriendlyName() +
+                   " to: " + to_type->FriendlyName();
         return 0;
     }
 
@@ -1572,9 +1577,9 @@
                     return;
             }
         },
-        [&](Default) { error_ = "unknown literal type"; });
+        [&](Default) { TINT_ICE(Writer, builder_.Diagnostics()) << "unknown literal type"; });
 
-    if (!error_.empty()) {
+    if (has_error()) {
         return false;
     }
 
@@ -1645,14 +1650,15 @@
         [&](const type::Array* a) {
             auto count = a->ConstantCount();
             if (!count) {
-                error_ = type::Array::kErrExpectedConstantCount;
+                TINT_ICE(Writer, builder_.Diagnostics()) << type::Array::kErrExpectedConstantCount;
                 return static_cast<uint32_t>(0);
             }
             return composite(count.value());
         },
         [&](const type::Struct* s) { return composite(s->Members().Length()); },
         [&](Default) {
-            error_ = "unhandled constant type: " + ty->FriendlyName();
+            TINT_ICE(Writer, builder_.Diagnostics())
+                << "unhandled constant type: " + ty->FriendlyName();
             return 0;
         });
 }
@@ -1963,7 +1969,8 @@
 
         // This should already have been validated by resolver
         if (lhs_mat->rows() != rhs_mat->rows() || lhs_mat->columns() != rhs_mat->columns()) {
-            error_ = "matrices must have same dimensionality for add or subtract";
+            TINT_ICE(Writer, builder_.Diagnostics())
+                << "matrices must have same dimensionality for add or subtract";
             return 0;
         }
 
@@ -2008,7 +2015,7 @@
         } else if (lhs_is_bool_or_vec) {
             op = spv::Op::OpLogicalAnd;
         } else {
-            error_ = "invalid and expression";
+            TINT_ICE(Writer, builder_.Diagnostics()) << "invalid and expression";
             return 0;
         }
     } else if (expr->IsAdd()) {
@@ -2029,7 +2036,7 @@
         } else if (lhs_is_integer_or_vec) {
             op = spv::Op::OpIEqual;
         } else {
-            error_ = "invalid equal expression";
+            TINT_ICE(Writer, builder_.Diagnostics()) << "invalid equal expression";
             return 0;
         }
     } else if (expr->IsGreaterThan()) {
@@ -2109,7 +2116,7 @@
             // float matrix * matrix
             op = spv::Op::OpMatrixTimesMatrix;
         } else {
-            error_ = "invalid multiply expression";
+            TINT_ICE(Writer, builder_.Diagnostics()) << "invalid multiply expression";
             return 0;
         }
     } else if (expr->IsNotEqual()) {
@@ -2120,7 +2127,7 @@
         } else if (lhs_is_integer_or_vec) {
             op = spv::Op::OpINotEqual;
         } else {
-            error_ = "invalid not-equal expression";
+            TINT_ICE(Writer, builder_.Diagnostics()) << "invalid not-equal expression";
             return 0;
         }
     } else if (expr->IsOr()) {
@@ -2129,7 +2136,7 @@
         } else if (lhs_is_bool_or_vec) {
             op = spv::Op::OpLogicalOr;
         } else {
-            error_ = "invalid and expression";
+            TINT_ICE(Writer, builder_.Diagnostics()) << "invalid and expression";
             return 0;
         }
     } else if (expr->IsShiftLeft()) {
@@ -2144,7 +2151,7 @@
     } else if (expr->IsXor()) {
         op = spv::Op::OpBitwiseXor;
     } else {
-        error_ = "unknown binary expression";
+        TINT_ICE(Writer, builder_.Diagnostics()) << "unknown binary expression";
         return 0;
     }
 
@@ -2205,7 +2212,8 @@
 
     auto func_id = func_symbol_to_id_[ident->symbol];
     if (func_id == 0) {
-        error_ = "unable to find called function: " + ident->symbol.Name();
+        TINT_ICE(Writer, builder_.Diagnostics())
+            << "unable to find called function: " + ident->symbol.Name();
         return 0;
     }
     ops.push_back(Operand(func_id));
@@ -2309,16 +2317,18 @@
         case builtin::Function::kArrayLength: {
             auto* address_of = call->Arguments()[0]->Declaration()->As<ast::UnaryOpExpression>();
             if (!address_of || address_of->op != ast::UnaryOp::kAddressOf) {
-                error_ = "arrayLength() expected pointer to member access, got " +
-                         std::string(address_of->TypeInfo().name);
+                TINT_ICE(Writer, builder_.Diagnostics())
+                    << "arrayLength() expected pointer to member access, got " +
+                           std::string(address_of->TypeInfo().name);
                 return 0;
             }
             auto* array_expr = address_of->expr;
 
             auto* accessor = array_expr->As<ast::MemberAccessorExpression>();
             if (!accessor) {
-                error_ = "arrayLength() expected pointer to member access, got pointer to " +
-                         std::string(array_expr->TypeInfo().name);
+                TINT_ICE(Writer, builder_.Diagnostics())
+                    << "arrayLength() expected pointer to member access, got pointer to " +
+                           std::string(array_expr->TypeInfo().name);
                 return 0;
             }
 
@@ -2330,7 +2340,8 @@
 
             auto* type = TypeOf(accessor->object)->UnwrapRef();
             if (!type->Is<type::Struct>()) {
-                error_ = "invalid type (" + type->FriendlyName() + ") for runtime array length";
+                TINT_ICE(Writer, builder_.Diagnostics())
+                    << "invalid type (" + type->FriendlyName() + ") for runtime array length";
                 return 0;
             }
             // Runtime array must be the last member in the structure
@@ -2527,7 +2538,8 @@
         default: {
             auto inst_id = builtin_to_glsl_method(builtin);
             if (inst_id == 0) {
-                error_ = "unknown method " + std::string(builtin->str());
+                TINT_ICE(Writer, builder_.Diagnostics())
+                    << "unknown method " + std::string(builtin->str());
                 return 0;
             }
             glsl_std450(inst_id);
@@ -2536,7 +2548,8 @@
     }
 
     if (op == spv::Op::OpNop) {
-        error_ = "unable to determine operator for: " + std::string(builtin->str());
+        TINT_ICE(Writer, builder_.Diagnostics())
+            << "unable to determine operator for: " + std::string(builtin->str());
         return 0;
     }
 
@@ -2727,7 +2740,7 @@
             uint32_t spirv_dims = 0;
             switch (texture_type->dim()) {
                 case type::TextureDimension::kNone:
-                    error_ = "texture dimension is kNone";
+                    TINT_ICE(Writer, builder_.Diagnostics()) << "texture dimension is kNone";
                     return false;
                 case type::TextureDimension::k1d:
                 case type::TextureDimension::k2d:
@@ -2764,7 +2777,7 @@
             uint32_t spirv_dims = 0;
             switch (texture_type->dim()) {
                 default:
-                    error_ = "texture is not arrayed";
+                    TINT_ICE(Writer, builder_.Diagnostics()) << "texture is not arrayed";
                     return false;
                 case type::TextureDimension::k2dArray:
                 case type::TextureDimension::kCubeArray:
@@ -2954,7 +2967,8 @@
     }
 
     if (op == spv::Op::OpNop) {
-        error_ = "unable to determine operator for: " + std::string(builtin->str());
+        TINT_ICE(Writer, builder_.Diagnostics())
+            << "unable to determine operator for: " + std::string(builtin->str());
         return false;
     }
 
@@ -2984,8 +2998,8 @@
         semantics = static_cast<uint32_t>(spv::MemorySemanticsMask::AcquireRelease) |
                     static_cast<uint32_t>(spv::MemorySemanticsMask::UniformMemory);
     } else {
-        error_ = "unexpected barrier builtin type ";
-        error_ += builtin::str(builtin->Type());
+        TINT_ICE(Writer, builder_.Diagnostics())
+            << "unexpected barrier builtin type " << builtin::str(builtin->Type());
         return false;
     }
 
@@ -3559,7 +3573,8 @@
             return true;  // Not emitted
         },
         [&](Default) {
-            error_ = "unknown statement type: " + std::string(stmt->TypeInfo().name);
+            TINT_ICE(Writer, builder_.Diagnostics())
+                << "unknown statement type: " + std::string(stmt->TypeInfo().name);
             return false;
         });
 }
@@ -3570,7 +3585,7 @@
 
 uint32_t Builder::GenerateTypeIfNeeded(const type::Type* type) {
     if (type == nullptr) {
-        error_ = "attempting to generate type from null type";
+        TINT_ICE(Writer, builder_.Diagnostics()) << "attempting to generate type from null type";
         return 0;
     }
 
@@ -3686,7 +3701,8 @@
                 return true;
             },
             [&](Default) {
-                error_ = "unable to convert type: " + type->FriendlyName();
+                TINT_ICE(Writer, builder_.Diagnostics())
+                    << "unable to convert type: " + type->FriendlyName();
                 return false;
             });
 
@@ -3790,7 +3806,7 @@
     } else {
         auto count = arr->ConstantCount();
         if (!count) {
-            error_ = type::Array::kErrExpectedConstantCount;
+            TINT_ICE(Writer, builder_.Diagnostics()) << type::Array::kErrExpectedConstantCount;
             return static_cast<uint32_t>(0);
         }
 
@@ -3828,7 +3844,7 @@
 
     auto stg_class = ConvertAddressSpace(ptr->AddressSpace());
     if (stg_class == SpvStorageClassMax) {
-        error_ = "invalid address space for pointer";
+        TINT_ICE(Writer, builder_.Diagnostics()) << "invalid address space for pointer";
         return false;
     }
 
@@ -3845,7 +3861,7 @@
 
     auto stg_class = ConvertAddressSpace(ref->AddressSpace());
     if (stg_class == SpvStorageClassMax) {
-        error_ = "invalid address space for reference";
+        TINT_ICE(Writer, builder_.Diagnostics()) << "invalid address space for reference";
         return false;
     }
 
@@ -4077,7 +4093,7 @@
         utils::StringStream ss;
         ss << "Internal error: trying to add SPIR-V instruction " << int(op)
            << " outside a function";
-        error_ = ss.str();
+        TINT_ICE(Writer, builder_.Diagnostics()) << ss.str();
         return false;
     }
     current_function_.push_inst(op, operands);
diff --git a/src/tint/writer/spirv/builder.h b/src/tint/writer/spirv/builder.h
index 5ffa3d3..17e96cd 100644
--- a/src/tint/writer/spirv/builder.h
+++ b/src/tint/writer/spirv/builder.h
@@ -89,10 +89,11 @@
     /// @returns true if the SPIR-V was successfully built
     bool Build();
 
-    /// @returns the error string or blank if no error was reported.
-    const std::string& error() const { return error_; }
+    /// @returns the list of diagnostics raised by the builder
+    const diag::List& Diagnostics() const { return builder_.Diagnostics(); }
+
     /// @returns true if the builder encountered an error
-    bool has_error() const { return !error_.empty(); }
+    bool has_error() const { return Diagnostics().contains_errors(); }
 
     /// @returns the module that this builder has produced
     spirv::Module& Module() { return module_; }
@@ -509,7 +510,6 @@
     void PopScope();
 
     ProgramBuilder builder_;
-    std::string error_;
     spirv::Module module_;
     Function current_function_;
     uint32_t current_label_id_ = 0;
diff --git a/src/tint/writer/spirv/builder_accessor_expression_test.cc b/src/tint/writer/spirv/builder_accessor_expression_test.cc
index 6150d5a..d93b414 100644
--- a/src/tint/writer/spirv/builder_accessor_expression_test.cc
+++ b/src/tint/writer/spirv/builder_accessor_expression_test.cc
@@ -32,7 +32,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -67,7 +67,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -97,7 +97,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -136,7 +136,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -175,7 +175,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -210,7 +210,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -249,7 +249,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -293,7 +293,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -341,7 +341,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -371,7 +371,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -414,7 +414,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -460,7 +460,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -507,7 +507,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -552,7 +552,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -604,7 +604,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -652,7 +652,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -682,7 +682,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -724,7 +724,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -770,7 +770,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -813,7 +813,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -846,7 +846,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -886,7 +886,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -936,7 +936,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -984,7 +984,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -1030,7 +1030,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -1072,7 +1072,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -1117,7 +1117,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -1165,7 +1165,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -1218,7 +1218,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -1256,7 +1256,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -1290,7 +1290,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -1321,7 +1321,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -1353,7 +1353,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -1384,7 +1384,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
@@ -1438,7 +1438,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
diff --git a/src/tint/writer/spirv/builder_assign_test.cc b/src/tint/writer/spirv/builder_assign_test.cc
index 08962ce..cab0ed4 100644
--- a/src/tint/writer/spirv/builder_assign_test.cc
+++ b/src/tint/writer/spirv/builder_assign_test.cc
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "gmock/gmock.h"
 #include "src/tint/writer/spirv/spv_dump.h"
 #include "src/tint/writer/spirv/test_helper.h"
 
@@ -32,10 +33,10 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
-    EXPECT_TRUE(b.GenerateAssignStatement(assign)) << b.error();
+    EXPECT_TRUE(b.GenerateAssignStatement(assign)) << b.Diagnostics();
     EXPECT_FALSE(b.has_error());
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeFloat 32
@@ -59,14 +60,15 @@
 
     spirv::Builder& b = Build();
 
-    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
-    EXPECT_FALSE(b.GenerateAssignStatement(assign)) << b.error();
+    tint::SetInternalCompilerErrorReporter(nullptr);
+
+    EXPECT_FALSE(b.GenerateAssignStatement(assign)) << b.Diagnostics();
     EXPECT_TRUE(b.has_error());
-    EXPECT_EQ(b.error(),
-              "Internal error: trying to add SPIR-V instruction 62 outside a "
-              "function");
+    EXPECT_THAT(b.Diagnostics().str(),
+                ::testing::HasSubstr("trying to add SPIR-V instruction 62 outside a function"));
 }
 
 TEST_F(BuilderTest, Assign_Var_ZeroInitializer) {
@@ -80,10 +82,10 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
-    EXPECT_TRUE(b.GenerateAssignStatement(assign)) << b.error();
+    EXPECT_TRUE(b.GenerateAssignStatement(assign)) << b.Diagnostics();
     EXPECT_FALSE(b.has_error());
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeFloat 32
@@ -110,10 +112,10 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
-    EXPECT_TRUE(b.GenerateAssignStatement(assign)) << b.error();
+    EXPECT_TRUE(b.GenerateAssignStatement(assign)) << b.Diagnostics();
     EXPECT_FALSE(b.has_error());
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeFloat 32
@@ -143,10 +145,10 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
-    EXPECT_TRUE(b.GenerateAssignStatement(assign)) << b.error();
+    EXPECT_TRUE(b.GenerateAssignStatement(assign)) << b.Diagnostics();
     EXPECT_FALSE(b.has_error());
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeFloat 32
@@ -186,10 +188,10 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
-    EXPECT_TRUE(b.GenerateAssignStatement(assign)) << b.error();
+    EXPECT_TRUE(b.GenerateAssignStatement(assign)) << b.Diagnostics();
     EXPECT_FALSE(b.has_error());
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeFloat 32
@@ -219,10 +221,10 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
-    EXPECT_TRUE(b.GenerateAssignStatement(assign)) << b.error();
+    EXPECT_TRUE(b.GenerateAssignStatement(assign)) << b.Diagnostics();
     EXPECT_FALSE(b.has_error());
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeFloat 32
@@ -252,10 +254,10 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
-    EXPECT_TRUE(b.GenerateAssignStatement(assign)) << b.error();
+    EXPECT_TRUE(b.GenerateAssignStatement(assign)) << b.Diagnostics();
     EXPECT_FALSE(b.has_error());
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeFloat 32
@@ -287,10 +289,10 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
-    EXPECT_TRUE(b.GenerateAssignStatement(assign)) << b.error();
+    EXPECT_TRUE(b.GenerateAssignStatement(assign)) << b.Diagnostics();
     EXPECT_FALSE(b.has_error());
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeFloat 32
diff --git a/src/tint/writer/spirv/builder_binary_expression_test.cc b/src/tint/writer/spirv/builder_binary_expression_test.cc
index ed4dc59..36bd427 100644
--- a/src/tint/writer/spirv/builder_binary_expression_test.cc
+++ b/src/tint/writer/spirv/builder_binary_expression_test.cc
@@ -48,7 +48,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 4u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 4u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeInt 32 1
 %2 = OpConstant %1 3
 %3 = OpConstant %1 4
@@ -77,7 +77,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeInt 32 1
 %1 = OpTypeVector %2 3
 %3 = OpConstant %2 1
@@ -97,9 +97,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 7u) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateFunctionVariable(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 7u) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeInt 32 1
 %2 = OpTypePointer Function %3
@@ -142,7 +142,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 4u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 4u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeInt 32 0
 %2 = OpConstant %1 3
 %3 = OpConstant %1 4
@@ -170,7 +170,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeInt 32 0
 %1 = OpTypeVector %2 3
 %3 = OpConstant %2 1
@@ -208,7 +208,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 4u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 4u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeFloat 32
 %2 = OpConstant %1 3.20000005
 %3 = OpConstant %1 4.5
@@ -231,7 +231,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeVector %2 3
 %3 = OpConstant %2 1
@@ -265,7 +265,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 4u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 4u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeFloat 16
 %2 = OpConstant %1 0x1.998p+1
 %3 = OpConstant %1 0x1.2p+2
@@ -290,7 +290,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 16
 %1 = OpTypeVector %2 3
 %3 = OpConstant %2 0x1p+0
@@ -322,7 +322,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 4u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 4u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeBool
 %2 = OpConstantTrue %1
 %3 = OpConstantNull %1
@@ -345,7 +345,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 7u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 7u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeBool
 %1 = OpTypeVector %2 3
 %3 = OpConstantNull %2
@@ -378,7 +378,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 4u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 4u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeInt 32 0
 %2 = OpConstant %1 3
 %3 = OpConstant %1 4
@@ -402,7 +402,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeInt 32 0
 %1 = OpTypeVector %2 3
 %3 = OpConstant %2 1
@@ -438,7 +438,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 4u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 4u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeInt 32 1
 %2 = OpConstant %1 3
 %3 = OpConstant %1 4
@@ -462,7 +462,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeInt 32 1
 %1 = OpTypeVector %2 3
 %3 = OpConstant %2 1
@@ -498,7 +498,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 4u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 4u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeFloat 32
 %2 = OpConstant %1 3.20000005
 %3 = OpConstant %1 4.5
@@ -522,7 +522,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeVector %2 3
 %3 = OpConstant %2 1
@@ -560,7 +560,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 4u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 4u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeFloat 16
 %2 = OpConstant %1 0x1.998p+1
 %3 = OpConstant %1 0x1.2p+2
@@ -586,7 +586,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 16
 %1 = OpTypeVector %2 3
 %3 = OpConstant %2 0x1p+0
@@ -619,7 +619,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%2 = OpTypeFloat 32
 %1 = OpTypeVector %2 3
@@ -644,7 +644,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%2 = OpTypeFloat 16
 %1 = OpTypeVector %2 3
@@ -667,7 +667,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%1 = OpTypeFloat 32
 %2 = OpConstant %1 1
@@ -692,7 +692,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 5u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%1 = OpTypeFloat 16
 %2 = OpConstant %1 0x1p+0
@@ -712,9 +712,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.Diagnostics();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 9u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 9u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%5 = OpTypeFloat 32
 %4 = OpTypeVector %5 3
@@ -740,9 +740,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.Diagnostics();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 9u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 9u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%5 = OpTypeFloat 16
 %4 = OpTypeVector %5 3
@@ -766,9 +766,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.Diagnostics();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 9u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 9u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%5 = OpTypeFloat 32
 %4 = OpTypeVector %5 3
@@ -794,9 +794,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.Diagnostics();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 9u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 9u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%5 = OpTypeFloat 16
 %4 = OpTypeVector %5 3
@@ -821,9 +821,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.Diagnostics();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 10u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 10u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%5 = OpTypeFloat 32
 %4 = OpTypeVector %5 3
@@ -851,9 +851,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.Diagnostics();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 10u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 10u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%5 = OpTypeFloat 16
 %4 = OpTypeVector %5 3
@@ -879,9 +879,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.Diagnostics();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 10u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 10u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%5 = OpTypeFloat 32
 %4 = OpTypeVector %5 3
@@ -910,9 +910,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.Diagnostics();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 10u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 10u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%5 = OpTypeFloat 16
 %4 = OpTypeVector %5 3
@@ -937,9 +937,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.Diagnostics();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 9u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 9u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%5 = OpTypeFloat 32
 %4 = OpTypeVector %5 3
@@ -965,9 +965,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.Diagnostics();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 9u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 9u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%5 = OpTypeFloat 16
 %4 = OpTypeVector %5 3
@@ -995,12 +995,12 @@
 
     b.PushFunctionForTesting();
     b.GenerateLabel(b.Module().NextId());
-    ASSERT_TRUE(b.GenerateFunctionVariable(v0)) << b.error();
-    ASSERT_TRUE(b.GenerateFunctionVariable(v1)) << b.error();
-    ASSERT_TRUE(b.GenerateFunctionVariable(v2)) << b.error();
-    ASSERT_TRUE(b.GenerateFunctionVariable(v3)) << b.error();
+    ASSERT_TRUE(b.GenerateFunctionVariable(v0)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunctionVariable(v1)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunctionVariable(v2)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunctionVariable(v3)) << b.Diagnostics();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 22u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 22u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%2 = OpTypeInt 32 1
 %3 = OpConstant %2 1
@@ -1044,10 +1044,10 @@
     b.PushFunctionForTesting();
     b.GenerateLabel(b.Module().NextId());
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(a_var)) << b.error();
-    ASSERT_TRUE(b.GenerateGlobalVariable(b_var)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(a_var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateGlobalVariable(b_var)) << b.Diagnostics();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 12u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 12u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeBool
 %3 = OpConstantTrue %2
 %5 = OpTypePointer Private %2
@@ -1087,11 +1087,11 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateFunctionVariable(t)) << b.error();
-    ASSERT_TRUE(b.GenerateFunctionVariable(f)) << b.error();
+    ASSERT_TRUE(b.GenerateFunctionVariable(t)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunctionVariable(f)) << b.Diagnostics();
     b.GenerateLabel(b.Module().NextId());
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 10u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 10u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeBool
 %2 = OpConstantTrue %1
 %3 = OpConstantNull %1
@@ -1132,11 +1132,11 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateFunctionVariable(t)) << b.error();
-    ASSERT_TRUE(b.GenerateFunctionVariable(f)) << b.error();
+    ASSERT_TRUE(b.GenerateFunctionVariable(t)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunctionVariable(f)) << b.Diagnostics();
     b.GenerateLabel(b.Module().NextId());
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 10u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 10u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeBool
 %2 = OpConstantTrue %1
 %3 = OpConstantNull %1
@@ -1171,12 +1171,12 @@
 
     b.PushFunctionForTesting();
     b.GenerateLabel(b.Module().NextId());
-    ASSERT_TRUE(b.GenerateFunctionVariable(v0)) << b.error();
-    ASSERT_TRUE(b.GenerateFunctionVariable(v1)) << b.error();
-    ASSERT_TRUE(b.GenerateFunctionVariable(v2)) << b.error();
-    ASSERT_TRUE(b.GenerateFunctionVariable(v3)) << b.error();
+    ASSERT_TRUE(b.GenerateFunctionVariable(v0)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunctionVariable(v1)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunctionVariable(v2)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunctionVariable(v3)) << b.Diagnostics();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 22u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 22u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%2 = OpTypeInt 32 1
 %3 = OpConstant %2 1
@@ -1221,10 +1221,10 @@
     b.PushFunctionForTesting();
     b.GenerateLabel(b.Module().NextId());
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(a_var)) << b.error();
-    ASSERT_TRUE(b.GenerateGlobalVariable(b_var)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(a_var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateGlobalVariable(b_var)) << b.Diagnostics();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr), 12u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr), 12u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeBool
 %3 = OpConstantTrue %2
 %5 = OpTypePointer Private %2
@@ -1357,7 +1357,7 @@
     WrapInFunction(expr);
 
     spirv::Builder& b = Build();
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
     EXPECT_EQ(DumpBuilder(b), capability_decl + R"(
 OpMemoryModel Logical GLSL450
 OpEntryPoint GLCompute %11 "test_function"
@@ -1409,7 +1409,7 @@
     WrapInFunction(expr);
 
     spirv::Builder& b = Build();
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
     EXPECT_EQ(DumpBuilder(b), capability_decl + R"(
 OpMemoryModel Logical GLSL450
 OpEntryPoint GLCompute %11 "test_function"
@@ -1489,7 +1489,7 @@
     WrapInFunction(expr);
 
     spirv::Builder& b = Build();
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
     EXPECT_EQ(DumpBuilder(b), capability_decl + R"(
 OpMemoryModel Logical GLSL450
 OpEntryPoint GLCompute %11 "test_function"
@@ -1537,7 +1537,7 @@
     WrapInFunction(expr);
 
     spirv::Builder& b = Build();
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
     EXPECT_EQ(DumpBuilder(b), capability_decl + R"(
 OpMemoryModel Logical GLSL450
 OpEntryPoint GLCompute %11 "test_function"
@@ -1651,7 +1651,7 @@
     WrapInFunction(expr);
 
     spirv::Builder& b = Build();
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
     EXPECT_EQ(DumpBuilder(b), capability_decl + R"(
 OpMemoryModel Logical GLSL450
 OpEntryPoint GLCompute %10 "test_function"
@@ -1714,7 +1714,7 @@
     WrapInFunction(expr);
 
     spirv::Builder& b = Build();
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
     EXPECT_EQ(DumpBuilder(b), capability_decl + R"(
 OpMemoryModel Logical GLSL450
 OpEntryPoint GLCompute %14 "test_function"
diff --git a/src/tint/writer/spirv/builder_block_test.cc b/src/tint/writer/spirv/builder_block_test.cc
index 66a9d03..4783360 100644
--- a/src/tint/writer/spirv/builder_block_test.cc
+++ b/src/tint/writer/spirv/builder_block_test.cc
@@ -33,9 +33,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
-    EXPECT_TRUE(b.GenerateStatement(outer)) << b.error();
+    EXPECT_TRUE(b.GenerateStatement(outer)) << b.Diagnostics();
     EXPECT_FALSE(b.has_error());
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeFloat 32
diff --git a/src/tint/writer/spirv/builder_builtin_test.cc b/src/tint/writer/spirv/builder_builtin_test.cc
index 5db3bff..ba33a44 100644
--- a/src/tint/writer/spirv/builder_builtin_test.cc
+++ b/src/tint/writer/spirv/builder_builtin_test.cc
@@ -65,11 +65,11 @@
 
     b.PushFunctionForTesting();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
-    ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.Diagnostics();
 
-    EXPECT_EQ(b.GenerateExpression(expr1), 8u) << b.error();
-    EXPECT_EQ(b.GenerateExpression(expr2), 17u) << b.error();
+    EXPECT_EQ(b.GenerateExpression(expr1), 8u) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(expr2), 17u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeFloat 32
 %3 = OpTypeImage %4 2D 0 0 0 1 Unknown
@@ -107,8 +107,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect =
@@ -143,8 +143,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect =
@@ -182,8 +182,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeBool
 %2 = OpTypePointer Private %3
@@ -209,8 +209,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeBool
 %3 = OpTypeVector %4 3
@@ -244,9 +244,9 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(v3)) << b.error();
-    ASSERT_TRUE(b.GenerateGlobalVariable(bool_v3)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(v3)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateGlobalVariable(bool_v3)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeFloat 32
 %3 = OpTypeVector %4 3
@@ -293,7 +293,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     ASSERT_EQ(b.Module().Functions().size(), 1_u);
 
@@ -337,7 +337,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     ASSERT_EQ(b.Module().Functions().size(), 1_u);
 
@@ -385,7 +385,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     ASSERT_EQ(b.Module().Functions().size(), 1_u);
 
@@ -446,7 +446,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     ASSERT_EQ(b.Module().Functions().size(), 1_u);
 
@@ -490,7 +490,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%11 = OpExtInstImport "GLSL.std.450"
@@ -531,7 +531,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%11 = OpExtInstImport "GLSL.std.450"
@@ -571,7 +571,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -615,7 +615,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -681,7 +681,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%11 = OpExtInstImport "GLSL.std.450"
@@ -718,7 +718,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%11 = OpExtInstImport "GLSL.std.450"
@@ -753,7 +753,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -792,7 +792,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -829,7 +829,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -868,7 +868,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -907,7 +907,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%11 = OpExtInstImport "GLSL.std.450"
@@ -948,7 +948,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%11 = OpExtInstImport "GLSL.std.450"
@@ -987,7 +987,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -1030,7 +1030,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -1078,7 +1078,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -1118,7 +1118,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -1156,7 +1156,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%11 = OpExtInstImport "GLSL.std.450"
@@ -1194,7 +1194,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%11 = OpExtInstImport "GLSL.std.450"
@@ -1230,7 +1230,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -1270,7 +1270,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -1308,7 +1308,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -1348,7 +1348,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -1388,7 +1388,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%11 = OpExtInstImport "GLSL.std.450"
@@ -1430,7 +1430,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%11 = OpExtInstImport "GLSL.std.450"
@@ -1470,7 +1470,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -1514,7 +1514,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -1563,7 +1563,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -1604,7 +1604,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -1646,7 +1646,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
     auto got = DumpBuilder(b);
     auto* expect = R"(OpCapability Shader
 %15 = OpExtInstImport "GLSL.std.450"
@@ -1700,7 +1700,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
     auto got = DumpBuilder(b);
     auto* expect = R"(OpCapability Shader
 OpCapability Float16
@@ -1754,7 +1754,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
     auto got = DumpBuilder(b);
     auto* expect = R"(OpCapability Shader
 OpMemoryModel Logical GLSL450
@@ -1800,7 +1800,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
     auto got = DumpBuilder(b);
     auto* expect = R"(OpCapability Shader
 OpCapability Float16
@@ -1850,7 +1850,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
     auto got = DumpBuilder(b);
     auto* expect = R"(OpCapability Shader
 %17 = OpExtInstImport "GLSL.std.450"
@@ -1906,7 +1906,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
     auto got = DumpBuilder(b);
     auto* expect = R"(OpCapability Shader
 OpCapability Float16
@@ -1961,7 +1961,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
     auto got = DumpBuilder(b);
     auto* expect = R"(OpCapability Shader
 OpMemoryModel Logical GLSL450
@@ -2009,7 +2009,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
     auto got = DumpBuilder(b);
     auto* expect = R"(OpCapability Shader
 OpCapability Float16
@@ -2061,7 +2061,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
     auto got = DumpBuilder(b);
     auto* expect = R"(OpCapability Shader
 OpMemoryModel Logical GLSL450
@@ -2100,7 +2100,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
     auto got = DumpBuilder(b);
     auto* expect = R"(OpCapability Shader
 OpMemoryModel Logical GLSL450
@@ -2164,8 +2164,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeInt 32 1
 %2 = OpTypePointer Private %3
@@ -2194,8 +2194,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeInt 32 1
 %3 = OpTypeVector %4 3
@@ -2225,8 +2225,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeInt 32 0
 %2 = OpTypePointer Private %3
@@ -2255,8 +2255,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeInt 32 0
 %3 = OpTypeVector %4 3
@@ -2292,7 +2292,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%11 = OpExtInstImport "GLSL.std.450"
@@ -2330,7 +2330,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -2374,7 +2374,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(OpName %3 "a_func"
@@ -2407,7 +2407,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(OpName %3 "a_func"
@@ -2444,7 +2444,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%11 = OpExtInstImport "GLSL.std.450"
@@ -2483,7 +2483,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -2528,7 +2528,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%11 = OpExtInstImport "GLSL.std.450"
@@ -2567,7 +2567,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -2612,7 +2612,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%11 = OpExtInstImport "GLSL.std.450"
@@ -2652,7 +2652,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -2698,7 +2698,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%11 = OpExtInstImport "GLSL.std.450"
@@ -2738,7 +2738,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%13 = OpExtInstImport "GLSL.std.450"
@@ -2780,7 +2780,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
@@ -2821,7 +2821,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
@@ -2859,7 +2859,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
@@ -2901,7 +2901,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
@@ -2943,7 +2943,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
@@ -2988,7 +2988,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
@@ -3030,7 +3030,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
@@ -3076,7 +3076,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
@@ -3126,8 +3126,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%12 = OpExtInstImport "GLSL.std.450"
@@ -3163,8 +3163,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(%12 = OpExtInstImport "GLSL.std.450"
@@ -3198,8 +3198,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(OpName %1 "var"
@@ -3236,8 +3236,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(OpName %1 "var"
@@ -3277,8 +3277,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeFloat 32
 %3 = OpTypeVector %4 3
@@ -3308,8 +3308,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeFloat 16
 %3 = OpTypeVector %4 3
@@ -3337,8 +3337,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeInt 32 0
 %3 = OpTypeVector %4 3
@@ -3376,8 +3376,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeInt 32 1
 %3 = OpTypeVector %4 3
@@ -3425,8 +3425,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeFloat 32
 %2 = OpTypePointer Private %3
@@ -3458,8 +3458,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     if (param.name != "dpdx" && param.name != "dpdy" && param.name != "fwidth") {
         EXPECT_EQ(DumpInstructions(b.Module().Capabilities()),
@@ -3530,7 +3530,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     ASSERT_EQ(b.Module().Functions().size(), 1_u);
 
@@ -3596,7 +3596,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     ASSERT_EQ(b.Module().Functions().size(), 1_u);
 
@@ -3667,7 +3667,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     ASSERT_EQ(b.Module().Functions().size(), 1_u);
 
@@ -3740,7 +3740,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     ASSERT_EQ(b.Module().Functions().size(), 1_u);
 
@@ -3818,7 +3818,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     ASSERT_EQ(b.Module().Functions().size(), 1_u);
 
@@ -3892,7 +3892,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     ASSERT_EQ(b.Module().Functions().size(), 1_u);
 
@@ -3954,7 +3954,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     if (pack4) {
         auto got = DumpBuilder(b);
@@ -4025,7 +4025,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     if (pack4) {
         auto got = DumpBuilder(b);
@@ -4093,7 +4093,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     ASSERT_EQ(b.Module().Functions().size(), 1_u);
 
@@ -4127,7 +4127,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     ASSERT_EQ(b.Module().Functions().size(), 1_u);
 
@@ -4164,7 +4164,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
@@ -4201,7 +4201,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto got = DumpBuilder(b);
     auto expect = R"(OpEntryPoint GLCompute %3 "test_function"
diff --git a/src/tint/writer/spirv/builder_builtin_texture_test.cc b/src/tint/writer/spirv/builder_builtin_texture_test.cc
index 6bbd866..cd17ec1 100644
--- a/src/tint/writer/spirv/builder_builtin_texture_test.cc
+++ b/src/tint/writer/spirv/builder_builtin_texture_test.cc
@@ -3727,10 +3727,10 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(texture)) << b.error();
-    ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(texture)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.Diagnostics();
 
-    EXPECT_EQ(b.GenerateExpression(call), 8u) << b.error();
+    EXPECT_EQ(b.GenerateExpression(call), 8u) << b.Diagnostics();
 
     auto expected = expected_texture_overload(param.overload);
     EXPECT_EQ(expected.types, "\n" + DumpInstructions(b.Module().Types()));
@@ -3756,7 +3756,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     Validate(b);
 }
@@ -3781,12 +3781,14 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(texture)) << b.error();
-    ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error();
+    tint::SetInternalCompilerErrorReporter(nullptr);
+
+    ASSERT_TRUE(b.GenerateGlobalVariable(texture)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.Diagnostics();
     EXPECT_EQ(b.GenerateExpression(call), 0u);
-    EXPECT_THAT(b.error(),
-                ::testing::StartsWith("Internal error: trying to add SPIR-V instruction "));
-    EXPECT_THAT(b.error(), ::testing::EndsWith(" outside a function"));
+    EXPECT_THAT(b.Diagnostics().str(),
+                ::testing::HasSubstr("Internal error: trying to add SPIR-V instruction "));
+    EXPECT_THAT(b.Diagnostics().str(), ::testing::HasSubstr(" outside a function"));
 }
 
 }  // namespace
diff --git a/src/tint/writer/spirv/builder_call_test.cc b/src/tint/writer/spirv/builder_call_test.cc
index a0631ea..b4774cb 100644
--- a/src/tint/writer/spirv/builder_call_test.cc
+++ b/src/tint/writer/spirv/builder_call_test.cc
@@ -36,8 +36,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(a_func)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(a_func)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpBuilder(b), R"(OpName %3 "a_func"
 OpName %4 "a"
@@ -76,8 +76,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(a_func)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(a_func)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpBuilder(b), R"(OpName %3 "a_func"
 OpName %4 "a"
diff --git a/src/tint/writer/spirv/builder_const_assert_test.cc b/src/tint/writer/spirv/builder_const_assert_test.cc
index e6c9f98..0644c28 100644
--- a/src/tint/writer/spirv/builder_const_assert_test.cc
+++ b/src/tint/writer/spirv/builder_const_assert_test.cc
@@ -27,7 +27,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     // const asserts are not emitted
     EXPECT_EQ(DumpInstructions(b.Module().Types()), "");
@@ -39,7 +39,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     // const asserts are not emitted
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
diff --git a/src/tint/writer/spirv/builder_constructor_expression_test.cc b/src/tint/writer/spirv/builder_constructor_expression_test.cc
index d539820..7416bc2 100644
--- a/src/tint/writer/spirv/builder_constructor_expression_test.cc
+++ b/src/tint/writer/spirv/builder_constructor_expression_test.cc
@@ -29,7 +29,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateConstructorExpression(g, c), 2u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeFloat 32
 %2 = OpConstant %1 42.2000008
@@ -43,7 +43,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateConstructorExpression(nullptr, t), 5u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeVector %2 3
@@ -62,7 +62,7 @@
     b.PushFunctionForTesting();
 
     EXPECT_EQ(b.GenerateExpression(t), 4u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeVector %2 2
@@ -100,10 +100,10 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.Diagnostics();
 
     EXPECT_EQ(b.GenerateExpression(t), 8u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeFloat 32
 %2 = OpTypePointer Function %3
@@ -129,8 +129,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
-    ASSERT_EQ(b.GenerateExpression(cast), 10u) << b.error();
+    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.Diagnostics();
+    ASSERT_EQ(b.GenerateExpression(cast), 10u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeVector %2 3
@@ -159,7 +159,7 @@
     b.PushFunctionForTesting();
 
     EXPECT_EQ(b.GenerateExpression(cast), 2u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeBool
 %2 = OpConstantTrue %1
@@ -254,8 +254,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
-    ASSERT_EQ(b.GenerateExpression(cast), 8u) << b.error();
+    ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.Diagnostics();
+    ASSERT_EQ(b.GenerateExpression(cast), 8u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeBool
 %2 = OpConstantTrue %1
@@ -3709,7 +3709,7 @@
     b.PushFunctionForTesting();
 
     EXPECT_EQ(b.GenerateExpression(t), 6u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
 %3 = OpTypeVector %2 3
@@ -3730,7 +3730,7 @@
     b.PushFunctionForTesting();
 
     EXPECT_EQ(b.GenerateExpression(t), 2u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeFloat 32
 %2 = OpConstantNull %1
@@ -3749,7 +3749,7 @@
     b.PushFunctionForTesting();
 
     EXPECT_EQ(b.GenerateExpression(t), 2u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeFloat 16
 %2 = OpConstantNull %1
@@ -3766,7 +3766,7 @@
     b.PushFunctionForTesting();
 
     EXPECT_EQ(b.GenerateExpression(t), 2u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeInt 32 1
 %2 = OpConstantNull %1
@@ -3783,7 +3783,7 @@
     b.PushFunctionForTesting();
 
     EXPECT_EQ(b.GenerateExpression(t), 2u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeInt 32 0
 %2 = OpConstantNull %1
@@ -3800,7 +3800,7 @@
     b.PushFunctionForTesting();
 
     EXPECT_EQ(b.GenerateExpression(t), 2u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeBool
 %2 = OpConstantNull %1
@@ -3817,7 +3817,7 @@
     b.PushFunctionForTesting();
 
     EXPECT_EQ(b.GenerateExpression(t), 3u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeInt 32 1
 %1 = OpTypeVector %2 2
@@ -3835,7 +3835,7 @@
     b.PushFunctionForTesting();
 
     EXPECT_EQ(b.GenerateExpression(t), 4u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeFloat 32
 %2 = OpTypeVector %3 2
@@ -3856,7 +3856,7 @@
     b.PushFunctionForTesting();
 
     EXPECT_EQ(b.GenerateExpression(t), 4u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeFloat 16
 %2 = OpTypeVector %3 2
@@ -3875,7 +3875,7 @@
     b.PushFunctionForTesting();
 
     EXPECT_EQ(b.GenerateExpression(t), 5u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeInt 32 1
 %3 = OpTypeInt 32 0
@@ -3895,7 +3895,7 @@
     b.PushFunctionForTesting();
 
     EXPECT_EQ(b.GenerateExpression(t), 3u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeStruct %2
@@ -3911,8 +3911,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateStatement(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    EXPECT_TRUE(b.GenerateStatement(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeInt 32 0
 %2 = OpConstant %1 2
@@ -3935,8 +3935,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateStatement(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    EXPECT_TRUE(b.GenerateStatement(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeFloat 32
 %2 = OpConstant %1 2.4000001
@@ -3961,8 +3961,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateStatement(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    EXPECT_TRUE(b.GenerateStatement(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeFloat 16
 %2 = OpConstant %1 0x1.33p+1
@@ -3985,8 +3985,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateStatement(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    EXPECT_TRUE(b.GenerateStatement(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeInt 32 1
 %2 = OpConstant %1 2
@@ -4009,8 +4009,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateStatement(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    EXPECT_TRUE(b.GenerateStatement(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeFloat 32
 %2 = OpConstant %1 2.4000001
@@ -4035,8 +4035,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateStatement(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    EXPECT_TRUE(b.GenerateStatement(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeFloat 16
 %2 = OpConstant %1 0x1.33p+1
@@ -4059,8 +4059,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateStatement(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    EXPECT_TRUE(b.GenerateStatement(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeInt 32 1
 %2 = OpConstant %1 2
@@ -4083,8 +4083,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateStatement(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    EXPECT_TRUE(b.GenerateStatement(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeInt 32 0
 %2 = OpConstant %1 2
@@ -4109,8 +4109,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateStatement(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    EXPECT_TRUE(b.GenerateStatement(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeFloat 16
 %2 = OpConstant %1 0x1p+1
@@ -4135,8 +4135,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateStatement(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    EXPECT_TRUE(b.GenerateStatement(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeInt 32 1
 %2 = OpConstant %1 2
@@ -4161,8 +4161,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateStatement(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    EXPECT_TRUE(b.GenerateStatement(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeInt 32 0
 %2 = OpConstant %1 2
@@ -4187,8 +4187,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateStatement(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    EXPECT_TRUE(b.GenerateStatement(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeFloat 32
 %2 = OpConstant %1 2
@@ -4212,8 +4212,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeInt 32 0
 %3 = OpTypeVector %4 3
@@ -4238,8 +4238,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeFloat 32
 %3 = OpTypeVector %4 3
@@ -4266,8 +4266,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeFloat 16
 %3 = OpTypeVector %4 3
@@ -4292,8 +4292,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeInt 32 1
 %3 = OpTypeVector %4 3
@@ -4318,8 +4318,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeFloat 32
 %3 = OpTypeVector %4 3
@@ -4346,8 +4346,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeFloat 16
 %3 = OpTypeVector %4 3
@@ -4372,8 +4372,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeInt 32 1
 %3 = OpTypeVector %4 3
@@ -4398,8 +4398,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeInt 32 0
 %3 = OpTypeVector %4 3
@@ -4426,8 +4426,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeFloat 16
 %3 = OpTypeVector %4 3
@@ -4454,8 +4454,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeInt 32 1
 %3 = OpTypeVector %4 3
@@ -4482,8 +4482,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeInt 32 0
 %3 = OpTypeVector %4 3
@@ -4510,8 +4510,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateExpression(cast), 6u) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeFloat 32
 %3 = OpTypeVector %4 3
diff --git a/src/tint/writer/spirv/builder_discard_test.cc b/src/tint/writer/spirv/builder_discard_test.cc
index a268d95..f5c2f8a 100644
--- a/src/tint/writer/spirv/builder_discard_test.cc
+++ b/src/tint/writer/spirv/builder_discard_test.cc
@@ -29,7 +29,7 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateStatement(stmt)) << b.error();
+    EXPECT_TRUE(b.GenerateStatement(stmt)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.CurrentFunction().instructions()), R"(OpKill
 )");
 }
diff --git a/src/tint/writer/spirv/builder_entry_point_test.cc b/src/tint/writer/spirv/builder_entry_point_test.cc
index 406b3db..0e057a3 100644
--- a/src/tint/writer/spirv/builder_entry_point_test.cc
+++ b/src/tint/writer/spirv/builder_entry_point_test.cc
@@ -233,7 +233,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpBuilder(b), R"(OpCapability Shader
 OpMemoryModel Logical GLSL450
@@ -330,7 +330,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     // Make sure we generate the SampleRateShading capability.
     EXPECT_EQ(DumpInstructions(b.Module().Capabilities()),
diff --git a/src/tint/writer/spirv/builder_function_attribute_test.cc b/src/tint/writer/spirv/builder_function_attribute_test.cc
index f4de7f5..c215f21 100644
--- a/src/tint/writer/spirv/builder_function_attribute_test.cc
+++ b/src/tint/writer/spirv/builder_function_attribute_test.cc
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "gmock/gmock.h"
 #include "src/tint/ast/stage_attribute.h"
 #include "src/tint/ast/workgroup_attribute.h"
 #include "src/tint/writer/spirv/spv_dump.h"
@@ -32,7 +33,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().EntryPoints()),
               R"(OpEntryPoint Fragment %3 "main"
 )");
@@ -72,9 +73,9 @@
     spirv::Builder& b = Build();
 
     if (var) {
-        ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
+        ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
     }
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     auto preamble = b.Module().EntryPoints();
     ASSERT_GE(preamble.size(), 1u);
@@ -98,7 +99,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateExecutionModes(func, 3)) << b.error();
+    ASSERT_TRUE(b.GenerateExecutionModes(func, 3)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().ExecutionModes()),
               R"(OpExecutionMode %3 OriginUpperLeft
 )");
@@ -110,7 +111,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateExecutionModes(func, 3)) << b.error();
+    ASSERT_TRUE(b.GenerateExecutionModes(func, 3)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().ExecutionModes()),
               R"(OpExecutionMode %3 LocalSize 1 1 1
 )");
@@ -125,7 +126,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateExecutionModes(func, 3)) << b.error();
+    ASSERT_TRUE(b.GenerateExecutionModes(func, 3)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().ExecutionModes()),
               R"(OpExecutionMode %3 LocalSize 2 4 6
 )");
@@ -143,7 +144,7 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateExecutionModes(func, 3)) << b.error();
+    ASSERT_TRUE(b.GenerateExecutionModes(func, 3)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().ExecutionModes()),
               R"(OpExecutionMode %3 LocalSize 2 3 4
 )");
@@ -161,10 +162,13 @@
 
     spirv::Builder& b = Build();
 
-    EXPECT_FALSE(b.GenerateExecutionModes(func, 3)) << b.error();
-    EXPECT_EQ(
-        b.error(),
-        R"(override-expressions should have been removed with the SubstituteOverride transform)");
+    tint::SetInternalCompilerErrorReporter(nullptr);
+
+    EXPECT_FALSE(b.GenerateExecutionModes(func, 3)) << b.Diagnostics();
+    EXPECT_THAT(
+        b.Diagnostics().str(),
+        ::testing::HasSubstr(
+            "override-expressions should have been removed with the SubstituteOverride transform"));
 }
 
 TEST_F(BuilderTest, Decoration_ExecutionMode_WorkgroupSize_LiteralAndConst) {
@@ -178,10 +182,13 @@
 
     spirv::Builder& b = Build();
 
-    EXPECT_FALSE(b.GenerateExecutionModes(func, 3)) << b.error();
-    EXPECT_EQ(
-        b.error(),
-        R"(override-expressions should have been removed with the SubstituteOverride transform)");
+    tint::SetInternalCompilerErrorReporter(nullptr);
+
+    EXPECT_FALSE(b.GenerateExecutionModes(func, 3)) << b.Diagnostics();
+    EXPECT_THAT(
+        b.Diagnostics().str(),
+        ::testing::HasSubstr(
+            "override-expressions should have been removed with the SubstituteOverride transform"));
 }
 
 TEST_F(BuilderTest, Decoration_ExecutionMode_MultipleFragment) {
@@ -197,8 +204,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateFunction(func1)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func2)) << b.error();
+    ASSERT_TRUE(b.GenerateFunction(func1)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func2)) << b.Diagnostics();
     EXPECT_EQ(DumpBuilder(b),
               R"(OpEntryPoint Fragment %3 "main1"
 OpEntryPoint Fragment %5 "main2"
diff --git a/src/tint/writer/spirv/builder_function_test.cc b/src/tint/writer/spirv/builder_function_test.cc
index 1cab162..04b5a84 100644
--- a/src/tint/writer/spirv/builder_function_test.cc
+++ b/src/tint/writer/spirv/builder_function_test.cc
@@ -70,8 +70,8 @@
     auto* var_a = program->AST().GlobalVariables()[0];
     auto* func = program->AST().Functions()[0];
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var_a)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var_a)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
     EXPECT_EQ(DumpBuilder(b), R"(OpName %1 "a"
 OpName %6 "a_func"
 %3 = OpTypeFloat 32
diff --git a/src/tint/writer/spirv/builder_function_variable_test.cc b/src/tint/writer/spirv/builder_function_variable_test.cc
index 354ad66..9f77d4e 100644
--- a/src/tint/writer/spirv/builder_function_variable_test.cc
+++ b/src/tint/writer/spirv/builder_function_variable_test.cc
@@ -29,7 +29,7 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.error();
+    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Debug()), R"(OpName %1 "var"
 )");
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeFloat 32
@@ -51,8 +51,8 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Debug()), R"(OpName %6 "var"
 )");
@@ -82,9 +82,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateFunctionVariable(a)) << b.error();
-    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateFunctionVariable(a)) << b.Diagnostics();
+    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Debug()), R"(OpName %7 "var"
 )");
@@ -117,9 +117,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.error();
-    EXPECT_TRUE(b.GenerateFunctionVariable(v2)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.Diagnostics();
+    EXPECT_TRUE(b.GenerateFunctionVariable(v2)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Debug()), R"(OpName %3 "v"
 OpName %7 "v2"
@@ -152,9 +152,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.error();
-    EXPECT_TRUE(b.GenerateFunctionVariable(v2)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.Diagnostics();
+    EXPECT_TRUE(b.GenerateFunctionVariable(v2)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Debug()), R"(OpName %3 "v"
 OpName %7 "v2"
@@ -187,9 +187,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.error();
-    EXPECT_TRUE(b.GenerateFunctionVariable(v2)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.Diagnostics();
+    EXPECT_TRUE(b.GenerateFunctionVariable(v2)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Debug()), R"(OpName %3 "v2"
 )");
@@ -215,8 +215,8 @@
 
     spirv::Builder& b = Build();
 
-    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeVector %2 3
@@ -235,8 +235,8 @@
 
     spirv::Builder& b = Build();
 
-    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), "");  // Not a mistake - 'const' is inlined
 }
diff --git a/src/tint/writer/spirv/builder_global_variable_test.cc b/src/tint/writer/spirv/builder_global_variable_test.cc
index 27c2402..671bacc 100644
--- a/src/tint/writer/spirv/builder_global_variable_test.cc
+++ b/src/tint/writer/spirv/builder_global_variable_test.cc
@@ -30,7 +30,7 @@
 
     spirv::Builder& b = Build();
 
-    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
+    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Debug()), R"(OpName %1 "var"
 )");
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeFloat 32
@@ -47,8 +47,8 @@
 
     spirv::Builder& b = Build();
 
-    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Debug()), R"(OpName %6 "var"
 )");
@@ -71,7 +71,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeInt 32 1
 %2 = OpConstant %1 42
@@ -96,7 +96,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeVector %2 3
@@ -126,7 +126,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 16
 %1 = OpTypeVector %2 3
@@ -155,7 +155,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeInt 32 1
 %1 = OpTypeVector %2 3
@@ -184,7 +184,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeVector %2 3
@@ -213,7 +213,7 @@
 
     spirv::Builder& b = SanitizeAndBuild();
 
-    ASSERT_TRUE(b.Build()) << b.error();
+    ASSERT_TRUE(b.Build()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeVector %2 3
@@ -238,7 +238,7 @@
 
     spirv::Builder& b = Build();
 
-    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
+    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Debug()), R"(OpName %1 "var"
 )");
     EXPECT_EQ(DumpInstructions(b.Module().Annots()), R"(OpDecorate %1 Binding 2
@@ -486,7 +486,7 @@
 
     spirv::Builder& b = Build();
 
-    EXPECT_TRUE(b.GenerateGlobalVariable(var_a)) << b.error();
+    EXPECT_TRUE(b.GenerateGlobalVariable(var_a)) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Annots()), R"(OpDecorate %1 NonReadable
 OpDecorate %1 Binding 0
@@ -518,10 +518,10 @@
     std::unique_ptr<spirv::Builder> b =
         std::make_unique<spirv::Builder>(program.get(), kZeroInitializeWorkgroupMemory);
 
-    EXPECT_TRUE(b->GenerateGlobalVariable(var_scalar)) << b->error();
-    EXPECT_TRUE(b->GenerateGlobalVariable(var_array)) << b->error();
-    EXPECT_TRUE(b->GenerateGlobalVariable(var_struct)) << b->error();
-    ASSERT_FALSE(b->has_error()) << b->error();
+    EXPECT_TRUE(b->GenerateGlobalVariable(var_scalar)) << b->Diagnostics();
+    EXPECT_TRUE(b->GenerateGlobalVariable(var_array)) << b->Diagnostics();
+    EXPECT_TRUE(b->GenerateGlobalVariable(var_struct)) << b->Diagnostics();
+    ASSERT_FALSE(b->has_error()) << b->Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b->Module().Types()), R"(%3 = OpTypeInt 32 1
 %2 = OpTypePointer Workgroup %3
diff --git a/src/tint/writer/spirv/builder_ident_expression_test.cc b/src/tint/writer/spirv/builder_ident_expression_test.cc
index 110619e..3917028 100644
--- a/src/tint/writer/spirv/builder_ident_expression_test.cc
+++ b/src/tint/writer/spirv/builder_ident_expression_test.cc
@@ -32,8 +32,8 @@
 
     spirv::Builder& b = Build();
 
-    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"()");
 
@@ -49,7 +49,7 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
+    EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Debug()), R"(OpName %1 "var"
 )");
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeFloat 32
@@ -71,8 +71,8 @@
 
     spirv::Builder& b = Build();
 
-    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeVector %2 3
@@ -92,7 +92,7 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.error();
+    EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Debug()), R"(OpName %1 "var"
 )");
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeFloat 32
@@ -116,9 +116,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr->As<ast::BinaryExpression>()), 7u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr->As<ast::BinaryExpression>()), 7u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeInt 32 1
 %2 = OpTypePointer Private %3
 %4 = OpConstantNull %3
@@ -139,9 +139,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateFunctionVariable(let)) << b.error();
+    ASSERT_TRUE(b.GenerateFunctionVariable(let)) << b.Diagnostics();
 
-    EXPECT_EQ(b.GenerateBinaryExpression(expr->As<ast::BinaryExpression>()), 3u) << b.error();
+    EXPECT_EQ(b.GenerateBinaryExpression(expr->As<ast::BinaryExpression>()), 3u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeInt 32 1
 %2 = OpConstant %1 2
 )");
diff --git a/src/tint/writer/spirv/builder_if_test.cc b/src/tint/writer/spirv/builder_if_test.cc
index 52ef0b6..3bd4bb2 100644
--- a/src/tint/writer/spirv/builder_if_test.cc
+++ b/src/tint/writer/spirv/builder_if_test.cc
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "gmock/gmock.h"
 #include "src/tint/writer/spirv/spv_dump.h"
 #include "src/tint/writer/spirv/test_helper.h"
 
@@ -32,7 +33,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_TRUE(b.GenerateIfStatement(expr)) << b.error();
+    EXPECT_TRUE(b.GenerateIfStatement(expr)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeBool
 %2 = OpConstantTrue %1
 )");
@@ -56,11 +57,13 @@
 
     spirv::Builder& b = Build();
 
-    EXPECT_FALSE(b.GenerateIfStatement(expr)) << b.error();
+    tint::SetInternalCompilerErrorReporter(nullptr);
+
+    EXPECT_FALSE(b.GenerateIfStatement(expr)) << b.Diagnostics();
     EXPECT_TRUE(b.has_error());
-    EXPECT_EQ(b.error(),
-              "Internal error: trying to add SPIR-V instruction 247 outside a "
-              "function");
+    EXPECT_THAT(b.Diagnostics().str(),
+                ::testing::HasSubstr(
+                    "Internal error: trying to add SPIR-V instruction 247 outside a function"));
 }
 
 TEST_F(BuilderTest, If_WithStatements) {
@@ -76,9 +79,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
 
-    EXPECT_TRUE(b.GenerateIfStatement(expr)) << b.error();
+    EXPECT_TRUE(b.GenerateIfStatement(expr)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeInt 32 1
 %2 = OpTypePointer Private %3
 %4 = OpConstantNull %3
@@ -114,9 +117,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
 
-    EXPECT_TRUE(b.GenerateIfStatement(expr)) << b.error();
+    EXPECT_TRUE(b.GenerateIfStatement(expr)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeInt 32 1
 %2 = OpTypePointer Private %3
 %4 = OpConstantNull %3
@@ -156,9 +159,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
 
-    EXPECT_TRUE(b.GenerateIfStatement(expr)) << b.error();
+    EXPECT_TRUE(b.GenerateIfStatement(expr)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeInt 32 1
 %2 = OpTypePointer Private %3
 %4 = OpConstantNull %3
@@ -212,9 +215,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
 
-    EXPECT_TRUE(b.GenerateIfStatement(expr)) << b.error();
+    EXPECT_TRUE(b.GenerateIfStatement(expr)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeInt 32 1
 %2 = OpTypePointer Private %3
 %4 = OpConstantNull %3
@@ -276,7 +279,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_TRUE(b.GenerateLoopStatement(expr)) << b.error();
+    EXPECT_TRUE(b.GenerateLoopStatement(expr)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%5 = OpTypeBool
 %6 = OpConstantTrue %5
 )");
@@ -318,7 +321,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_TRUE(b.GenerateLoopStatement(expr)) << b.error();
+    EXPECT_TRUE(b.GenerateLoopStatement(expr)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%5 = OpTypeBool
 %6 = OpConstantTrue %5
 )");
@@ -360,7 +363,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_TRUE(b.GenerateLoopStatement(expr)) << b.error();
+    EXPECT_TRUE(b.GenerateLoopStatement(expr)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%5 = OpTypeBool
 %6 = OpConstantTrue %5
 )");
@@ -405,7 +408,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_TRUE(b.GenerateLoopStatement(expr)) << b.error();
+    EXPECT_TRUE(b.GenerateLoopStatement(expr)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%5 = OpTypeBool
 %6 = OpConstantTrue %5
 )");
@@ -441,7 +444,7 @@
 
     spirv::Builder& b = Build();
 
-    EXPECT_TRUE(b.GenerateFunction(fn)) << b.error();
+    EXPECT_TRUE(b.GenerateFunction(fn)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
 %5 = OpTypeBool
@@ -471,7 +474,7 @@
 
     spirv::Builder& b = Build();
 
-    EXPECT_TRUE(b.GenerateFunction(fn)) << b.error();
+    EXPECT_TRUE(b.GenerateFunction(fn)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeBool
 %1 = OpTypeFunction %2
 %5 = OpConstantTrue %2
@@ -503,7 +506,7 @@
 
     spirv::Builder& b = Build();
 
-    EXPECT_TRUE(b.GenerateFunction(fn)) << b.error();
+    EXPECT_TRUE(b.GenerateFunction(fn)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeBool
 %1 = OpTypeFunction %2
 %5 = OpConstantTrue %2
@@ -541,7 +544,7 @@
 
     spirv::Builder& b = Build();
 
-    EXPECT_TRUE(b.GenerateFunction(fn)) << b.error();
+    EXPECT_TRUE(b.GenerateFunction(fn)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeBool
 %1 = OpTypeFunction %2
 %5 = OpConstantTrue %2
@@ -570,8 +573,8 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
-    EXPECT_TRUE(b.GenerateFunction(fn)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
+    EXPECT_TRUE(b.GenerateFunction(fn)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeBool
 %2 = OpTypePointer Private %3
 %4 = OpConstantNull %3
@@ -602,7 +605,7 @@
 
     spirv::Builder& b = Build();
 
-    EXPECT_TRUE(b.GenerateFunction(fn)) << b.error();
+    EXPECT_TRUE(b.GenerateFunction(fn)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
 %5 = OpTypeBool
@@ -643,7 +646,7 @@
 
     spirv::Builder& b = Build();
 
-    EXPECT_TRUE(b.GenerateFunction(fn)) << b.error();
+    EXPECT_TRUE(b.GenerateFunction(fn)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeVoid
 %1 = OpTypeFunction %2
 %9 = OpTypeBool
diff --git a/src/tint/writer/spirv/builder_literal_test.cc b/src/tint/writer/spirv/builder_literal_test.cc
index eea1d8c..0bfc7b3 100644
--- a/src/tint/writer/spirv/builder_literal_test.cc
+++ b/src/tint/writer/spirv/builder_literal_test.cc
@@ -28,7 +28,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateLiteralIfNeeded(b_true);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(2u, id);
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeBool
@@ -43,7 +43,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateLiteralIfNeeded(b_false);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(2u, id);
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeBool
@@ -59,11 +59,11 @@
     spirv::Builder& b = Build();
 
     ASSERT_NE(b.GenerateLiteralIfNeeded(b_true), 0u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     ASSERT_NE(b.GenerateLiteralIfNeeded(b_false), 0u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     ASSERT_NE(b.GenerateLiteralIfNeeded(b_true), 0u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeBool
 %2 = OpConstantTrue %1
@@ -77,7 +77,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateLiteralIfNeeded(i);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(2u, id);
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeInt 32 1
@@ -94,7 +94,7 @@
 
     ASSERT_NE(b.GenerateLiteralIfNeeded(i1), 0u);
     ASSERT_NE(b.GenerateLiteralIfNeeded(i2), 0u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeInt 32 1
 %2 = OpConstant %1 -23
@@ -108,7 +108,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateLiteralIfNeeded(i);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(2u, id);
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeInt 32 0
@@ -125,7 +125,7 @@
 
     ASSERT_NE(b.GenerateLiteralIfNeeded(i1), 0u);
     ASSERT_NE(b.GenerateLiteralIfNeeded(i2), 0u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeInt 32 0
 %2 = OpConstant %1 23
@@ -139,7 +139,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateLiteralIfNeeded(i);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(2u, id);
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeFloat 32
@@ -156,7 +156,7 @@
 
     ASSERT_NE(b.GenerateLiteralIfNeeded(i1), 0u);
     ASSERT_NE(b.GenerateLiteralIfNeeded(i2), 0u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeFloat 32
 %2 = OpConstant %1 23.2450008
@@ -172,7 +172,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateLiteralIfNeeded(i);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(2u, id);
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeFloat 16
@@ -191,7 +191,7 @@
 
     ASSERT_NE(b.GenerateLiteralIfNeeded(i1), 0u);
     ASSERT_NE(b.GenerateLiteralIfNeeded(i2), 0u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%1 = OpTypeFloat 16
 %2 = OpConstant %1 0x1.73cp+4
diff --git a/src/tint/writer/spirv/builder_loop_test.cc b/src/tint/writer/spirv/builder_loop_test.cc
index addb283..380b2b2 100644
--- a/src/tint/writer/spirv/builder_loop_test.cc
+++ b/src/tint/writer/spirv/builder_loop_test.cc
@@ -34,7 +34,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_TRUE(b.GenerateLoopStatement(loop)) << b.error();
+    EXPECT_TRUE(b.GenerateLoopStatement(loop)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.CurrentFunction().instructions()),
               R"(OpBranch %1
 %1 = OpLabel
@@ -64,9 +64,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
 
-    EXPECT_TRUE(b.GenerateLoopStatement(loop)) << b.error();
+    EXPECT_TRUE(b.GenerateLoopStatement(loop)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeInt 32 1
 %2 = OpTypePointer Private %3
 %4 = OpConstantNull %3
@@ -107,9 +107,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.Diagnostics();
 
-    EXPECT_TRUE(b.GenerateLoopStatement(loop)) << b.error();
+    EXPECT_TRUE(b.GenerateLoopStatement(loop)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeInt 32 1
 %2 = OpTypePointer Private %3
 %4 = OpConstantNull %3
@@ -151,7 +151,7 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateLoopStatement(loop)) << b.error();
+    EXPECT_TRUE(b.GenerateLoopStatement(loop)) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%7 = OpTypeInt 32 1
 %6 = OpTypePointer Function %7
@@ -186,7 +186,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_TRUE(b.GenerateLoopStatement(loop)) << b.error();
+    EXPECT_TRUE(b.GenerateLoopStatement(loop)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.CurrentFunction().instructions()),
               R"(OpBranch %1
 %1 = OpLabel
@@ -217,7 +217,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_TRUE(b.GenerateLoopStatement(loop)) << b.error();
+    EXPECT_TRUE(b.GenerateLoopStatement(loop)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.CurrentFunction().instructions()),
               R"(OpBranch %1
 %1 = OpLabel
@@ -246,7 +246,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_TRUE(b.GenerateLoopStatement(loop)) << b.error();
+    EXPECT_TRUE(b.GenerateLoopStatement(loop)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%5 = OpTypeBool
 %6 = OpConstantTrue %5
 )");
@@ -277,7 +277,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_TRUE(b.GenerateLoopStatement(loop)) << b.error();
+    EXPECT_TRUE(b.GenerateLoopStatement(loop)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%5 = OpTypeBool
 %6 = OpConstantNull %5
 )");
@@ -311,7 +311,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_TRUE(b.GenerateLoopStatement(loop)) << b.error();
+    EXPECT_TRUE(b.GenerateLoopStatement(loop)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%5 = OpTypeBool
 %6 = OpConstantTrue %5
 %8 = OpTypePointer Function %5
@@ -357,7 +357,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_TRUE(b.GenerateLoopStatement(outer_loop)) << b.error();
+    EXPECT_TRUE(b.GenerateLoopStatement(outer_loop)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%9 = OpTypeBool
 %10 = OpConstantTrue %9
 )");
diff --git a/src/tint/writer/spirv/builder_return_test.cc b/src/tint/writer/spirv/builder_return_test.cc
index 897211c..13a65d6 100644
--- a/src/tint/writer/spirv/builder_return_test.cc
+++ b/src/tint/writer/spirv/builder_return_test.cc
@@ -30,7 +30,7 @@
 
     b.PushFunctionForTesting();
     EXPECT_TRUE(b.GenerateReturnStatement(ret));
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.CurrentFunction().instructions()), R"(OpReturn
 )");
@@ -46,7 +46,7 @@
 
     b.PushFunctionForTesting();
     EXPECT_TRUE(b.GenerateReturnStatement(ret));
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeVector %2 3
@@ -68,9 +68,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
-    EXPECT_TRUE(b.GenerateReturnStatement(ret)) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateFunctionVariable(var)) << b.Diagnostics();
+    EXPECT_TRUE(b.GenerateReturnStatement(ret)) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%3 = OpTypeFloat 32
 %2 = OpTypePointer Function %3
diff --git a/src/tint/writer/spirv/builder_switch_test.cc b/src/tint/writer/spirv/builder_switch_test.cc
index e950c41..a66ecd8 100644
--- a/src/tint/writer/spirv/builder_switch_test.cc
+++ b/src/tint/writer/spirv/builder_switch_test.cc
@@ -34,7 +34,7 @@
 
     b.PushFunctionForTesting();
 
-    EXPECT_TRUE(b.GenerateSwitchStatement(expr)) << b.error();
+    EXPECT_TRUE(b.GenerateSwitchStatement(expr)) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeInt 32 1
 %3 = OpConstant %2 1
 )");
@@ -69,9 +69,9 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
-    ASSERT_TRUE(b.GenerateGlobalVariable(a)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(v)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateGlobalVariable(a)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpBuilder(b), R"(OpName %1 "v"
 OpName %5 "a"
@@ -126,9 +126,9 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
-    ASSERT_TRUE(b.GenerateGlobalVariable(a)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(v)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateGlobalVariable(a)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpBuilder(b), R"(OpName %1 "v"
 OpName %5 "a"
@@ -181,9 +181,9 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
-    ASSERT_TRUE(b.GenerateGlobalVariable(a)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(v)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateGlobalVariable(a)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpBuilder(b), R"(OpName %1 "v"
 OpName %5 "a"
@@ -235,9 +235,9 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
-    ASSERT_TRUE(b.GenerateGlobalVariable(a)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(v)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateGlobalVariable(a)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpBuilder(b), R"(OpName %1 "v"
 OpName %5 "a"
@@ -294,9 +294,9 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
-    ASSERT_TRUE(b.GenerateGlobalVariable(a)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(v)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateGlobalVariable(a)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpBuilder(b), R"(OpName %1 "v"
 OpName %5 "a"
@@ -352,9 +352,9 @@
 
     spirv::Builder& b = Build();
 
-    ASSERT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
-    ASSERT_TRUE(b.GenerateGlobalVariable(a)) << b.error();
-    ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
+    ASSERT_TRUE(b.GenerateGlobalVariable(v)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateGlobalVariable(a)) << b.Diagnostics();
+    ASSERT_TRUE(b.GenerateFunction(func)) << b.Diagnostics();
 
     EXPECT_EQ(DumpBuilder(b), R"(OpName %1 "v"
 OpName %5 "a"
@@ -413,7 +413,7 @@
 
     spirv::Builder& b = Build();
 
-    EXPECT_TRUE(b.GenerateFunction(fn)) << b.error();
+    EXPECT_TRUE(b.GenerateFunction(fn)) << b.Diagnostics();
     EXPECT_EQ(DumpBuilder(b), R"(OpName %3 "f"
 %2 = OpTypeInt 32 1
 %1 = OpTypeFunction %2
diff --git a/src/tint/writer/spirv/builder_type_test.cc b/src/tint/writer/spirv/builder_type_test.cc
index 1edb4a8..87c4cf3 100644
--- a/src/tint/writer/spirv/builder_type_test.cc
+++ b/src/tint/writer/spirv/builder_type_test.cc
@@ -36,7 +36,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateTypeIfNeeded(program->TypeOf(type));
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(1u, id);
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeInt 32 1
@@ -55,7 +55,7 @@
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(program->TypeOf(type)), 1u);
     EXPECT_EQ(b.GenerateTypeIfNeeded(program->TypeOf(type)), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeInt 32 1
 %1 = OpTypeRuntimeArray %2
@@ -69,7 +69,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateTypeIfNeeded(program->TypeOf(type));
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(1u, id);
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeInt 32 1
@@ -86,7 +86,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateTypeIfNeeded(program->TypeOf(ty));
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(1u, id);
 
     EXPECT_EQ(DumpInstructions(b.Module().Annots()), R"(OpDecorate %1 ArrayStride 16
@@ -107,7 +107,7 @@
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(program->TypeOf(ty)), 1u);
     EXPECT_EQ(b.GenerateTypeIfNeeded(program->TypeOf(ty)), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeInt 32 1
 %3 = OpTypeInt 32 0
@@ -122,7 +122,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateTypeIfNeeded(bool_);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(id, 1u);
 
     ASSERT_EQ(b.Module().Types().size(), 1u);
@@ -137,11 +137,11 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(bool_), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(b.GenerateTypeIfNeeded(i32), 2u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(b.GenerateTypeIfNeeded(bool_), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 }
 
 TEST_F(BuilderTest_Type, GenerateF32) {
@@ -150,7 +150,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateTypeIfNeeded(f32);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(id, 1u);
 
     ASSERT_EQ(b.Module().Types().size(), 1u);
@@ -165,11 +165,11 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(f32), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(b.GenerateTypeIfNeeded(i32), 2u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(b.GenerateTypeIfNeeded(f32), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 }
 
 TEST_F(BuilderTest_Type, GenerateF16) {
@@ -178,7 +178,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateTypeIfNeeded(f16);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(id, 1u);
 
     ASSERT_EQ(b.Module().Types().size(), 1u);
@@ -193,11 +193,11 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(f16), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(b.GenerateTypeIfNeeded(i32), 2u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(b.GenerateTypeIfNeeded(f16), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 }
 
 TEST_F(BuilderTest_Type, GenerateI32) {
@@ -206,7 +206,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateTypeIfNeeded(i32);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(id, 1u);
 
     ASSERT_EQ(b.Module().Types().size(), 1u);
@@ -221,11 +221,11 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(i32), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(b.GenerateTypeIfNeeded(f32), 2u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(b.GenerateTypeIfNeeded(i32), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 }
 
 TEST_F(BuilderTest_Type, GenerateMatrix) {
@@ -236,7 +236,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateTypeIfNeeded(mat2x3);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(id, 1u);
 
     EXPECT_EQ(b.Module().Types().size(), 3u);
@@ -254,11 +254,11 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(mat), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(b.GenerateTypeIfNeeded(i32), 3u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(b.GenerateTypeIfNeeded(mat), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 }
 
 TEST_F(BuilderTest_Type, GenerateF16Matrix) {
@@ -269,7 +269,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateTypeIfNeeded(mat2x3);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(id, 1u);
 
     EXPECT_EQ(b.Module().Types().size(), 3u);
@@ -287,11 +287,11 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(mat), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(b.GenerateTypeIfNeeded(f16), 3u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(b.GenerateTypeIfNeeded(mat), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 }
 
 TEST_F(BuilderTest_Type, GeneratePtr) {
@@ -302,7 +302,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateTypeIfNeeded(ptr);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(1u, id);
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeInt 32 1
@@ -329,7 +329,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateTypeIfNeeded(program->TypeOf(s));
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(id, 1u);
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
@@ -355,7 +355,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateTypeIfNeeded(program->TypeOf(s));
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(id, 1u);
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
@@ -391,7 +391,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateTypeIfNeeded(program->TypeOf(s));
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(id, 1u);
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeFloat 32
@@ -462,7 +462,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateTypeIfNeeded(program->TypeOf(s));
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(id, 1u);
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%5 = OpTypeFloat 32
@@ -527,7 +527,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateTypeIfNeeded(u32);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(id, 1u);
 
     ASSERT_EQ(b.Module().Types().size(), 1u);
@@ -542,11 +542,11 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(u32), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(b.GenerateTypeIfNeeded(f32), 2u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(b.GenerateTypeIfNeeded(u32), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 }
 
 TEST_F(BuilderTest_Type, GenerateVector) {
@@ -555,7 +555,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateTypeIfNeeded(vec);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(id, 1u);
 
     EXPECT_EQ(b.Module().Types().size(), 2u);
@@ -571,11 +571,11 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(vec), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(b.GenerateTypeIfNeeded(i32), 2u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(b.GenerateTypeIfNeeded(vec), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 }
 
 TEST_F(BuilderTest_Type, GenerateVoid) {
@@ -584,7 +584,7 @@
     spirv::Builder& b = Build();
 
     auto id = b.GenerateTypeIfNeeded(void_);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(id, 1u);
 
     ASSERT_EQ(b.Module().Types().size(), 1u);
@@ -599,11 +599,11 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(void_), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(b.GenerateTypeIfNeeded(i32), 2u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(b.GenerateTypeIfNeeded(void_), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 }
 
 struct PtrData {
@@ -643,7 +643,7 @@
     spirv::Builder& b = Build();
 
     auto id_two_d = b.GenerateTypeIfNeeded(two_d);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(1u, id_two_d);
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
@@ -657,7 +657,7 @@
     spirv::Builder& b = Build();
 
     auto id_two_d_array = b.GenerateTypeIfNeeded(two_d_array);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(1u, id_two_d_array);
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
@@ -671,7 +671,7 @@
     spirv::Builder& b = Build();
 
     auto id_cube = b.GenerateTypeIfNeeded(cube);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(1u, id_cube);
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
@@ -686,7 +686,7 @@
     spirv::Builder& b = Build();
 
     auto id_cube_array = b.GenerateTypeIfNeeded(cube_array);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(1u, id_cube_array);
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
@@ -704,7 +704,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(1u, b.GenerateTypeIfNeeded(ms));
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeInt 32 1
 %1 = OpTypeImage %2 2D 0 0 1 1 Unknown
 )");
@@ -717,7 +717,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(ms), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%2 = OpTypeInt 32 0
 %1 = OpTypeImage %2 2D 0 0 1 1 Unknown
@@ -731,7 +731,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(ms), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%2 = OpTypeFloat 32
 %1 = OpTypeImage %2 2D 0 0 1 1 Unknown
@@ -744,7 +744,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(s), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%2 = OpTypeInt 32 1
 %1 = OpTypeImage %2 1D 0 0 0 1 Unknown
@@ -762,7 +762,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(s), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%2 = OpTypeInt 32 0
 %1 = OpTypeImage %2 1D 0 0 0 1 Unknown
@@ -780,7 +780,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(s), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%2 = OpTypeFloat 32
 %1 = OpTypeImage %2 1D 0 0 0 1 Unknown
@@ -798,7 +798,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(s), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%2 = OpTypeFloat 32
 %1 = OpTypeImage %2 2D 0 0 0 1 Unknown
@@ -812,7 +812,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(s), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%2 = OpTypeFloat 32
 %1 = OpTypeImage %2 2D 0 1 0 1 Unknown
@@ -826,7 +826,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(s), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%2 = OpTypeFloat 32
 %1 = OpTypeImage %2 3D 0 0 0 1 Unknown
@@ -840,7 +840,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(s), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%2 = OpTypeFloat 32
 %1 = OpTypeImage %2 Cube 0 0 0 1 Unknown
@@ -855,7 +855,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(s), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()),
               R"(%2 = OpTypeFloat 32
 %1 = OpTypeImage %2 Cube 0 1 0 1 Unknown
@@ -874,7 +874,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(program->TypeOf(ty)), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeImage %2 1D 0 0 0 2 R32f
 )");
@@ -889,7 +889,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(program->TypeOf(ty)), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeImage %2 2D 0 0 0 2 R32f
 )");
@@ -904,7 +904,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(program->TypeOf(ty)), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeImage %2 2D 0 1 0 2 R32f
 )");
@@ -919,7 +919,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(program->TypeOf(ty)), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeImage %2 3D 0 0 0 2 R32f
 )");
@@ -934,7 +934,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(program->TypeOf(ty)), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
 %1 = OpTypeImage %2 2D 0 0 0 2 R32f
 )");
@@ -949,7 +949,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(program->TypeOf(ty)), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeInt 32 1
 %1 = OpTypeImage %2 2D 0 0 0 2 R32i
 )");
@@ -964,7 +964,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(program->TypeOf(ty)), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeInt 32 0
 %1 = OpTypeImage %2 2D 0 0 0 2 R32ui
 )");
@@ -976,7 +976,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(sampler), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), "%1 = OpTypeSampler\n");
 }
 
@@ -986,7 +986,7 @@
     spirv::Builder& b = Build();
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(sampler), 1u);
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), "%1 = OpTypeSampler\n");
 }
 
@@ -1000,7 +1000,7 @@
 
     EXPECT_EQ(b.GenerateTypeIfNeeded(sampler), 1u);
 
-    ASSERT_FALSE(b.has_error()) << b.error();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), "%1 = OpTypeSampler\n");
 }
 
diff --git a/src/tint/writer/spirv/builder_unary_op_expression_test.cc b/src/tint/writer/spirv/builder_unary_op_expression_test.cc
index 79de457..3998371 100644
--- a/src/tint/writer/spirv/builder_unary_op_expression_test.cc
+++ b/src/tint/writer/spirv/builder_unary_op_expression_test.cc
@@ -29,7 +29,7 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_EQ(b.GenerateUnaryOpExpression(expr), 1u) << b.error();
+    EXPECT_EQ(b.GenerateUnaryOpExpression(expr), 1u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeInt 32 1
 %3 = OpConstant %2 1
 )");
@@ -45,7 +45,7 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_EQ(b.GenerateUnaryOpExpression(expr), 1u) << b.error();
+    EXPECT_EQ(b.GenerateUnaryOpExpression(expr), 1u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeFloat 32
 %3 = OpConstant %2 1
 )");
@@ -61,7 +61,7 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_EQ(b.GenerateUnaryOpExpression(expr), 1u) << b.error();
+    EXPECT_EQ(b.GenerateUnaryOpExpression(expr), 1u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeInt 32 1
 %3 = OpConstant %2 1
 )");
@@ -77,7 +77,7 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_EQ(b.GenerateUnaryOpExpression(expr), 1u) << b.error();
+    EXPECT_EQ(b.GenerateUnaryOpExpression(expr), 1u) << b.Diagnostics();
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%2 = OpTypeBool
 %3 = OpConstantNull %2
 )");
@@ -95,9 +95,9 @@
     spirv::Builder& b = Build();
 
     b.PushFunctionForTesting();
-    EXPECT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
-    EXPECT_EQ(b.GenerateUnaryOpExpression(expr), 6u) << b.error();
-    ASSERT_FALSE(b.has_error()) << b.error();
+    EXPECT_TRUE(b.GenerateFunctionVariable(var)) << b.Diagnostics();
+    EXPECT_EQ(b.GenerateUnaryOpExpression(expr), 6u) << b.Diagnostics();
+    ASSERT_FALSE(b.has_error()) << b.Diagnostics();
 
     EXPECT_EQ(DumpInstructions(b.Module().Types()), R"(%4 = OpTypeFloat 32
 %3 = OpTypeVector %4 3
diff --git a/src/tint/writer/spirv/generator.cc b/src/tint/writer/spirv/generator.cc
index 93ac6e1..ffebedd 100644
--- a/src/tint/writer/spirv/generator.cc
+++ b/src/tint/writer/spirv/generator.cc
@@ -46,8 +46,8 @@
     auto impl = std::make_unique<GeneratorImpl>(&sanitized_result.program,
                                                 zero_initialize_workgroup_memory);
     result.success = impl->Generate();
-    result.error = impl->error();
-    result.spirv = std::move(impl->result());
+    result.error = impl->Diagnostics().str();
+    result.spirv = std::move(impl->Result());
 
     return result;
 }
diff --git a/src/tint/writer/spirv/generator_impl.cc b/src/tint/writer/spirv/generator_impl.cc
index 6b4a59b..88bd39a 100644
--- a/src/tint/writer/spirv/generator_impl.cc
+++ b/src/tint/writer/spirv/generator_impl.cc
@@ -183,16 +183,4 @@
     return false;
 }
 
-const std::vector<uint32_t>& GeneratorImpl::result() const {
-    return writer_.result();
-}
-
-std::vector<uint32_t>& GeneratorImpl::result() {
-    return writer_.result();
-}
-
-std::string GeneratorImpl::error() const {
-    return builder_.error();
-}
-
 }  // namespace tint::writer::spirv
diff --git a/src/tint/writer/spirv/generator_impl.h b/src/tint/writer/spirv/generator_impl.h
index c83f144..3fd745d 100644
--- a/src/tint/writer/spirv/generator_impl.h
+++ b/src/tint/writer/spirv/generator_impl.h
@@ -49,13 +49,10 @@
     bool Generate();
 
     /// @returns the result data
-    const std::vector<uint32_t>& result() const;
+    const std::vector<uint32_t>& Result() const { return writer_.result(); }
 
-    /// @returns the result data
-    std::vector<uint32_t>& result();
-
-    /// @returns the error
-    std::string error() const;
+    /// @returns the list of diagnostics raised by the generator
+    diag::List Diagnostics() const { return builder_.Diagnostics(); }
 
   private:
     Builder builder_;