[tint] Use StyledText for all diagnostics
And use the styles in the WGSL resolver package to provide coloured
errors.
Change-Id: I4c7c25ef9efcede1da962ac68b688da8319e19ee
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/173140
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/include/tint/tint.h b/include/tint/tint.h
index 492f11b..23d1d3e 100644
--- a/include/tint/tint.h
+++ b/include/tint/tint.h
@@ -51,7 +51,7 @@
#include "src/tint/lang/wgsl/helpers/flatten_bindings.h"
#include "src/tint/lang/wgsl/inspector/inspector.h"
#include "src/tint/utils/diagnostic/formatter.h"
-#include "src/tint/utils/diagnostic/printer.h"
+#include "src/tint/utils/text/styled_text.h"
#if TINT_BUILD_SPV_READER
#include "src/tint/lang/spirv/reader/reader.h"
diff --git a/src/dawn/native/CompilationMessages.cpp b/src/dawn/native/CompilationMessages.cpp
index 8dc0a3b..c3feb40 100644
--- a/src/dawn/native/CompilationMessages.cpp
+++ b/src/dawn/native/CompilationMessages.cpp
@@ -161,7 +161,7 @@
}
AddMessage(
- diagnostic.message,
+ diagnostic.message.Plain(),
{nullptr, nullptr, tintSeverityToMessageType(diagnostic.severity), lineNum, linePosInBytes,
offsetInBytes, lengthInBytes, linePosInUTF16, offsetInUTF16, lengthInUTF16});
@@ -273,7 +273,7 @@
t << warningCount << " warning(s) ";
}
t << "generated while compiling the shader:" << std::endl
- << tint::diag::Formatter{style}.Format(messageList);
+ << tint::diag::Formatter{style}.Format(messageList).Plain();
mFormattedTintMessages.push_back(t.str());
}
diff --git a/src/tint/cmd/common/helper.cc b/src/tint/cmd/common/helper.cc
index 4dd0ea1..c043588 100644
--- a/src/tint/cmd/common/helper.cc
+++ b/src/tint/cmd/common/helper.cc
@@ -46,8 +46,10 @@
#endif
#include "src/tint/utils/diagnostic/formatter.h"
-#include "src/tint/utils/diagnostic/printer.h"
#include "src/tint/utils/text/string.h"
+#include "src/tint/utils/text/styled_text.h"
+#include "src/tint/utils/text/styled_text_printer.h"
+#include "src/tint/utils/text/text_style.h"
#include "src/tint/utils/traits/traits.h"
namespace tint::cmd {
@@ -145,10 +147,10 @@
} // namespace
[[noreturn]] void TintInternalCompilerErrorReporter(const InternalCompilerError& err) {
- auto printer = diag::Printer::Create(stderr, true);
- diag::Style bold_red{diag::Color::kRed, true};
- printer->Write(err.Error(), bold_red);
- constexpr const char* please_file_bug = R"(
+ auto printer = StyledTextPrinter::Create(stderr);
+ StyledText msg;
+ msg << (style::Error + style::Bold) << err.Error();
+ msg << R"(
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
@@ -156,7 +158,7 @@
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************
)";
- printer->Write(please_file_bug, bold_red);
+ printer->Print(msg);
exit(1);
}
@@ -267,9 +269,9 @@
PrintWGSL(std::cout, info.program);
}
- auto diag_printer = tint::diag::Printer::Create(stderr, true);
- tint::diag::Formatter diag_formatter;
- diag_formatter.Format(info.program.Diagnostics(), diag_printer.get());
+ auto printer = tint::StyledTextPrinter::Create(stderr);
+ tint::diag::Formatter formatter;
+ printer->Print(formatter.Format(info.program.Diagnostics()));
}
if (!info.program.IsValid()) {
diff --git a/src/tint/cmd/tint/main.cc b/src/tint/cmd/tint/main.cc
index 8db9a64..947355e 100644
--- a/src/tint/cmd/tint/main.cc
+++ b/src/tint/cmd/tint/main.cc
@@ -56,10 +56,11 @@
#include "src/tint/utils/command/command.h"
#include "src/tint/utils/containers/transform.h"
#include "src/tint/utils/diagnostic/formatter.h"
-#include "src/tint/utils/diagnostic/printer.h"
#include "src/tint/utils/macros/defer.h"
#include "src/tint/utils/text/string.h"
#include "src/tint/utils/text/string_stream.h"
+#include "src/tint/utils/text/styled_text.h"
+#include "src/tint/utils/text/styled_text_printer.h"
#if TINT_BUILD_WGSL_READER
#include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"
@@ -789,9 +790,9 @@
auto source = std::make_unique<tint::Source::File>(options.input_filename, result->wgsl);
auto reparsed_program = tint::wgsl::reader::Parse(source.get(), parser_options);
if (!reparsed_program.IsValid()) {
- auto diag_printer = tint::diag::Printer::Create(stderr, true);
+ auto printer = tint::StyledTextPrinter::Create(stderr);
tint::diag::Formatter diag_formatter;
- diag_formatter.Format(reparsed_program.Diagnostics(), diag_printer.get());
+ printer->Print(diag_formatter.Format(reparsed_program.Diagnostics()));
return false;
}
}
diff --git a/src/tint/fuzzers/BUILD.gn b/src/tint/fuzzers/BUILD.gn
index bf83f01..3809954 100644
--- a/src/tint/fuzzers/BUILD.gn
+++ b/src/tint/fuzzers/BUILD.gn
@@ -101,6 +101,7 @@
"${tint_src_dir}/lang/wgsl/writer",
"${tint_src_dir}/utils/diagnostic",
"${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/text",
]
sources = [
diff --git a/src/tint/fuzzers/tint_common_fuzzer.cc b/src/tint/fuzzers/tint_common_fuzzer.cc
index a50ca8e..be3a673 100644
--- a/src/tint/fuzzers/tint_common_fuzzer.cc
+++ b/src/tint/fuzzers/tint_common_fuzzer.cc
@@ -51,8 +51,10 @@
#include "src/tint/lang/wgsl/program/program.h"
#include "src/tint/lang/wgsl/sem/variable.h"
#include "src/tint/utils/diagnostic/formatter.h"
-#include "src/tint/utils/diagnostic/printer.h"
#include "src/tint/utils/math/hash.h"
+#include "src/tint/utils/text/styled_text.h"
+#include "src/tint/utils/text/styled_text_printer.h"
+#include "src/tint/utils/text/text_style.h"
#if TINT_BUILD_SPV_WRITER
#include "src/tint/lang/spirv/writer/helpers/ast_generate_bindings.h"
@@ -74,15 +76,14 @@
// to better de-duplication of bug reports, because ClusterFuzz only uses the
// top few stack frames for de-duplication, and a FATAL_ERROR stack frame
// provides no useful information.
-#define FATAL_ERROR(diags, msg_string) \
- do { \
- std::string msg = msg_string; \
- auto printer = tint::diag::Printer::Create(stderr, true); \
- if (!msg.empty()) { \
- printer->Write(msg + "\n", {diag::Color::kRed, true}); \
- } \
- tint::diag::Formatter().Format(diags, printer.get()); \
- __builtin_trap(); \
+#define FATAL_ERROR(diags, msg_string) \
+ do { \
+ StyledText msg; \
+ msg << (style::Error + style::Bold) << msg_string; \
+ auto printer = tint::StyledTextPrinter::Create(stderr); \
+ printer->Print(msg); \
+ printer->Print(tint::diag::Formatter().Format(diags)); \
+ __builtin_trap(); \
} while (false)
[[noreturn]] void TintInternalCompilerErrorReporter(const InternalCompilerError& err) {
@@ -117,13 +118,13 @@
const tint::diag::List& diags = program.Diagnostics();
tools.SetMessageConsumer(
[diags](spv_message_level_t, const char*, const spv_position_t& pos, const char* msg) {
- std::stringstream out;
+ StyledText out;
out << "Unexpected spirv-val error:\n"
- << (pos.line + 1) << ":" << (pos.column + 1) << ": " << msg << std::endl;
+ << (pos.line + 1) << ":" << (pos.column + 1) << ": " << msg;
- auto printer = tint::diag::Printer::Create(stderr, true);
- printer->Write(out.str(), {diag::Color::kYellow, false});
- tint::diag::Formatter().Format(diags, printer.get());
+ auto printer = tint::StyledTextPrinter::Create(stderr);
+ printer->Print(out);
+ printer->Print(tint::diag::Formatter().Format(diags));
});
return tools.Validate(spirv.data(), spirv.size(), spvtools::ValidatorOptions());
diff --git a/src/tint/lang/core/constant/eval.cc b/src/tint/lang/core/constant/eval.cc
index 74b9022..0b78386 100644
--- a/src/tint/lang/core/constant/eval.cc
+++ b/src/tint/lang/core/constant/eval.cc
@@ -281,7 +281,7 @@
// [abstract-numeric -> x] - materialization failure
auto msg = OverflowErrorMessage(scalar->value, target_ty->FriendlyName());
if (ctx.use_runtime_semantics) {
- ctx.diags.AddWarning(tint::diag::System::Resolver, msg, ctx.source);
+ ctx.diags.AddWarning(tint::diag::System::Resolver, ctx.source) << msg;
switch (conv.Failure()) {
case ConversionFailure::kExceedsNegativeLimit:
return ctx.mgr.Get<Scalar<TO>>(target_ty, TO::Lowest());
@@ -289,7 +289,7 @@
return ctx.mgr.Get<Scalar<TO>>(target_ty, TO::Highest());
}
} else {
- ctx.diags.AddError(tint::diag::System::Resolver, msg, ctx.source);
+ ctx.diags.AddError(tint::diag::System::Resolver, ctx.source) << msg;
return nullptr;
}
} else if constexpr (IsFloatingPoint<TO>) {
@@ -297,7 +297,7 @@
// https://www.w3.org/TR/WGSL/#floating-point-conversion
auto msg = OverflowErrorMessage(scalar->value, target_ty->FriendlyName());
if (ctx.use_runtime_semantics) {
- ctx.diags.AddWarning(tint::diag::System::Resolver, msg, ctx.source);
+ ctx.diags.AddWarning(tint::diag::System::Resolver, ctx.source) << msg;
switch (conv.Failure()) {
case ConversionFailure::kExceedsNegativeLimit:
return ctx.mgr.Get<Scalar<TO>>(target_ty, TO::Lowest());
@@ -305,7 +305,7 @@
return ctx.mgr.Get<Scalar<TO>>(target_ty, TO::Highest());
}
} else {
- ctx.diags.AddError(tint::diag::System::Resolver, msg, ctx.source);
+ ctx.diags.AddError(tint::diag::System::Resolver, ctx.source) << msg;
return nullptr;
}
} else if constexpr (IsFloatingPoint<FROM>) {
@@ -648,7 +648,7 @@
if constexpr (IsFloatingPoint<T>) {
if (!std::isfinite(v.value)) {
- AddError(OverflowErrorMessage(v, t->FriendlyName()), source);
+ AddError(source) << OverflowErrorMessage(v, t->FriendlyName());
if (use_runtime_semantics_) {
return mgr.Zero(t);
} else {
@@ -666,7 +666,7 @@
if (auto r = CheckedAdd(a, b)) {
result = r->value;
} else {
- AddError(OverflowErrorMessage(a, "+", b), source);
+ AddError(source) << OverflowErrorMessage(a, "+", b);
if (use_runtime_semantics_) {
return NumberT{0};
} else {
@@ -696,7 +696,7 @@
if (auto r = CheckedSub(a, b)) {
result = r->value;
} else {
- AddError(OverflowErrorMessage(a, "-", b), source);
+ AddError(source) << OverflowErrorMessage(a, "-", b);
if (use_runtime_semantics_) {
return NumberT{0};
} else {
@@ -727,7 +727,7 @@
if (auto r = CheckedMul(a, b)) {
result = r->value;
} else {
- AddError(OverflowErrorMessage(a, "*", b), source);
+ AddError(source) << OverflowErrorMessage(a, "*", b);
if (use_runtime_semantics_) {
return NumberT{0};
} else {
@@ -756,7 +756,7 @@
if (auto r = CheckedDiv(a, b)) {
result = r->value;
} else {
- AddError(OverflowErrorMessage(a, "/", b), source);
+ AddError(source) << OverflowErrorMessage(a, "/", b);
if (use_runtime_semantics_) {
return a;
} else {
@@ -769,7 +769,7 @@
auto rhs = b.value;
if (rhs == 0) {
// For integers (as for floats), lhs / 0 is an error
- AddError(OverflowErrorMessage(a, "/", b), source);
+ AddError(source) << OverflowErrorMessage(a, "/", b);
if (use_runtime_semantics_) {
return a;
} else {
@@ -780,7 +780,7 @@
// For signed integers, lhs / -1 where lhs is the
// most negative value is an error
if (rhs == -1 && lhs == std::numeric_limits<T>::min()) {
- AddError(OverflowErrorMessage(a, "/", b), source);
+ AddError(source) << OverflowErrorMessage(a, "/", b);
if (use_runtime_semantics_) {
return a;
} else {
@@ -800,7 +800,7 @@
if (auto r = CheckedMod(a, b)) {
result = r->value;
} else {
- AddError(OverflowErrorMessage(a, "%", b), source);
+ AddError(source) << OverflowErrorMessage(a, "%", b);
if (use_runtime_semantics_) {
return NumberT{0};
} else {
@@ -813,7 +813,7 @@
auto rhs = b.value;
if (rhs == 0) {
// lhs % 0 is an error
- AddError(OverflowErrorMessage(a, "%", b), source);
+ AddError(source) << OverflowErrorMessage(a, "%", b);
if (use_runtime_semantics_) {
return NumberT{0};
} else {
@@ -824,7 +824,7 @@
// For signed integers, lhs % -1 where lhs is the
// most negative value is an error
if (rhs == -1 && lhs == std::numeric_limits<T>::min()) {
- AddError(OverflowErrorMessage(a, "%", b), source);
+ AddError(source) << OverflowErrorMessage(a, "%", b);
if (use_runtime_semantics_) {
return NumberT{0};
} else {
@@ -1084,7 +1084,7 @@
template <typename NumberT>
tint::Result<NumberT, Eval::Error> Eval::Sqrt(const Source& source, NumberT v) {
if (v < NumberT(0)) {
- AddError("sqrt must be called with a value >= 0", source);
+ AddError(source) << "sqrt must be called with a value >= 0";
if (use_runtime_semantics_) {
return NumberT{0};
} else {
@@ -1109,9 +1109,8 @@
NumberT low,
NumberT high) {
if (low > high) {
- StringStream ss;
- ss << "clamp called with 'low' (" << low << ") greater than 'high' (" << high << ")";
- AddError(ss.str(), source);
+ AddError(source) << "clamp called with 'low' (" << low << ") greater than 'high' (" << high
+ << ")";
if (!use_runtime_semantics_) {
return error;
}
@@ -1403,11 +1402,11 @@
AInt idx = idx_val->ValueAs<AInt>();
if (idx < 0 || (el.count > 0 && idx >= el.count)) {
- std::string range;
+ auto& err = AddError(idx_source) << "index " << idx << " out of bounds";
if (el.count > 0) {
- range = " [0.." + std::to_string(el.count - 1) + "]";
+ err << " [0.." + std::to_string(el.count - 1) + "]";
}
- AddError("index " + std::to_string(idx) + " out of bounds" + range, idx_source);
+
if (use_runtime_semantics_) {
return mgr.Zero(el.type);
} else {
@@ -1998,7 +1997,7 @@
UT must_match_msb = e2u + 1;
UT mask = ~UT{0} << (bit_width - must_match_msb);
if ((e1u & mask) != 0 && (e1u & mask) != mask) {
- AddError("shift left operation results in sign change", source);
+ AddError(source) << "shift left operation results in sign change";
if (!use_runtime_semantics_) {
return error;
}
@@ -2006,7 +2005,7 @@
} else {
// If shift value >= bit_width, then any non-zero value would overflow
if (e1 != 0) {
- AddError(OverflowErrorMessage(e1, "<<", e2), source);
+ AddError(source) << OverflowErrorMessage(e1, "<<", e2);
if (!use_runtime_semantics_) {
return error;
}
@@ -2021,10 +2020,9 @@
// At shader/pipeline-creation time, it is an error to shift by the bit width of
// the lhs or greater.
// NOTE: At runtime, we shift by e2 % (bit width of e1).
- AddError(
- "shift left value must be less than the bit width of the lhs, which is " +
- std::to_string(bit_width),
- source);
+ AddError(source)
+ << "shift left value must be less than the bit width of the lhs, which is "
+ << bit_width;
if (use_runtime_semantics_) {
e2u = e2u % bit_width;
} else {
@@ -2038,7 +2036,7 @@
size_t must_match_msb = e2u + 1;
UT mask = ~UT{0} << (bit_width - must_match_msb);
if ((e1u & mask) != 0 && (e1u & mask) != mask) {
- AddError("shift left operation results in sign change", source);
+ AddError(source) << "shift left operation results in sign change";
if (!use_runtime_semantics_) {
return error;
}
@@ -2050,7 +2048,7 @@
size_t must_be_zero_msb = e2u;
UT mask = ~UT{0} << (bit_width - must_be_zero_msb);
if ((e1u & mask) != 0) {
- AddError(OverflowErrorMessage(e1, "<<", e2), source);
+ AddError(source) << OverflowErrorMessage(e1, "<<", e2);
if (!use_runtime_semantics_) {
return error;
}
@@ -2111,10 +2109,9 @@
if (static_cast<size_t>(e2) >= bit_width) {
// At shader/pipeline-creation time, it is an error to shift by the bit width of
// the lhs or greater. NOTE: At runtime, we shift by e2 % (bit width of e1).
- AddError(
- "shift right value must be less than the bit width of the lhs, which is " +
- std::to_string(bit_width),
- source);
+ AddError(source)
+ << "shift right value must be less than the bit width of the lhs, which is "
+ << bit_width;
if (use_runtime_semantics_) {
e2u = e2u % bit_width;
} else {
@@ -2169,22 +2166,23 @@
Eval::Result Eval::acos(const core::type::Type* ty,
VectorRef<const Value*> args,
const Source& source) {
- auto transform = [&](const Value* c0) {
- auto create = [&](auto i) -> Eval::Result {
- using NumberT = decltype(i);
- if (i < NumberT(-1.0) || i > NumberT(1.0)) {
- AddError("acos must be called with a value in the range [-1 .. 1] (inclusive)",
- source);
- if (use_runtime_semantics_) {
- return mgr.Zero(c0->Type());
- } else {
- return error;
+ auto transform =
+ [&](const Value* c0) {
+ auto create = [&](auto i) -> Eval::Result {
+ using NumberT = decltype(i);
+ if (i < NumberT(-1.0) || i > NumberT(1.0)) {
+ AddError(source)
+ << "acos must be called with a value in the range [-1 .. 1] (inclusive)";
+ if (use_runtime_semantics_) {
+ return mgr.Zero(c0->Type());
+ } else {
+ return error;
+ }
}
- }
- return CreateScalar(source, c0->Type(), NumberT(std::acos(i.value)));
+ return CreateScalar(source, c0->Type(), NumberT(std::acos(i.value)));
+ };
+ return Dispatch_fa_f32_f16(create, c0);
};
- return Dispatch_fa_f32_f16(create, c0);
- };
return TransformUnaryElements(mgr, ty, transform, args[0]);
}
@@ -2195,7 +2193,7 @@
auto create = [&](auto i) -> Eval::Result {
using NumberT = decltype(i);
if (i < NumberT(1.0)) {
- AddError("acosh must be called with a value >= 1.0", source);
+ AddError(source) << "acosh must be called with a value >= 1.0";
if (use_runtime_semantics_) {
return mgr.Zero(c0->Type());
} else {
@@ -2225,22 +2223,23 @@
Eval::Result Eval::asin(const core::type::Type* ty,
VectorRef<const Value*> args,
const Source& source) {
- auto transform = [&](const Value* c0) {
- auto create = [&](auto i) -> Eval::Result {
- using NumberT = decltype(i);
- if (i < NumberT(-1.0) || i > NumberT(1.0)) {
- AddError("asin must be called with a value in the range [-1 .. 1] (inclusive)",
- source);
- if (use_runtime_semantics_) {
- return mgr.Zero(c0->Type());
- } else {
- return error;
+ auto transform =
+ [&](const Value* c0) {
+ auto create = [&](auto i) -> Eval::Result {
+ using NumberT = decltype(i);
+ if (i < NumberT(-1.0) || i > NumberT(1.0)) {
+ AddError(source)
+ << "asin must be called with a value in the range [-1 .. 1] (inclusive)";
+ if (use_runtime_semantics_) {
+ return mgr.Zero(c0->Type());
+ } else {
+ return error;
+ }
}
- }
- return CreateScalar(source, c0->Type(), NumberT(std::asin(i.value)));
+ return CreateScalar(source, c0->Type(), NumberT(std::asin(i.value)));
+ };
+ return Dispatch_fa_f32_f16(create, c0);
};
- return Dispatch_fa_f32_f16(create, c0);
- };
return TransformUnaryElements(mgr, ty, transform, args[0]);
}
@@ -2272,22 +2271,23 @@
Eval::Result Eval::atanh(const core::type::Type* ty,
VectorRef<const Value*> args,
const Source& source) {
- auto transform = [&](const Value* c0) {
- auto create = [&](auto i) -> Eval::Result {
- using NumberT = decltype(i);
- if (i <= NumberT(-1.0) || i >= NumberT(1.0)) {
- AddError("atanh must be called with a value in the range (-1 .. 1) (exclusive)",
- source);
- if (use_runtime_semantics_) {
- return mgr.Zero(c0->Type());
- } else {
- return error;
+ auto transform =
+ [&](const Value* c0) {
+ auto create = [&](auto i) -> Eval::Result {
+ using NumberT = decltype(i);
+ if (i <= NumberT(-1.0) || i >= NumberT(1.0)) {
+ AddError(source)
+ << "atanh must be called with a value in the range (-1 .. 1) (exclusive)";
+ if (use_runtime_semantics_) {
+ return mgr.Zero(c0->Type());
+ } else {
+ return error;
+ }
}
- }
- return CreateScalar(source, c0->Type(), NumberT(std::atanh(i.value)));
+ return CreateScalar(source, c0->Type(), NumberT(std::atanh(i.value)));
+ };
+ return Dispatch_fa_f32_f16(create, c0);
};
- return Dispatch_fa_f32_f16(create, c0);
- };
return TransformUnaryElements(mgr, ty, transform, args[0]);
}
@@ -2458,12 +2458,12 @@
auto pi = kPi<T>;
auto scale = Div(source, NumberT(180), NumberT(pi));
if (scale != Success) {
- AddNote("when calculating degrees", source);
+ AddNote(source) << "when calculating degrees";
return error;
}
auto result = Mul(source, e, scale.Get());
if (result != Success) {
- AddNote("when calculating degrees", source);
+ AddNote(source) << "when calculating degrees";
return error;
}
return CreateScalar(source, c0->Type(), result.Get());
@@ -2504,7 +2504,7 @@
};
auto r = calculate();
if (r != Success) {
- AddNote("when calculating determinant", source);
+ AddNote(source) << "when calculating determinant";
}
return r;
}
@@ -2513,7 +2513,7 @@
VectorRef<const Value*> args,
const Source& source) {
auto err = [&]() -> Eval::Result {
- AddNote("when calculating distance", source);
+ AddNote(source) << "when calculating distance";
return error;
};
@@ -2534,7 +2534,7 @@
const Source& source) {
auto r = Dot(source, args[0], args[1]);
if (r != Success) {
- AddNote("when calculating dot", source);
+ AddNote(source) << "when calculating dot";
}
return r;
}
@@ -2577,7 +2577,7 @@
using NumberT = decltype(e0);
auto val = NumberT(std::exp(e0));
if (!std::isfinite(val.value)) {
- AddError(OverflowExpErrorMessage("e", e0), source);
+ AddError(source) << OverflowExpErrorMessage("e", e0);
if (use_runtime_semantics_) {
return mgr.Zero(c0->Type());
} else {
@@ -2599,7 +2599,7 @@
using NumberT = decltype(e0);
auto val = NumberT(std::exp2(e0));
if (!std::isfinite(val.value)) {
- AddError(OverflowExpErrorMessage("2", e0), source);
+ AddError(source) << OverflowExpErrorMessage("2", e0);
if (use_runtime_semantics_) {
return mgr.Zero(c0->Type());
} else {
@@ -2616,60 +2616,62 @@
Eval::Result Eval::extractBits(const core::type::Type* ty,
VectorRef<const Value*> args,
const Source& source) {
- auto transform = [&](const Value* c0) {
- auto create = [&](auto in_e) -> Eval::Result {
- using NumberT = decltype(in_e);
- using T = UnwrapNumber<NumberT>;
- using UT = std::make_unsigned_t<T>;
- using NumberUT = Number<UT>;
+ auto transform =
+ [&](const Value* c0) {
+ auto create = [&](auto in_e) -> Eval::Result {
+ using NumberT = decltype(in_e);
+ using T = UnwrapNumber<NumberT>;
+ using UT = std::make_unsigned_t<T>;
+ using NumberUT = Number<UT>;
- // Read args that are always scalar
- NumberUT in_offset = args[1]->ValueAs<NumberUT>();
- NumberUT in_count = args[2]->ValueAs<NumberUT>();
+ // Read args that are always scalar
+ NumberUT in_offset = args[1]->ValueAs<NumberUT>();
+ NumberUT in_count = args[2]->ValueAs<NumberUT>();
- // Cast all to unsigned
- UT e = static_cast<UT>(in_e);
- UT o = static_cast<UT>(in_offset);
- UT c = static_cast<UT>(in_count);
+ // Cast all to unsigned
+ UT e = static_cast<UT>(in_e);
+ UT o = static_cast<UT>(in_offset);
+ UT c = static_cast<UT>(in_count);
- constexpr UT w = sizeof(UT) * 8;
- if (o > w || c > w || (o + c) > w) {
- AddError("'offset + 'count' must be less than or equal to the bit width of 'e'",
- source);
- if (use_runtime_semantics_) {
- o = std::min(o, w);
- c = std::min(c, w - o);
- } else {
- return error;
- }
- }
-
- NumberT result;
- if (c == UT{0}) {
- // The result is 0 if c is 0
- result = NumberT{0};
- } else if (c == w) {
- // The result is e if c is w
- result = NumberT{e};
- } else {
- // Otherwise, bits 0..c - 1 of the result are copied from bits o..o + c - 1 of e.
- UT src_mask = ((UT{1} << c) - UT{1}) << o;
- UT r = (e & src_mask) >> o;
- if constexpr (IsSignedIntegral<NumberT>) {
- // Other bits of the result are the same as bit c - 1 of the result.
- // Only need to set other bits if bit at c - 1 of result is 1
- if ((r & (UT{1} << (c - UT{1}))) != UT{0}) {
- UT dst_mask = src_mask >> o;
- r |= (~UT{0} & ~dst_mask);
+ constexpr UT w = sizeof(UT) * 8;
+ if (o > w || c > w || (o + c) > w) {
+ AddError(source)
+ << "'offset + 'count' must be less than or equal to the bit width of 'e'";
+ if (use_runtime_semantics_) {
+ o = std::min(o, w);
+ c = std::min(c, w - o);
+ } else {
+ return error;
}
}
- result = NumberT{r};
- }
- return CreateScalar(source, c0->Type(), result);
+ NumberT result;
+ if (c == UT{0}) {
+ // The result is 0 if c is 0
+ result = NumberT{0};
+ } else if (c == w) {
+ // The result is e if c is w
+ result = NumberT{e};
+ } else {
+ // Otherwise, bits 0..c - 1 of the result are copied from bits o..o + c - 1 of
+ // e.
+ UT src_mask = ((UT{1} << c) - UT{1}) << o;
+ UT r = (e & src_mask) >> o;
+ if constexpr (IsSignedIntegral<NumberT>) {
+ // Other bits of the result are the same as bit c - 1 of the result.
+ // Only need to set other bits if bit at c - 1 of result is 1
+ if ((r & (UT{1} << (c - UT{1}))) != UT{0}) {
+ UT dst_mask = src_mask >> o;
+ r |= (~UT{0} & ~dst_mask);
+ }
+ }
+
+ result = NumberT{r};
+ }
+ return CreateScalar(source, c0->Type(), result);
+ };
+ return Dispatch_iu32(create, c0);
};
- return Dispatch_iu32(create, c0);
- };
return TransformUnaryElements(mgr, ty, transform, args[0]);
}
@@ -2682,7 +2684,7 @@
auto* e3 = args[2];
auto r = Dot(source, e2, e3);
if (r != Success) {
- AddNote("when calculating faceForward", source);
+ AddNote(source) << "when calculating faceForward";
return error;
}
auto is_negative = [](auto v) { return v < 0; };
@@ -2780,7 +2782,7 @@
auto transform = [&](const Value* c1, const Value* c2, const Value* c3) {
auto create = [&](auto e1, auto e2, auto e3) -> Eval::Result {
auto err_msg = [&] {
- AddNote("when calculating fma", source);
+ AddNote(source) << "when calculating fma";
return error;
};
@@ -2882,57 +2884,58 @@
Eval::Result Eval::insertBits(const core::type::Type* ty,
VectorRef<const Value*> args,
const Source& source) {
- auto transform = [&](const Value* c0, const Value* c1) {
- auto create = [&](auto in_e, auto in_newbits) -> Eval::Result {
- using NumberT = decltype(in_e);
- using T = UnwrapNumber<NumberT>;
- using UT = std::make_unsigned_t<T>;
- using NumberUT = Number<UT>;
+ auto transform =
+ [&](const Value* c0, const Value* c1) {
+ auto create = [&](auto in_e, auto in_newbits) -> Eval::Result {
+ using NumberT = decltype(in_e);
+ using T = UnwrapNumber<NumberT>;
+ using UT = std::make_unsigned_t<T>;
+ using NumberUT = Number<UT>;
- // Read args that are always scalar
- NumberUT in_offset = args[2]->ValueAs<NumberUT>();
- NumberUT in_count = args[3]->ValueAs<NumberUT>();
+ // Read args that are always scalar
+ NumberUT in_offset = args[2]->ValueAs<NumberUT>();
+ NumberUT in_count = args[3]->ValueAs<NumberUT>();
- // Cast all to unsigned
- UT e = static_cast<UT>(in_e);
- UT newbits = static_cast<UT>(in_newbits);
- UT o = static_cast<UT>(in_offset);
- UT c = static_cast<UT>(in_count);
+ // Cast all to unsigned
+ UT e = static_cast<UT>(in_e);
+ UT newbits = static_cast<UT>(in_newbits);
+ UT o = static_cast<UT>(in_offset);
+ UT c = static_cast<UT>(in_count);
- constexpr UT w = sizeof(UT) * 8;
- if (o > w || c > w || (o + c) > w) {
- AddError("'offset + 'count' must be less than or equal to the bit width of 'e'",
- source);
- if (use_runtime_semantics_) {
- o = std::min(o, w);
- c = std::min(c, w - o);
- } else {
- return error;
+ constexpr UT w = sizeof(UT) * 8;
+ if (o > w || c > w || (o + c) > w) {
+ AddError(source)
+ << "'offset + 'count' must be less than or equal to the bit width of 'e'";
+ if (use_runtime_semantics_) {
+ o = std::min(o, w);
+ c = std::min(c, w - o);
+ } else {
+ return error;
+ }
}
- }
- NumberT result;
- if (c == UT{0}) {
- // The result is e if c is 0
- result = NumberT{e};
- } else if (c == w) {
- // The result is newbits if c is w
- result = NumberT{newbits};
- } else {
- // Otherwise, bits o..o + c - 1 of the result are copied from bits 0..c - 1 of
- // newbits. Other bits of the result are copied from e.
- UT from = newbits << o;
- UT mask = ((UT{1} << c) - UT{1}) << UT{o};
- auto r = e; // Start with 'e' as the result
- r &= ~mask; // Zero the bits in 'e' we're overwriting
- r |= (from & mask); // Overwrite from 'newbits' (shifted into position)
- result = NumberT{r};
- }
+ NumberT result;
+ if (c == UT{0}) {
+ // The result is e if c is 0
+ result = NumberT{e};
+ } else if (c == w) {
+ // The result is newbits if c is w
+ result = NumberT{newbits};
+ } else {
+ // Otherwise, bits o..o + c - 1 of the result are copied from bits 0..c - 1 of
+ // newbits. Other bits of the result are copied from e.
+ UT from = newbits << o;
+ UT mask = ((UT{1} << c) - UT{1}) << UT{o};
+ auto r = e; // Start with 'e' as the result
+ r &= ~mask; // Zero the bits in 'e' we're overwriting
+ r |= (from & mask); // Overwrite from 'newbits' (shifted into position)
+ result = NumberT{r};
+ }
- return CreateScalar(source, c0->Type(), result);
+ return CreateScalar(source, c0->Type(), result);
+ };
+ return Dispatch_iu32(create, c0, c1);
};
- return Dispatch_iu32(create, c0, c1);
- };
return TransformBinaryElements(mgr, ty, transform, args[0], args[1]);
}
@@ -2944,7 +2947,7 @@
using NumberT = decltype(e);
if (e <= NumberT(0)) {
- AddError("inverseSqrt must be called with a value > 0", source);
+ AddError(source) << "inverseSqrt must be called with a value > 0";
if (use_runtime_semantics_) {
return mgr.Zero(c0->Type());
} else {
@@ -2953,7 +2956,7 @@
}
auto err = [&] {
- AddNote("when calculating inverseSqrt", source);
+ AddNote(source) << "when calculating inverseSqrt";
return error;
};
@@ -3001,7 +3004,7 @@
}
if (e2 > bias + 1) {
- AddError("e2 must be less than or equal to " + std::to_string(bias + 1), source);
+ AddError(source) << "e2 must be less than or equal to " << (bias + 1);
if (use_runtime_semantics_) {
return mgr.Zero(c1->Type());
} else {
@@ -3025,7 +3028,7 @@
const Source& source) {
auto r = Length(source, ty, args[0]);
if (r != Success) {
- AddNote("when calculating length", source);
+ AddNote(source) << "when calculating length";
}
return r;
}
@@ -3037,7 +3040,7 @@
auto create = [&](auto v) -> Eval::Result {
using NumberT = decltype(v);
if (v <= NumberT(0)) {
- AddError("log must be called with a value > 0", source);
+ AddError(source) << "log must be called with a value > 0";
if (use_runtime_semantics_) {
return mgr.Zero(c0->Type());
} else {
@@ -3058,7 +3061,7 @@
auto create = [&](auto v) -> Eval::Result {
using NumberT = decltype(v);
if (v <= NumberT(0)) {
- AddError("log2 must be called with a value > 0", source);
+ AddError(source) << "log2 must be called with a value > 0";
if (use_runtime_semantics_) {
return mgr.Zero(c0->Type());
} else {
@@ -3134,7 +3137,7 @@
};
auto r = TransformElements(mgr, ty, transform, 0, args[0], args[1]);
if (r != Success) {
- AddNote("when calculating mix", source);
+ AddNote(source) << "when calculating mix";
}
return r;
}
@@ -3180,12 +3183,12 @@
auto* len_ty = ty->DeepestElement();
auto len = Length(source, len_ty, args[0]);
if (len != Success) {
- AddNote("when calculating normalize", source);
+ AddNote(source) << "when calculating normalize";
return error;
}
auto* v = len.Get();
if (v->AllZero()) {
- AddError("zero length vector can not be normalized", source);
+ AddError(source) << "zero length vector can not be normalized";
if (use_runtime_semantics_) {
return mgr.Zero(ty);
} else {
@@ -3201,7 +3204,7 @@
auto convert = [&](f32 val) -> tint::Result<uint32_t, Error> {
auto conv = CheckedConvert<f16>(val);
if (conv != Success) {
- AddError(OverflowErrorMessage(val, "f16"), source);
+ AddError(source) << OverflowErrorMessage(val, "f16");
if (use_runtime_semantics_) {
return 0;
} else {
@@ -3365,7 +3368,7 @@
auto create = [&](auto e1, auto e2) -> Eval::Result {
auto r = CheckedPow(e1, e2);
if (!r) {
- AddError(OverflowErrorMessage(e1, "^", e2), source);
+ AddError(source) << OverflowErrorMessage(e1, "^", e2);
if (use_runtime_semantics_) {
return mgr.Zero(c0->Type());
} else {
@@ -3390,12 +3393,12 @@
auto pi = kPi<T>;
auto scale = Div(source, NumberT(pi), NumberT(180));
if (scale != Success) {
- AddNote("when calculating radians", source);
+ AddNote(source) << "when calculating radians";
return error;
}
auto result = Mul(source, e, scale.Get());
if (result != Success) {
- AddNote("when calculating radians", source);
+ AddNote(source) << "when calculating radians";
return error;
}
return CreateScalar(source, c0->Type(), result.Get());
@@ -3443,7 +3446,7 @@
};
auto r = calculate();
if (r != Success) {
- AddNote("when calculating reflect", source);
+ AddNote(source) << "when calculating reflect";
}
return r;
}
@@ -3541,7 +3544,7 @@
};
auto r = calculate();
if (r != Success) {
- AddNote("when calculating refract", source);
+ AddNote(source) << "when calculating refract";
}
return r;
}
@@ -3708,7 +3711,7 @@
using NumberT = decltype(low);
auto err = [&] {
- AddNote("when calculating smoothstep", source);
+ AddNote(source) << "when calculating smoothstep";
return error;
};
@@ -3844,7 +3847,7 @@
auto in = f16::FromBits(uint16_t((e >> (16 * i)) & 0x0000'ffff));
auto val = CheckedConvert<f32>(in);
if (val != Success) {
- AddError(OverflowErrorMessage(in, "f32"), source);
+ AddError(source) << OverflowErrorMessage(in, "f32");
if (use_runtime_semantics_) {
val = f32(0.f);
} else {
@@ -3986,7 +3989,7 @@
auto value = c->ValueAs<f32>();
auto conv = CheckedConvert<f32>(f16(value));
if (conv != Success) {
- AddError(OverflowErrorMessage(value, "f16"), source);
+ AddError(source) << OverflowErrorMessage(value, "f16");
if (use_runtime_semantics_) {
return mgr.Zero(c->Type());
} else {
@@ -4009,20 +4012,20 @@
return converted ? Result(converted) : Result(error);
}
-void Eval::AddError(const std::string& msg, const Source& source) const {
+diag::Diagnostic& Eval::AddError(const Source& source) const {
if (use_runtime_semantics_) {
- diags.AddWarning(diag::System::Constant, msg, source);
+ return diags.AddWarning(diag::System::Constant, source);
} else {
- diags.AddError(diag::System::Constant, msg, source);
+ return diags.AddError(diag::System::Constant, source);
}
}
-void Eval::AddWarning(const std::string& msg, const Source& source) const {
- diags.AddWarning(diag::System::Constant, msg, source);
+diag::Diagnostic& Eval::AddWarning(const Source& source) const {
+ return diags.AddWarning(diag::System::Constant, source);
}
-void Eval::AddNote(const std::string& msg, const Source& source) const {
- diags.AddNote(diag::System::Constant, msg, source);
+diag::Diagnostic& Eval::AddNote(const Source& source) const {
+ return diags.AddNote(diag::System::Constant, source);
}
} // namespace tint::core::constant
diff --git a/src/tint/lang/core/constant/eval.h b/src/tint/lang/core/constant/eval.h
index de6624a..f3c4e6e 100644
--- a/src/tint/lang/core/constant/eval.h
+++ b/src/tint/lang/core/constant/eval.h
@@ -1025,14 +1025,14 @@
const Source& source);
private:
- /// Adds the given error message to the diagnostics
- void AddError(const std::string& msg, const Source& source) const;
+ /// @returns a new error diagnostic
+ diag::Diagnostic& AddError(const Source& source) const;
- /// Adds the given warning message to the diagnostics
- void AddWarning(const std::string& msg, const Source& source) const;
+ /// @returns a new warning diagnostic
+ diag::Diagnostic& AddWarning(const Source& source) const;
- /// Adds the given note message to the diagnostics
- void AddNote(const std::string& msg, const Source& source) const;
+ /// @returns a new note diagnostic
+ diag::Diagnostic& AddNote(const Source& source) const;
/// CreateScalar constructs and returns a constant::Scalar<T>.
/// @param source the source location
diff --git a/src/tint/lang/core/constant/eval_binary_op_test.cc b/src/tint/lang/core/constant/eval_binary_op_test.cc
index 1a1fbe2..7859908 100644
--- a/src/tint/lang/core/constant/eval_binary_op_test.cc
+++ b/src/tint/lang/core/constant/eval_binary_op_test.cc
@@ -1508,11 +1508,11 @@
GlobalConst("result", LogicalAnd(lhs, rhs));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:34 error: no matching overload for operator ! (abstract-int)
+ EXPECT_EQ(r()->error(), R"(12:34 error: no matching overload for 'operator ! (abstract-int)'
2 candidate operators:
- operator ! (bool) -> bool
- operator ! (vecN<bool>) -> vecN<bool>
+ 'operator ! (bool) -> bool'
+ 'operator ! (vecN<bool>) -> vecN<bool>'
)");
}
@@ -1525,11 +1525,11 @@
GlobalConst("result", LogicalOr(lhs, rhs));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:34 error: no matching overload for operator ! (abstract-int)
+ EXPECT_EQ(r()->error(), R"(12:34 error: no matching overload for 'operator ! (abstract-int)'
2 candidate operators:
- operator ! (bool) -> bool
- operator ! (vecN<bool>) -> vecN<bool>
+ 'operator ! (bool) -> bool'
+ 'operator ! (vecN<bool>) -> vecN<bool>'
)");
}
@@ -1574,10 +1574,10 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(12:34 error: no matching overload for operator && (bool, abstract-int)
+ R"(12:34 error: no matching overload for 'operator && (bool, abstract-int)'
1 candidate operator:
- operator && (bool, bool) -> bool
+ 'operator && (bool, bool) -> bool'
)");
}
@@ -1618,10 +1618,10 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(12:34 error: no matching overload for operator || (bool, abstract-int)
+ R"(12:34 error: no matching overload for 'operator || (bool, abstract-int)'
1 candidate operator:
- operator || (bool, bool) -> bool
+ 'operator || (bool, bool) -> bool'
)");
}
@@ -1672,11 +1672,11 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(12:34 error: no matching overload for operator == (abstract-float, i32)
+ R"(12:34 error: no matching overload for 'operator == (abstract-float, i32)'
2 candidate operators:
- operator == (T, T) -> bool where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- operator == (vecN<T>, vecN<T>) -> vecN<bool> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
+ 'operator == (T, T) -> bool' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'operator == (vecN<T>, vecN<T>) -> vecN<bool>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
)");
}
@@ -1723,11 +1723,11 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(12:34 error: no matching overload for operator == (abstract-float, i32)
+ R"(12:34 error: no matching overload for 'operator == (abstract-float, i32)'
2 candidate operators:
- operator == (T, T) -> bool where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- operator == (vecN<T>, vecN<T>) -> vecN<bool> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
+ 'operator == (T, T) -> bool' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'operator == (vecN<T>, vecN<T>) -> vecN<bool>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
)");
}
@@ -1784,11 +1784,11 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(12:34 error: no matching overload for operator == (i32, f32)
+ R"(12:34 error: no matching overload for 'operator == (i32, f32)'
2 candidate operators:
- operator == (T, T) -> bool where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- operator == (vecN<T>, vecN<T>) -> vecN<bool> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
+ 'operator == (T, T) -> bool' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'operator == (vecN<T>, vecN<T>) -> vecN<bool>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
)");
}
@@ -1841,11 +1841,11 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(12:34 error: no matching overload for operator == (i32, f32)
+ R"(12:34 error: no matching overload for 'operator == (i32, f32)'
2 candidate operators:
- operator == (T, T) -> bool where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- operator == (vecN<T>, vecN<T>) -> vecN<bool> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
+ 'operator == (T, T) -> bool' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'operator == (vecN<T>, vecN<T>) -> vecN<bool>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
)");
}
@@ -1895,11 +1895,11 @@
GlobalConst("result", binary);
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:34 error: no matching overload for operator == (f32, i32)
+ EXPECT_EQ(r()->error(), R"(12:34 error: no matching overload for 'operator == (f32, i32)'
2 candidate operators:
- operator == (T, T) -> bool where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- operator == (vecN<T>, vecN<T>) -> vecN<bool> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
+ 'operator == (T, T) -> bool' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'operator == (vecN<T>, vecN<T>) -> vecN<bool>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
)");
}
@@ -1945,11 +1945,11 @@
GlobalConst("result", binary);
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:34 error: no matching overload for operator == (f32, i32)
+ EXPECT_EQ(r()->error(), R"(12:34 error: no matching overload for 'operator == (f32, i32)'
2 candidate operators:
- operator == (T, T) -> bool where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- operator == (vecN<T>, vecN<T>) -> vecN<bool> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
+ 'operator == (T, T) -> bool' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'operator == (vecN<T>, vecN<T>) -> vecN<bool>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
)");
}
@@ -1971,24 +1971,24 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(12:34 error: no matching constructor for vec2<f32>(abstract-float, bool)
+ R"(12:34 error: no matching constructor for 'vec2<f32>(abstract-float, bool)'
8 candidate constructors:
- vec2<T>(x: T, y: T) -> vec2<T> where: T is f32, f16, i32, u32 or bool
- vec2<T>(T) -> vec2<T> where: T is f32, f16, i32, u32 or bool
- vec2(T) -> vec2<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- vec2<T>(vec2<T>) -> vec2<T> where: T is f32, f16, i32, u32 or bool
- vec2(vec2<T>) -> vec2<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- vec2() -> vec2<abstract-int>
- vec2<T>() -> vec2<T> where: T is f32, f16, i32, u32 or bool
- vec2(x: T, y: T) -> vec2<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
+ 'vec2<T>(x: T, y: T) -> vec2<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec2<T>(T) -> vec2<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec2(T) -> vec2<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec2<T>(vec2<T>) -> vec2<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec2(vec2<T>) -> vec2<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec2() -> vec2<abstract-int>'
+ 'vec2<T>() -> vec2<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec2(x: T, y: T) -> vec2<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
5 candidate conversions:
- vec2<T>(vec2<U>) -> vec2<T> where: T is f32, U is abstract-int, abstract-float, i32, f16, u32 or bool
- vec2<T>(vec2<U>) -> vec2<T> where: T is f16, U is abstract-int, abstract-float, f32, i32, u32 or bool
- vec2<T>(vec2<U>) -> vec2<T> where: T is i32, U is abstract-int, abstract-float, f32, f16, u32 or bool
- vec2<T>(vec2<U>) -> vec2<T> where: T is u32, U is abstract-int, abstract-float, f32, f16, i32 or bool
- vec2<T>(vec2<U>) -> vec2<T> where: T is bool, U is abstract-int, abstract-float, f32, f16, i32 or u32
+ 'vec2<T>(vec2<U>) -> vec2<T>' where: 'T' is 'f32', 'U' is 'abstract-int', 'abstract-float', 'i32', 'f16', 'u32' or 'bool'
+ 'vec2<T>(vec2<U>) -> vec2<T>' where: 'T' is 'f16', 'U' is 'abstract-int', 'abstract-float', 'f32', 'i32', 'u32' or 'bool'
+ 'vec2<T>(vec2<U>) -> vec2<T>' where: 'T' is 'i32', 'U' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'u32' or 'bool'
+ 'vec2<T>(vec2<U>) -> vec2<T>' where: 'T' is 'u32', 'U' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32' or 'bool'
+ 'vec2<T>(vec2<U>) -> vec2<T>' where: 'T' is 'bool', 'U' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32' or 'u32'
)");
}
@@ -2003,24 +2003,24 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(12:34 error: no matching constructor for vec2<f32>(abstract-float, bool)
+ R"(12:34 error: no matching constructor for 'vec2<f32>(abstract-float, bool)'
8 candidate constructors:
- vec2<T>(x: T, y: T) -> vec2<T> where: T is f32, f16, i32, u32 or bool
- vec2<T>(T) -> vec2<T> where: T is f32, f16, i32, u32 or bool
- vec2(T) -> vec2<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- vec2<T>(vec2<T>) -> vec2<T> where: T is f32, f16, i32, u32 or bool
- vec2(vec2<T>) -> vec2<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- vec2() -> vec2<abstract-int>
- vec2<T>() -> vec2<T> where: T is f32, f16, i32, u32 or bool
- vec2(x: T, y: T) -> vec2<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
+ 'vec2<T>(x: T, y: T) -> vec2<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec2<T>(T) -> vec2<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec2(T) -> vec2<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec2<T>(vec2<T>) -> vec2<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec2(vec2<T>) -> vec2<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec2() -> vec2<abstract-int>'
+ 'vec2<T>() -> vec2<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec2(x: T, y: T) -> vec2<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
5 candidate conversions:
- vec2<T>(vec2<U>) -> vec2<T> where: T is f32, U is abstract-int, abstract-float, i32, f16, u32 or bool
- vec2<T>(vec2<U>) -> vec2<T> where: T is f16, U is abstract-int, abstract-float, f32, i32, u32 or bool
- vec2<T>(vec2<U>) -> vec2<T> where: T is i32, U is abstract-int, abstract-float, f32, f16, u32 or bool
- vec2<T>(vec2<U>) -> vec2<T> where: T is u32, U is abstract-int, abstract-float, f32, f16, i32 or bool
- vec2<T>(vec2<U>) -> vec2<T> where: T is bool, U is abstract-int, abstract-float, f32, f16, i32 or u32
+ 'vec2<T>(vec2<U>) -> vec2<T>' where: 'T' is 'f32', 'U' is 'abstract-int', 'abstract-float', 'i32', 'f16', 'u32' or 'bool'
+ 'vec2<T>(vec2<U>) -> vec2<T>' where: 'T' is 'f16', 'U' is 'abstract-int', 'abstract-float', 'f32', 'i32', 'u32' or 'bool'
+ 'vec2<T>(vec2<U>) -> vec2<T>' where: 'T' is 'i32', 'U' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'u32' or 'bool'
+ 'vec2<T>(vec2<U>) -> vec2<T>' where: 'T' is 'u32', 'U' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32' or 'bool'
+ 'vec2<T>(vec2<U>) -> vec2<T>' where: 'T' is 'bool', 'U' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32' or 'u32'
)");
}
@@ -2078,12 +2078,13 @@
GlobalConst("result", LogicalAnd(lhs, rhs));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(),
- R"(error: no matching overload for operator == (array<abstract-int, 1>, abstract-int)
+ EXPECT_EQ(
+ r()->error(),
+ R"(error: no matching overload for 'operator == (array<abstract-int, 1>, abstract-int)'
2 candidate operators:
- operator == (T, T) -> bool where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- operator == (vecN<T>, vecN<T>) -> vecN<bool> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
+ 'operator == (T, T) -> bool' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'operator == (vecN<T>, vecN<T>) -> vecN<bool>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
)");
}
@@ -2096,12 +2097,13 @@
GlobalConst("result", LogicalOr(lhs, rhs));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(),
- R"(error: no matching overload for operator == (array<abstract-int, 1>, abstract-int)
+ EXPECT_EQ(
+ r()->error(),
+ R"(error: no matching overload for 'operator == (array<abstract-int, 1>, abstract-int)'
2 candidate operators:
- operator == (T, T) -> bool where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- operator == (vecN<T>, vecN<T>) -> vecN<bool> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
+ 'operator == (T, T) -> bool' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'operator == (vecN<T>, vecN<T>) -> vecN<bool>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
)");
}
@@ -2147,11 +2149,11 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(12:34 error: no matching overload for operator == (i32, abstract-float)
+ R"(12:34 error: no matching overload for 'operator == (i32, abstract-float)'
2 candidate operators:
- operator == (T, T) -> bool where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- operator == (vecN<T>, vecN<T>) -> vecN<bool> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
+ 'operator == (T, T) -> bool' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'operator == (vecN<T>, vecN<T>) -> vecN<bool>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
)");
}
@@ -2193,11 +2195,11 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(12:34 error: no matching overload for operator == (i32, abstract-float)
+ R"(12:34 error: no matching overload for 'operator == (i32, abstract-float)'
2 candidate operators:
- operator == (T, T) -> bool where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- operator == (vecN<T>, vecN<T>) -> vecN<bool> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
+ 'operator == (T, T) -> bool' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'operator == (vecN<T>, vecN<T>) -> vecN<bool>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
)");
}
diff --git a/src/tint/lang/core/intrinsic/data.cc b/src/tint/lang/core/intrinsic/data.cc
index d5db81e..46637b1 100644
--- a/src/tint/lang/core/intrinsic/data.cc
+++ b/src/tint/lang/core/intrinsic/data.cc
@@ -80,8 +80,8 @@
}
return BuildBool(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "bool";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "bool";
}
};
@@ -94,8 +94,8 @@
}
return BuildI32(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "i32";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "i32";
}
};
@@ -108,8 +108,8 @@
}
return BuildU32(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "u32";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "u32";
}
};
@@ -122,8 +122,8 @@
}
return BuildF32(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "f32";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "f32";
}
};
@@ -136,8 +136,8 @@
}
return BuildF16(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "f16";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "f16";
}
};
@@ -155,9 +155,9 @@
}
return BuildVec2(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "vec2<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "vec2" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -175,9 +175,9 @@
}
return BuildVec3(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "vec3<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "vec3" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -195,9 +195,9 @@
}
return BuildVec4(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "vec4<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "vec4" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -215,9 +215,9 @@
}
return BuildMat2X2(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat2x2<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat2x2" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -235,9 +235,9 @@
}
return BuildMat2X3(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat2x3<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat2x3" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -255,9 +255,9 @@
}
return BuildMat2X4(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat2x4<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat2x4" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -275,9 +275,9 @@
}
return BuildMat3X2(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat3x2<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat3x2" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -295,9 +295,9 @@
}
return BuildMat3X3(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat3x3<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat3x3" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -315,9 +315,9 @@
}
return BuildMat3X4(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat3x4<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat3x4" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -335,9 +335,9 @@
}
return BuildMat4X2(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat4x2<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat4x2" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -355,9 +355,9 @@
}
return BuildMat4X3(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat4x3<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat4x3" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -375,9 +375,9 @@
}
return BuildMat4X4(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat4x4<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat4x4" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -400,12 +400,10 @@
}
return BuildVec(state, ty, N, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string N = state->NumName();
- const std::string T = state->TypeName();
- StringStream ss;
- ss << "vec" << N << "<" << T << ">";
- return ss.str();
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N;
+ state->PrintNum(N);StyledText T;
+ state->PrintType(T);
+ out << style::Type << "vec" << style::Type << N << style::Type << "<" << style::Type << T << style::Type << ">";
}
};
@@ -433,13 +431,11 @@
}
return BuildMat(state, ty, N, M, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string N = state->NumName();
- const std::string M = state->NumName();
- const std::string T = state->TypeName();
- StringStream ss;
- ss << "mat" << N << "x" << M << "<" << T << ">";
- return ss.str();
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N;
+ state->PrintNum(N);StyledText M;
+ state->PrintNum(M);StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat" << style::Type << N << style::Type << "x" << style::Type << M << style::Type << "<" << style::Type << T << style::Type << ">";
}
};
@@ -467,11 +463,11 @@
}
return BuildPtr(state, ty, S, T, A);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string S = state->NumName();
- const std::string T = state->TypeName();
- const std::string A = state->NumName();
- return "ptr<" + S + ", " + T + ", " + A + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText S;
+ state->PrintNum(S);StyledText T;
+ state->PrintType(T);StyledText A;
+ state->PrintNum(A);
+ out << style::Type << "ptr" << style::Code << "<" << style::Type << S << style::Code << ", " << style::Type << T << style::Code << ", " << style::Type << A << style::Code << ">";
}
};
@@ -489,9 +485,9 @@
}
return BuildAtomic(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "atomic<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "atomic" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -509,9 +505,9 @@
}
return BuildArray(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "array<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "array" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -524,8 +520,8 @@
}
return BuildSampler(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "sampler";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "sampler";
}
};
@@ -538,8 +534,8 @@
}
return BuildSamplerComparison(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "sampler_comparison";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "sampler_comparison";
}
};
@@ -557,9 +553,9 @@
}
return BuildTexture1D(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_1d<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_1d" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -577,9 +573,9 @@
}
return BuildTexture2D(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_2d<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_2d" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -597,9 +593,9 @@
}
return BuildTexture2DArray(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_2d_array<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_2d_array" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -617,9 +613,9 @@
}
return BuildTexture3D(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_3d<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_3d" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -637,9 +633,9 @@
}
return BuildTextureCube(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_cube<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_cube" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -657,9 +653,9 @@
}
return BuildTextureCubeArray(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_cube_array<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_cube_array" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -677,9 +673,9 @@
}
return BuildTextureMultisampled2D(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_multisampled_2d<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_multisampled_2d" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -692,8 +688,8 @@
}
return BuildTextureDepth2D(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "texture_depth_2d";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "texture_depth_2d";
}
};
@@ -706,8 +702,8 @@
}
return BuildTextureDepth2DArray(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "texture_depth_2d_array";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "texture_depth_2d_array";
}
};
@@ -720,8 +716,8 @@
}
return BuildTextureDepthCube(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "texture_depth_cube";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "texture_depth_cube";
}
};
@@ -734,8 +730,8 @@
}
return BuildTextureDepthCubeArray(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "texture_depth_cube_array";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "texture_depth_cube_array";
}
};
@@ -748,8 +744,8 @@
}
return BuildTextureDepthMultisampled2D(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "texture_depth_multisampled_2d";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "texture_depth_multisampled_2d";
}
};
@@ -772,10 +768,10 @@
}
return BuildTextureStorage1D(state, ty, F, A);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string F = state->NumName();
- const std::string A = state->NumName();
- return "texture_storage_1d<" + F + ", " + A + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F;
+ state->PrintNum(F);StyledText A;
+ state->PrintNum(A);
+ out << style::Type << "texture_storage_1d" << style::Code << "<" << style::Type << F << style::Code << ", " << style::Type << A << style::Code << ">";
}
};
@@ -798,10 +794,10 @@
}
return BuildTextureStorage2D(state, ty, F, A);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string F = state->NumName();
- const std::string A = state->NumName();
- return "texture_storage_2d<" + F + ", " + A + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F;
+ state->PrintNum(F);StyledText A;
+ state->PrintNum(A);
+ out << style::Type << "texture_storage_2d" << style::Code << "<" << style::Type << F << style::Code << ", " << style::Type << A << style::Code << ">";
}
};
@@ -824,10 +820,10 @@
}
return BuildTextureStorage2DArray(state, ty, F, A);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string F = state->NumName();
- const std::string A = state->NumName();
- return "texture_storage_2d_array<" + F + ", " + A + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F;
+ state->PrintNum(F);StyledText A;
+ state->PrintNum(A);
+ out << style::Type << "texture_storage_2d_array" << style::Code << "<" << style::Type << F << style::Code << ", " << style::Type << A << style::Code << ">";
}
};
@@ -850,10 +846,10 @@
}
return BuildTextureStorage3D(state, ty, F, A);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string F = state->NumName();
- const std::string A = state->NumName();
- return "texture_storage_3d<" + F + ", " + A + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F;
+ state->PrintNum(F);StyledText A;
+ state->PrintNum(A);
+ out << style::Type << "texture_storage_3d" << style::Code << "<" << style::Type << F << style::Code << ", " << style::Type << A << style::Code << ">";
}
};
@@ -866,8 +862,8 @@
}
return BuildTextureExternal(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "texture_external";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "texture_external";
}
};
@@ -885,11 +881,9 @@
}
return BuildModfResult(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- StringStream ss;
- ss << "__modf_result_" << T;
- return ss.str();
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "__modf_result_" << style::Type << T;
}
};
@@ -912,12 +906,10 @@
}
return BuildModfResultVec(state, ty, N, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string N = state->NumName();
- const std::string T = state->TypeName();
- StringStream ss;
- ss << "__modf_result_vec" << N << "_" << T;
- return ss.str();
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N;
+ state->PrintNum(N);StyledText T;
+ state->PrintType(T);
+ out << style::Type << "__modf_result_vec" << style::Type << N << style::Type << "_" << style::Type << T;
}
};
@@ -935,11 +927,9 @@
}
return BuildFrexpResult(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- StringStream ss;
- ss << "__frexp_result_" << T;
- return ss.str();
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "__frexp_result_" << style::Type << T;
}
};
@@ -962,12 +952,10 @@
}
return BuildFrexpResultVec(state, ty, N, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string N = state->NumName();
- const std::string T = state->TypeName();
- StringStream ss;
- ss << "__frexp_result_vec" << N << "_" << T;
- return ss.str();
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N;
+ state->PrintNum(N);StyledText T;
+ state->PrintType(T);
+ out << style::Type << "__frexp_result_vec" << style::Type << N << style::Type << "_" << style::Type << T;
}
};
@@ -985,9 +973,9 @@
}
return BuildAtomicCompareExchangeResult(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "__atomic_compare_exchange_result<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "__atomic_compare_exchange_result" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -1012,13 +1000,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kF32Matcher.string(nullptr) << ", " << kF16Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << ", " << kU32Matcher.string(nullptr) << " or " << kBoolMatcher.string(nullptr);
- return ss.str();
- }
+ kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kF16Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kU32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kBoolMatcher.print(nullptr, out);}
};
/// TypeMatcher for 'match scalar_no_f32'
@@ -1038,13 +1023,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kI32Matcher.string(nullptr) << ", " << kF16Matcher.string(nullptr) << ", " << kU32Matcher.string(nullptr) << " or " << kBoolMatcher.string(nullptr);
- return ss.str();
- }
+ kI32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kF16Matcher.print(nullptr, out); out << TextStyle{} << ", "; kU32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kBoolMatcher.print(nullptr, out);}
};
/// TypeMatcher for 'match scalar_no_f16'
@@ -1064,13 +1046,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kF32Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << ", " << kU32Matcher.string(nullptr) << " or " << kBoolMatcher.string(nullptr);
- return ss.str();
- }
+ kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kU32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kBoolMatcher.print(nullptr, out);}
};
/// TypeMatcher for 'match scalar_no_i32'
@@ -1090,13 +1069,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kF32Matcher.string(nullptr) << ", " << kF16Matcher.string(nullptr) << ", " << kU32Matcher.string(nullptr) << " or " << kBoolMatcher.string(nullptr);
- return ss.str();
- }
+ kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kF16Matcher.print(nullptr, out); out << TextStyle{} << ", "; kU32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kBoolMatcher.print(nullptr, out);}
};
/// TypeMatcher for 'match scalar_no_u32'
@@ -1116,13 +1092,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kF32Matcher.string(nullptr) << ", " << kF16Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << " or " << kBoolMatcher.string(nullptr);
- return ss.str();
- }
+ kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kF16Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kBoolMatcher.print(nullptr, out);}
};
/// TypeMatcher for 'match scalar_no_bool'
@@ -1142,13 +1115,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kF32Matcher.string(nullptr) << ", " << kF16Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << " or " << kU32Matcher.string(nullptr);
- return ss.str();
- }
+ kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kF16Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kU32Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match fiu32_f16'
@@ -1168,13 +1138,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kF32Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << ", " << kU32Matcher.string(nullptr) << " or " << kF16Matcher.string(nullptr);
- return ss.str();
- }
+ kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kU32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kF16Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match fiu32'
@@ -1191,13 +1158,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kF32Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << " or " << kU32Matcher.string(nullptr);
- return ss.str();
- }
+ kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kU32Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match fi32_f16'
@@ -1214,13 +1178,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kF32Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << " or " << kF16Matcher.string(nullptr);
- return ss.str();
- }
+ kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kF16Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match fi32'
@@ -1234,13 +1195,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kF32Matcher.string(nullptr) << " or " << kI32Matcher.string(nullptr);
- return ss.str();
- }
+ kF32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kI32Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match f32_f16'
@@ -1254,13 +1212,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kF32Matcher.string(nullptr) << " or " << kF16Matcher.string(nullptr);
- return ss.str();
- }
+ kF32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kF16Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match iu32'
@@ -1274,13 +1229,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kI32Matcher.string(nullptr) << " or " << kU32Matcher.string(nullptr);
- return ss.str();
- }
+ kI32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kU32Matcher.print(nullptr, out);}
};
/// EnumMatcher for 'match f32_texel_format'
@@ -1299,8 +1251,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "bgra8unorm, rgba8unorm, rgba8snorm, rgba16float, r32float, rg32float or rgba32float";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "bgra8unorm"<< TextStyle{} << ", " << style::Enum << "rgba8unorm"<< TextStyle{} << ", " << style::Enum << "rgba8snorm"<< TextStyle{} << ", " << style::Enum << "rgba16float"<< TextStyle{} << ", " << style::Enum << "r32float"<< TextStyle{} << ", " << style::Enum << "rg32float"<< TextStyle{} << " or " << style::Enum << "rgba32float";
}
};
@@ -1318,8 +1270,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "rgba8sint, rgba16sint, r32sint, rg32sint or rgba32sint";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "rgba8sint"<< TextStyle{} << ", " << style::Enum << "rgba16sint"<< TextStyle{} << ", " << style::Enum << "r32sint"<< TextStyle{} << ", " << style::Enum << "rg32sint"<< TextStyle{} << " or " << style::Enum << "rgba32sint";
}
};
@@ -1337,8 +1289,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "rgba8uint, rgba16uint, r32uint, rg32uint or rgba32uint";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "rgba8uint"<< TextStyle{} << ", " << style::Enum << "rgba16uint"<< TextStyle{} << ", " << style::Enum << "r32uint"<< TextStyle{} << ", " << style::Enum << "rg32uint"<< TextStyle{} << " or " << style::Enum << "rgba32uint";
}
};
@@ -1350,8 +1302,8 @@
}
return Number::invalid;
},
-/* string */ [](MatchState*) -> std::string {
- return "write";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "write";
}
};
@@ -1363,8 +1315,8 @@
}
return Number::invalid;
},
-/* string */ [](MatchState*) -> std::string {
- return "read_write";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "read_write";
}
};
@@ -1379,8 +1331,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "read or read_write";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "read"<< TextStyle{} << " or " << style::Enum << "read_write";
}
};
@@ -1395,8 +1347,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "write or read_write";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "write"<< TextStyle{} << " or " << style::Enum << "read_write";
}
};
@@ -1412,8 +1364,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "function, private or workgroup";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "function"<< TextStyle{} << ", " << style::Enum << "private"<< TextStyle{} << " or " << style::Enum << "workgroup";
}
};
@@ -1428,8 +1380,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "workgroup or storage";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "workgroup"<< TextStyle{} << " or " << style::Enum << "storage";
}
};
@@ -1441,8 +1393,8 @@
}
return Number::invalid;
},
-/* string */ [](MatchState*) -> std::string {
- return "storage";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "storage";
}
};
@@ -1454,8 +1406,8 @@
}
return Number::invalid;
},
-/* string */ [](MatchState*) -> std::string {
- return "workgroup";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "workgroup";
}
};
diff --git a/src/tint/lang/core/intrinsic/table.cc b/src/tint/lang/core/intrinsic/table.cc
index d7c080e..dd96db5 100644
--- a/src/tint/lang/core/intrinsic/table.cc
+++ b/src/tint/lang/core/intrinsic/table.cc
@@ -37,7 +37,10 @@
#include "src/tint/lang/core/type/manager.h"
#include "src/tint/lang/core/type/void.h"
#include "src/tint/utils/ice/ice.h"
+#include "src/tint/utils/macros/defer.h"
#include "src/tint/utils/text/string_stream.h"
+#include "src/tint/utils/text/styled_text.h"
+#include "src/tint/utils/text/text_style.h"
namespace tint::core::intrinsic {
@@ -86,7 +89,7 @@
using Candidates = Vector<Candidate, kNumFixedCandidates>;
/// Callback function when no overloads match.
-using OnNoMatch = std::function<std::string(VectorRef<Candidate>)>;
+using OnNoMatch = std::function<StyledText(VectorRef<Candidate>)>;
/// Sorts the candidates based on their score, with the lowest (best-ranking) scores first.
static inline void SortCandidates(Candidates& candidates) {
@@ -94,15 +97,17 @@
[&](const Candidate& a, const Candidate& b) { return a.score < b.score; });
}
-static void PrintTypeList(StringStream& ss, VectorRef<const core::type::Type*> types) {
+/// Prints a list of types. Ends with the style of @p ss set to style::Code.
+static void PrintTypeList(StyledText& ss, VectorRef<const core::type::Type*> types) {
bool first = true;
for (auto* arg : types) {
if (!first) {
- ss << ", ";
+ ss << style::Code << ", ";
}
first = false;
- ss << arg->FriendlyName();
+ ss << style::Type << arg->FriendlyName();
}
+ ss << style::Code;
}
/// Attempts to find a single intrinsic overload that matches the provided argument types.
@@ -114,13 +119,13 @@
/// @param on_no_match an error callback when no intrinsic overloads matched the provided
/// arguments.
/// @returns the matched intrinsic
-Result<Overload, std::string> MatchIntrinsic(Context& context,
- const IntrinsicInfo& intrinsic,
- std::string_view intrinsic_name,
- VectorRef<const core::type::Type*> template_args,
- VectorRef<const core::type::Type*> args,
- EvaluationStage earliest_eval_stage,
- const OnNoMatch& on_no_match);
+Result<Overload, StyledText> MatchIntrinsic(Context& context,
+ const IntrinsicInfo& intrinsic,
+ std::string_view intrinsic_name,
+ VectorRef<const core::type::Type*> template_args,
+ VectorRef<const core::type::Type*> args,
+ EvaluationStage earliest_eval_stage,
+ const OnNoMatch& on_no_match);
/// The scoring mode for ScoreOverload()
enum class ScoreMode {
@@ -156,11 +161,11 @@
/// @param args the argument types
/// @see https://www.w3.org/TR/WGSL/#overload-resolution-section
/// @returns the resolved Candidate.
-Result<Candidate, std::string> ResolveCandidate(Context& context,
- Candidates&& candidates,
- std::string_view intrinsic_name,
- VectorRef<const core::type::Type*> template_args,
- VectorRef<const core::type::Type*> args);
+Result<Candidate, StyledText> ResolveCandidate(Context& context,
+ Candidates&& candidates,
+ std::string_view intrinsic_name,
+ VectorRef<const core::type::Type*> template_args,
+ VectorRef<const core::type::Type*> args);
/// Match constructs a new MatchState
/// @param context the intrinsic context
@@ -174,43 +179,44 @@
EvaluationStage earliest_eval_stage);
// Prints the list of candidates for emitting diagnostics
-void PrintCandidates(StringStream& ss,
+void PrintCandidates(StyledText& err,
Context& context,
VectorRef<Candidate> candidates,
std::string_view intrinsic_name);
/// Raises an ICE when no overload is a clear winner of overload resolution
-std::string ErrAmbiguousOverload(Context& context,
- std::string_view intrinsic_name,
- VectorRef<const core::type::Type*> template_args,
- VectorRef<const core::type::Type*> args,
- VectorRef<Candidate> candidates);
+StyledText ErrAmbiguousOverload(Context& context,
+ std::string_view intrinsic_name,
+ VectorRef<const core::type::Type*> template_args,
+ VectorRef<const core::type::Type*> args,
+ VectorRef<Candidate> candidates);
/// @return a string representing a call to a builtin with the given argument
/// types.
-std::string CallSignature(std::string_view intrinsic_name,
- VectorRef<const core::type::Type*> template_args,
- VectorRef<const core::type::Type*> args) {
- StringStream ss;
- ss << intrinsic_name;
+StyledText CallSignature(std::string_view intrinsic_name,
+ VectorRef<const core::type::Type*> template_args,
+ VectorRef<const core::type::Type*> args) {
+ StyledText out;
+ out << style::Function << intrinsic_name << style::Code;
if (!template_args.IsEmpty()) {
- ss << "<";
- PrintTypeList(ss, template_args);
- ss << ">";
+ out << "<";
+ PrintTypeList(out, template_args);
+ out << ">";
}
- ss << "(";
- PrintTypeList(ss, args);
- ss << ")";
- return ss.str();
+ out << "(";
+ PrintTypeList(out, args);
+ out << ")" << style::Plain;
+
+ return out;
}
-Result<Overload, std::string> MatchIntrinsic(Context& context,
- const IntrinsicInfo& intrinsic,
- std::string_view intrinsic_name,
- VectorRef<const core::type::Type*> template_args,
- VectorRef<const core::type::Type*> args,
- EvaluationStage earliest_eval_stage,
- const OnNoMatch& on_no_match) {
+Result<Overload, StyledText> MatchIntrinsic(Context& context,
+ const IntrinsicInfo& intrinsic,
+ std::string_view intrinsic_name,
+ VectorRef<const core::type::Type*> template_args,
+ VectorRef<const core::type::Type*> args,
+ EvaluationStage earliest_eval_stage,
+ const OnNoMatch& on_no_match) {
const size_t num_overloads = static_cast<size_t>(intrinsic.num_overloads);
size_t num_matched = 0;
size_t match_idx = 0;
@@ -261,8 +267,9 @@
Match(context, match.templates, *match.overload, matcher_indices, earliest_eval_stage)
.Type(&any);
if (TINT_UNLIKELY(!return_type)) {
- std::string err = "MatchState.Match() returned null";
- TINT_ICE() << err;
+ StyledText err;
+ err << "MatchState.Match() returned null";
+ TINT_ICE() << err.Plain();
return err;
}
} else {
@@ -423,11 +430,11 @@
#undef MATCH_FAILURE
}
-Result<Candidate, std::string> ResolveCandidate(Context& context,
- Candidates&& candidates,
- std::string_view intrinsic_name,
- VectorRef<const core::type::Type*> template_args,
- VectorRef<const core::type::Type*> args) {
+Result<Candidate, StyledText> ResolveCandidate(Context& context,
+ Candidates&& candidates,
+ std::string_view intrinsic_name,
+ VectorRef<const core::type::Type*> template_args,
+ VectorRef<const core::type::Type*> args) {
Vector<uint32_t, kNumFixedParams> best_ranks;
best_ranks.Resize(args.Length(), 0xffffffff);
size_t num_matched = 0;
@@ -497,57 +504,59 @@
overload, matcher_indices, earliest_eval_stage};
}
-void PrintCandidates(StringStream& ss,
+void PrintCandidates(StyledText& ss,
Context& context,
VectorRef<Candidate> candidates,
std::string_view intrinsic_name) {
for (auto& candidate : candidates) {
ss << " ";
PrintOverload(ss, context, *candidate.overload, intrinsic_name);
- ss << std::endl;
+ ss << "\n";
}
}
-std::string ErrAmbiguousOverload(Context& context,
- std::string_view intrinsic_name,
- VectorRef<const core::type::Type*> template_args,
- VectorRef<const core::type::Type*> args,
- VectorRef<Candidate> candidates) {
- StringStream ss;
- ss << "ambiguous overload while attempting to match "
- << CallSignature(intrinsic_name, template_args, args) << "\n";
+StyledText ErrAmbiguousOverload(Context& context,
+ std::string_view intrinsic_name,
+ VectorRef<const core::type::Type*> template_args,
+ VectorRef<const core::type::Type*> args,
+ VectorRef<Candidate> candidates) {
+ StyledText err;
+ err << "ambiguous overload while attempting to match "
+ << CallSignature(intrinsic_name, template_args, args) << "\n";
for (auto& candidate : candidates) {
if (candidate.score == 0) {
- ss << " ";
- PrintOverload(ss, context, *candidate.overload, intrinsic_name);
- ss << "\n";
+ err << " ";
+ PrintOverload(err, context, *candidate.overload, intrinsic_name);
+ err << "\n";
}
}
- TINT_ICE() << ss.str();
- return ss.str();
+ TINT_ICE() << err.Plain();
+ return err;
}
} // namespace
-void PrintOverload(StringStream& ss,
+void PrintOverload(StyledText& ss,
Context& context,
const OverloadInfo& overload,
std::string_view intrinsic_name) {
+ TINT_DEFER(ss << style::Plain);
+
TemplateState templates;
// TODO(crbug.com/tint/1730): Use input evaluation stage to output only relevant overloads.
auto earliest_eval_stage = EvaluationStage::kConstant;
- ss << intrinsic_name;
+ ss << style::Function << intrinsic_name << style::Code;
if (overload.num_explicit_templates > 0) {
ss << "<";
for (size_t i = 0; i < overload.num_explicit_templates; i++) {
if (i > 0) {
- ss << ", ";
+ ss << style::Code << ", ";
}
- ss << context.data[overload.templates + i].name;
+ ss << style::Type << context.data[overload.templates + i].name;
}
ss << ">";
}
@@ -555,24 +564,24 @@
for (size_t p = 0; p < overload.num_parameters; p++) {
auto& parameter = context.data[overload.parameters + p];
if (p > 0) {
- ss << ", ";
+ ss << style::Code << ", ";
}
if (parameter.usage != ParameterUsage::kNone) {
- ss << ToString(parameter.usage) << ": ";
+ ss << style::Variable << ToString(parameter.usage) << style::Code << ": ";
}
auto* matcher_indices = context.data[parameter.matcher_indices];
- ss << Match(context, templates, overload, matcher_indices, earliest_eval_stage).TypeName();
+ Match(context, templates, overload, matcher_indices, earliest_eval_stage).PrintType(ss);
}
- ss << ")";
+ ss << style::Code << ")";
if (overload.return_matcher_indices.IsValid()) {
ss << " -> ";
auto* matcher_indices = context.data[overload.return_matcher_indices];
- ss << Match(context, templates, overload, matcher_indices, earliest_eval_stage).TypeName();
+ Match(context, templates, overload, matcher_indices, earliest_eval_stage).PrintType(ss);
}
bool first = true;
auto separator = [&] {
- ss << (first ? " where: " : ", ");
+ ss << style::Plain << (first ? " where: " : ", ");
first = false;
};
@@ -583,35 +592,33 @@
Match(context, templates, overload, matcher_indices, earliest_eval_stage);
separator();
- ss << tmpl.name;
- ss << " is ";
+ ss << style::Type << tmpl.name << style::Plain << " is ";
if (tmpl.kind == TemplateInfo::Kind::kType) {
- ss << matcher.TypeName();
+ matcher.PrintType(ss);
} else {
- ss << matcher.NumName();
+ matcher.PrintNum(ss);
}
}
}
}
-Result<Overload, std::string> LookupFn(Context& context,
- std::string_view intrinsic_name,
- size_t function_id,
- VectorRef<const core::type::Type*> template_args,
- VectorRef<const core::type::Type*> args,
- EvaluationStage earliest_eval_stage) {
+Result<Overload, StyledText> LookupFn(Context& context,
+ std::string_view intrinsic_name,
+ size_t function_id,
+ VectorRef<const core::type::Type*> template_args,
+ VectorRef<const core::type::Type*> args,
+ EvaluationStage earliest_eval_stage) {
// Generates an error when no overloads match the provided arguments
auto on_no_match = [&](VectorRef<Candidate> candidates) {
- StringStream ss;
- ss << "no matching call to " << CallSignature(intrinsic_name, template_args, args)
- << std::endl;
+ StyledText err;
+ err << "no matching call to " << CallSignature(intrinsic_name, template_args, args) << "\n";
if (!candidates.IsEmpty()) {
- ss << std::endl
- << candidates.Length() << " candidate function"
- << (candidates.Length() > 1 ? "s:" : ":") << std::endl;
- PrintCandidates(ss, context, candidates, intrinsic_name);
+ err << "\n"
+ << candidates.Length() << " candidate function"
+ << (candidates.Length() > 1 ? "s:" : ":") << "\n";
+ PrintCandidates(err, context, candidates, intrinsic_name);
}
- return ss.str();
+ return err;
};
// Resolve the intrinsic overload
@@ -619,10 +626,10 @@
template_args, args, earliest_eval_stage, on_no_match);
}
-Result<Overload, std::string> LookupUnary(Context& context,
- core::UnaryOp op,
- const core::type::Type* arg,
- EvaluationStage earliest_eval_stage) {
+Result<Overload, StyledText> LookupUnary(Context& context,
+ core::UnaryOp op,
+ const core::type::Type* arg,
+ EvaluationStage earliest_eval_stage) {
const IntrinsicInfo* intrinsic_info = nullptr;
std::string_view intrinsic_name;
switch (op) {
@@ -652,15 +659,15 @@
// Generates an error when no overloads match the provided arguments
auto on_no_match = [&, name = intrinsic_name](VectorRef<Candidate> candidates) {
- StringStream ss;
- ss << "no matching overload for " << CallSignature(name, Empty, args) << std::endl;
+ StyledText err;
+ err << "no matching overload for " << CallSignature(name, Empty, args) << "\n";
if (!candidates.IsEmpty()) {
- ss << std::endl
- << candidates.Length() << " candidate operator"
- << (candidates.Length() > 1 ? "s:" : ":") << std::endl;
- PrintCandidates(ss, context, candidates, name);
+ err << "\n"
+ << candidates.Length() << " candidate operator"
+ << (candidates.Length() > 1 ? "s:" : ":") << "\n";
+ PrintCandidates(err, context, candidates, name);
}
- return ss.str();
+ return err;
};
// Resolve the intrinsic overload
@@ -668,12 +675,12 @@
earliest_eval_stage, on_no_match);
}
-Result<Overload, std::string> LookupBinary(Context& context,
- core::BinaryOp op,
- const core::type::Type* lhs,
- const core::type::Type* rhs,
- EvaluationStage earliest_eval_stage,
- bool is_compound) {
+Result<Overload, StyledText> LookupBinary(Context& context,
+ core::BinaryOp op,
+ const core::type::Type* lhs,
+ const core::type::Type* rhs,
+ EvaluationStage earliest_eval_stage,
+ bool is_compound) {
const IntrinsicInfo* intrinsic_info = nullptr;
std::string_view intrinsic_name;
switch (op) {
@@ -755,15 +762,15 @@
// Generates an error when no overloads match the provided arguments
auto on_no_match = [&, name = intrinsic_name](VectorRef<Candidate> candidates) {
- StringStream ss;
- ss << "no matching overload for " << CallSignature(name, Empty, args) << std::endl;
+ StyledText err;
+ err << "no matching overload for " << CallSignature(name, Empty, args) << "\n";
if (!candidates.IsEmpty()) {
- ss << std::endl
- << candidates.Length() << " candidate operator"
- << (candidates.Length() > 1 ? "s:" : ":") << std::endl;
- PrintCandidates(ss, context, candidates, name);
+ err << "\n"
+ << candidates.Length() << " candidate operator"
+ << (candidates.Length() > 1 ? "s:" : ":") << "\n";
+ PrintCandidates(err, context, candidates, name);
}
- return ss.str();
+ return err;
};
// Resolve the intrinsic overload
@@ -771,17 +778,17 @@
earliest_eval_stage, on_no_match);
}
-Result<Overload, std::string> LookupCtorConv(Context& context,
- std::string_view type_name,
- size_t type_id,
- VectorRef<const core::type::Type*> template_args,
- VectorRef<const core::type::Type*> args,
- EvaluationStage earliest_eval_stage) {
+Result<Overload, StyledText> LookupCtorConv(Context& context,
+ std::string_view type_name,
+ size_t type_id,
+ VectorRef<const core::type::Type*> template_args,
+ VectorRef<const core::type::Type*> args,
+ EvaluationStage earliest_eval_stage) {
// Generates an error when no overloads match the provided arguments
auto on_no_match = [&](VectorRef<Candidate> candidates) {
- StringStream ss;
- ss << "no matching constructor for " << CallSignature(type_name, template_args, args)
- << std::endl;
+ StyledText err;
+ err << "no matching constructor for " << CallSignature(type_name, template_args, args)
+ << "\n";
Candidates ctor, conv;
for (auto candidate : candidates) {
if (candidate.overload->flags.Contains(OverloadFlag::kIsConstructor)) {
@@ -791,18 +798,18 @@
}
}
if (!ctor.IsEmpty()) {
- ss << std::endl
- << ctor.Length() << " candidate constructor" << (ctor.Length() > 1 ? "s:" : ":")
- << std::endl;
- PrintCandidates(ss, context, ctor, type_name);
+ err << "\n"
+ << ctor.Length() << " candidate constructor" << (ctor.Length() > 1 ? "s:" : ":")
+ << "\n";
+ PrintCandidates(err, context, ctor, type_name);
}
if (!conv.IsEmpty()) {
- ss << std::endl
- << conv.Length() << " candidate conversion" << (conv.Length() > 1 ? "s:" : ":")
- << std::endl;
- PrintCandidates(ss, context, conv, type_name);
+ err << "\n"
+ << conv.Length() << " candidate conversion" << (conv.Length() > 1 ? "s:" : ":")
+ << "\n";
+ PrintCandidates(err, context, conv, type_name);
}
- return ss.str();
+ return err;
};
// Resolve the intrinsic overload
diff --git a/src/tint/lang/core/intrinsic/table.h b/src/tint/lang/core/intrinsic/table.h
index c77e61b..56f590a 100644
--- a/src/tint/lang/core/intrinsic/table.h
+++ b/src/tint/lang/core/intrinsic/table.h
@@ -39,7 +39,9 @@
#include "src/tint/lang/core/parameter_usage.h"
#include "src/tint/lang/core/unary_op.h"
#include "src/tint/utils/containers/vector.h"
+#include "src/tint/utils/text/string.h"
#include "src/tint/utils/text/string_stream.h"
+#include "src/tint/utils/text/styled_text.h"
// Forward declarations
namespace tint::diag {
@@ -107,7 +109,7 @@
};
// Prints the overload for emitting diagnostics
-void PrintOverload(StringStream& ss,
+void PrintOverload(StyledText& ss,
Context& context,
const OverloadInfo& overload,
std::string_view intrinsic_name);
@@ -126,12 +128,12 @@
/// abstract-numerics will have been materialized after shader creation time
/// (EvaluationStage::kConstant).
/// @return the resolved builtin function overload
-Result<Overload, std::string> LookupFn(Context& context,
- std::string_view function_name,
- size_t function_id,
- VectorRef<const core::type::Type*> template_args,
- VectorRef<const core::type::Type*> args,
- EvaluationStage earliest_eval_stage);
+Result<Overload, StyledText> LookupFn(Context& context,
+ std::string_view function_name,
+ size_t function_id,
+ VectorRef<const core::type::Type*> template_args,
+ VectorRef<const core::type::Type*> args,
+ EvaluationStage earliest_eval_stage);
/// Lookup looks for the unary op overload with the given signature, raising an error
/// diagnostic if the operator was not found.
@@ -145,10 +147,10 @@
/// will be considered, as all abstract-numerics will have been materialized
/// after shader creation time (EvaluationStage::kConstant).
/// @return the resolved unary operator overload
-Result<Overload, std::string> LookupUnary(Context& context,
- core::UnaryOp op,
- const core::type::Type* arg,
- EvaluationStage earliest_eval_stage);
+Result<Overload, StyledText> LookupUnary(Context& context,
+ core::UnaryOp op,
+ const core::type::Type* arg,
+ EvaluationStage earliest_eval_stage);
/// Lookup looks for the binary op overload with the given signature, raising an error
/// diagnostic if the operator was not found.
@@ -164,12 +166,12 @@
/// after shader creation time (EvaluationStage::kConstant).
/// @param is_compound true if the binary operator is being used as a compound assignment
/// @return the resolved binary operator overload
-Result<Overload, std::string> LookupBinary(Context& context,
- core::BinaryOp op,
- const core::type::Type* lhs,
- const core::type::Type* rhs,
- EvaluationStage earliest_eval_stage,
- bool is_compound);
+Result<Overload, StyledText> LookupBinary(Context& context,
+ core::BinaryOp op,
+ const core::type::Type* lhs,
+ const core::type::Type* rhs,
+ EvaluationStage earliest_eval_stage,
+ bool is_compound);
/// Lookup looks for the value constructor or conversion overload for the given CtorConv.
/// @param context the intrinsic context
@@ -184,12 +186,12 @@
/// will be considered, as all abstract-numerics will have been materialized
/// after shader creation time (EvaluationStage::kConstant).
/// @return the resolved type constructor or conversion function overload
-Result<Overload, std::string> LookupCtorConv(Context& context,
- std::string_view type_name,
- size_t type_id,
- VectorRef<const core::type::Type*> template_args,
- VectorRef<const core::type::Type*> args,
- EvaluationStage earliest_eval_stage);
+Result<Overload, StyledText> LookupCtorConv(Context& context,
+ std::string_view type_name,
+ size_t type_id,
+ VectorRef<const core::type::Type*> template_args,
+ VectorRef<const core::type::Type*> args,
+ EvaluationStage earliest_eval_stage);
/// Table is a wrapper around a dialect to provide type-safe interface to the intrinsic table.
template <typename DIALECT>
@@ -219,12 +221,11 @@
/// only overloads with concrete argument types will be considered, as all
/// abstract-numerics will have been materialized after shader creation time
/// (EvaluationStage::kConstant).
-
/// @return the resolved builtin function overload
- Result<Overload, std::string> Lookup(BuiltinFn builtin_fn,
- VectorRef<const core::type::Type*> template_args,
- VectorRef<const core::type::Type*> args,
- EvaluationStage earliest_eval_stage) {
+ Result<Overload, StyledText> Lookup(BuiltinFn builtin_fn,
+ VectorRef<const core::type::Type*> template_args,
+ VectorRef<const core::type::Type*> args,
+ EvaluationStage earliest_eval_stage) {
std::string_view name = DIALECT::ToString(builtin_fn);
size_t id = static_cast<size_t>(builtin_fn);
return LookupFn(context, name, id, std::move(template_args), std::move(args),
@@ -243,9 +244,9 @@
/// after shader creation time (EvaluationStage::kConstant).
/// @return the resolved unary operator overload
- Result<Overload, std::string> Lookup(core::UnaryOp op,
- const core::type::Type* arg,
- EvaluationStage earliest_eval_stage) {
+ Result<Overload, StyledText> Lookup(core::UnaryOp op,
+ const core::type::Type* arg,
+ EvaluationStage earliest_eval_stage) {
return LookupUnary(context, op, arg, earliest_eval_stage);
}
@@ -263,11 +264,11 @@
/// @param is_compound true if the binary operator is being used as a compound assignment
/// @return the resolved binary operator overload
- Result<Overload, std::string> Lookup(core::BinaryOp op,
- const core::type::Type* lhs,
- const core::type::Type* rhs,
- EvaluationStage earliest_eval_stage,
- bool is_compound) {
+ Result<Overload, StyledText> Lookup(core::BinaryOp op,
+ const core::type::Type* lhs,
+ const core::type::Type* rhs,
+ EvaluationStage earliest_eval_stage,
+ bool is_compound) {
return LookupBinary(context, op, lhs, rhs, earliest_eval_stage, is_compound);
}
@@ -281,12 +282,11 @@
/// `EvaluationStage::kRuntime`, then only overloads with concrete argument types
/// will be considered, as all abstract-numerics will have been materialized
/// after shader creation time (EvaluationStage::kConstant).
-
/// @return the resolved type constructor or conversion function overload
- Result<Overload, std::string> Lookup(CtorConv type,
- VectorRef<const core::type::Type*> template_args,
- VectorRef<const core::type::Type*> args,
- EvaluationStage earliest_eval_stage) {
+ Result<Overload, StyledText> Lookup(CtorConv type,
+ VectorRef<const core::type::Type*> template_args,
+ VectorRef<const core::type::Type*> args,
+ EvaluationStage earliest_eval_stage) {
std::string_view name = DIALECT::ToString(type);
size_t id = static_cast<size_t>(type);
return LookupCtorConv(context, name, id, std::move(template_args), std::move(args),
diff --git a/src/tint/lang/core/intrinsic/table_data.h b/src/tint/lang/core/intrinsic/table_data.h
index b2d86c0..1ed619d 100644
--- a/src/tint/lang/core/intrinsic/table_data.h
+++ b/src/tint/lang/core/intrinsic/table_data.h
@@ -37,6 +37,8 @@
#include "src/tint/lang/core/parameter_usage.h"
#include "src/tint/utils/containers/enum_set.h"
#include "src/tint/utils/containers/slice.h"
+#include "src/tint/utils/text/styled_text.h"
+#include "src/tint/utils/text/text_style.h"
/// Forward declaration
namespace tint::core::intrinsic {
@@ -414,13 +416,13 @@
/// @note: The matcher indices are progressed on calling.
inline Number Num(Number number);
- /// @returns a string representation of the next TypeMatcher from the matcher indices.
+ /// Prints the type matcher representation to @p out
/// @note: The matcher indices are progressed on calling.
- inline std::string TypeName();
+ inline void PrintType(StyledText& out);
- /// @returns a string representation of the next NumberMatcher from the matcher indices.
+ /// Prints the number matcher representation to @p out
/// @note: The matcher indices are progressed on calling.
- inline std::string NumName();
+ inline void PrintNum(StyledText& out);
private:
const MatcherIndex* matcher_indices_ = nullptr;
@@ -439,12 +441,12 @@
/// @see #MatchFn
MatchFn* const match;
- /// Returns a string representation of the matcher.
+ /// Prints the representation of the matcher.
/// Used for printing error messages when no overload is found.
- using StringFn = std::string(MatchState* state);
+ using PrintFn = void(MatchState* state, StyledText& out);
- /// @see #StringFn
- StringFn* const string;
+ /// @see #PrintFn
+ PrintFn* const print;
};
/// A NumberMatcher is the interface used to match a number or enumerator used
@@ -459,12 +461,12 @@
/// @see #MatchFn
MatchFn* const match;
- /// Returns a string representation of the matcher.
+ /// Prints the representation of the matcher.
/// Used for printing error messages when no overload is found.
- using StringFn = std::string(MatchState* state);
+ using PrintFn = void(MatchState* state, StyledText& out);
- /// @see #StringFn
- StringFn* const string;
+ /// @see #PrintFn
+ PrintFn* const print;
};
/// TableData holds the immutable data that holds the intrinsic data for a language.
@@ -600,16 +602,16 @@
return matcher.match(*this, number);
}
-std::string MatchState::TypeName() {
+void MatchState::PrintType(StyledText& out) {
TypeMatcherIndex matcher_index{(*matcher_indices_++).value};
auto& matcher = data[matcher_index];
- return matcher.string(this);
+ matcher.print(this, out);
}
-std::string MatchState::NumName() {
+void MatchState::PrintNum(StyledText& out) {
NumberMatcherIndex matcher_index{(*matcher_indices_++).value};
auto& matcher = data[matcher_index];
- return matcher.string(this);
+ matcher.print(this, out);
}
/// TemplateTypeMatcher is a Matcher for a template type.
@@ -630,9 +632,9 @@
}
return nullptr;
},
- /* string */
- [](MatchState* state) -> std::string {
- return state->data[state->overload.templates + INDEX].name;
+ /* print */
+ [](MatchState* state, StyledText& out) {
+ out << style::Type << state->data[state->overload.templates + INDEX].name;
},
};
};
@@ -651,9 +653,9 @@
}
return state.templates.Num(INDEX, number) ? number : Number::invalid;
},
- /* string */
- [](MatchState* state) -> std::string {
- return state->data[state->overload.templates + INDEX].name;
+ /* print */
+ [](MatchState* state, StyledText& out) {
+ out << style::Variable << state->data[state->overload.templates + INDEX].name;
},
};
};
diff --git a/src/tint/lang/core/intrinsic/table_test.cc b/src/tint/lang/core/intrinsic/table_test.cc
index ddf205f..52b25f4 100644
--- a/src/tint/lang/core/intrinsic/table_test.cc
+++ b/src/tint/lang/core/intrinsic/table_test.cc
@@ -65,7 +65,7 @@
auto* i32 = create<type::I32>();
auto result = table.Lookup(BuiltinFn::kCos, Empty, Vector{i32}, EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(CoreIntrinsicTableTest, MatchU32) {
@@ -85,7 +85,7 @@
auto result =
table.Lookup(BuiltinFn::kUnpack2X16Float, Empty, Vector{f32}, EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(CoreIntrinsicTableTest, MatchI32) {
@@ -112,7 +112,7 @@
auto result =
table.Lookup(BuiltinFn::kTextureLoad, Empty, Vector{tex, f32}, EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(CoreIntrinsicTableTest, MatchIU32AsI32) {
@@ -140,7 +140,7 @@
auto result =
table.Lookup(BuiltinFn::kCountOneBits, Empty, Vector{f32}, EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(CoreIntrinsicTableTest, MatchFIU32AsI32) {
@@ -184,7 +184,7 @@
auto result = table.Lookup(BuiltinFn::kClamp, Empty, Vector{bool_, bool_, bool_},
EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(CoreIntrinsicTableTest, MatchBool) {
@@ -205,7 +205,7 @@
auto result =
table.Lookup(BuiltinFn::kSelect, Empty, Vector{f32, f32, f32}, EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(CoreIntrinsicTableTest, MatchPointer) {
@@ -226,7 +226,7 @@
auto result =
table.Lookup(BuiltinFn::kAtomicLoad, Empty, Vector{atomic_i32}, EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(CoreIntrinsicTableTest, MatchArray) {
@@ -248,7 +248,7 @@
auto result =
table.Lookup(BuiltinFn::kArrayLength, Empty, Vector{f32}, EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(CoreIntrinsicTableTest, MatchSampler) {
@@ -277,7 +277,7 @@
auto result = table.Lookup(BuiltinFn::kTextureSample, Empty, Vector{tex, f32, vec2f},
EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(CoreIntrinsicTableTest, MatchSampledTexture) {
@@ -400,7 +400,7 @@
auto result = table.Lookup(BuiltinFn::kTextureLoad, Empty, Vector{f32, vec2i},
EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(CoreIntrinsicTableTest, MatchTemplateType) {
@@ -420,7 +420,7 @@
auto result =
table.Lookup(BuiltinFn::kClamp, Empty, Vector{f32, u32, f32}, EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(CoreIntrinsicTableTest, MatchOpenSizeVector) {
@@ -443,7 +443,7 @@
auto result = table.Lookup(BuiltinFn::kClamp, Empty, Vector{vec2f, u32, vec2f},
EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(CoreIntrinsicTableTest, MatchOpenSizeMatrix) {
@@ -465,7 +465,7 @@
auto result =
table.Lookup(BuiltinFn::kDeterminant, Empty, Vector{mat3x2f}, EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(CoreIntrinsicTableTest, MatchDifferentArgsElementType_Builtin_ConstantEval) {
@@ -524,37 +524,37 @@
auto result = table.Lookup(BuiltinFn::kTextureDimensions, Empty, Vector{bool_, bool_},
EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_EQ(result.Failure(),
- R"(no matching call to textureDimensions(bool, bool)
+ ASSERT_EQ(result.Failure().Plain(),
+ R"(no matching call to 'textureDimensions(bool, bool)'
27 candidate functions:
- textureDimensions(texture: texture_1d<T>, level: L) -> u32 where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_2d<T>, level: L) -> vec2<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_2d_array<T>, level: L) -> vec2<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_3d<T>, level: L) -> vec3<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_cube<T>, level: L) -> vec2<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_cube_array<T>, level: L) -> vec2<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_depth_2d, level: L) -> vec2<u32> where: L is i32 or u32
- textureDimensions(texture: texture_depth_2d_array, level: L) -> vec2<u32> where: L is i32 or u32
- textureDimensions(texture: texture_depth_cube, level: L) -> vec2<u32> where: L is i32 or u32
- textureDimensions(texture: texture_depth_cube_array, level: L) -> vec2<u32> where: L is i32 or u32
- textureDimensions(texture: texture_1d<T>) -> u32 where: T is f32, i32 or u32
- textureDimensions(texture: texture_2d<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_2d_array<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_3d<T>) -> vec3<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_cube<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_cube_array<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_multisampled_2d<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_depth_2d) -> vec2<u32>
- textureDimensions(texture: texture_depth_2d_array) -> vec2<u32>
- textureDimensions(texture: texture_depth_cube) -> vec2<u32>
- textureDimensions(texture: texture_depth_cube_array) -> vec2<u32>
- textureDimensions(texture: texture_depth_multisampled_2d) -> vec2<u32>
- textureDimensions(texture: texture_storage_1d<F, A>) -> u32
- textureDimensions(texture: texture_storage_2d<F, A>) -> vec2<u32>
- textureDimensions(texture: texture_storage_2d_array<F, A>) -> vec2<u32>
- textureDimensions(texture: texture_storage_3d<F, A>) -> vec3<u32>
- textureDimensions(texture: texture_external) -> vec2<u32>
+ 'textureDimensions(texture: texture_1d<T>, level: L) -> u32' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_2d<T>, level: L) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_2d_array<T>, level: L) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_3d<T>, level: L) -> vec3<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_cube<T>, level: L) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_cube_array<T>, level: L) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_2d, level: L) -> vec2<u32>' where: 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_2d_array, level: L) -> vec2<u32>' where: 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_cube, level: L) -> vec2<u32>' where: 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_cube_array, level: L) -> vec2<u32>' where: 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_1d<T>) -> u32' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_2d<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_2d_array<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_3d<T>) -> vec3<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_cube<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_cube_array<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_multisampled_2d<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_2d) -> vec2<u32>'
+ 'textureDimensions(texture: texture_depth_2d_array) -> vec2<u32>'
+ 'textureDimensions(texture: texture_depth_cube) -> vec2<u32>'
+ 'textureDimensions(texture: texture_depth_cube_array) -> vec2<u32>'
+ 'textureDimensions(texture: texture_depth_multisampled_2d) -> vec2<u32>'
+ 'textureDimensions(texture: texture_storage_1d<F, A>) -> u32'
+ 'textureDimensions(texture: texture_storage_2d<F, A>) -> vec2<u32>'
+ 'textureDimensions(texture: texture_storage_2d_array<F, A>) -> vec2<u32>'
+ 'textureDimensions(texture: texture_storage_3d<F, A>) -> vec3<u32>'
+ 'textureDimensions(texture: texture_external) -> vec2<u32>'
)");
}
@@ -564,37 +564,37 @@
auto result = table.Lookup(BuiltinFn::kTextureDimensions, Empty, Vector{tex, bool_},
EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_EQ(result.Failure(),
- R"(no matching call to textureDimensions(texture_depth_2d, bool)
+ ASSERT_EQ(result.Failure().Plain(),
+ R"(no matching call to 'textureDimensions(texture_depth_2d, bool)'
27 candidate functions:
- textureDimensions(texture: texture_depth_2d, level: L) -> vec2<u32> where: L is i32 or u32
- textureDimensions(texture: texture_1d<T>, level: L) -> u32 where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_2d<T>, level: L) -> vec2<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_2d_array<T>, level: L) -> vec2<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_3d<T>, level: L) -> vec3<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_cube<T>, level: L) -> vec2<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_cube_array<T>, level: L) -> vec2<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_depth_2d_array, level: L) -> vec2<u32> where: L is i32 or u32
- textureDimensions(texture: texture_depth_cube, level: L) -> vec2<u32> where: L is i32 or u32
- textureDimensions(texture: texture_depth_cube_array, level: L) -> vec2<u32> where: L is i32 or u32
- textureDimensions(texture: texture_depth_2d) -> vec2<u32>
- textureDimensions(texture: texture_1d<T>) -> u32 where: T is f32, i32 or u32
- textureDimensions(texture: texture_2d<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_2d_array<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_3d<T>) -> vec3<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_cube<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_cube_array<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_multisampled_2d<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_depth_2d_array) -> vec2<u32>
- textureDimensions(texture: texture_depth_cube) -> vec2<u32>
- textureDimensions(texture: texture_depth_cube_array) -> vec2<u32>
- textureDimensions(texture: texture_depth_multisampled_2d) -> vec2<u32>
- textureDimensions(texture: texture_storage_1d<F, A>) -> u32
- textureDimensions(texture: texture_storage_2d<F, A>) -> vec2<u32>
- textureDimensions(texture: texture_storage_2d_array<F, A>) -> vec2<u32>
- textureDimensions(texture: texture_storage_3d<F, A>) -> vec3<u32>
- textureDimensions(texture: texture_external) -> vec2<u32>
+ 'textureDimensions(texture: texture_depth_2d, level: L) -> vec2<u32>' where: 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_1d<T>, level: L) -> u32' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_2d<T>, level: L) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_2d_array<T>, level: L) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_3d<T>, level: L) -> vec3<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_cube<T>, level: L) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_cube_array<T>, level: L) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_2d_array, level: L) -> vec2<u32>' where: 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_cube, level: L) -> vec2<u32>' where: 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_cube_array, level: L) -> vec2<u32>' where: 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_2d) -> vec2<u32>'
+ 'textureDimensions(texture: texture_1d<T>) -> u32' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_2d<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_2d_array<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_3d<T>) -> vec3<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_cube<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_cube_array<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_multisampled_2d<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_2d_array) -> vec2<u32>'
+ 'textureDimensions(texture: texture_depth_cube) -> vec2<u32>'
+ 'textureDimensions(texture: texture_depth_cube_array) -> vec2<u32>'
+ 'textureDimensions(texture: texture_depth_multisampled_2d) -> vec2<u32>'
+ 'textureDimensions(texture: texture_storage_1d<F, A>) -> u32'
+ 'textureDimensions(texture: texture_storage_2d<F, A>) -> vec2<u32>'
+ 'textureDimensions(texture: texture_storage_2d_array<F, A>) -> vec2<u32>'
+ 'textureDimensions(texture: texture_storage_3d<F, A>) -> vec3<u32>'
+ 'textureDimensions(texture: texture_external) -> vec2<u32>'
)");
}
@@ -610,11 +610,11 @@
auto* bool_ = create<type::Bool>();
auto result = table.Lookup(UnaryOp::kNegation, bool_, EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- EXPECT_EQ(result.Failure(), R"(no matching overload for operator - (bool)
+ EXPECT_EQ(result.Failure().Plain(), R"(no matching overload for 'operator - (bool)'
2 candidate operators:
- operator - (T) -> T where: T is f32, i32 or f16
- operator - (vecN<T>) -> vecN<T> where: T is f32, i32 or f16
+ 'operator - (T) -> T' where: 'T' is 'f32', 'i32' or 'f16'
+ 'operator - (vecN<T>) -> vecN<T>' where: 'T' is 'f32', 'i32' or 'f16'
)");
}
@@ -649,18 +649,18 @@
auto result = table.Lookup(BinaryOp::kMultiply, f32, bool_, EvaluationStage::kConstant,
/* is_compound */ false);
ASSERT_NE(result, Success);
- EXPECT_EQ(result.Failure(), R"(no matching overload for operator * (f32, bool)
+ EXPECT_EQ(result.Failure().Plain(), R"(no matching overload for 'operator * (f32, bool)'
9 candidate operators:
- operator * (T, T) -> T where: T is f32, i32, u32 or f16
- operator * (vecN<T>, T) -> vecN<T> where: T is f32, i32, u32 or f16
- operator * (T, vecN<T>) -> vecN<T> where: T is f32, i32, u32 or f16
- operator * (T, matNxM<T>) -> matNxM<T> where: T is f32 or f16
- operator * (matNxM<T>, T) -> matNxM<T> where: T is f32 or f16
- operator * (vecN<T>, vecN<T>) -> vecN<T> where: T is f32, i32, u32 or f16
- operator * (matCxR<T>, vecC<T>) -> vecR<T> where: T is f32 or f16
- operator * (vecR<T>, matCxR<T>) -> vecC<T> where: T is f32 or f16
- operator * (matKxR<T>, matCxK<T>) -> matCxR<T> where: T is f32 or f16
+ 'operator * (T, T) -> T' where: 'T' is 'f32', 'i32', 'u32' or 'f16'
+ 'operator * (vecN<T>, T) -> vecN<T>' where: 'T' is 'f32', 'i32', 'u32' or 'f16'
+ 'operator * (T, vecN<T>) -> vecN<T>' where: 'T' is 'f32', 'i32', 'u32' or 'f16'
+ 'operator * (T, matNxM<T>) -> matNxM<T>' where: 'T' is 'f32' or 'f16'
+ 'operator * (matNxM<T>, T) -> matNxM<T>' where: 'T' is 'f32' or 'f16'
+ 'operator * (vecN<T>, vecN<T>) -> vecN<T>' where: 'T' is 'f32', 'i32', 'u32' or 'f16'
+ 'operator * (matCxR<T>, vecC<T>) -> vecR<T>' where: 'T' is 'f32' or 'f16'
+ 'operator * (vecR<T>, matCxR<T>) -> vecC<T>' where: 'T' is 'f32' or 'f16'
+ 'operator * (matKxR<T>, matCxK<T>) -> matCxR<T>' where: 'T' is 'f32' or 'f16'
)");
}
@@ -681,18 +681,18 @@
auto result = table.Lookup(BinaryOp::kMultiply, f32, bool_, EvaluationStage::kConstant,
/* is_compound */ true);
ASSERT_NE(result, Success);
- EXPECT_EQ(result.Failure(), R"(no matching overload for operator *= (f32, bool)
+ EXPECT_EQ(result.Failure().Plain(), R"(no matching overload for 'operator *= (f32, bool)'
9 candidate operators:
- operator *= (T, T) -> T where: T is f32, i32, u32 or f16
- operator *= (vecN<T>, T) -> vecN<T> where: T is f32, i32, u32 or f16
- operator *= (T, vecN<T>) -> vecN<T> where: T is f32, i32, u32 or f16
- operator *= (T, matNxM<T>) -> matNxM<T> where: T is f32 or f16
- operator *= (matNxM<T>, T) -> matNxM<T> where: T is f32 or f16
- operator *= (vecN<T>, vecN<T>) -> vecN<T> where: T is f32, i32, u32 or f16
- operator *= (matCxR<T>, vecC<T>) -> vecR<T> where: T is f32 or f16
- operator *= (vecR<T>, matCxR<T>) -> vecC<T> where: T is f32 or f16
- operator *= (matKxR<T>, matCxK<T>) -> matCxR<T> where: T is f32 or f16
+ 'operator *= (T, T) -> T' where: 'T' is 'f32', 'i32', 'u32' or 'f16'
+ 'operator *= (vecN<T>, T) -> vecN<T>' where: 'T' is 'f32', 'i32', 'u32' or 'f16'
+ 'operator *= (T, vecN<T>) -> vecN<T>' where: 'T' is 'f32', 'i32', 'u32' or 'f16'
+ 'operator *= (T, matNxM<T>) -> matNxM<T>' where: 'T' is 'f32' or 'f16'
+ 'operator *= (matNxM<T>, T) -> matNxM<T>' where: 'T' is 'f32' or 'f16'
+ 'operator *= (vecN<T>, vecN<T>) -> vecN<T>' where: 'T' is 'f32', 'i32', 'u32' or 'f16'
+ 'operator *= (matCxR<T>, vecC<T>) -> vecR<T>' where: 'T' is 'f32' or 'f16'
+ 'operator *= (vecR<T>, matCxR<T>) -> vecC<T>' where: 'T' is 'f32' or 'f16'
+ 'operator *= (matKxR<T>, matCxK<T>) -> matCxR<T>' where: 'T' is 'f32' or 'f16'
)");
}
@@ -717,23 +717,23 @@
auto result = table.Lookup(CtorConv::kVec3, Vector{i32}, Vector{i32, f32, i32},
EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- EXPECT_EQ(result.Failure(),
- R"(no matching constructor for vec3<i32>(i32, f32, i32)
+ EXPECT_EQ(result.Failure().Plain(),
+ R"(no matching constructor for 'vec3<i32>(i32, f32, i32)'
6 candidate constructors:
- vec3<T>(x: T, y: T, z: T) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3<T>(xy: vec2<T>, z: T) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3<T>(x: T, yz: vec2<T>) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3<T>(T) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3<T>(vec3<T>) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3<T>() -> vec3<T> where: T is f32, f16, i32, u32 or bool
+ 'vec3<T>(x: T, y: T, z: T) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(xy: vec2<T>, z: T) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(x: T, yz: vec2<T>) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(T) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(vec3<T>) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>() -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
5 candidate conversions:
- vec3<T>(vec3<U>) -> vec3<T> where: T is f32, U is i32, f16, u32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is f16, U is f32, i32, u32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is i32, U is f32, f16, u32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is u32, U is f32, f16, i32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is bool, U is f32, f16, i32 or u32
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'f32', 'U' is 'i32', 'f16', 'u32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'f16', 'U' is 'f32', 'i32', 'u32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'i32', 'U' is 'f32', 'f16', 'u32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'u32', 'U' is 'f32', 'f16', 'i32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'bool', 'U' is 'f32', 'f16', 'i32' or 'u32'
)");
}
@@ -790,23 +790,23 @@
auto result =
table.Lookup(CtorConv::kVec3, Vector{f32}, Vector{arr}, EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- EXPECT_EQ(result.Failure(),
- R"(no matching constructor for vec3<f32>(array<u32>)
+ EXPECT_EQ(result.Failure().Plain(),
+ R"(no matching constructor for 'vec3<f32>(array<u32>)'
6 candidate constructors:
- vec3<T>(vec3<T>) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3<T>(T) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3<T>() -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3<T>(x: T, yz: vec2<T>) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3<T>(xy: vec2<T>, z: T) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3<T>(x: T, y: T, z: T) -> vec3<T> where: T is f32, f16, i32, u32 or bool
+ 'vec3<T>(vec3<T>) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(T) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>() -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(x: T, yz: vec2<T>) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(xy: vec2<T>, z: T) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(x: T, y: T, z: T) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
5 candidate conversions:
- vec3<T>(vec3<U>) -> vec3<T> where: T is f32, U is i32, f16, u32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is f16, U is f32, i32, u32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is i32, U is f32, f16, u32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is u32, U is f32, f16, i32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is bool, U is f32, f16, i32 or u32
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'f32', 'U' is 'i32', 'f16', 'u32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'f16', 'U' is 'f32', 'i32', 'u32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'i32', 'U' is 'f32', 'f16', 'u32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'u32', 'U' is 'f32', 'f16', 'i32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'bool', 'U' is 'f32', 'f16', 'i32' or 'u32'
)");
}
@@ -848,7 +848,7 @@
auto result =
table.Lookup(BuiltinFn::kAbs, Empty, std::move(arg_tys), EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
} // namespace
diff --git a/src/tint/lang/core/ir/validator.cc b/src/tint/lang/core/ir/validator.cc
index afc234f..e0feca2 100644
--- a/src/tint/lang/core/ir/validator.cc
+++ b/src/tint/lang/core/ir/validator.cc
@@ -101,60 +101,51 @@
Result<SuccessType> Run();
protected:
- /// @param inst the instruction
- /// @param err the error message
- /// @returns a string with the instruction name name and error message formatted
- std::string InstError(const Instruction* inst, std::string err);
-
/// Adds an error for the @p inst and highlights the instruction in the disassembly
/// @param inst the instruction
- /// @param err the error string
- void AddError(const Instruction* inst, std::string err);
+ /// @returns the diagnostic
+ diag::Diagnostic& AddError(const Instruction* inst);
/// Adds an error for the @p inst operand at @p idx and highlights the operand in the
/// disassembly
/// @param inst the instaruction
/// @param idx the operand index
- /// @param err the error string
- void AddError(const Instruction* inst, size_t idx, std::string err);
+ /// @returns the diagnostic
+ diag::Diagnostic& AddError(const Instruction* inst, size_t idx);
/// Adds an error for the @p inst result at @p idx and highlgihts the result in the disassembly
/// @param inst the instruction
/// @param idx the result index
- /// @param err the error string
- void AddResultError(const Instruction* inst, size_t idx, std::string err);
+ /// @returns the diagnostic
+ diag::Diagnostic& AddResultError(const Instruction* inst, size_t idx);
/// Adds an error the @p block and highlights the block header in the disassembly
/// @param blk the block
- /// @param err the error string
- void AddError(const Block* blk, std::string err);
+ /// @returns the diagnostic
+ diag::Diagnostic& AddError(const Block* blk);
+
+ /// Adds an error the @p block and highlights the block header in the disassembly
+ /// @param src the source lines to highlight
+ /// @returns the diagnostic
+ diag::Diagnostic& AddError(Source src);
/// Adds a note to @p inst and highlights the instruction in the disassembly
/// @param inst the instruction
- /// @param err the message to emit
- void AddNote(const Instruction* inst, std::string err);
+ diag::Diagnostic& AddNote(const Instruction* inst);
/// Adds a note to @p inst for operand @p idx and highlights the operand in the
/// disassembly
/// @param inst the instruction
/// @param idx the operand index
- /// @param err the message string
- void AddNote(const Instruction* inst, size_t idx, std::string err);
+ diag::Diagnostic& AddNote(const Instruction* inst, size_t idx);
/// Adds a note to @p blk and highlights the block in the disassembly
/// @param blk the block
- /// @param err the message to emit
- void AddNote(const Block* blk, std::string err);
-
- /// Adds an error to the diagnostics
- /// @param err the message to emit
- /// @param src the source lines to highlight
- void AddError(std::string err, Source src = {});
+ diag::Diagnostic& AddNote(const Block* blk);
/// Adds a note to the diagnostics
- /// @param note the note to emit
/// @param src the source lines to highlight
- void AddNote(std::string note, Source src = {});
+ diag::Diagnostic& AddNote(Source src = {});
/// @param v the value to get the name for
/// @returns the name for the given value
@@ -316,7 +307,8 @@
for (auto& func : mod_.functions) {
if (!all_functions_.Add(func.Get())) {
- AddError("function '" + Name(func.Get()) + "' added to module multiple times");
+ AddError(Source{}) << "function '" << Name(func.Get())
+ << "' added to module multiple times";
}
}
@@ -328,92 +320,94 @@
// Check for orphaned instructions.
for (auto* inst : mod_.instructions.Objects()) {
if (inst->Alive() && !visited_instructions_.Contains(inst)) {
- AddError("orphaned instruction: " + inst->FriendlyName());
+ AddError(inst) << "orphaned instruction: " << inst->FriendlyName();
}
}
}
if (diagnostics_.ContainsErrors()) {
DisassembleIfNeeded();
- diagnostics_.AddNote(tint::diag::System::IR,
- "# Disassembly\n" + disassembly_file->content.data, {});
+ diagnostics_.AddNote(tint::diag::System::IR, Source{}) << "# Disassembly\n"
+ << disassembly_file->content.data;
return Failure{std::move(diagnostics_)};
}
return Success;
}
-std::string Validator::InstError(const Instruction* inst, std::string err) {
- return std::string(inst->FriendlyName()) + ": " + err;
-}
-
-void Validator::AddError(const Instruction* inst, std::string err) {
+diag::Diagnostic& Validator::AddError(const Instruction* inst) {
DisassembleIfNeeded();
auto src = dis_.InstructionSource(inst);
- AddError(std::move(err), src);
+ auto& diag = AddError(src) << inst->FriendlyName() << ": ";
if (current_block_) {
- AddNote(current_block_, "In block");
+ AddNote(current_block_) << "In block";
}
+ return diag;
}
-void Validator::AddError(const Instruction* inst, size_t idx, std::string err) {
+diag::Diagnostic& Validator::AddError(const Instruction* inst, size_t idx) {
DisassembleIfNeeded();
auto src = dis_.OperandSource(Disassembler::IndexedValue{inst, static_cast<uint32_t>(idx)});
- AddError(std::move(err), src);
+ auto& diag = AddError(src) << inst->FriendlyName() << ": ";
if (current_block_) {
- AddNote(current_block_, "In block");
+ AddNote(current_block_) << "In block";
}
+
+ return diag;
}
-void Validator::AddResultError(const Instruction* inst, size_t idx, std::string err) {
+diag::Diagnostic& Validator::AddResultError(const Instruction* inst, size_t idx) {
DisassembleIfNeeded();
auto src = dis_.ResultSource(Disassembler::IndexedValue{inst, static_cast<uint32_t>(idx)});
- AddError(std::move(err), src);
+ auto& diag = AddError(src) << inst->FriendlyName() << ": ";
if (current_block_) {
- AddNote(current_block_, "In block");
+ AddNote(current_block_) << "In block";
}
+ return diag;
}
-void Validator::AddError(const Block* blk, std::string err) {
+diag::Diagnostic& Validator::AddError(const Block* blk) {
DisassembleIfNeeded();
auto src = dis_.BlockSource(blk);
- AddError(std::move(err), src);
+ return AddError(src);
}
-void Validator::AddNote(const Instruction* inst, std::string err) {
+diag::Diagnostic& Validator::AddNote(const Instruction* inst) {
DisassembleIfNeeded();
auto src = dis_.InstructionSource(inst);
- AddNote(std::move(err), src);
+ return AddNote(src);
}
-void Validator::AddNote(const Instruction* inst, size_t idx, std::string err) {
+diag::Diagnostic& Validator::AddNote(const Instruction* inst, size_t idx) {
DisassembleIfNeeded();
auto src = dis_.OperandSource(Disassembler::IndexedValue{inst, static_cast<uint32_t>(idx)});
- AddNote(std::move(err), src);
+ return AddNote(src);
}
-void Validator::AddNote(const Block* blk, std::string err) {
+diag::Diagnostic& Validator::AddNote(const Block* blk) {
DisassembleIfNeeded();
auto src = dis_.BlockSource(blk);
- AddNote(std::move(err), src);
+ return AddNote(src);
}
-void Validator::AddError(std::string err, Source src) {
- auto& diag = diagnostics_.AddError(tint::diag::System::IR, std::move(err), src);
+diag::Diagnostic& Validator::AddError(Source src) {
+ auto& diag = diagnostics_.AddError(tint::diag::System::IR, src);
if (src.range != Source::Range{{}}) {
diag.source.file = disassembly_file.get();
diag.owned_file = disassembly_file;
}
+ return diag;
}
-void Validator::AddNote(std::string note, Source src) {
- auto& diag = diagnostics_.AddNote(tint::diag::System::IR, std::move(note), src);
+diag::Diagnostic& Validator::AddNote(Source src) {
+ auto& diag = diagnostics_.AddNote(tint::diag::System::IR, src);
if (src.range != Source::Range{{}}) {
diag.source.file = disassembly_file.get();
diag.owned_file = disassembly_file;
}
+ return diag;
}
std::string Validator::Name(const Value* v) {
@@ -422,7 +416,7 @@
void Validator::CheckOperandNotNull(const Instruction* inst, const ir::Value* operand, size_t idx) {
if (operand == nullptr) {
- AddError(inst, idx, InstError(inst, "operand is undefined"));
+ AddError(inst, idx) << "operand is undefined";
}
}
@@ -440,15 +434,12 @@
for (auto* inst : *blk) {
if (inst->Block() != blk) {
- AddError(
- inst,
- InstError(inst, "instruction in root block does not have root block as parent"));
+ AddError(inst) << "instruction in root block does not have root block as parent";
continue;
}
auto* var = inst->As<ir::Var>();
if (!var) {
- AddError(inst,
- std::string("root block: invalid instruction: ") + inst->TypeInfo().name);
+ AddError(inst) << "root block: invalid instruction: " << inst->TypeInfo().name;
continue;
}
CheckInstruction(var);
@@ -463,17 +454,17 @@
TINT_SCOPED_ASSIGNMENT(current_block_, blk);
if (!blk->Terminator()) {
- AddError(blk, "block: does not end in a terminator instruction");
+ AddError(blk) << "block: does not end in a terminator instruction";
}
for (auto* inst : *blk) {
if (inst->Block() != blk) {
- AddError(inst, InstError(inst, "block instruction does not have same block as parent"));
- AddNote(current_block_, "In block");
+ AddError(inst) << "block instruction does not have same block as parent";
+ AddNote(current_block_) << "In block";
continue;
}
if (inst->Is<ir::Terminator>() && inst != blk->Terminator()) {
- AddError(inst, "block: terminator which isn't the final instruction");
+ AddError(inst) << "block: terminator which isn't the final instruction";
continue;
}
@@ -484,22 +475,21 @@
void Validator::CheckInstruction(const Instruction* inst) {
visited_instructions_.Add(inst);
if (!inst->Alive()) {
- AddError(inst, InstError(inst, "destroyed instruction found in instruction list"));
+ AddError(inst) << "destroyed instruction found in instruction list";
return;
}
auto results = inst->Results();
for (size_t i = 0; i < results.Length(); ++i) {
auto* res = results[i];
if (!res) {
- AddResultError(inst, i, InstError(inst, "result is undefined"));
+ AddResultError(inst, i) << "result is undefined";
continue;
}
if (res->Instruction() == nullptr) {
- AddResultError(inst, i, InstError(inst, "instruction of result is undefined"));
+ AddResultError(inst, i) << "instruction of result is undefined";
} else if (res->Instruction() != inst) {
- AddResultError(inst, i,
- InstError(inst, "instruction of result is a different instruction"));
+ AddResultError(inst, i) << "instruction of result is a different instruction";
}
}
@@ -513,11 +503,11 @@
// Note, a `nullptr` is a valid operand in some cases, like `var` so we can't just check
// for `nullptr` here.
if (!op->Alive()) {
- AddError(inst, i, InstError(inst, "operand is not alive"));
+ AddError(inst, i) << "operand is not alive";
}
if (!op->HasUsage(inst, i)) {
- AddError(inst, i, InstError(inst, "operand missing usage"));
+ AddError(inst, i) << "operand missing usage";
}
}
@@ -538,13 +528,13 @@
[&](const Terminator* b) { CheckTerminator(b); }, //
[&](const Unary* u) { CheckUnary(u); }, //
[&](const Var* var) { CheckVar(var); }, //
- [&](const Default) { AddError(inst, InstError(inst, "missing validation")); });
+ [&](const Default) { AddError(inst) << "missing validation"; });
}
void Validator::CheckVar(const Var* var) {
if (var->Result(0) && var->Initializer()) {
if (var->Initializer()->Type() != var->Result(0)->Type()->UnwrapPtr()) {
- AddError(var, InstError(var, "initializer has incorrect type"));
+ AddError(var) << "initializer has incorrect type";
}
}
}
@@ -554,7 +544,7 @@
if (let->Result(0) && let->Value()) {
if (let->Result(0)->Type() != let->Value()->Type()) {
- AddError(let, InstError(let, "result type does not match value type"));
+ AddError(let) << "result type does not match value type";
}
}
}
@@ -587,42 +577,39 @@
auto result = core::intrinsic::LookupFn(context, call->FriendlyName().c_str(), call->FuncId(),
Empty, args, core::EvaluationStage::kRuntime);
if (result != Success) {
- AddError(call, InstError(call, result.Failure()));
+ AddError(call) << result.Failure();
return;
}
if (result->return_type != call->Result(0)->Type()) {
- AddError(call, InstError(call, "call result type does not match builtin return type"));
+ AddError(call) << "call result type does not match builtin return type";
}
}
void Validator::CheckUserCall(const UserCall* call) {
if (!all_functions_.Contains(call->Target())) {
- AddError(call, UserCall::kFunctionOperandOffset,
- InstError(call, "call target is not part of the module"));
+ AddError(call, UserCall::kFunctionOperandOffset) << "call target is not part of the module";
}
if (call->Target()->Stage() != Function::PipelineStage::kUndefined) {
- AddError(call, UserCall::kFunctionOperandOffset,
- InstError(call, "call target must not have a pipeline stage"));
+ AddError(call, UserCall::kFunctionOperandOffset)
+ << "call target must not have a pipeline stage";
}
auto args = call->Args();
auto params = call->Target()->Params();
if (args.Length() != params.Length()) {
- StringStream err;
- err << "function has " << params.Length() << " parameters, but call provides "
+ AddError(call, UserCall::kFunctionOperandOffset)
+ << "function has " << params.Length() << " parameters, but call provides "
<< args.Length() << " arguments";
- AddError(call, UserCall::kFunctionOperandOffset, InstError(call, err.str()));
return;
}
for (size_t i = 0; i < args.Length(); i++) {
if (args[i]->Type() != params[i]->Type()) {
- StringStream err;
- err << "function parameter " << i << " is of type " << params[i]->Type()->FriendlyName()
+ AddError(call, UserCall::kArgsOperandOffset + i)
+ << "function parameter " << i << " is of type " << params[i]->Type()->FriendlyName()
<< ", but argument is of type " << args[i]->Type()->FriendlyName();
- AddError(call, UserCall::kArgsOperandOffset + i, InstError(call, err.str()));
}
}
}
@@ -643,10 +630,8 @@
};
for (size_t i = 0; i < a->Indices().Length(); i++) {
- auto err = [&](std::string msg) {
- AddError(a, i + Access::kIndicesOperandOffset, InstError(a, msg));
- };
- auto note = [&](std::string msg) { AddNote(a, i + Access::kIndicesOperandOffset, msg); };
+ auto err = [&](std::string msg) { AddError(a, i + Access::kIndicesOperandOffset) << msg; };
+ auto note = [&](std::string msg) { AddNote(a, i + Access::kIndicesOperandOffset) << msg; };
auto* index = a->Indices()[i];
if (TINT_UNLIKELY(!index->Type()->is_integer_scalar())) {
@@ -705,8 +690,8 @@
}
if (TINT_UNLIKELY(!ok)) {
- AddError(a, InstError(a, "result of access chain is type " + current() +
- " but instruction type is " + want->FriendlyName()));
+ AddError(a) << "result of access chain is type " << current() << " but instruction type is "
+ << want->FriendlyName();
}
}
@@ -725,7 +710,7 @@
core::intrinsic::LookupBinary(context, b->Op(), b->LHS()->Type(), b->RHS()->Type(),
core::EvaluationStage::kRuntime, /* is_compound */ false);
if (overload != Success) {
- AddError(b, InstError(b, overload.Failure()));
+ AddError(b) << overload.Failure();
return;
}
@@ -735,7 +720,7 @@
err << "binary instruction result type (" << result->Type()->FriendlyName()
<< ") does not match overload result type ("
<< overload->return_type->FriendlyName() << ")";
- AddError(b, InstError(b, err.str()));
+ AddError(b) << err.str();
}
}
}
@@ -755,7 +740,7 @@
auto overload = core::intrinsic::LookupUnary(context, u->Op(), u->Val()->Type(),
core::EvaluationStage::kRuntime);
if (overload != Success) {
- AddError(u, InstError(u, overload.Failure()));
+ AddError(u) << overload.Failure();
return;
}
@@ -765,7 +750,7 @@
err << "unary instruction result type (" << result->Type()->FriendlyName()
<< ") does not match overload result type ("
<< overload->return_type->FriendlyName() << ")";
- AddError(u, InstError(u, err.str()));
+ AddError(u) << err.str();
}
}
}
@@ -775,8 +760,7 @@
CheckOperandNotNull(if_, if_->Condition(), If::kConditionOperandOffset);
if (if_->Condition() && !if_->Condition()->Type()->Is<core::type::Bool>()) {
- AddError(if_, If::kConditionOperandOffset,
- InstError(if_, "condition must be a `bool` type"));
+ AddError(if_, If::kConditionOperandOffset) << "condition must be a `bool` type";
}
control_stack_.Push(if_);
@@ -824,38 +808,36 @@
[&](const ir::Return* ret) { CheckReturn(ret); }, //
[&](const ir::TerminateInvocation*) {}, //
[&](const ir::Unreachable*) {}, //
- [&](Default) { AddError(b, InstError(b, "missing validation")); });
+ [&](Default) { AddError(b) << "missing validation"; });
}
void Validator::CheckExit(const Exit* e) {
if (e->ControlInstruction() == nullptr) {
- AddError(e, InstError(e, "has no parent control instruction"));
+ AddError(e) << "has no parent control instruction";
return;
}
if (control_stack_.IsEmpty()) {
- AddError(e, InstError(e, "found outside all control instructions"));
+ AddError(e) << "found outside all control instructions";
return;
}
auto results = e->ControlInstruction()->Results();
auto args = e->Args();
if (results.Length() != args.Length()) {
- AddError(e, InstError(e, std::string("args count (") + std::to_string(args.Length()) +
- ") does not match control instruction result count (" +
- std::to_string(results.Length()) + ")"));
- AddNote(e->ControlInstruction(), "control instruction");
+ AddError(e) << ("args count (") << args.Length()
+ << ") does not match control instruction result count (" << results.Length()
+ << ")";
+ AddNote(e->ControlInstruction()) << "control instruction";
return;
}
for (size_t i = 0; i < results.Length(); ++i) {
if (results[i] && args[i] && results[i]->Type() != args[i]->Type()) {
- AddError(
- e, i,
- InstError(e, std::string("argument type (") + results[i]->Type()->FriendlyName() +
- ") does not match control instruction type (" +
- args[i]->Type()->FriendlyName() + ")"));
- AddNote(e->ControlInstruction(), "control instruction");
+ AddError(e, i) << "argument type (" << results[i]->Type()->FriendlyName()
+ << ") does not match control instruction type ("
+ << args[i]->Type()->FriendlyName() << ")";
+ AddNote(e->ControlInstruction()) << "control instruction";
}
}
@@ -864,31 +846,31 @@
[&](const ir::ExitIf* i) { CheckExitIf(i); }, //
[&](const ir::ExitLoop* l) { CheckExitLoop(l); }, //
[&](const ir::ExitSwitch* s) { CheckExitSwitch(s); }, //
- [&](Default) { AddError(e, InstError(e, "missing validation")); });
+ [&](Default) { AddError(e) << "missing validation"; });
}
void Validator::CheckExitIf(const ExitIf* e) {
if (control_stack_.Back() != e->If()) {
- AddError(e, InstError(e, "if target jumps over other control instructions"));
- AddNote(control_stack_.Back(), "first control instruction jumped");
+ AddError(e) << "if target jumps over other control instructions";
+ AddNote(control_stack_.Back()) << "first control instruction jumped";
}
}
void Validator::CheckReturn(const Return* ret) {
auto* func = ret->Func();
if (func == nullptr) {
- AddError(ret, InstError(ret, "undefined function"));
+ AddError(ret) << "undefined function";
return;
}
if (func->ReturnType()->Is<core::type::Void>()) {
if (ret->Value()) {
- AddError(ret, InstError(ret, "unexpected return value"));
+ AddError(ret) << "unexpected return value";
}
} else {
if (!ret->Value()) {
- AddError(ret, InstError(ret, "expected return value"));
+ AddError(ret) << "expected return value";
} else if (ret->Value()->Type() != func->ReturnType()) {
- AddError(ret, InstError(ret, "return value type does not match function return type"));
+ AddError(ret) << "return value type does not match function return type";
}
}
}
@@ -902,15 +884,14 @@
}
// A exit switch can step over if instructions, but no others.
if (!ctrl->Is<ir::If>()) {
- AddError(exit, InstError(exit, std::string(control->FriendlyName()) +
- " target jumps over other control instructions"));
- AddNote(ctrl, "first control instruction jumped");
+ AddError(exit) << control->FriendlyName()
+ << " target jumps over other control instructions";
+ AddNote(ctrl) << "first control instruction jumped";
return;
}
}
if (!found) {
- AddError(exit, InstError(exit, std::string(control->FriendlyName()) +
- " not found in parent control instructions"));
+ AddError(exit) << control->FriendlyName() << " not found in parent control instructions";
}
}
@@ -927,14 +908,14 @@
// Found parent loop
if (inst->Block()->Parent() == control) {
if (inst->Block() == control->Continuing()) {
- AddError(l, InstError(l, "loop exit jumps out of continuing block"));
+ AddError(l) << "loop exit jumps out of continuing block";
if (control->Continuing() != l->Block()) {
- AddNote(control->Continuing(), "in continuing block");
+ AddNote(control->Continuing()) << "in continuing block";
}
} else if (inst->Block() == control->Initializer()) {
- AddError(l, InstError(l, "loop exit not permitted in loop initializer"));
+ AddError(l) << "loop exit not permitted in loop initializer";
if (control->Initializer() != l->Block()) {
- AddNote(control->Initializer(), "in initializer block");
+ AddNote(control->Initializer()) << "in initializer block";
}
}
break;
@@ -949,11 +930,11 @@
if (auto* from = l->From()) {
auto* mv = from->Type()->As<core::type::MemoryView>();
if (!mv) {
- AddError(l, Load::kFromOperandOffset, "load source operand is not a memory view");
+ AddError(l, Load::kFromOperandOffset) << "load source operand is not a memory view";
return;
}
if (l->Result(0)->Type() != mv->StoreType()) {
- AddError(l, Load::kFromOperandOffset, "result type does not match source store type");
+ AddError(l, Load::kFromOperandOffset) << "result type does not match source store type";
}
}
}
@@ -965,11 +946,12 @@
if (auto* to = s->To()) {
auto* mv = to->Type()->As<core::type::MemoryView>();
if (!mv) {
- AddError(s, Store::kFromOperandOffset, "store target operand is not a memory view");
+ AddError(s, Store::kFromOperandOffset)
+ << "store target operand is not a memory view";
return;
}
if (from->Type() != mv->StoreType()) {
- AddError(s, Store::kFromOperandOffset, "value type does not match store type");
+ AddError(s, Store::kFromOperandOffset) << "value type does not match store type";
}
}
}
@@ -983,7 +965,7 @@
if (auto* res = l->Result(0)) {
if (auto* el_ty = GetVectorPtrElementType(l, LoadVectorElement::kFromOperandOffset)) {
if (res->Type() != el_ty) {
- AddResultError(l, 0, "result type does not match vector pointer element type");
+ AddResultError(l, 0) << "result type does not match vector pointer element type";
}
}
}
@@ -997,8 +979,8 @@
if (auto* value = s->Value()) {
if (auto* el_ty = GetVectorPtrElementType(s, StoreVectorElement::kToOperandOffset)) {
if (value->Type() != el_ty) {
- AddError(s, StoreVectorElement::kValueOperandOffset,
- "value type does not match vector pointer element type");
+ AddError(s, StoreVectorElement::kValueOperandOffset)
+ << "value type does not match vector pointer element type";
}
}
}
@@ -1023,7 +1005,7 @@
}
}
- AddError(inst, idx, "operand must be a pointer to vector, got " + type->FriendlyName());
+ AddError(inst, idx) << "operand must be a pointer to vector, got " << type->FriendlyName();
return nullptr;
}
diff --git a/src/tint/lang/core/ir/validator_test.cc b/src/tint/lang/core/ir/validator_test.cc
index cd5faeb..256cf8f 100644
--- a/src/tint/lang/core/ir/validator_test.cc
+++ b/src/tint/lang/core/ir/validator_test.cc
@@ -60,7 +60,7 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
EXPECT_EQ(res.Failure().reason.Str(),
- R"(:2:3 error: root block: invalid instruction: tint::core::ir::Loop
+ R"(:2:3 error: loop: root block: invalid instruction: tint::core::ir::Loop
loop [b: %b2] { # loop_1
^^^^^^^^^^^^^
@@ -922,7 +922,7 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
EXPECT_EQ(res.Failure().reason.Str(),
- R"(:3:5 error: block: terminator which isn't the final instruction
+ R"(:3:5 error: return: block: terminator which isn't the final instruction
ret
^^^
@@ -1447,7 +1447,7 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
- EXPECT_EQ(res.Failure().reason.Str(), R"(error: orphaned instruction: load
+ EXPECT_EQ(res.Failure().reason.Str(), R"(error: load: orphaned instruction: load
note: # Disassembly
%my_func = func():void -> %b1 {
%b1 = block {
@@ -3157,7 +3157,7 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
EXPECT_EQ(res.Failure().reason.Str(),
- R"(:4:19 error: load source operand is not a memory view
+ R"(:4:19 error: load: load source operand is not a memory view
%3:f32 = load %l
^^
@@ -3188,7 +3188,7 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
EXPECT_EQ(res.Failure().reason.Str(),
- R"(:4:19 error: result type does not match source store type
+ R"(:4:19 error: load: result type does not match source store type
%3:f32 = load %2
^^
@@ -3277,7 +3277,7 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
EXPECT_EQ(res.Failure().reason.Str(),
- R"(:4:15 error: store target operand is not a memory view
+ R"(:4:15 error: store: store target operand is not a memory view
store %l, 42u
^^^
@@ -3308,7 +3308,7 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
EXPECT_EQ(res.Failure().reason.Str(),
- R"(:4:15 error: value type does not match store type
+ R"(:4:15 error: store: value type does not match store type
store %2, 42u
^^^
@@ -3468,7 +3468,7 @@
%b1 = block {
^^^^^^^^^^^
-:4:37 error: value type does not match vector pointer element type
+:4:37 error: store_vector_element: value type does not match vector pointer element type
store_vector_element %2, undef, 2i
^^
diff --git a/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc b/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
index c40bcbb..6ecc839 100644
--- a/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
@@ -393,8 +393,8 @@
auto* dst_type = TypeOf(call);
if (!dst_type->is_integer_scalar_or_vector() && !dst_type->is_float_scalar_or_vector()) {
- diagnostics_.AddError(diag::System::Writer,
- "Unable to do bitcast to type " + dst_type->FriendlyName());
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "Unable to do bitcast to type " << dst_type->FriendlyName();
return;
}
@@ -1517,9 +1517,7 @@
out << "imageStore";
break;
default:
- diagnostics_.AddError(diag::System::Writer,
- "Internal compiler error: Unhandled texture builtin '" +
- std::string(builtin->str()) + "'");
+ TINT_ICE() << "Unhandled texture builtin '" << std::string(builtin->str()) << "'";
return;
}
@@ -1742,8 +1740,8 @@
case wgsl::BuiltinFn::kUnpack4X8Unorm:
return "unpackUnorm4x8";
default:
- diagnostics_.AddError(diag::System::Writer,
- "Unknown builtin method: " + std::string(builtin->str()));
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "Unknown builtin method: " << builtin;
}
return "";
@@ -1921,9 +1919,9 @@
[&](const ast::Let* let) { EmitProgramConstVariable(let); },
[&](const ast::Override*) {
// Override is removed with SubstituteOverride
- diagnostics_.AddError(diag::System::Writer,
- "override-expressions should have been removed with the "
- "SubstituteOverride transform");
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "override-expressions should have been removed with the "
+ "SubstituteOverride transform";
},
[&](const ast::Const*) {
// Constants are embedded at their use
@@ -2187,10 +2185,9 @@
out << "local_size_" << (i == 0 ? "x" : i == 1 ? "y" : "z") << " = ";
if (!wgsize[i].has_value()) {
- diagnostics_.AddError(
- diag::System::Writer,
- "override-expressions should have been removed with the SubstituteOverride "
- "transform");
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "override-expressions should have been removed with the SubstituteOverride "
+ "transform";
return;
}
out << std::to_string(wgsize[i].value());
@@ -2291,8 +2288,8 @@
auto count = a->ConstantCount();
if (!count) {
- diagnostics_.AddError(diag::System::Writer,
- core::type::Array::kErrExpectedConstantCount);
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << core::type::Array::kErrExpectedConstantCount;
return;
}
@@ -2343,7 +2340,8 @@
return;
}
}
- diagnostics_.AddError(diag::System::Writer, "unknown integer literal suffix type");
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "unknown integer literal suffix type";
}, //
TINT_ICE_ON_NO_MATCH);
}
@@ -2395,8 +2393,8 @@
auto count = arr->ConstantCount();
if (!count) {
- diagnostics_.AddError(diag::System::Writer,
- core::type::Array::kErrExpectedConstantCount);
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << core::type::Array::kErrExpectedConstantCount;
return;
}
@@ -2407,8 +2405,8 @@
EmitZeroValue(out, arr->ElemType());
}
} else {
- diagnostics_.AddError(diag::System::Writer,
- "Invalid type for zero emission: " + type->FriendlyName());
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "Invalid type for zero emission: " << type->FriendlyName();
}
}
@@ -2683,8 +2681,8 @@
} else {
auto count = arr->ConstantCount();
if (!count) {
- diagnostics_.AddError(diag::System::Writer,
- core::type::Array::kErrExpectedConstantCount);
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << core::type::Array::kErrExpectedConstantCount;
return;
}
sizes.push_back(count.value());
@@ -2839,7 +2837,7 @@
} else if (type->Is<core::type::Void>()) {
out << "void";
} else {
- diagnostics_.AddError(diag::System::Writer, "unknown type in EmitType");
+ diagnostics_.AddError(diag::System::Writer, Source{}) << "unknown type in EmitType";
}
}
diff --git a/src/tint/lang/glsl/writer/ast_printer/ast_printer_test.cc b/src/tint/lang/glsl/writer/ast_printer/ast_printer_test.cc
index 475f00a..4c8c40c 100644
--- a/src/tint/lang/glsl/writer/ast_printer/ast_printer_test.cc
+++ b/src/tint/lang/glsl/writer/ast_printer/ast_printer_test.cc
@@ -35,7 +35,7 @@
using GlslASTPrinterTest = TestHelper;
TEST_F(GlslASTPrinterTest, InvalidProgram) {
- Diagnostics().AddError(diag::System::Writer, "make the program invalid");
+ Diagnostics().AddError(diag::System::Writer, Source{}) << "make the program invalid";
ASSERT_FALSE(IsValid());
auto program = resolver::Resolve(*this);
ASSERT_FALSE(program.IsValid());
diff --git a/src/tint/lang/glsl/writer/ast_raise/combine_samplers.cc b/src/tint/lang/glsl/writer/ast_raise/combine_samplers.cc
index 25cc723d..9b09f57 100644
--- a/src/tint/lang/glsl/writer/ast_raise/combine_samplers.cc
+++ b/src/tint/lang/glsl/writer/ast_raise/combine_samplers.cc
@@ -441,8 +441,8 @@
auto* binding_info = inputs.Get<BindingInfo>();
if (!binding_info) {
ProgramBuilder b;
- b.Diagnostics().AddError(diag::System::Transform,
- "missing transform data for " + std::string(TypeInfo().name));
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "missing transform data for " << TypeInfo().name;
return resolver::Resolve(b);
}
diff --git a/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform.cc b/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform.cc
index 7d3a4ab..89cebe1 100644
--- a/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform.cc
+++ b/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform.cc
@@ -74,10 +74,9 @@
ApplyResult Run() {
auto* cfg = inputs.Get<Config>();
if (cfg == nullptr) {
- b.Diagnostics().AddError(
- diag::System::Transform,
- "missing transform data for " +
- std::string(tint::TypeInfo::Of<TextureBuiltinsFromUniform>().name));
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "missing transform data for "
+ << tint::TypeInfo::Of<TextureBuiltinsFromUniform>().name;
return resolver::Resolve(b);
}
ubo_bindingpoint_ordering = cfg->ubo_bindingpoint_ordering;
diff --git a/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc b/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc
index ab2551a..658beeb 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc
@@ -702,8 +702,8 @@
auto* dst_el_type = dst_type->DeepestElement();
if (!dst_el_type->is_integer_scalar() && !dst_el_type->is_float_scalar()) {
- diagnostics_.AddError(diag::System::Writer,
- "Unable to do bitcast to type " + dst_el_type->FriendlyName());
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "Unable to do bitcast to type " << dst_el_type->FriendlyName();
return false;
}
@@ -2450,8 +2450,7 @@
break;
}
default:
- diagnostics_.AddError(diag::System::Writer,
- "Internal error: unhandled data packing builtin");
+ TINT_ICE() << " unhandled data packing builtin";
return false;
}
@@ -2517,8 +2516,7 @@
Line(b) << "return f16tof32(uint2(i & 0xffff, i >> 16));";
break;
default:
- diagnostics_.AddError(diag::System::Writer,
- "Internal error: unhandled data packing builtin");
+ TINT_ICE() << "unhandled data packing builtin";
return false;
}
@@ -2579,28 +2577,27 @@
return false;
}
- return CallBuiltinHelper(
- out, expr, builtin, [&](TextBuffer* b, const std::vector<std::string>& params) {
- std::string functionName;
- switch (builtin->Fn()) {
- case wgsl::BuiltinFn::kDot4I8Packed:
- Line(b) << "int accumulator = 0;";
- functionName = "dot4add_i8packed";
- break;
- case wgsl::BuiltinFn::kDot4U8Packed:
- Line(b) << "uint accumulator = 0u;";
- functionName = "dot4add_u8packed";
- break;
- default:
- diagnostics_.AddError(diag::System::Writer,
- "Internal error: unhandled DP4a builtin");
- return false;
- }
- Line(b) << "return " << functionName << "(" << params[0] << ", " << params[1]
- << ", accumulator);";
+ return CallBuiltinHelper(out, expr, builtin,
+ [&](TextBuffer* b, const std::vector<std::string>& params) {
+ std::string functionName;
+ switch (builtin->Fn()) {
+ case wgsl::BuiltinFn::kDot4I8Packed:
+ Line(b) << "int accumulator = 0;";
+ functionName = "dot4add_i8packed";
+ break;
+ case wgsl::BuiltinFn::kDot4U8Packed:
+ Line(b) << "uint accumulator = 0u;";
+ functionName = "dot4add_u8packed";
+ break;
+ default:
+ TINT_ICE() << "Internal error: unhandled DP4a builtin";
+ return false;
+ }
+ Line(b) << "return " << functionName << "(" << params[0] << ", "
+ << params[1] << ", accumulator);";
- return true;
- });
+ return true;
+ });
}
bool ASTPrinter::EmitBarrierCall(StringStream& out, const sem::BuiltinFn* builtin) {
@@ -2932,9 +2929,7 @@
out << "[";
break;
default:
- diagnostics_.AddError(diag::System::Writer,
- "Internal compiler error: Unhandled texture builtin '" +
- std::string(builtin->str()) + "'");
+ TINT_ICE() << "Unhandled texture builtin '" << builtin << "'";
return false;
}
@@ -3120,8 +3115,8 @@
case wgsl::BuiltinFn::kSubgroupBroadcast:
return "WaveReadLaneAt";
default:
- diagnostics_.AddError(diag::System::Writer,
- "Unknown builtin method: " + std::string(builtin->str()));
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "Unknown builtin method: " << builtin->str();
}
return "";
@@ -3392,9 +3387,8 @@
case core::AddressSpace::kWorkgroup:
return EmitWorkgroupVariable(sem);
case core::AddressSpace::kPushConstant:
- diagnostics_.AddError(
- diag::System::Writer,
- "unhandled address space " + tint::ToString(sem->AddressSpace()));
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "unhandled address space " << sem->AddressSpace();
return false;
default: {
TINT_ICE() << "unhandled address space " << sem->AddressSpace();
@@ -3404,9 +3398,9 @@
},
[&](const ast::Override*) {
// Override is removed with SubstituteOverride
- diagnostics_.AddError(diag::System::Writer,
- "override-expressions should have been removed with the "
- "SubstituteOverride transform");
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "override-expressions should have been removed with the SubstituteOverride "
+ "transform";
return false;
},
[&](const ast::Const*) {
@@ -3629,10 +3623,9 @@
out << ", ";
}
if (!wgsize[i].has_value()) {
- diagnostics_.AddError(
- diag::System::Writer,
- "override-expressions should have been removed with the SubstituteOverride "
- "transform");
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "override-expressions should have been removed with the "
+ "SubstituteOverride transform";
return false;
}
out << std::to_string(wgsize[i].value());
@@ -3784,8 +3777,8 @@
auto count = a->ConstantCount();
if (!count) {
- diagnostics_.AddError(diag::System::Writer,
- core::type::Array::kErrExpectedConstantCount);
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << core::type::Array::kErrExpectedConstantCount;
return false;
}
@@ -3880,7 +3873,8 @@
out << "u";
return true;
}
- diagnostics_.AddError(diag::System::Writer, "unknown integer literal suffix type");
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "unknown integer literal suffix type";
return false;
}, //
TINT_ICE_ON_NO_MATCH);
@@ -4347,8 +4341,8 @@
}
const auto count = arr->ConstantCount();
if (!count) {
- diagnostics_.AddError(diag::System::Writer,
- core::type::Array::kErrExpectedConstantCount);
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << core::type::Array::kErrExpectedConstantCount;
return false;
}
@@ -4587,7 +4581,7 @@
if (auto builtin = attributes.builtin) {
auto name = builtin_to_attribute(builtin.value());
if (name.empty()) {
- diagnostics_.AddError(diag::System::Writer, "unsupported builtin");
+ diagnostics_.AddError(diag::System::Writer, Source{}) << "unsupported builtin";
return false;
}
post += " : " + name;
@@ -4595,7 +4589,8 @@
if (auto interpolation = attributes.interpolation) {
auto mod = interpolation_to_modifiers(interpolation->type, interpolation->sampling);
if (mod.empty()) {
- diagnostics_.AddError(diag::System::Writer, "unsupported interpolation");
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "unsupported interpolation";
return false;
}
pre += mod;
diff --git a/src/tint/lang/hlsl/writer/ast_printer/ast_printer_test.cc b/src/tint/lang/hlsl/writer/ast_printer/ast_printer_test.cc
index 88db758..8348b54 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/ast_printer_test.cc
+++ b/src/tint/lang/hlsl/writer/ast_printer/ast_printer_test.cc
@@ -35,7 +35,7 @@
using HlslASTPrinterTest = TestHelper;
TEST_F(HlslASTPrinterTest, InvalidProgram) {
- Diagnostics().AddError(diag::System::Writer, "make the program invalid");
+ Diagnostics().AddError(diag::System::Writer, Source{}) << "make the program invalid";
ASSERT_FALSE(IsValid());
auto program = resolver::Resolve(*this);
ASSERT_FALSE(program.IsValid());
diff --git a/src/tint/lang/hlsl/writer/ast_raise/num_workgroups_from_uniform.cc b/src/tint/lang/hlsl/writer/ast_raise/num_workgroups_from_uniform.cc
index 610fc4b..f266d83 100644
--- a/src/tint/lang/hlsl/writer/ast_raise/num_workgroups_from_uniform.cc
+++ b/src/tint/lang/hlsl/writer/ast_raise/num_workgroups_from_uniform.cc
@@ -90,8 +90,8 @@
auto* cfg = inputs.Get<Config>();
if (cfg == nullptr) {
- b.Diagnostics().AddError(diag::System::Transform,
- "missing transform data for " + std::string(TypeInfo().name));
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "missing transform data for " << TypeInfo().name;
return resolver::Resolve(b);
}
diff --git a/src/tint/lang/hlsl/writer/ast_raise/pixel_local.cc b/src/tint/lang/hlsl/writer/ast_raise/pixel_local.cc
index b3fa496..04e7b14 100644
--- a/src/tint/lang/hlsl/writer/ast_raise/pixel_local.cc
+++ b/src/tint/lang/hlsl/writer/ast_raise/pixel_local.cc
@@ -453,9 +453,8 @@
uint32_t ROVRegisterIndex(uint32_t field_index) {
auto idx = cfg.pls_member_to_rov_reg.Get(field_index);
if (TINT_UNLIKELY(!idx)) {
- b.Diagnostics().AddError(diag::System::Transform,
- "PixelLocal::Config::attachments missing entry for field " +
- std::to_string(field_index));
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "PixelLocal::Config::attachments missing entry for field " << field_index;
return 0;
}
return *idx;
@@ -466,9 +465,8 @@
core::TexelFormat ROVTexelFormat(uint32_t field_index) {
auto format = cfg.pls_member_to_rov_format.Get(field_index);
if (TINT_UNLIKELY(!format)) {
- b.Diagnostics().AddError(diag::System::Transform,
- "PixelLocal::Config::attachments missing entry for field " +
- std::to_string(field_index));
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "PixelLocal::Config::attachments missing entry for field " << field_index;
return core::TexelFormat::kUndefined;
}
return *format;
@@ -485,8 +483,8 @@
auto* cfg = inputs.Get<Config>();
if (!cfg) {
ProgramBuilder b;
- b.Diagnostics().AddError(diag::System::Transform,
- "missing transform data for " + std::string(TypeInfo().name));
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "missing transform data for " << TypeInfo().name;
return resolver::Resolve(b);
}
diff --git a/src/tint/lang/hlsl/writer/ast_raise/truncate_interstage_variables.cc b/src/tint/lang/hlsl/writer/ast_raise/truncate_interstage_variables.cc
index d6c1b25..7028093 100644
--- a/src/tint/lang/hlsl/writer/ast_raise/truncate_interstage_variables.cc
+++ b/src/tint/lang/hlsl/writer/ast_raise/truncate_interstage_variables.cc
@@ -70,10 +70,9 @@
const auto* data = config.Get<Config>();
if (data == nullptr) {
- b.Diagnostics().AddError(
- diag::System::Transform,
- "missing transform data for " +
- std::string(tint::TypeInfo::Of<TruncateInterstageVariables>().name));
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "missing transform data for "
+ << tint::TypeInfo::Of<TruncateInterstageVariables>().name;
return resolver::Resolve(b);
}
diff --git a/src/tint/lang/hlsl/writer/common/option_helpers.cc b/src/tint/lang/hlsl/writer/common/option_helpers.cc
index aace10b..416569d 100644
--- a/src/tint/lang/hlsl/writer/common/option_helpers.cc
+++ b/src/tint/lang/hlsl/writer/common/option_helpers.cc
@@ -54,10 +54,8 @@
const binding::BindingInfo& dst) -> bool {
if (auto binding = seen_wgsl_bindings.Get(src)) {
if (*binding != dst) {
- std::stringstream str;
- str << "found duplicate WGSL binding point: " << src;
-
- diagnostics.AddError(diag::System::Writer, str.str());
+ diagnostics.AddError(diag::System::Writer, Source{})
+ << "found duplicate WGSL binding point: " << src;
return true;
}
}
@@ -69,9 +67,8 @@
const tint::BindingPoint& dst) -> bool {
if (auto binding = map.Get(src)) {
if (*binding != dst) {
- std::stringstream str;
- str << "found duplicate MSL binding point: [binding: " << src.binding << "]";
- diagnostics.AddError(diag::System::Writer, str.str());
+ diagnostics.AddError(diag::System::Writer, Source{})
+ << "found duplicate MSL binding point: [binding: " << src.binding << "]";
return true;
}
}
@@ -97,27 +94,27 @@
// Storage and uniform are both [[buffer()]]
if (!valid(seen_hlsl_buffer_bindings, options.bindings.uniform)) {
- diagnostics.AddNote(diag::System::Writer, "when processing uniform", {});
+ diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing uniform";
return Failure{std::move(diagnostics)};
}
if (!valid(seen_hlsl_buffer_bindings, options.bindings.storage)) {
- diagnostics.AddNote(diag::System::Writer, "when processing storage", {});
+ diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing storage";
return Failure{std::move(diagnostics)};
}
// Sampler is [[sampler()]]
if (!valid(seen_hlsl_sampler_bindings, options.bindings.sampler)) {
- diagnostics.AddNote(diag::System::Writer, "when processing sampler", {});
+ diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing sampler";
return Failure{std::move(diagnostics)};
}
// Texture and storage texture are [[texture()]]
if (!valid(seen_hlsl_texture_bindings, options.bindings.texture)) {
- diagnostics.AddNote(diag::System::Writer, "when processing texture", {});
+ diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing texture";
return Failure{std::move(diagnostics)};
}
if (!valid(seen_hlsl_texture_bindings, options.bindings.storage_texture)) {
- diagnostics.AddNote(diag::System::Writer, "when processing storage_texture", {});
+ diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing storage_texture";
return Failure{std::move(diagnostics)};
}
@@ -129,22 +126,26 @@
// Validate with the actual source regardless of what the remapper will do
if (wgsl_seen(src_binding, plane0)) {
- diagnostics.AddNote(diag::System::Writer, "when processing external_texture", {});
+ diagnostics.AddNote(diag::System::Writer, Source{})
+ << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
// Plane0 & Plane1 are [[texture()]]
if (hlsl_seen(seen_hlsl_texture_bindings, plane0, src_binding)) {
- diagnostics.AddNote(diag::System::Writer, "when processing external_texture", {});
+ diagnostics.AddNote(diag::System::Writer, Source{})
+ << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
if (hlsl_seen(seen_hlsl_texture_bindings, plane1, src_binding)) {
- diagnostics.AddNote(diag::System::Writer, "when processing external_texture", {});
+ diagnostics.AddNote(diag::System::Writer, Source{})
+ << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
// Metadata is [[buffer()]]
if (hlsl_seen(seen_hlsl_buffer_bindings, metadata, src_binding)) {
- diagnostics.AddNote(diag::System::Writer, "when processing external_texture", {});
+ diagnostics.AddNote(diag::System::Writer, Source{})
+ << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
}
diff --git a/src/tint/lang/msl/intrinsic/data.cc b/src/tint/lang/msl/intrinsic/data.cc
index 261ee51..c4f7487 100644
--- a/src/tint/lang/msl/intrinsic/data.cc
+++ b/src/tint/lang/msl/intrinsic/data.cc
@@ -82,8 +82,8 @@
}
return BuildU32(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "u32";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "u32";
}
};
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_printer.cc b/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
index 5a3a574..c2442f5 100644
--- a/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
@@ -305,9 +305,9 @@
},
[&](const ast::Override*) {
// Override is removed with SubstituteOverride
- diagnostics_.AddError(diag::System::Writer,
- "override-expressions should have been removed with the "
- "SubstituteOverride transform.");
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "override-expressions should have been removed with the "
+ "SubstituteOverride transform.";
return false;
},
[&](const ast::Function* func) {
@@ -364,7 +364,8 @@
return false;
}
} else {
- diagnostics_.AddError(diag::System::Writer, "unknown alias type: " + ty->FriendlyName());
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "unknown alias type: " << ty->FriendlyName();
return false;
}
@@ -1063,7 +1064,8 @@
std::vector<const char*> dims;
switch (texture_type->dim()) {
case core::type::TextureDimension::kNone:
- diagnostics_.AddError(diag::System::Writer, "texture dimension is kNone");
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "texture dimension is kNone";
return false;
case core::type::TextureDimension::k1d:
dims = {"width"};
@@ -1262,9 +1264,8 @@
out << "gradientcube(";
break;
default: {
- StringStream err;
- err << "MSL does not support gradients for " << dim << " textures";
- diagnostics_.AddError(diag::System::Writer, err.str());
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "MSL does not support gradients for " << dim << " textures";
return false;
}
}
@@ -1620,15 +1621,13 @@
out += "unpack_unorm2x16_to_float";
break;
case wgsl::BuiltinFn::kArrayLength:
- diagnostics_.AddError(
- diag::System::Writer,
- "Unable to translate builtin: " + std::string(builtin->str()) +
- "\nDid you forget to pass array_length_from_uniform generator "
- "options?");
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "Unable to translate builtin: " << builtin->Fn()
+ << "\nDid you forget to pass array_length_from_uniform generator options?";
return "";
default:
- diagnostics_.AddError(diag::System::Writer,
- "Unknown import method: " + std::string(builtin->str()));
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "Unknown import method: " << builtin->Fn();
return "";
}
return out;
@@ -1803,8 +1802,8 @@
auto count = a->ConstantCount();
if (!count) {
- diagnostics_.AddError(diag::System::Writer,
- core::type::Array::kErrExpectedConstantCount);
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << core::type::Array::kErrExpectedConstantCount;
return false;
}
@@ -1874,7 +1873,8 @@
return true;
}
}
- diagnostics_.AddError(diag::System::Writer, "unknown integer literal suffix type");
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "unknown integer literal suffix type";
return false;
}, //
TINT_ICE_ON_NO_MATCH);
@@ -2069,7 +2069,8 @@
auto name = BuiltinToAttribute(builtin);
if (name.empty()) {
- diagnostics_.AddError(diag::System::Writer, "unknown builtin");
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "unknown builtin";
return false;
}
out << " [[" << name << "]]";
@@ -2526,8 +2527,8 @@
} else {
auto count = arr->ConstantCount();
if (!count) {
- diagnostics_.AddError(diag::System::Writer,
- core::type::Array::kErrExpectedConstantCount);
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << core::type::Array::kErrExpectedConstantCount;
return false;
}
@@ -2622,7 +2623,8 @@
out << "cube_array";
break;
default:
- diagnostics_.AddError(diag::System::Writer, "Invalid texture dimensions");
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "Invalid texture dimensions";
return false;
}
if (tex->IsAnyOf<core::type::MultisampledTexture,
@@ -2655,8 +2657,8 @@
} else if (storage->access() == core::Access::kWrite) {
out << ", access::write";
} else {
- diagnostics_.AddError(diag::System::Writer,
- "Invalid access control for storage texture");
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "Invalid access control for storage texture";
return false;
}
return true;
@@ -2797,7 +2799,7 @@
if (auto builtin = attributes.builtin) {
auto name = BuiltinToAttribute(builtin.value());
if (name.empty()) {
- diagnostics_.AddError(diag::System::Writer, "unknown builtin");
+ diagnostics_.AddError(diag::System::Writer, Source{}) << "unknown builtin";
return false;
}
out << " [[" << name << "]]";
@@ -2839,7 +2841,8 @@
if (auto interpolation = attributes.interpolation) {
auto name = InterpolationToAttribute(interpolation->type, interpolation->sampling);
if (name.empty()) {
- diagnostics_.AddError(diag::System::Writer, "unknown interpolation attribute");
+ diagnostics_.AddError(diag::System::Writer, Source{})
+ << "unknown interpolation attribute";
return false;
}
out << " [[" << name << "]]";
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_printer_test.cc b/src/tint/lang/msl/writer/ast_printer/ast_printer_test.cc
index ab858e3..a78f3ee 100644
--- a/src/tint/lang/msl/writer/ast_printer/ast_printer_test.cc
+++ b/src/tint/lang/msl/writer/ast_printer/ast_printer_test.cc
@@ -39,7 +39,7 @@
using MslASTPrinterTest = TestHelper;
TEST_F(MslASTPrinterTest, InvalidProgram) {
- Diagnostics().AddError(diag::System::Writer, "make the program invalid");
+ Diagnostics().AddError(diag::System::Writer, Source{}) << "make the program invalid";
ASSERT_FALSE(IsValid());
auto program = resolver::Resolve(*this);
ASSERT_FALSE(program.IsValid());
diff --git a/src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.cc b/src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.cc
index 140b209..0084d30a 100644
--- a/src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.cc
+++ b/src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.cc
@@ -244,9 +244,8 @@
case core::AddressSpace::kWorkgroup:
break;
case core::AddressSpace::kPushConstant: {
- ctx.dst->Diagnostics().AddError(
- diag::System::Transform,
- "unhandled module-scope address space (" + tint::ToString(sc) + ")");
+ ctx.dst->Diagnostics().AddError(diag::System::Transform, Source{})
+ << "unhandled module-scope address space (" << sc << ")";
break;
}
default: {
diff --git a/src/tint/lang/msl/writer/ast_raise/pixel_local.cc b/src/tint/lang/msl/writer/ast_raise/pixel_local.cc
index 2f2a216..c6cc55a 100644
--- a/src/tint/lang/msl/writer/ast_raise/pixel_local.cc
+++ b/src/tint/lang/msl/writer/ast_raise/pixel_local.cc
@@ -257,9 +257,8 @@
uint32_t AttachmentIndex(uint32_t field_index) {
auto idx = cfg.attachments.Get(field_index);
if (TINT_UNLIKELY(!idx)) {
- b.Diagnostics().AddError(diag::System::Transform,
- "PixelLocal::Config::attachments missing entry for field " +
- std::to_string(field_index));
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "PixelLocal::Config::attachments missing entry for field " << field_index;
return 0;
}
return *idx;
@@ -276,8 +275,8 @@
auto* cfg = inputs.Get<Config>();
if (!cfg) {
ProgramBuilder b;
- b.Diagnostics().AddError(diag::System::Transform,
- "missing transform data for " + std::string(TypeInfo().name));
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "missing transform data for " << TypeInfo().name;
return resolver::Resolve(b);
}
diff --git a/src/tint/lang/msl/writer/common/option_helpers.cc b/src/tint/lang/msl/writer/common/option_helpers.cc
index d72d984..cb6a162 100644
--- a/src/tint/lang/msl/writer/common/option_helpers.cc
+++ b/src/tint/lang/msl/writer/common/option_helpers.cc
@@ -54,10 +54,8 @@
const binding::BindingInfo& dst) -> bool {
if (auto binding = seen_wgsl_bindings.Get(src)) {
if (*binding != dst) {
- std::stringstream str;
- str << "found duplicate WGSL binding point: " << src;
-
- diagnostics.AddError(diag::System::Writer, str.str());
+ diagnostics.AddError(diag::System::Writer, Source{})
+ << "found duplicate WGSL binding point: " << src;
return true;
}
}
@@ -69,9 +67,8 @@
const tint::BindingPoint& dst) -> bool {
if (auto binding = map.Get(src)) {
if (*binding != dst) {
- std::stringstream str;
- str << "found duplicate MSL binding point: [binding: " << src.binding << "]";
- diagnostics.AddError(diag::System::Writer, str.str());
+ diagnostics.AddError(diag::System::Writer, Source{})
+ << "found duplicate MSL binding point: [binding: " << src.binding << "]";
return true;
}
}
@@ -97,27 +94,27 @@
// Storage and uniform are both [[buffer()]]
if (!valid(seen_msl_buffer_bindings, options.bindings.uniform)) {
- diagnostics.AddNote(diag::System::Writer, "when processing uniform", {});
+ diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing uniform";
return Failure{std::move(diagnostics)};
}
if (!valid(seen_msl_buffer_bindings, options.bindings.storage)) {
- diagnostics.AddNote(diag::System::Writer, "when processing storage", {});
+ diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing storage";
return Failure{std::move(diagnostics)};
}
// Sampler is [[sampler()]]
if (!valid(seen_msl_sampler_bindings, options.bindings.sampler)) {
- diagnostics.AddNote(diag::System::Writer, "when processing sampler", {});
+ diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing sampler";
return Failure{std::move(diagnostics)};
}
// Texture and storage texture are [[texture()]]
if (!valid(seen_msl_texture_bindings, options.bindings.texture)) {
- diagnostics.AddNote(diag::System::Writer, "when processing texture", {});
+ diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing texture";
return Failure{std::move(diagnostics)};
}
if (!valid(seen_msl_texture_bindings, options.bindings.storage_texture)) {
- diagnostics.AddNote(diag::System::Writer, "when processing storage_texture", {});
+ diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing storage_texture";
return Failure{std::move(diagnostics)};
}
@@ -129,22 +126,26 @@
// Validate with the actual source regardless of what the remapper will do
if (wgsl_seen(src_binding, plane0)) {
- diagnostics.AddNote(diag::System::Writer, "when processing external_texture", {});
+ diagnostics.AddNote(diag::System::Writer, Source{})
+ << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
// Plane0 & Plane1 are [[texture()]]
if (msl_seen(seen_msl_texture_bindings, plane0, src_binding)) {
- diagnostics.AddNote(diag::System::Writer, "when processing external_texture", {});
+ diagnostics.AddNote(diag::System::Writer, Source{})
+ << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
if (msl_seen(seen_msl_texture_bindings, plane1, src_binding)) {
- diagnostics.AddNote(diag::System::Writer, "when processing external_texture", {});
+ diagnostics.AddNote(diag::System::Writer, Source{})
+ << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
// Metadata is [[buffer()]]
if (msl_seen(seen_msl_buffer_bindings, metadata, src_binding)) {
- diagnostics.AddNote(diag::System::Writer, "when processing external_texture", {});
+ diagnostics.AddNote(diag::System::Writer, Source{})
+ << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
}
diff --git a/src/tint/lang/spirv/intrinsic/data.cc b/src/tint/lang/spirv/intrinsic/data.cc
index 110a151..691263a 100644
--- a/src/tint/lang/spirv/intrinsic/data.cc
+++ b/src/tint/lang/spirv/intrinsic/data.cc
@@ -83,8 +83,8 @@
}
return BuildBool(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "bool";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "bool";
}
};
@@ -97,8 +97,8 @@
}
return BuildF32(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "f32";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "f32";
}
};
@@ -111,8 +111,8 @@
}
return BuildF16(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "f16";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "f16";
}
};
@@ -125,8 +125,8 @@
}
return BuildI32(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "i32";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "i32";
}
};
@@ -139,8 +139,8 @@
}
return BuildU32(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "u32";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "u32";
}
};
@@ -158,9 +158,9 @@
}
return BuildVec2(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "vec2<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "vec2" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -178,9 +178,9 @@
}
return BuildVec3(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "vec3<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "vec3" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -198,9 +198,9 @@
}
return BuildVec4(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "vec4<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "vec4" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -218,9 +218,9 @@
}
return BuildMat2X2(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat2x2<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat2x2" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -238,9 +238,9 @@
}
return BuildMat2X3(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat2x3<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat2x3" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -258,9 +258,9 @@
}
return BuildMat2X4(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat2x4<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat2x4" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -278,9 +278,9 @@
}
return BuildMat3X2(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat3x2<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat3x2" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -298,9 +298,9 @@
}
return BuildMat3X3(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat3x3<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat3x3" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -318,9 +318,9 @@
}
return BuildMat3X4(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat3x4<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat3x4" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -338,9 +338,9 @@
}
return BuildMat4X2(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat4x2<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat4x2" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -358,9 +358,9 @@
}
return BuildMat4X3(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat4x3<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat4x3" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -378,9 +378,9 @@
}
return BuildMat4X4(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat4x4<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat4x4" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -403,12 +403,10 @@
}
return BuildVec(state, ty, N, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string N = state->NumName();
- const std::string T = state->TypeName();
- StringStream ss;
- ss << "vec" << N << "<" << T << ">";
- return ss.str();
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N;
+ state->PrintNum(N);StyledText T;
+ state->PrintType(T);
+ out << style::Type << "vec" << style::Type << N << style::Type << "<" << style::Type << T << style::Type << ">";
}
};
@@ -436,13 +434,11 @@
}
return BuildMat(state, ty, N, M, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string N = state->NumName();
- const std::string M = state->NumName();
- const std::string T = state->TypeName();
- StringStream ss;
- ss << "mat" << N << "x" << M << "<" << T << ">";
- return ss.str();
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N;
+ state->PrintNum(N);StyledText M;
+ state->PrintNum(M);StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat" << style::Type << N << style::Type << "x" << style::Type << M << style::Type << "<" << style::Type << T << style::Type << ">";
}
};
@@ -460,9 +456,9 @@
}
return BuildAtomic(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "atomic<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "atomic" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -475,8 +471,8 @@
}
return BuildSampler(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "sampler";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "sampler";
}
};
@@ -489,8 +485,8 @@
}
return BuildSamplerComparison(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "sampler_comparison";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "sampler_comparison";
}
};
@@ -508,9 +504,9 @@
}
return BuildTexture1D(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_1d<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_1d" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -528,9 +524,9 @@
}
return BuildTexture2D(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_2d<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_2d" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -548,9 +544,9 @@
}
return BuildTexture2DArray(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_2d_array<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_2d_array" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -568,9 +564,9 @@
}
return BuildTexture3D(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_3d<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_3d" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -588,9 +584,9 @@
}
return BuildTextureCube(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_cube<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_cube" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -608,9 +604,9 @@
}
return BuildTextureCubeArray(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_cube_array<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_cube_array" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -628,9 +624,9 @@
}
return BuildTextureMultisampled2D(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_multisampled_2d<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_multisampled_2d" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -643,8 +639,8 @@
}
return BuildTextureDepth2D(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "texture_depth_2d";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "texture_depth_2d";
}
};
@@ -657,8 +653,8 @@
}
return BuildTextureDepth2DArray(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "texture_depth_2d_array";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "texture_depth_2d_array";
}
};
@@ -671,8 +667,8 @@
}
return BuildTextureDepthCube(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "texture_depth_cube";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "texture_depth_cube";
}
};
@@ -685,8 +681,8 @@
}
return BuildTextureDepthCubeArray(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "texture_depth_cube_array";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "texture_depth_cube_array";
}
};
@@ -699,8 +695,8 @@
}
return BuildTextureDepthMultisampled2D(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "texture_depth_multisampled_2d";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "texture_depth_multisampled_2d";
}
};
@@ -723,10 +719,10 @@
}
return BuildTextureStorage1D(state, ty, F, A);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string F = state->NumName();
- const std::string A = state->NumName();
- return "texture_storage_1d<" + F + ", " + A + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F;
+ state->PrintNum(F);StyledText A;
+ state->PrintNum(A);
+ out << style::Type << "texture_storage_1d" << style::Code << "<" << style::Type << F << style::Code << ", " << style::Type << A << style::Code << ">";
}
};
@@ -749,10 +745,10 @@
}
return BuildTextureStorage2D(state, ty, F, A);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string F = state->NumName();
- const std::string A = state->NumName();
- return "texture_storage_2d<" + F + ", " + A + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F;
+ state->PrintNum(F);StyledText A;
+ state->PrintNum(A);
+ out << style::Type << "texture_storage_2d" << style::Code << "<" << style::Type << F << style::Code << ", " << style::Type << A << style::Code << ">";
}
};
@@ -775,10 +771,10 @@
}
return BuildTextureStorage2DArray(state, ty, F, A);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string F = state->NumName();
- const std::string A = state->NumName();
- return "texture_storage_2d_array<" + F + ", " + A + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F;
+ state->PrintNum(F);StyledText A;
+ state->PrintNum(A);
+ out << style::Type << "texture_storage_2d_array" << style::Code << "<" << style::Type << F << style::Code << ", " << style::Type << A << style::Code << ">";
}
};
@@ -801,10 +797,10 @@
}
return BuildTextureStorage3D(state, ty, F, A);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string F = state->NumName();
- const std::string A = state->NumName();
- return "texture_storage_3d<" + F + ", " + A + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F;
+ state->PrintNum(F);StyledText A;
+ state->PrintNum(A);
+ out << style::Type << "texture_storage_3d" << style::Code << "<" << style::Type << F << style::Code << ", " << style::Type << A << style::Code << ">";
}
};
@@ -832,11 +828,11 @@
}
return BuildPtr(state, ty, S, T, A);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string S = state->NumName();
- const std::string T = state->TypeName();
- const std::string A = state->NumName();
- return "ptr<" + S + ", " + T + ", " + A + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText S;
+ state->PrintNum(S);StyledText T;
+ state->PrintType(T);StyledText A;
+ state->PrintNum(A);
+ out << style::Type << "ptr" << style::Code << "<" << style::Type << S << style::Code << ", " << style::Type << T << style::Code << ", " << style::Type << A << style::Code << ">";
}
};
@@ -849,8 +845,8 @@
}
return BuildStructWithRuntimeArray(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "struct_with_runtime_array";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "struct_with_runtime_array";
}
};
@@ -868,9 +864,9 @@
}
return BuildSampledImage(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "sampled_image<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "sampled_image" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -886,13 +882,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kF32Matcher.string(nullptr) << " or " << kF16Matcher.string(nullptr);
- return ss.str();
- }
+ kF32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kF16Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match iu32'
@@ -906,13 +899,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kI32Matcher.string(nullptr) << " or " << kU32Matcher.string(nullptr);
- return ss.str();
- }
+ kI32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kU32Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match fiu32'
@@ -929,13 +919,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kF32Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << " or " << kU32Matcher.string(nullptr);
- return ss.str();
- }
+ kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kU32Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match scalar'
@@ -958,13 +945,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kF32Matcher.string(nullptr) << ", " << kF16Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << ", " << kU32Matcher.string(nullptr) << " or " << kBoolMatcher.string(nullptr);
- return ss.str();
- }
+ kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kF16Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kU32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kBoolMatcher.print(nullptr, out);}
};
/// TypeMatcher for 'match samplers'
@@ -978,13 +962,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kSamplerMatcher.string(nullptr) << " or " << kSamplerComparisonMatcher.string(nullptr);
- return ss.str();
- }
+ kSamplerMatcher.print(nullptr, out); out << TextStyle{} << " or "; kSamplerComparisonMatcher.print(nullptr, out);}
};
/// EnumMatcher for 'match read_write'
@@ -995,8 +976,8 @@
}
return Number::invalid;
},
-/* string */ [](MatchState*) -> std::string {
- return "read_write";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "read_write";
}
};
@@ -1008,8 +989,8 @@
}
return Number::invalid;
},
-/* string */ [](MatchState*) -> std::string {
- return "storage";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "storage";
}
};
@@ -1024,8 +1005,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "workgroup or storage";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "workgroup"<< TextStyle{} << " or " << style::Enum << "storage";
}
};
@@ -1045,8 +1026,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "bgra8unorm, rgba8unorm, rgba8snorm, rgba16float, r32float, rg32float or rgba32float";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "bgra8unorm"<< TextStyle{} << ", " << style::Enum << "rgba8unorm"<< TextStyle{} << ", " << style::Enum << "rgba8snorm"<< TextStyle{} << ", " << style::Enum << "rgba16float"<< TextStyle{} << ", " << style::Enum << "r32float"<< TextStyle{} << ", " << style::Enum << "rg32float"<< TextStyle{} << " or " << style::Enum << "rgba32float";
}
};
@@ -1064,8 +1045,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "rgba8sint, rgba16sint, r32sint, rg32sint or rgba32sint";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "rgba8sint"<< TextStyle{} << ", " << style::Enum << "rgba16sint"<< TextStyle{} << ", " << style::Enum << "r32sint"<< TextStyle{} << ", " << style::Enum << "rg32sint"<< TextStyle{} << " or " << style::Enum << "rgba32sint";
}
};
@@ -1083,8 +1064,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "rgba8uint, rgba16uint, r32uint, rg32uint or rgba32uint";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "rgba8uint"<< TextStyle{} << ", " << style::Enum << "rgba16uint"<< TextStyle{} << ", " << style::Enum << "r32uint"<< TextStyle{} << ", " << style::Enum << "rg32uint"<< TextStyle{} << " or " << style::Enum << "rgba32uint";
}
};
@@ -1099,8 +1080,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "read or read_write";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "read"<< TextStyle{} << " or " << style::Enum << "read_write";
}
};
@@ -1115,8 +1096,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "write or read_write";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "write"<< TextStyle{} << " or " << style::Enum << "read_write";
}
};
diff --git a/src/tint/lang/spirv/reader/ast_lower/atomics.cc b/src/tint/lang/spirv/reader/ast_lower/atomics.cc
index 06e9d43..181ab19 100644
--- a/src/tint/lang/spirv/reader/ast_lower/atomics.cc
+++ b/src/tint/lang/spirv/reader/ast_lower/atomics.cc
@@ -224,10 +224,9 @@
}
auto count = arr->ConstantCount();
if (!count) {
- ctx.dst->Diagnostics().AddError(
- diag::System::Transform,
- "the Atomics transform does not currently support array counts that "
- "use override values");
+ ctx.dst->Diagnostics().AddError(diag::System::Transform, Source{})
+ << "the Atomics transform does not currently support array counts that use "
+ "override values";
count = 1;
}
return b.ty.array(AtomicTypeFor(arr->ElemType()), u32(count.value()));
diff --git a/src/tint/lang/spirv/reader/ast_parser/barrier_test.cc b/src/tint/lang/spirv/reader/ast_parser/barrier_test.cc
index d106222..7fa6c89 100644
--- a/src/tint/lang/spirv/reader/ast_parser/barrier_test.cc
+++ b/src/tint/lang/spirv/reader/ast_parser/barrier_test.cc
@@ -51,7 +51,7 @@
auto p = std::make_unique<ASTParser>(test::Assemble(preamble + spirv));
if (!p->BuildAndParseInternalModule()) {
ProgramBuilder builder;
- builder.Diagnostics().AddError(diag::System::Reader, p->error());
+ builder.Diagnostics().AddError(diag::System::Reader, Source{}) << p->error();
return Program(std::move(builder));
}
return p->Program();
diff --git a/src/tint/lang/spirv/reader/ast_parser/parse.cc b/src/tint/lang/spirv/reader/ast_parser/parse.cc
index 988fc08..c3dea0e 100644
--- a/src/tint/lang/spirv/reader/ast_parser/parse.cc
+++ b/src/tint/lang/spirv/reader/ast_parser/parse.cc
@@ -83,7 +83,7 @@
ProgramBuilder& builder = parser.builder();
if (!parsed) {
// TODO(bclayton): Migrate ASTParser to using diagnostics.
- builder.Diagnostics().AddError(diag::System::Reader, parser.error());
+ builder.Diagnostics().AddError(diag::System::Reader, Source{}) << parser.error();
return Program(std::move(builder));
}
diff --git a/src/tint/lang/spirv/writer/ast_printer/ast_printer_test.cc b/src/tint/lang/spirv/writer/ast_printer/ast_printer_test.cc
index ad5f484..e76c3c2 100644
--- a/src/tint/lang/spirv/writer/ast_printer/ast_printer_test.cc
+++ b/src/tint/lang/spirv/writer/ast_printer/ast_printer_test.cc
@@ -34,7 +34,7 @@
using SpirvASTPrinterTest = TestHelper;
TEST_F(SpirvASTPrinterTest, InvalidProgram) {
- Diagnostics().AddError(diag::System::Writer, "make the program invalid");
+ Diagnostics().AddError(diag::System::Writer, Source{}) << "make the program invalid";
ASSERT_FALSE(IsValid());
auto program = resolver::Resolve(*this);
ASSERT_FALSE(program.IsValid());
diff --git a/src/tint/lang/spirv/writer/common/option_helper.cc b/src/tint/lang/spirv/writer/common/option_helper.cc
index 37f2377..76a21ed 100644
--- a/src/tint/lang/spirv/writer/common/option_helper.cc
+++ b/src/tint/lang/spirv/writer/common/option_helper.cc
@@ -48,10 +48,8 @@
const binding::BindingInfo& dst) -> bool {
if (auto binding = seen_wgsl_bindings.Get(src)) {
if (*binding != dst) {
- std::stringstream str;
- str << "found duplicate WGSL binding point: " << src;
-
- diagnostics.AddError(diag::System::Writer, str.str());
+ diagnostics.AddError(diag::System::Writer, Source{})
+ << "found duplicate WGSL binding point: " << src;
return true;
}
}
@@ -63,10 +61,9 @@
const tint::BindingPoint& dst) -> bool {
if (auto binding = seen_spirv_bindings.Get(src)) {
if (*binding != dst) {
- std::stringstream str;
- str << "found duplicate SPIR-V binding point: [group: " << src.group
+ diagnostics.AddError(diag::System::Writer, Source{})
+ << "found duplicate SPIR-V binding point: [group: " << src.group
<< ", binding: " << src.binding << "]";
- diagnostics.AddError(diag::System::Writer, str.str());
return true;
}
}
@@ -91,23 +88,23 @@
};
if (!valid(options.bindings.uniform)) {
- diagnostics.AddNote(diag::System::Writer, "when processing uniform", {});
+ diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing uniform";
return Failure{std::move(diagnostics)};
}
if (!valid(options.bindings.storage)) {
- diagnostics.AddNote(diag::System::Writer, "when processing storage", {});
+ diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing storage";
return Failure{std::move(diagnostics)};
}
if (!valid(options.bindings.texture)) {
- diagnostics.AddNote(diag::System::Writer, "when processing texture", {});
+ diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing texture";
return Failure{std::move(diagnostics)};
}
if (!valid(options.bindings.storage_texture)) {
- diagnostics.AddNote(diag::System::Writer, "when processing storage_texture", {});
+ diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing storage_texture";
return Failure{std::move(diagnostics)};
}
if (!valid(options.bindings.sampler)) {
- diagnostics.AddNote(diag::System::Writer, "when processing sampler", {});
+ diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing sampler";
return Failure{std::move(diagnostics)};
}
@@ -119,20 +116,24 @@
// Validate with the actual source regardless of what the remapper will do
if (wgsl_seen(src_binding, plane0)) {
- diagnostics.AddNote(diag::System::Writer, "when processing external_texture", {});
+ diagnostics.AddNote(diag::System::Writer, Source{})
+ << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
if (spirv_seen(plane0, src_binding)) {
- diagnostics.AddNote(diag::System::Writer, "when processing external_texture", {});
+ diagnostics.AddNote(diag::System::Writer, Source{})
+ << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
if (spirv_seen(plane1, src_binding)) {
- diagnostics.AddNote(diag::System::Writer, "when processing external_texture", {});
+ diagnostics.AddNote(diag::System::Writer, Source{})
+ << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
if (spirv_seen(metadata, src_binding)) {
- diagnostics.AddNote(diag::System::Writer, "when processing external_texture", {});
+ diagnostics.AddNote(diag::System::Writer, Source{})
+ << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
}
diff --git a/src/tint/lang/wgsl/ast/transform/array_length_from_uniform.cc b/src/tint/lang/wgsl/ast/transform/array_length_from_uniform.cc
index fa6bc9e..bdb43cf 100644
--- a/src/tint/lang/wgsl/ast/transform/array_length_from_uniform.cc
+++ b/src/tint/lang/wgsl/ast/transform/array_length_from_uniform.cc
@@ -82,10 +82,9 @@
ApplyResult Run() {
auto* cfg = inputs.Get<Config>();
if (cfg == nullptr) {
- b.Diagnostics().AddError(
- diag::System::Transform,
- "missing transform data for " +
- std::string(tint::TypeInfo::Of<ArrayLengthFromUniform>().name));
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "missing transform data for "
+ << tint::TypeInfo::Of<ArrayLengthFromUniform>().name;
return resolver::Resolve(b);
}
diff --git a/src/tint/lang/wgsl/ast/transform/binding_remapper.cc b/src/tint/lang/wgsl/ast/transform/binding_remapper.cc
index c3c8cbe..31ef518 100644
--- a/src/tint/lang/wgsl/ast/transform/binding_remapper.cc
+++ b/src/tint/lang/wgsl/ast/transform/binding_remapper.cc
@@ -66,8 +66,8 @@
auto* remappings = inputs.Get<Remappings>();
if (!remappings) {
- b.Diagnostics().AddError(diag::System::Transform,
- "missing transform data for " + std::string(TypeInfo().name));
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "missing transform data for " << TypeInfo().name;
return resolver::Resolve(b);
}
@@ -112,18 +112,15 @@
if (ac_it != remappings->access_controls.end()) {
core::Access access = ac_it->second;
if (access == core::Access::kUndefined) {
- b.Diagnostics().AddError(diag::System::Transform,
- "invalid access mode (" +
- std::to_string(static_cast<uint32_t>(access)) +
- ")");
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "invalid access mode (" << static_cast<uint32_t>(access) << ")";
return resolver::Resolve(b);
}
auto* sem = src.Sem().Get(var);
if (sem->AddressSpace() != core::AddressSpace::kStorage) {
- b.Diagnostics().AddError(
- diag::System::Transform,
- "cannot apply access control to variable with address space " +
- std::string(tint::ToString(sem->AddressSpace())));
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "cannot apply access control to variable with address space "
+ << sem->AddressSpace();
return resolver::Resolve(b);
}
auto* ty = sem->Type()->UnwrapRef();
diff --git a/src/tint/lang/wgsl/ast/transform/canonicalize_entry_point_io.cc b/src/tint/lang/wgsl/ast/transform/canonicalize_entry_point_io.cc
index db9a682..3e2029b 100644
--- a/src/tint/lang/wgsl/ast/transform/canonicalize_entry_point_io.cc
+++ b/src/tint/lang/wgsl/ast/transform/canonicalize_entry_point_io.cc
@@ -979,8 +979,8 @@
auto* cfg = inputs.Get<Config>();
if (cfg == nullptr) {
- b.Diagnostics().AddError(diag::System::Transform,
- "missing transform data for " + std::string(TypeInfo().name));
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "missing transform data for " << TypeInfo().name;
return resolver::Resolve(b);
}
diff --git a/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture.cc b/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture.cc
index 815a3ed..6cbaec6 100644
--- a/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture.cc
+++ b/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture.cc
@@ -135,10 +135,9 @@
BindingsMap::const_iterator it = new_binding_points->bindings_map.find(bp);
if (it == new_binding_points->bindings_map.end()) {
- b.Diagnostics().AddError(
- diag::System::Transform,
- "missing new binding points for texture_external at binding {" +
- std::to_string(bp.group) + "," + std::to_string(bp.binding) + "}");
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "missing new binding points for texture_external at binding {" << bp.group
+ << "," << bp.binding << "}";
continue;
}
@@ -552,8 +551,8 @@
ProgramBuilder b;
program::CloneContext ctx{&b, &src, /* auto_clone_symbols */ true};
if (!new_binding_points) {
- b.Diagnostics().AddError(diag::System::Transform, "missing new binding point data for " +
- std::string(TypeInfo().name));
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "missing new binding point data for " << TypeInfo().name;
return resolver::Resolve(b);
}
diff --git a/src/tint/lang/wgsl/ast/transform/push_constant_helper.cc b/src/tint/lang/wgsl/ast/transform/push_constant_helper.cc
index af6fe57..ba10cf4 100644
--- a/src/tint/lang/wgsl/ast/transform/push_constant_helper.cc
+++ b/src/tint/lang/wgsl/ast/transform/push_constant_helper.cc
@@ -64,7 +64,8 @@
void PushConstantHelper::InsertMember(const char* name, ast::Type type, uint32_t offset) {
auto& member = member_map[offset];
if (TINT_UNLIKELY(member != nullptr)) {
- ctx.dst->Diagnostics().AddError(diag::System::Transform, "struct member offset collision");
+ ctx.dst->Diagnostics().AddError(diag::System::Transform, Source{})
+ << "struct member offset collision";
}
member = ctx.dst->Member(name, type, Vector{ctx.dst->MemberOffset(core::AInt(offset))});
}
diff --git a/src/tint/lang/wgsl/ast/transform/robustness.cc b/src/tint/lang/wgsl/ast/transform/robustness.cc
index c3f9c57..42273c5 100644
--- a/src/tint/lang/wgsl/ast/transform/robustness.cc
+++ b/src/tint/lang/wgsl/ast/transform/robustness.cc
@@ -272,8 +272,8 @@
}
// Note: Don't be tempted to use the array override variable as an expression here,
// the name might be shadowed!
- b.Diagnostics().AddError(diag::System::Transform,
- core::type::Array::kErrExpectedConstantCount);
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << core::type::Array::kErrExpectedConstantCount;
return nullptr;
}, //
TINT_ICE_ON_NO_MATCH);
diff --git a/src/tint/lang/wgsl/ast/transform/single_entry_point.cc b/src/tint/lang/wgsl/ast/transform/single_entry_point.cc
index 78843cc..a0952eb 100644
--- a/src/tint/lang/wgsl/ast/transform/single_entry_point.cc
+++ b/src/tint/lang/wgsl/ast/transform/single_entry_point.cc
@@ -55,8 +55,8 @@
auto* cfg = inputs.Get<Config>();
if (cfg == nullptr) {
- b.Diagnostics().AddError(diag::System::Transform,
- "missing transform data for " + std::string(TypeInfo().name));
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "missing transform data for " << TypeInfo().name;
return resolver::Resolve(b);
}
@@ -72,8 +72,8 @@
}
}
if (entry_point == nullptr) {
- b.Diagnostics().AddError(diag::System::Transform,
- "entry point '" + cfg->entry_point_name + "' not found");
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "entry point '" << cfg->entry_point_name << "' not found";
return resolver::Resolve(b);
}
diff --git a/src/tint/lang/wgsl/ast/transform/substitute_override.cc b/src/tint/lang/wgsl/ast/transform/substitute_override.cc
index 74d8b7b..4711b36 100644
--- a/src/tint/lang/wgsl/ast/transform/substitute_override.cc
+++ b/src/tint/lang/wgsl/ast/transform/substitute_override.cc
@@ -71,7 +71,8 @@
const auto* data = config.Get<Config>();
if (!data) {
- b.Diagnostics().AddError(diag::System::Transform, "Missing override substitution data");
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "Missing override substitution data";
return resolver::Resolve(b);
}
@@ -90,9 +91,8 @@
auto iter = data->map.find(sem->Attributes().override_id.value());
if (iter == data->map.end()) {
if (!w->initializer) {
- b.Diagnostics().AddError(
- diag::System::Transform,
- "Initializer not provided for override, and override not overridden.");
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "Initializer not provided for override, and override not overridden.";
return nullptr;
}
return b.Const(source, sym, ty, ctx.Clone(w->initializer));
@@ -108,8 +108,8 @@
[&](const core::type::F16*) { return b.Expr(f16(value)); });
if (!ctor) {
- b.Diagnostics().AddError(diag::System::Transform,
- "Failed to create override-expression");
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "Failed to create override-expression";
return nullptr;
}
diff --git a/src/tint/lang/wgsl/ast/transform/vertex_pulling.cc b/src/tint/lang/wgsl/ast/transform/vertex_pulling.cc
index 31c2c29..8eae5a6 100644
--- a/src/tint/lang/wgsl/ast/transform/vertex_pulling.cc
+++ b/src/tint/lang/wgsl/ast/transform/vertex_pulling.cc
@@ -72,11 +72,11 @@
kFloat, // unsigned normalized, signed normalized, and float
};
-/// Writes the VertexFormat to the stream.
+/// Writes the VertexFormat to the diagnostic.
/// @param out the stream to write to
/// @param format the VertexFormat to write
/// @returns out so calls can be chained
-StringStream& operator<<(StringStream& out, VertexFormat format) {
+diag::Diagnostic& operator<<(diag::Diagnostic& out, VertexFormat format) {
switch (format) {
case VertexFormat::kUint8x2:
return out << "uint8x2";
@@ -260,16 +260,16 @@
for (auto* fn : src.AST().Functions()) {
if (fn->PipelineStage() == PipelineStage::kVertex) {
if (func != nullptr) {
- b.Diagnostics().AddError(
- diag::System::Transform,
- "VertexPulling found more than one vertex entry point");
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "VertexPulling found more than one vertex entry point";
return resolver::Resolve(b);
}
func = fn;
}
}
if (func == nullptr) {
- b.Diagnostics().AddError(diag::System::Transform, "Vertex stage entry point not found");
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "Vertex stage entry point not found";
return resolver::Resolve(b);
}
@@ -357,12 +357,10 @@
const VertexBufferLayoutDescriptor& buffer_layout = cfg.vertex_state[buffer_idx];
if ((buffer_layout.array_stride & 3) != 0) {
- b.Diagnostics().AddError(
- diag::System::Transform,
- "WebGPU requires that vertex stride must be a multiple of 4 bytes, "
- "but VertexPulling array stride for buffer " +
- std::to_string(buffer_idx) + " was " +
- std::to_string(buffer_layout.array_stride) + " bytes");
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "WebGPU requires that vertex stride must be a multiple of 4 bytes, "
+ "but VertexPulling array stride for buffer "
+ << buffer_idx << " was " << buffer_layout.array_stride << " bytes";
return nullptr;
}
@@ -397,12 +395,10 @@
// Base types must match between the vertex stream and the WGSL variable
if (!IsTypeCompatible(var_dt, fmt_dt)) {
- StringStream err;
- err << "VertexAttributeDescriptor for location "
- << std::to_string(attribute_desc.shader_location) << " has format "
- << attribute_desc.format << " but shader expects "
- << var.type->FriendlyName();
- b.Diagnostics().AddError(diag::System::Transform, err.str());
+ b.Diagnostics().AddError(diag::System::Transform, Source{})
+ << "VertexAttributeDescriptor for location "
+ << attribute_desc.shader_location << " has format " << attribute_desc.format
+ << " but shader expects " << var.type->FriendlyName();
return nullptr;
}
diff --git a/src/tint/lang/wgsl/ast/transform/zero_init_workgroup_memory.cc b/src/tint/lang/wgsl/ast/transform/zero_init_workgroup_memory.cc
index e394520..d0e7f74 100644
--- a/src/tint/lang/wgsl/ast/transform/zero_init_workgroup_memory.cc
+++ b/src/tint/lang/wgsl/ast/transform/zero_init_workgroup_memory.cc
@@ -381,8 +381,8 @@
// `(idx % modulo) / division`
auto count = arr->ConstantCount();
if (!count) {
- ctx.dst->Diagnostics().AddError(diag::System::Transform,
- core::type::Array::kErrExpectedConstantCount);
+ ctx.dst->Diagnostics().AddError(diag::System::Transform, Source{})
+ << core::type::Array::kErrExpectedConstantCount;
return Expression{}; // error
}
auto modulo = num_values * count.value();
diff --git a/src/tint/lang/wgsl/helpers/check_supported_extensions.cc b/src/tint/lang/wgsl/helpers/check_supported_extensions.cc
index bb35e15..72f65c6 100644
--- a/src/tint/lang/wgsl/helpers/check_supported_extensions.cc
+++ b/src/tint/lang/wgsl/helpers/check_supported_extensions.cc
@@ -48,10 +48,9 @@
for (auto* enable : module.Enables()) {
for (auto* ext : enable->extensions) {
if (!set.Contains(ext->name)) {
- diags.AddError(diag::System::Writer,
- std::string(writer_name) + " backend does not support extension '" +
- tint::ToString(ext->name) + "'",
- ext->source);
+ diags.AddError(diag::System::Writer, ext->source)
+ << writer_name << " backend does not support extension " << style::Code
+ << ext->name;
return false;
}
}
diff --git a/src/tint/lang/wgsl/inspector/inspector.cc b/src/tint/lang/wgsl/inspector/inspector.cc
index 8efa350..f6f7980 100644
--- a/src/tint/lang/wgsl/inspector/inspector.cc
+++ b/src/tint/lang/wgsl/inspector/inspector.cc
@@ -571,12 +571,13 @@
const ast::Function* Inspector::FindEntryPointByName(const std::string& name) {
auto* func = program_.AST().Functions().Find(program_.Symbols().Get(name));
if (!func) {
- diagnostics_.AddError(diag::System::Inspector, name + " was not found!");
+ diagnostics_.AddError(diag::System::Inspector, Source{}) << name << " was not found!";
return nullptr;
}
if (!func->IsEntryPoint()) {
- diagnostics_.AddError(diag::System::Inspector, name + " is not an entry point!");
+ diagnostics_.AddError(diag::System::Inspector, Source{})
+ << name << " is not an entry point!";
return nullptr;
}
diff --git a/src/tint/lang/wgsl/intrinsic/data.cc b/src/tint/lang/wgsl/intrinsic/data.cc
index 7c54003..96b5ad0 100644
--- a/src/tint/lang/wgsl/intrinsic/data.cc
+++ b/src/tint/lang/wgsl/intrinsic/data.cc
@@ -105,8 +105,8 @@
}
return BuildBool(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "bool";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "bool";
}
};
@@ -119,10 +119,8 @@
}
return BuildIa(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- ss << "abstract-int";
- return ss.str();
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "abstract-int";
}
};
@@ -135,10 +133,8 @@
}
return BuildFa(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- ss << "abstract-float";
- return ss.str();
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "abstract-float";
}
};
@@ -151,8 +147,8 @@
}
return BuildI32(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "i32";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "i32";
}
};
@@ -165,8 +161,8 @@
}
return BuildU32(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "u32";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "u32";
}
};
@@ -179,8 +175,8 @@
}
return BuildF32(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "f32";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "f32";
}
};
@@ -193,8 +189,8 @@
}
return BuildF16(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "f16";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "f16";
}
};
@@ -212,9 +208,9 @@
}
return BuildVec2(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "vec2<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "vec2" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -232,9 +228,9 @@
}
return BuildVec3(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "vec3<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "vec3" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -252,9 +248,9 @@
}
return BuildVec4(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "vec4<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "vec4" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -272,9 +268,9 @@
}
return BuildMat2X2(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat2x2<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat2x2" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -292,9 +288,9 @@
}
return BuildMat2X3(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat2x3<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat2x3" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -312,9 +308,9 @@
}
return BuildMat2X4(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat2x4<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat2x4" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -332,9 +328,9 @@
}
return BuildMat3X2(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat3x2<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat3x2" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -352,9 +348,9 @@
}
return BuildMat3X3(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat3x3<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat3x3" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -372,9 +368,9 @@
}
return BuildMat3X4(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat3x4<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat3x4" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -392,9 +388,9 @@
}
return BuildMat4X2(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat4x2<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat4x2" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -412,9 +408,9 @@
}
return BuildMat4X3(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat4x3<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat4x3" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -432,9 +428,9 @@
}
return BuildMat4X4(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "mat4x4<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat4x4" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -457,12 +453,10 @@
}
return BuildVec(state, ty, N, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string N = state->NumName();
- const std::string T = state->TypeName();
- StringStream ss;
- ss << "vec" << N << "<" << T << ">";
- return ss.str();
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N;
+ state->PrintNum(N);StyledText T;
+ state->PrintType(T);
+ out << style::Type << "vec" << style::Type << N << style::Type << "<" << style::Type << T << style::Type << ">";
}
};
@@ -490,13 +484,11 @@
}
return BuildMat(state, ty, N, M, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string N = state->NumName();
- const std::string M = state->NumName();
- const std::string T = state->TypeName();
- StringStream ss;
- ss << "mat" << N << "x" << M << "<" << T << ">";
- return ss.str();
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N;
+ state->PrintNum(N);StyledText M;
+ state->PrintNum(M);StyledText T;
+ state->PrintType(T);
+ out << style::Type << "mat" << style::Type << N << style::Type << "x" << style::Type << M << style::Type << "<" << style::Type << T << style::Type << ">";
}
};
@@ -524,11 +516,11 @@
}
return BuildPtr(state, ty, S, T, A);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string S = state->NumName();
- const std::string T = state->TypeName();
- const std::string A = state->NumName();
- return "ptr<" + S + ", " + T + ", " + A + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText S;
+ state->PrintNum(S);StyledText T;
+ state->PrintType(T);StyledText A;
+ state->PrintNum(A);
+ out << style::Type << "ptr" << style::Code << "<" << style::Type << S << style::Code << ", " << style::Type << T << style::Code << ", " << style::Type << A << style::Code << ">";
}
};
@@ -546,9 +538,9 @@
}
return BuildAtomic(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "atomic<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "atomic" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -566,9 +558,9 @@
}
return BuildArray(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "array<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "array" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -581,8 +573,8 @@
}
return BuildSampler(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "sampler";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "sampler";
}
};
@@ -595,8 +587,8 @@
}
return BuildSamplerComparison(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "sampler_comparison";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "sampler_comparison";
}
};
@@ -614,9 +606,9 @@
}
return BuildTexture1D(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_1d<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_1d" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -634,9 +626,9 @@
}
return BuildTexture2D(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_2d<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_2d" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -654,9 +646,9 @@
}
return BuildTexture2DArray(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_2d_array<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_2d_array" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -674,9 +666,9 @@
}
return BuildTexture3D(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_3d<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_3d" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -694,9 +686,9 @@
}
return BuildTextureCube(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_cube<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_cube" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -714,9 +706,9 @@
}
return BuildTextureCubeArray(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_cube_array<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_cube_array" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -734,9 +726,9 @@
}
return BuildTextureMultisampled2D(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "texture_multisampled_2d<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "texture_multisampled_2d" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -749,8 +741,8 @@
}
return BuildTextureDepth2D(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "texture_depth_2d";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "texture_depth_2d";
}
};
@@ -763,8 +755,8 @@
}
return BuildTextureDepth2DArray(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "texture_depth_2d_array";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "texture_depth_2d_array";
}
};
@@ -777,8 +769,8 @@
}
return BuildTextureDepthCube(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "texture_depth_cube";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "texture_depth_cube";
}
};
@@ -791,8 +783,8 @@
}
return BuildTextureDepthCubeArray(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "texture_depth_cube_array";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "texture_depth_cube_array";
}
};
@@ -805,8 +797,8 @@
}
return BuildTextureDepthMultisampled2D(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "texture_depth_multisampled_2d";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "texture_depth_multisampled_2d";
}
};
@@ -829,10 +821,10 @@
}
return BuildTextureStorage1D(state, ty, F, A);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string F = state->NumName();
- const std::string A = state->NumName();
- return "texture_storage_1d<" + F + ", " + A + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F;
+ state->PrintNum(F);StyledText A;
+ state->PrintNum(A);
+ out << style::Type << "texture_storage_1d" << style::Code << "<" << style::Type << F << style::Code << ", " << style::Type << A << style::Code << ">";
}
};
@@ -855,10 +847,10 @@
}
return BuildTextureStorage2D(state, ty, F, A);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string F = state->NumName();
- const std::string A = state->NumName();
- return "texture_storage_2d<" + F + ", " + A + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F;
+ state->PrintNum(F);StyledText A;
+ state->PrintNum(A);
+ out << style::Type << "texture_storage_2d" << style::Code << "<" << style::Type << F << style::Code << ", " << style::Type << A << style::Code << ">";
}
};
@@ -881,10 +873,10 @@
}
return BuildTextureStorage2DArray(state, ty, F, A);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string F = state->NumName();
- const std::string A = state->NumName();
- return "texture_storage_2d_array<" + F + ", " + A + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F;
+ state->PrintNum(F);StyledText A;
+ state->PrintNum(A);
+ out << style::Type << "texture_storage_2d_array" << style::Code << "<" << style::Type << F << style::Code << ", " << style::Type << A << style::Code << ">";
}
};
@@ -907,10 +899,10 @@
}
return BuildTextureStorage3D(state, ty, F, A);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string F = state->NumName();
- const std::string A = state->NumName();
- return "texture_storage_3d<" + F + ", " + A + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F;
+ state->PrintNum(F);StyledText A;
+ state->PrintNum(A);
+ out << style::Type << "texture_storage_3d" << style::Code << "<" << style::Type << F << style::Code << ", " << style::Type << A << style::Code << ">";
}
};
@@ -923,8 +915,8 @@
}
return BuildTextureExternal(state, ty);
},
-/* string */ [](MatchState*) -> std::string {
- return "texture_external";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
+ out << style::Type << "texture_external";
}
};
@@ -942,9 +934,9 @@
}
return BuildPackedVec3(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "packedVec3<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "packedVec3" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -962,11 +954,9 @@
}
return BuildModfResult(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- StringStream ss;
- ss << "__modf_result_" << T;
- return ss.str();
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "__modf_result_" << style::Type << T;
}
};
@@ -989,12 +979,10 @@
}
return BuildModfResultVec(state, ty, N, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string N = state->NumName();
- const std::string T = state->TypeName();
- StringStream ss;
- ss << "__modf_result_vec" << N << "_" << T;
- return ss.str();
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N;
+ state->PrintNum(N);StyledText T;
+ state->PrintType(T);
+ out << style::Type << "__modf_result_vec" << style::Type << N << style::Type << "_" << style::Type << T;
}
};
@@ -1012,11 +1000,9 @@
}
return BuildFrexpResult(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- StringStream ss;
- ss << "__frexp_result_" << T;
- return ss.str();
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "__frexp_result_" << style::Type << T;
}
};
@@ -1039,12 +1025,10 @@
}
return BuildFrexpResultVec(state, ty, N, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string N = state->NumName();
- const std::string T = state->TypeName();
- StringStream ss;
- ss << "__frexp_result_vec" << N << "_" << T;
- return ss.str();
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N;
+ state->PrintNum(N);StyledText T;
+ state->PrintType(T);
+ out << style::Type << "__frexp_result_vec" << style::Type << N << style::Type << "_" << style::Type << T;
}
};
@@ -1062,9 +1046,9 @@
}
return BuildAtomicCompareExchangeResult(state, ty, T);
},
-/* string */ [](MatchState* state) -> std::string {
- const std::string T = state->TypeName();
- return "__atomic_compare_exchange_result<" + T + ">";
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T;
+ state->PrintType(T);
+ out << style::Type << "__atomic_compare_exchange_result" << style::Code << "<" << style::Type << T << style::Code << ">";
}
};
@@ -1095,13 +1079,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kIaMatcher.string(nullptr) << ", " << kFaMatcher.string(nullptr) << ", " << kF32Matcher.string(nullptr) << ", " << kF16Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << ", " << kU32Matcher.string(nullptr) << " or " << kBoolMatcher.string(nullptr);
- return ss.str();
- }
+ kIaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kFaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kF16Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kU32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kBoolMatcher.print(nullptr, out);}
};
/// TypeMatcher for 'match concrete_scalar'
@@ -1124,13 +1105,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kF32Matcher.string(nullptr) << ", " << kF16Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << ", " << kU32Matcher.string(nullptr) << " or " << kBoolMatcher.string(nullptr);
- return ss.str();
- }
+ kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kF16Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kU32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kBoolMatcher.print(nullptr, out);}
};
/// TypeMatcher for 'match scalar_no_f32'
@@ -1156,13 +1134,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kIaMatcher.string(nullptr) << ", " << kFaMatcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << ", " << kF16Matcher.string(nullptr) << ", " << kU32Matcher.string(nullptr) << " or " << kBoolMatcher.string(nullptr);
- return ss.str();
- }
+ kIaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kFaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kF16Matcher.print(nullptr, out); out << TextStyle{} << ", "; kU32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kBoolMatcher.print(nullptr, out);}
};
/// TypeMatcher for 'match scalar_no_f16'
@@ -1188,13 +1163,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kIaMatcher.string(nullptr) << ", " << kFaMatcher.string(nullptr) << ", " << kF32Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << ", " << kU32Matcher.string(nullptr) << " or " << kBoolMatcher.string(nullptr);
- return ss.str();
- }
+ kIaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kFaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kU32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kBoolMatcher.print(nullptr, out);}
};
/// TypeMatcher for 'match scalar_no_i32'
@@ -1220,13 +1192,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kIaMatcher.string(nullptr) << ", " << kFaMatcher.string(nullptr) << ", " << kF32Matcher.string(nullptr) << ", " << kF16Matcher.string(nullptr) << ", " << kU32Matcher.string(nullptr) << " or " << kBoolMatcher.string(nullptr);
- return ss.str();
- }
+ kIaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kFaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kF16Matcher.print(nullptr, out); out << TextStyle{} << ", "; kU32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kBoolMatcher.print(nullptr, out);}
};
/// TypeMatcher for 'match scalar_no_u32'
@@ -1252,13 +1221,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kIaMatcher.string(nullptr) << ", " << kFaMatcher.string(nullptr) << ", " << kF32Matcher.string(nullptr) << ", " << kF16Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << " or " << kBoolMatcher.string(nullptr);
- return ss.str();
- }
+ kIaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kFaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kF16Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kBoolMatcher.print(nullptr, out);}
};
/// TypeMatcher for 'match scalar_no_bool'
@@ -1284,13 +1250,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kIaMatcher.string(nullptr) << ", " << kFaMatcher.string(nullptr) << ", " << kF32Matcher.string(nullptr) << ", " << kF16Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << " or " << kU32Matcher.string(nullptr);
- return ss.str();
- }
+ kIaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kFaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kF16Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kU32Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match fia_fiu32_f16'
@@ -1316,13 +1279,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kFaMatcher.string(nullptr) << ", " << kIaMatcher.string(nullptr) << ", " << kF32Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << ", " << kU32Matcher.string(nullptr) << " or " << kF16Matcher.string(nullptr);
- return ss.str();
- }
+ kFaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kIaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kU32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kF16Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match fia_fi32_f16'
@@ -1345,13 +1305,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kFaMatcher.string(nullptr) << ", " << kIaMatcher.string(nullptr) << ", " << kF32Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << " or " << kF16Matcher.string(nullptr);
- return ss.str();
- }
+ kFaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kIaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kF16Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match fia_fiu32'
@@ -1374,13 +1331,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kFaMatcher.string(nullptr) << ", " << kIaMatcher.string(nullptr) << ", " << kF32Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << " or " << kU32Matcher.string(nullptr);
- return ss.str();
- }
+ kFaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kIaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kU32Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match fa_f32'
@@ -1394,13 +1348,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kFaMatcher.string(nullptr) << " or " << kF32Matcher.string(nullptr);
- return ss.str();
- }
+ kFaMatcher.print(nullptr, out); out << TextStyle{} << " or "; kF32Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match fa_f32_f16'
@@ -1417,13 +1368,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kFaMatcher.string(nullptr) << ", " << kF32Matcher.string(nullptr) << " or " << kF16Matcher.string(nullptr);
- return ss.str();
- }
+ kFaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kF32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kF16Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match ia_iu32'
@@ -1440,13 +1388,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kIaMatcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << " or " << kU32Matcher.string(nullptr);
- return ss.str();
- }
+ kIaMatcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kU32Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match ia_i32'
@@ -1460,13 +1405,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kIaMatcher.string(nullptr) << " or " << kI32Matcher.string(nullptr);
- return ss.str();
- }
+ kIaMatcher.print(nullptr, out); out << TextStyle{} << " or "; kI32Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match fiu32_f16'
@@ -1486,13 +1428,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kF32Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << ", " << kU32Matcher.string(nullptr) << " or " << kF16Matcher.string(nullptr);
- return ss.str();
- }
+ kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kU32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kF16Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match fiu32'
@@ -1509,13 +1448,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kF32Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << " or " << kU32Matcher.string(nullptr);
- return ss.str();
- }
+ kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kU32Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match fi32_f16'
@@ -1532,13 +1468,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kF32Matcher.string(nullptr) << ", " << kI32Matcher.string(nullptr) << " or " << kF16Matcher.string(nullptr);
- return ss.str();
- }
+ kF32Matcher.print(nullptr, out); out << TextStyle{} << ", "; kI32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kF16Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match fi32'
@@ -1552,13 +1485,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kF32Matcher.string(nullptr) << " or " << kI32Matcher.string(nullptr);
- return ss.str();
- }
+ kF32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kI32Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match f32_f16'
@@ -1572,13 +1502,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kF32Matcher.string(nullptr) << " or " << kF16Matcher.string(nullptr);
- return ss.str();
- }
+ kF32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kF16Matcher.print(nullptr, out);}
};
/// TypeMatcher for 'match iu32'
@@ -1592,13 +1519,10 @@
}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss << kI32Matcher.string(nullptr) << " or " << kU32Matcher.string(nullptr);
- return ss.str();
- }
+ kI32Matcher.print(nullptr, out); out << TextStyle{} << " or "; kU32Matcher.print(nullptr, out);}
};
/// EnumMatcher for 'match f32_texel_format'
@@ -1617,8 +1541,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "bgra8unorm, rgba8unorm, rgba8snorm, rgba16float, r32float, rg32float or rgba32float";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "bgra8unorm"<< TextStyle{} << ", " << style::Enum << "rgba8unorm"<< TextStyle{} << ", " << style::Enum << "rgba8snorm"<< TextStyle{} << ", " << style::Enum << "rgba16float"<< TextStyle{} << ", " << style::Enum << "r32float"<< TextStyle{} << ", " << style::Enum << "rg32float"<< TextStyle{} << " or " << style::Enum << "rgba32float";
}
};
@@ -1636,8 +1560,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "rgba8sint, rgba16sint, r32sint, rg32sint or rgba32sint";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "rgba8sint"<< TextStyle{} << ", " << style::Enum << "rgba16sint"<< TextStyle{} << ", " << style::Enum << "r32sint"<< TextStyle{} << ", " << style::Enum << "rg32sint"<< TextStyle{} << " or " << style::Enum << "rgba32sint";
}
};
@@ -1655,8 +1579,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "rgba8uint, rgba16uint, r32uint, rg32uint or rgba32uint";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "rgba8uint"<< TextStyle{} << ", " << style::Enum << "rgba16uint"<< TextStyle{} << ", " << style::Enum << "r32uint"<< TextStyle{} << ", " << style::Enum << "rg32uint"<< TextStyle{} << " or " << style::Enum << "rgba32uint";
}
};
@@ -1668,8 +1592,8 @@
}
return Number::invalid;
},
-/* string */ [](MatchState*) -> std::string {
- return "write";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "write";
}
};
@@ -1681,8 +1605,8 @@
}
return Number::invalid;
},
-/* string */ [](MatchState*) -> std::string {
- return "read_write";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "read_write";
}
};
@@ -1697,8 +1621,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "read or read_write";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "read"<< TextStyle{} << " or " << style::Enum << "read_write";
}
};
@@ -1713,8 +1637,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "write or read_write";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "write"<< TextStyle{} << " or " << style::Enum << "read_write";
}
};
@@ -1730,8 +1654,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "function, private or workgroup";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "function"<< TextStyle{} << ", " << style::Enum << "private"<< TextStyle{} << " or " << style::Enum << "workgroup";
}
};
@@ -1746,8 +1670,8 @@
return Number::invalid;
}
},
-/* string */ [](MatchState*) -> std::string {
- return "workgroup or storage";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "workgroup"<< TextStyle{} << " or " << style::Enum << "storage";
}
};
@@ -1759,8 +1683,8 @@
}
return Number::invalid;
},
-/* string */ [](MatchState*) -> std::string {
- return "storage";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "storage";
}
};
@@ -1772,8 +1696,8 @@
}
return Number::invalid;
},
-/* string */ [](MatchState*) -> std::string {
- return "workgroup";
+/* print */ [](MatchState*, StyledText& out) {
+ out<< style::Enum << "workgroup";
}
};
diff --git a/src/tint/lang/wgsl/intrinsic/table_test.cc b/src/tint/lang/wgsl/intrinsic/table_test.cc
index 2c98839..cbbeeda 100644
--- a/src/tint/lang/wgsl/intrinsic/table_test.cc
+++ b/src/tint/lang/wgsl/intrinsic/table_test.cc
@@ -79,7 +79,7 @@
auto result =
table.Lookup(wgsl::BuiltinFn::kCos, Empty, Vector{i32}, core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(WgslIntrinsicTableTest, MatchU32) {
@@ -99,7 +99,7 @@
auto result = table.Lookup(wgsl::BuiltinFn::kUnpack2X16Float, Empty, Vector{f32},
core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(WgslIntrinsicTableTest, MatchI32) {
@@ -126,7 +126,7 @@
auto result = table.Lookup(wgsl::BuiltinFn::kTextureLoad, Empty, Vector{tex, f32},
core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(WgslIntrinsicTableTest, MatchIU32AsI32) {
@@ -154,7 +154,7 @@
auto result = table.Lookup(wgsl::BuiltinFn::kCountOneBits, Empty, Vector{f32},
core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(WgslIntrinsicTableTest, MatchFIU32AsI32) {
@@ -198,7 +198,7 @@
auto result = table.Lookup(wgsl::BuiltinFn::kClamp, Empty, Vector{bool_, bool_, bool_},
core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(WgslIntrinsicTableTest, MatchBool) {
@@ -219,7 +219,7 @@
auto result = table.Lookup(wgsl::BuiltinFn::kSelect, Empty, Vector{f32, f32, f32},
core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(WgslIntrinsicTableTest, MatchPointer) {
@@ -241,7 +241,7 @@
auto result = table.Lookup(wgsl::BuiltinFn::kAtomicLoad, Empty, Vector{atomic_i32},
core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(WgslIntrinsicTableTest, MatchArray) {
@@ -264,7 +264,7 @@
auto result = table.Lookup(wgsl::BuiltinFn::kArrayLength, Empty, Vector{f32},
core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(WgslIntrinsicTableTest, MatchSampler) {
@@ -293,7 +293,7 @@
auto result = table.Lookup(wgsl::BuiltinFn::kTextureSample, Empty, Vector{tex, f32, vec2f},
core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(WgslIntrinsicTableTest, MatchSampledTexture) {
@@ -417,7 +417,7 @@
auto result = table.Lookup(wgsl::BuiltinFn::kTextureLoad, Empty, Vector{f32, vec2i},
core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(WgslIntrinsicTableTest, MatchTemplateType) {
@@ -437,7 +437,7 @@
auto result = table.Lookup(wgsl::BuiltinFn::kClamp, Empty, Vector{f32, u32, f32},
core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(WgslIntrinsicTableTest, MatchOpenSizeVector) {
@@ -460,7 +460,7 @@
auto result = table.Lookup(wgsl::BuiltinFn::kClamp, Empty, Vector{vec2f, u32, vec2f},
core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(WgslIntrinsicTableTest, MatchOpenSizeMatrix) {
@@ -482,7 +482,7 @@
auto result = table.Lookup(wgsl::BuiltinFn::kDeterminant, Empty, Vector{mat3x2f},
core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(WgslIntrinsicTableTest, MatchDifferentArgsElementType_Builtin_ConstantEval) {
@@ -544,37 +544,37 @@
auto result = table.Lookup(wgsl::BuiltinFn::kTextureDimensions, Empty, Vector{bool_, bool_},
core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_EQ(result.Failure(),
- R"(no matching call to textureDimensions(bool, bool)
+ ASSERT_EQ(result.Failure().Plain(),
+ R"(no matching call to 'textureDimensions(bool, bool)'
27 candidate functions:
- textureDimensions(texture: texture_1d<T>, level: L) -> u32 where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_2d<T>, level: L) -> vec2<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_2d_array<T>, level: L) -> vec2<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_3d<T>, level: L) -> vec3<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_cube<T>, level: L) -> vec2<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_cube_array<T>, level: L) -> vec2<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_depth_2d, level: L) -> vec2<u32> where: L is i32 or u32
- textureDimensions(texture: texture_depth_2d_array, level: L) -> vec2<u32> where: L is i32 or u32
- textureDimensions(texture: texture_depth_cube, level: L) -> vec2<u32> where: L is i32 or u32
- textureDimensions(texture: texture_depth_cube_array, level: L) -> vec2<u32> where: L is i32 or u32
- textureDimensions(texture: texture_1d<T>) -> u32 where: T is f32, i32 or u32
- textureDimensions(texture: texture_2d<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_2d_array<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_3d<T>) -> vec3<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_cube<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_cube_array<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_multisampled_2d<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_depth_2d) -> vec2<u32>
- textureDimensions(texture: texture_depth_2d_array) -> vec2<u32>
- textureDimensions(texture: texture_depth_cube) -> vec2<u32>
- textureDimensions(texture: texture_depth_cube_array) -> vec2<u32>
- textureDimensions(texture: texture_depth_multisampled_2d) -> vec2<u32>
- textureDimensions(texture: texture_storage_1d<F, A>) -> u32
- textureDimensions(texture: texture_storage_2d<F, A>) -> vec2<u32>
- textureDimensions(texture: texture_storage_2d_array<F, A>) -> vec2<u32>
- textureDimensions(texture: texture_storage_3d<F, A>) -> vec3<u32>
- textureDimensions(texture: texture_external) -> vec2<u32>
+ 'textureDimensions(texture: texture_1d<T>, level: L) -> u32' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_2d<T>, level: L) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_2d_array<T>, level: L) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_3d<T>, level: L) -> vec3<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_cube<T>, level: L) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_cube_array<T>, level: L) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_2d, level: L) -> vec2<u32>' where: 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_2d_array, level: L) -> vec2<u32>' where: 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_cube, level: L) -> vec2<u32>' where: 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_cube_array, level: L) -> vec2<u32>' where: 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_1d<T>) -> u32' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_2d<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_2d_array<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_3d<T>) -> vec3<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_cube<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_cube_array<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_multisampled_2d<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_2d) -> vec2<u32>'
+ 'textureDimensions(texture: texture_depth_2d_array) -> vec2<u32>'
+ 'textureDimensions(texture: texture_depth_cube) -> vec2<u32>'
+ 'textureDimensions(texture: texture_depth_cube_array) -> vec2<u32>'
+ 'textureDimensions(texture: texture_depth_multisampled_2d) -> vec2<u32>'
+ 'textureDimensions(texture: texture_storage_1d<F, A>) -> u32'
+ 'textureDimensions(texture: texture_storage_2d<F, A>) -> vec2<u32>'
+ 'textureDimensions(texture: texture_storage_2d_array<F, A>) -> vec2<u32>'
+ 'textureDimensions(texture: texture_storage_3d<F, A>) -> vec3<u32>'
+ 'textureDimensions(texture: texture_external) -> vec2<u32>'
)");
}
@@ -584,37 +584,37 @@
auto result = table.Lookup(wgsl::BuiltinFn::kTextureDimensions, Empty, Vector{tex, bool_},
core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_EQ(result.Failure(),
- R"(no matching call to textureDimensions(texture_depth_2d, bool)
+ ASSERT_EQ(result.Failure().Plain(),
+ R"(no matching call to 'textureDimensions(texture_depth_2d, bool)'
27 candidate functions:
- textureDimensions(texture: texture_depth_2d, level: L) -> vec2<u32> where: L is i32 or u32
- textureDimensions(texture: texture_1d<T>, level: L) -> u32 where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_2d<T>, level: L) -> vec2<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_2d_array<T>, level: L) -> vec2<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_3d<T>, level: L) -> vec3<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_cube<T>, level: L) -> vec2<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_cube_array<T>, level: L) -> vec2<u32> where: T is f32, i32 or u32, L is i32 or u32
- textureDimensions(texture: texture_depth_2d_array, level: L) -> vec2<u32> where: L is i32 or u32
- textureDimensions(texture: texture_depth_cube, level: L) -> vec2<u32> where: L is i32 or u32
- textureDimensions(texture: texture_depth_cube_array, level: L) -> vec2<u32> where: L is i32 or u32
- textureDimensions(texture: texture_depth_2d) -> vec2<u32>
- textureDimensions(texture: texture_1d<T>) -> u32 where: T is f32, i32 or u32
- textureDimensions(texture: texture_2d<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_2d_array<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_3d<T>) -> vec3<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_cube<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_cube_array<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_multisampled_2d<T>) -> vec2<u32> where: T is f32, i32 or u32
- textureDimensions(texture: texture_depth_2d_array) -> vec2<u32>
- textureDimensions(texture: texture_depth_cube) -> vec2<u32>
- textureDimensions(texture: texture_depth_cube_array) -> vec2<u32>
- textureDimensions(texture: texture_depth_multisampled_2d) -> vec2<u32>
- textureDimensions(texture: texture_storage_1d<F, A>) -> u32
- textureDimensions(texture: texture_storage_2d<F, A>) -> vec2<u32>
- textureDimensions(texture: texture_storage_2d_array<F, A>) -> vec2<u32>
- textureDimensions(texture: texture_storage_3d<F, A>) -> vec3<u32>
- textureDimensions(texture: texture_external) -> vec2<u32>
+ 'textureDimensions(texture: texture_depth_2d, level: L) -> vec2<u32>' where: 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_1d<T>, level: L) -> u32' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_2d<T>, level: L) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_2d_array<T>, level: L) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_3d<T>, level: L) -> vec3<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_cube<T>, level: L) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_cube_array<T>, level: L) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32', 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_2d_array, level: L) -> vec2<u32>' where: 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_cube, level: L) -> vec2<u32>' where: 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_cube_array, level: L) -> vec2<u32>' where: 'L' is 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_2d) -> vec2<u32>'
+ 'textureDimensions(texture: texture_1d<T>) -> u32' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_2d<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_2d_array<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_3d<T>) -> vec3<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_cube<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_cube_array<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_multisampled_2d<T>) -> vec2<u32>' where: 'T' is 'f32', 'i32' or 'u32'
+ 'textureDimensions(texture: texture_depth_2d_array) -> vec2<u32>'
+ 'textureDimensions(texture: texture_depth_cube) -> vec2<u32>'
+ 'textureDimensions(texture: texture_depth_cube_array) -> vec2<u32>'
+ 'textureDimensions(texture: texture_depth_multisampled_2d) -> vec2<u32>'
+ 'textureDimensions(texture: texture_storage_1d<F, A>) -> u32'
+ 'textureDimensions(texture: texture_storage_2d<F, A>) -> vec2<u32>'
+ 'textureDimensions(texture: texture_storage_2d_array<F, A>) -> vec2<u32>'
+ 'textureDimensions(texture: texture_storage_3d<F, A>) -> vec3<u32>'
+ 'textureDimensions(texture: texture_external) -> vec2<u32>'
)");
}
@@ -630,11 +630,11 @@
auto* bool_ = create<core::type::Bool>();
auto result = table.Lookup(core::UnaryOp::kNegation, bool_, core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- EXPECT_EQ(result.Failure(), R"(no matching overload for operator - (bool)
+ EXPECT_EQ(result.Failure().Plain(), R"(no matching overload for 'operator - (bool)'
2 candidate operators:
- operator - (T) -> T where: T is abstract-float, abstract-int, f32, i32 or f16
- operator - (vecN<T>) -> vecN<T> where: T is abstract-float, abstract-int, f32, i32 or f16
+ 'operator - (T) -> T' where: 'T' is 'abstract-float', 'abstract-int', 'f32', 'i32' or 'f16'
+ 'operator - (vecN<T>) -> vecN<T>' where: 'T' is 'abstract-float', 'abstract-int', 'f32', 'i32' or 'f16'
)");
}
@@ -672,18 +672,18 @@
table.Lookup(core::BinaryOp::kMultiply, f32, bool_, core::EvaluationStage::kConstant,
/* is_compound */ false);
ASSERT_NE(result, Success);
- EXPECT_EQ(result.Failure(), R"(no matching overload for operator * (f32, bool)
+ EXPECT_EQ(result.Failure().Plain(), R"(no matching overload for 'operator * (f32, bool)'
9 candidate operators:
- operator * (T, T) -> T where: T is abstract-float, abstract-int, f32, i32, u32 or f16
- operator * (vecN<T>, T) -> vecN<T> where: T is abstract-float, abstract-int, f32, i32, u32 or f16
- operator * (T, vecN<T>) -> vecN<T> where: T is abstract-float, abstract-int, f32, i32, u32 or f16
- operator * (T, matNxM<T>) -> matNxM<T> where: T is abstract-float, f32 or f16
- operator * (matNxM<T>, T) -> matNxM<T> where: T is abstract-float, f32 or f16
- operator * (vecN<T>, vecN<T>) -> vecN<T> where: T is abstract-float, abstract-int, f32, i32, u32 or f16
- operator * (matCxR<T>, vecC<T>) -> vecR<T> where: T is abstract-float, f32 or f16
- operator * (vecR<T>, matCxR<T>) -> vecC<T> where: T is abstract-float, f32 or f16
- operator * (matKxR<T>, matCxK<T>) -> matCxR<T> where: T is abstract-float, f32 or f16
+ 'operator * (T, T) -> T' where: 'T' is 'abstract-float', 'abstract-int', 'f32', 'i32', 'u32' or 'f16'
+ 'operator * (vecN<T>, T) -> vecN<T>' where: 'T' is 'abstract-float', 'abstract-int', 'f32', 'i32', 'u32' or 'f16'
+ 'operator * (T, vecN<T>) -> vecN<T>' where: 'T' is 'abstract-float', 'abstract-int', 'f32', 'i32', 'u32' or 'f16'
+ 'operator * (T, matNxM<T>) -> matNxM<T>' where: 'T' is 'abstract-float', 'f32' or 'f16'
+ 'operator * (matNxM<T>, T) -> matNxM<T>' where: 'T' is 'abstract-float', 'f32' or 'f16'
+ 'operator * (vecN<T>, vecN<T>) -> vecN<T>' where: 'T' is 'abstract-float', 'abstract-int', 'f32', 'i32', 'u32' or 'f16'
+ 'operator * (matCxR<T>, vecC<T>) -> vecR<T>' where: 'T' is 'abstract-float', 'f32' or 'f16'
+ 'operator * (vecR<T>, matCxR<T>) -> vecC<T>' where: 'T' is 'abstract-float', 'f32' or 'f16'
+ 'operator * (matKxR<T>, matCxK<T>) -> matCxR<T>' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -706,18 +706,18 @@
table.Lookup(core::BinaryOp::kMultiply, f32, bool_, core::EvaluationStage::kConstant,
/* is_compound */ true);
ASSERT_NE(result, Success);
- EXPECT_EQ(result.Failure(), R"(no matching overload for operator *= (f32, bool)
+ EXPECT_EQ(result.Failure().Plain(), R"(no matching overload for 'operator *= (f32, bool)'
9 candidate operators:
- operator *= (T, T) -> T where: T is abstract-float, abstract-int, f32, i32, u32 or f16
- operator *= (vecN<T>, T) -> vecN<T> where: T is abstract-float, abstract-int, f32, i32, u32 or f16
- operator *= (T, vecN<T>) -> vecN<T> where: T is abstract-float, abstract-int, f32, i32, u32 or f16
- operator *= (T, matNxM<T>) -> matNxM<T> where: T is abstract-float, f32 or f16
- operator *= (matNxM<T>, T) -> matNxM<T> where: T is abstract-float, f32 or f16
- operator *= (vecN<T>, vecN<T>) -> vecN<T> where: T is abstract-float, abstract-int, f32, i32, u32 or f16
- operator *= (matCxR<T>, vecC<T>) -> vecR<T> where: T is abstract-float, f32 or f16
- operator *= (vecR<T>, matCxR<T>) -> vecC<T> where: T is abstract-float, f32 or f16
- operator *= (matKxR<T>, matCxK<T>) -> matCxR<T> where: T is abstract-float, f32 or f16
+ 'operator *= (T, T) -> T' where: 'T' is 'abstract-float', 'abstract-int', 'f32', 'i32', 'u32' or 'f16'
+ 'operator *= (vecN<T>, T) -> vecN<T>' where: 'T' is 'abstract-float', 'abstract-int', 'f32', 'i32', 'u32' or 'f16'
+ 'operator *= (T, vecN<T>) -> vecN<T>' where: 'T' is 'abstract-float', 'abstract-int', 'f32', 'i32', 'u32' or 'f16'
+ 'operator *= (T, matNxM<T>) -> matNxM<T>' where: 'T' is 'abstract-float', 'f32' or 'f16'
+ 'operator *= (matNxM<T>, T) -> matNxM<T>' where: 'T' is 'abstract-float', 'f32' or 'f16'
+ 'operator *= (vecN<T>, vecN<T>) -> vecN<T>' where: 'T' is 'abstract-float', 'abstract-int', 'f32', 'i32', 'u32' or 'f16'
+ 'operator *= (matCxR<T>, vecC<T>) -> vecR<T>' where: 'T' is 'abstract-float', 'f32' or 'f16'
+ 'operator *= (vecR<T>, matCxR<T>) -> vecC<T>' where: 'T' is 'abstract-float', 'f32' or 'f16'
+ 'operator *= (matKxR<T>, matCxK<T>) -> matCxR<T>' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -757,29 +757,29 @@
auto result = table.Lookup(CtorConv::kVec3, Empty, Vector{i32, f32, i32},
core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- EXPECT_EQ(result.Failure(),
- R"(no matching constructor for vec3(i32, f32, i32)
+ EXPECT_EQ(result.Failure().Plain(),
+ R"(no matching constructor for 'vec3(i32, f32, i32)'
12 candidate constructors:
- vec3(x: T, y: T, z: T) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- vec3<T>(xy: vec2<T>, z: T) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3(xy: vec2<T>, z: T) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- vec3<T>(x: T, yz: vec2<T>) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3(x: T, yz: vec2<T>) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- vec3<T>(T) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3(T) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- vec3<T>(vec3<T>) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3(vec3<T>) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- vec3() -> vec3<abstract-int>
- vec3<T>() -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3<T>(x: T, y: T, z: T) -> vec3<T> where: T is f32, f16, i32, u32 or bool
+ 'vec3(x: T, y: T, z: T) -> vec3<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(xy: vec2<T>, z: T) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3(xy: vec2<T>, z: T) -> vec3<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(x: T, yz: vec2<T>) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3(x: T, yz: vec2<T>) -> vec3<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(T) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3(T) -> vec3<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(vec3<T>) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3(vec3<T>) -> vec3<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3() -> vec3<abstract-int>'
+ 'vec3<T>() -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(x: T, y: T, z: T) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
5 candidate conversions:
- vec3<T>(vec3<U>) -> vec3<T> where: T is f32, U is abstract-int, abstract-float, i32, f16, u32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is f16, U is abstract-int, abstract-float, f32, i32, u32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is i32, U is abstract-int, abstract-float, f32, f16, u32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is u32, U is abstract-int, abstract-float, f32, f16, i32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is bool, U is abstract-int, abstract-float, f32, f16, i32 or u32
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'f32', 'U' is 'abstract-int', 'abstract-float', 'i32', 'f16', 'u32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'f16', 'U' is 'abstract-int', 'abstract-float', 'f32', 'i32', 'u32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'i32', 'U' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'u32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'u32', 'U' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'bool', 'U' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32' or 'u32'
)");
}
@@ -789,29 +789,29 @@
auto result = table.Lookup(CtorConv::kVec3, Vector{i32}, Vector{i32, f32, i32},
core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- EXPECT_EQ(result.Failure(),
- R"(no matching constructor for vec3<i32>(i32, f32, i32)
+ EXPECT_EQ(result.Failure().Plain(),
+ R"(no matching constructor for 'vec3<i32>(i32, f32, i32)'
12 candidate constructors:
- vec3<T>(x: T, y: T, z: T) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3<T>(xy: vec2<T>, z: T) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3(xy: vec2<T>, z: T) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- vec3<T>(x: T, yz: vec2<T>) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3(x: T, yz: vec2<T>) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- vec3<T>(T) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3(T) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- vec3<T>(vec3<T>) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3(vec3<T>) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- vec3() -> vec3<abstract-int>
- vec3<T>() -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3(x: T, y: T, z: T) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
+ 'vec3<T>(x: T, y: T, z: T) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(xy: vec2<T>, z: T) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3(xy: vec2<T>, z: T) -> vec3<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(x: T, yz: vec2<T>) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3(x: T, yz: vec2<T>) -> vec3<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(T) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3(T) -> vec3<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(vec3<T>) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3(vec3<T>) -> vec3<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3() -> vec3<abstract-int>'
+ 'vec3<T>() -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3(x: T, y: T, z: T) -> vec3<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
5 candidate conversions:
- vec3<T>(vec3<U>) -> vec3<T> where: T is f32, U is abstract-int, abstract-float, i32, f16, u32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is f16, U is abstract-int, abstract-float, f32, i32, u32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is i32, U is abstract-int, abstract-float, f32, f16, u32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is u32, U is abstract-int, abstract-float, f32, f16, i32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is bool, U is abstract-int, abstract-float, f32, f16, i32 or u32
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'f32', 'U' is 'abstract-int', 'abstract-float', 'i32', 'f16', 'u32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'f16', 'U' is 'abstract-int', 'abstract-float', 'f32', 'i32', 'u32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'i32', 'U' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'u32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'u32', 'U' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'bool', 'U' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32' or 'u32'
)");
}
@@ -898,29 +898,29 @@
auto result =
table.Lookup(CtorConv::kVec3, Vector{f32}, Vector{arr}, core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- EXPECT_EQ(result.Failure(),
- R"(no matching constructor for vec3<f32>(array<u32>)
+ EXPECT_EQ(result.Failure().Plain(),
+ R"(no matching constructor for 'vec3<f32>(array<u32>)'
12 candidate constructors:
- vec3<T>(vec3<T>) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3<T>(T) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3() -> vec3<abstract-int>
- vec3<T>() -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3<T>(x: T, yz: vec2<T>) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3(x: T, yz: vec2<T>) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- vec3<T>(xy: vec2<T>, z: T) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3(xy: vec2<T>, z: T) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- vec3<T>(x: T, y: T, z: T) -> vec3<T> where: T is f32, f16, i32, u32 or bool
- vec3(x: T, y: T, z: T) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- vec3(T) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- vec3(vec3<T>) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
+ 'vec3<T>(vec3<T>) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(T) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3() -> vec3<abstract-int>'
+ 'vec3<T>() -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(x: T, yz: vec2<T>) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3(x: T, yz: vec2<T>) -> vec3<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(xy: vec2<T>, z: T) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3(xy: vec2<T>, z: T) -> vec3<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3<T>(x: T, y: T, z: T) -> vec3<T>' where: 'T' is 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3(x: T, y: T, z: T) -> vec3<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3(T) -> vec3<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'vec3(vec3<T>) -> vec3<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
5 candidate conversions:
- vec3<T>(vec3<U>) -> vec3<T> where: T is f32, U is abstract-int, abstract-float, i32, f16, u32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is f16, U is abstract-int, abstract-float, f32, i32, u32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is i32, U is abstract-int, abstract-float, f32, f16, u32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is u32, U is abstract-int, abstract-float, f32, f16, i32 or bool
- vec3<T>(vec3<U>) -> vec3<T> where: T is bool, U is abstract-int, abstract-float, f32, f16, i32 or u32
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'f32', 'U' is 'abstract-int', 'abstract-float', 'i32', 'f16', 'u32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'f16', 'U' is 'abstract-int', 'abstract-float', 'f32', 'i32', 'u32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'i32', 'U' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'u32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'u32', 'U' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32' or 'bool'
+ 'vec3<T>(vec3<U>) -> vec3<T>' where: 'T' is 'bool', 'U' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32' or 'u32'
)");
}
@@ -964,7 +964,7 @@
auto result = table.Lookup(wgsl::BuiltinFn::kAbs, Empty, std::move(arg_tys),
core::EvaluationStage::kConstant);
ASSERT_NE(result, Success);
- ASSERT_THAT(result.Failure(), HasSubstr("no matching call"));
+ ASSERT_THAT(result.Failure().Plain(), HasSubstr("no matching call"));
}
TEST_F(WgslIntrinsicTableTest, OverloadResolution) {
diff --git a/src/tint/lang/wgsl/program/program.cc b/src/tint/lang/wgsl/program/program.cc
index bcd8e93..c649781 100644
--- a/src/tint/lang/wgsl/program/program.cc
+++ b/src/tint/lang/wgsl/program/program.cc
@@ -81,7 +81,7 @@
// If the builder claims to be invalid, then we really should have an error
// message generated. If we find a situation where the program is not valid
// and there are no errors reported, add one here.
- diagnostics_.AddError(diag::System::Program, "invalid program generated");
+ diagnostics_.AddError(diag::System::Program, Source{}) << "invalid program generated";
}
}
diff --git a/src/tint/lang/wgsl/program/program_test.cc b/src/tint/lang/wgsl/program/program_test.cc
index 1a59adb..2572ca5 100644
--- a/src/tint/lang/wgsl/program/program_test.cc
+++ b/src/tint/lang/wgsl/program/program_test.cc
@@ -93,19 +93,19 @@
}
TEST_F(ProgramTest, DiagnosticsMove) {
- Diagnostics().AddError(diag::System::Program, "an error message");
+ Diagnostics().AddError(diag::System::Program, Source{}) << "an error message";
Program program_a(std::move(*this));
EXPECT_FALSE(program_a.IsValid());
EXPECT_EQ(program_a.Diagnostics().Count(), 1u);
EXPECT_EQ(program_a.Diagnostics().NumErrors(), 1u);
- EXPECT_EQ(program_a.Diagnostics().begin()->message, "an error message");
+ EXPECT_EQ(program_a.Diagnostics().begin()->message.Plain(), "an error message");
Program program_b(std::move(program_a));
EXPECT_FALSE(program_b.IsValid());
EXPECT_EQ(program_b.Diagnostics().Count(), 1u);
EXPECT_EQ(program_b.Diagnostics().NumErrors(), 1u);
- EXPECT_EQ(program_b.Diagnostics().begin()->message, "an error message");
+ EXPECT_EQ(program_b.Diagnostics().begin()->message.Plain(), "an error message");
}
TEST_F(ProgramTest, ReuseMovedFromVariable) {
diff --git a/src/tint/lang/wgsl/reader/parser/error_msg_test.cc b/src/tint/lang/wgsl/reader/parser/error_msg_test.cc
index dc46bc5..2e79a9b 100644
--- a/src/tint/lang/wgsl/reader/parser/error_msg_test.cc
+++ b/src/tint/lang/wgsl/reader/parser/error_msg_test.cc
@@ -38,16 +38,16 @@
class ParserImplErrorTest : public WGSLParserTest {};
-#define EXPECT(SOURCE, EXPECTED) \
- do { \
- std::string source = SOURCE; \
- std::string expected = EXPECTED; \
- auto p = parser(source); \
- p->set_max_errors(5); \
- EXPECT_EQ(false, p->Parse()); \
- auto diagnostics = p->builder().Diagnostics(); \
- EXPECT_EQ(true, diagnostics.ContainsErrors()); \
- EXPECT_EQ(expected, diag::Formatter(formatter_style).Format(diagnostics)); \
+#define EXPECT(SOURCE, EXPECTED) \
+ do { \
+ std::string source = SOURCE; \
+ std::string expected = EXPECTED; \
+ auto p = parser(source); \
+ p->set_max_errors(5); \
+ EXPECT_EQ(false, p->Parse()); \
+ auto diagnostics = p->builder().Diagnostics(); \
+ EXPECT_EQ(true, diagnostics.ContainsErrors()); \
+ EXPECT_EQ(expected, diag::Formatter(formatter_style).Format(diagnostics).Plain()); \
} while (false)
TEST_F(ParserImplErrorTest, AdditiveInvalidExpr) {
diff --git a/src/tint/lang/wgsl/reader/parser/error_resync_test.cc b/src/tint/lang/wgsl/reader/parser/error_resync_test.cc
index 31a6dbc..54818ea 100644
--- a/src/tint/lang/wgsl/reader/parser/error_resync_test.cc
+++ b/src/tint/lang/wgsl/reader/parser/error_resync_test.cc
@@ -36,15 +36,15 @@
class ParserImplErrorResyncTest : public WGSLParserTest {};
-#define EXPECT(SOURCE, EXPECTED) \
- do { \
- std::string source = SOURCE; \
- std::string expected = EXPECTED; \
- auto p = parser(source); \
- EXPECT_EQ(false, p->Parse()); \
- auto diagnostics = p->builder().Diagnostics(); \
- EXPECT_EQ(true, diagnostics.ContainsErrors()); \
- EXPECT_EQ(expected, diag::Formatter(formatter_style).Format(diagnostics)); \
+#define EXPECT(SOURCE, EXPECTED) \
+ do { \
+ std::string source = SOURCE; \
+ std::string expected = EXPECTED; \
+ auto p = parser(source); \
+ EXPECT_EQ(false, p->Parse()); \
+ auto diagnostics = p->builder().Diagnostics(); \
+ EXPECT_EQ(true, diagnostics.ContainsErrors()); \
+ EXPECT_EQ(expected, diag::Formatter(formatter_style).Format(diagnostics).Plain()); \
} while (false)
TEST_F(ParserImplErrorResyncTest, BadFunctionDecls) {
diff --git a/src/tint/lang/wgsl/reader/parser/parser.cc b/src/tint/lang/wgsl/reader/parser/parser.cc
index 0716617..315d701 100644
--- a/src/tint/lang/wgsl/reader/parser/parser.cc
+++ b/src/tint/lang/wgsl/reader/parser/parser.cc
@@ -242,22 +242,28 @@
Parser::Failure::Errored Parser::AddError(const Source& source, std::string_view err) {
if (silence_diags_ == 0) {
- builder_.Diagnostics().AddError(diag::System::Reader, err, source);
+ builder_.Diagnostics().AddError(diag::System::Reader, source) << err;
+ }
+ return Failure::kErrored;
+}
+
+Parser::Failure::Errored Parser::AddError(const Source& source, StyledText&& err) {
+ if (silence_diags_ == 0) {
+ builder_.Diagnostics().AddError(diag::System::Reader, source) << std::move(err);
}
return Failure::kErrored;
}
void Parser::AddNote(const Source& source, std::string_view err) {
if (silence_diags_ == 0) {
- builder_.Diagnostics().AddNote(diag::System::Reader, err, source);
+ builder_.Diagnostics().AddNote(diag::System::Reader, source) << err;
}
}
void Parser::deprecated(const Source& source, std::string_view msg) {
if (silence_diags_ == 0) {
- builder_.Diagnostics().AddWarning(diag::System::Reader,
- "use of deprecated language feature: " + std::string(msg),
- source);
+ builder_.Diagnostics().AddWarning(diag::System::Reader, source)
+ << "use of deprecated language feature: " << msg;
}
}
@@ -927,7 +933,7 @@
}
/// Create a sensible error message
- StringStream err;
+ StyledText err;
err << "expected " << name;
if (!use.empty()) {
@@ -951,7 +957,7 @@
}
synchronized_ = false;
- return AddError(t.source(), err.str());
+ return AddError(t.source(), std::move(err));
}
Expect<ast::Type> Parser::expect_type(std::string_view use) {
diff --git a/src/tint/lang/wgsl/reader/parser/parser.h b/src/tint/lang/wgsl/reader/parser/parser.h
index 9124e89..993c544 100644
--- a/src/tint/lang/wgsl/reader/parser/parser.h
+++ b/src/tint/lang/wgsl/reader/parser/parser.h
@@ -41,6 +41,7 @@
#include "src/tint/lang/wgsl/reader/parser/token.h"
#include "src/tint/lang/wgsl/resolver/resolve.h"
#include "src/tint/utils/diagnostic/formatter.h"
+#include "src/tint/utils/text/styled_text.h"
namespace tint::ast {
class BreakStatement;
@@ -328,7 +329,7 @@
/// @returns the parser error string
std::string error() const {
diag::Formatter formatter{{false, false, false, false}};
- return formatter.Format(builder_.Diagnostics());
+ return formatter.Format(builder_.Diagnostics()).Plain();
}
/// @returns the Program. The program builder in the parser will be reset
@@ -373,6 +374,12 @@
/// @return `Failure::Errored::kError` so that you can combine an AddError()
/// call and return on the same line.
Failure::Errored AddError(const Source& source, std::string_view msg);
+ /// Appends an error at `source` with the message `msg`
+ /// @param source the source to associate the error with
+ /// @param msg the error message
+ /// @return `Failure::Errored::kError` so that you can combine an AddError()
+ /// call and return on the same line.
+ Failure::Errored AddError(const Source& source, StyledText&& msg);
/// Appends a note at `source` with the message `msg`
/// @param source the source to associate the error with
/// @param msg the note message
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
index 751f21c..f54aba6 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
@@ -200,8 +200,8 @@
~ControlStackScope() { impl_->control_stack_.Pop(); }
};
- void AddError(const Source& s, const std::string& err) {
- diagnostics_.AddError(tint::diag::System::IR, err, s);
+ diag::Diagnostic& AddError(const Source& source) {
+ return diagnostics_.AddError(tint::diag::System::IR, source);
}
bool NeedTerminator() { return current_block_ && !current_block_->Terminator(); }
@@ -1003,8 +1003,8 @@
if (mat->ConstantValue()) {
auto* cv = mat->ConstantValue()->Clone(impl.clone_ctx_);
if (!cv) {
- impl.AddError(expr->source, "failed to get constant value for call " +
- std::string(expr->TypeInfo().name));
+ impl.AddError(expr->source) << "failed to get constant value for call "
+ << expr->TypeInfo().name;
return;
}
Bind(expr, impl.builder_.Constant(cv));
@@ -1017,15 +1017,15 @@
for (const auto* arg : expr->args) {
auto value = GetValue(arg);
if (!value) {
- impl.AddError(arg->source, "failed to convert arguments");
+ impl.AddError(arg->source) << "failed to convert arguments";
return;
}
args.Push(value);
}
auto* sem = impl.program_.Sem().Get<sem::Call>(expr);
if (!sem) {
- impl.AddError(expr->source, "failed to get semantic information for call " +
- std::string(expr->TypeInfo().name));
+ impl.AddError(expr->source)
+ << "failed to get semantic information for call " << expr->TypeInfo().name;
return;
}
auto* ty = sem->Target()->ReturnType()->Clone(impl.clone_ctx_.type_ctx);
@@ -1063,8 +1063,8 @@
void EmitIdentifier(const ast::IdentifierExpression* i) {
auto* v = impl.scopes_.Get(i->identifier->symbol);
if (TINT_UNLIKELY(!v)) {
- impl.AddError(i->source,
- "unable to find identifier " + i->identifier->symbol.Name());
+ impl.AddError(i->source)
+ << "unable to find identifier " << i->identifier->symbol.Name();
return;
}
Bind(i, v);
@@ -1073,14 +1073,14 @@
void EmitLiteral(const ast::LiteralExpression* lit) {
auto* sem = impl.program_.Sem().Get(lit);
if (!sem) {
- impl.AddError(lit->source, "failed to get semantic information for node " +
- std::string(lit->TypeInfo().name));
+ impl.AddError(lit->source)
+ << "failed to get semantic information for node " << lit->TypeInfo().name;
return;
}
auto* cv = sem->ConstantValue()->Clone(impl.clone_ctx_);
if (!cv) {
- impl.AddError(lit->source, "failed to get constant value for node " +
- std::string(lit->TypeInfo().name));
+ impl.AddError(lit->source)
+ << "failed to get constant value for node " << lit->TypeInfo().name;
return;
}
auto* val = impl.builder_.Constant(cv);
@@ -1270,9 +1270,8 @@
scopes_.Set(l->name->symbol, let->Result(0));
},
[&](const ast::Override*) {
- AddError(var->source,
- "found an `Override` variable. The SubstituteOverrides "
- "transform must be run before converting to IR");
+ AddError(var->source) << "found an `Override` variable. The SubstituteOverrides "
+ "transform must be run before converting to IR";
},
[&](const ast::Const*) {
// Skip. This should be handled by const-eval already, so the const will be a
@@ -1344,7 +1343,7 @@
auto r = b.Build();
if (r != Success) {
diag::List err = std::move(r.Failure().reason);
- err.AddNote(diag::System::IR, "AST:\n" + Program::printer(program), Source{});
+ err.AddNote(diag::System::IR, Source{}) << "AST:\n" + Program::printer(program);
return Failure{err};
}
diff --git a/src/tint/lang/wgsl/reader/reader.cc b/src/tint/lang/wgsl/reader/reader.cc
index 40c4f79..f2e20be 100644
--- a/src/tint/lang/wgsl/reader/reader.cc
+++ b/src/tint/lang/wgsl/reader/reader.cc
@@ -41,8 +41,8 @@
if (TINT_UNLIKELY(file->content.data.size() >
static_cast<size_t>(std::numeric_limits<uint32_t>::max()))) {
ProgramBuilder b;
- b.Diagnostics().AddError(tint::diag::System::Reader,
- "WGSL source must be 0xffffffff bytes or fewer");
+ b.Diagnostics().AddError(tint::diag::System::Reader, Source{})
+ << "WGSL source must be 0xffffffff bytes or fewer";
return Program(std::move(b));
}
Parser parser(file);
diff --git a/src/tint/lang/wgsl/resolver/address_space_validation_test.cc b/src/tint/lang/wgsl/resolver/address_space_validation_test.cc
index c415620..f8c2f27b 100644
--- a/src/tint/lang/wgsl/resolver/address_space_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/address_space_validation_test.cc
@@ -56,7 +56,7 @@
Alias("g", ty(Source{{12, 34}}, "ptr", ty.f32()));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: 'ptr' requires at least 2 template arguments");
+ EXPECT_EQ(r()->error(), R"(12:34 error: 'ptr' requires at least 2 template arguments)");
}
TEST_F(ResolverAddressSpaceValidationTest, GlobalVariable_FunctionAddressSpace_Fail) {
diff --git a/src/tint/lang/wgsl/resolver/assignment_validation_test.cc b/src/tint/lang/wgsl/resolver/assignment_validation_test.cc
index 826fbd0..1df19ab 100644
--- a/src/tint/lang/wgsl/resolver/assignment_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/assignment_validation_test.cc
@@ -54,8 +54,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- "56:78 error: cannot store into a read-only type 'ref<storage, "
- "i32, read>'");
+ R"(56:78 error: cannot store into a read-only type 'ref<storage, i32, read>')");
}
TEST_F(ResolverAssignmentValidationTest, AssignIncompatibleTypes) {
@@ -234,9 +233,9 @@
WrapInFunction(Assign(Expr(Source{{12, 34}}, "a"), 2_i));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:34 error: cannot assign to override 'a'
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot assign to 'override a'
12:34 note: 'override' variables are immutable
-56:78 note: override 'a' declared here)");
+56:78 note: 'override a' declared here)");
}
TEST_F(ResolverAssignmentValidationTest, AssignToLet_Fail) {
@@ -248,9 +247,9 @@
Assign(Expr(Source{{12, 34}}, "a"), 2_i));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:34 error: cannot assign to let 'a'
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot assign to 'let a'
12:34 note: 'let' variables are immutable
-56:78 note: let 'a' declared here)");
+56:78 note: 'let a' declared here)");
}
TEST_F(ResolverAssignmentValidationTest, AssignToConst_Fail) {
@@ -262,9 +261,9 @@
Assign(Expr(Source{{12, 34}}, "a"), 2_i));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:34 error: cannot assign to const 'a'
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot assign to 'const a'
12:34 note: 'const' variables are immutable
-56:78 note: const 'a' declared here)");
+56:78 note: 'const a' declared here)");
}
TEST_F(ResolverAssignmentValidationTest, AssignToParam_Fail) {
@@ -294,7 +293,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), R"(12:34 error: cannot assign to value of type 'i32'
56:78 note: 'let' variables are immutable
-98:76 note: let 'a' declared here)");
+98:76 note: 'let a' declared here)");
}
TEST_F(ResolverAssignmentValidationTest, AssignNonConstructible_Handle) {
diff --git a/src/tint/lang/wgsl/resolver/attribute_validation_test.cc b/src/tint/lang/wgsl/resolver/attribute_validation_test.cc
index 33cccae..78a967d 100644
--- a/src/tint/lang/wgsl/resolver/attribute_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/attribute_validation_test.cc
@@ -1522,8 +1522,8 @@
Vector{Member(Source{{12, 5}}, "a", ty.f32(),
Vector{MemberAlign(Expr(Source{{12, 35}}, "val"))})});
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:35 error: var 'val' cannot be referenced at module-scope
-1:2 note: var 'val' declared here)");
+ EXPECT_EQ(r()->error(), R"(12:35 error: 'var val' cannot be referenced at module-scope
+1:2 note: 'var val' declared here)");
}
TEST_F(StructMemberAttributeTest, Align_Attribute_Override) {
@@ -1595,8 +1595,8 @@
Vector{Member(Source{{12, 5}}, "a", ty.f32(),
Vector{MemberSize(Expr(Source{{12, 35}}, "val"))})});
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:35 error: var 'val' cannot be referenced at module-scope
-1:2 note: var 'val' declared here)");
+ EXPECT_EQ(r()->error(), R"(12:35 error: 'var val' cannot be referenced at module-scope
+1:2 note: 'var val' declared here)");
}
TEST_F(StructMemberAttributeTest, Size_Attribute_Override) {
diff --git a/src/tint/lang/wgsl/resolver/bitcast_validation_test.cc b/src/tint/lang/wgsl/resolver/bitcast_validation_test.cc
index e96a255..bcd8bab 100644
--- a/src/tint/lang/wgsl/resolver/bitcast_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/bitcast_validation_test.cc
@@ -168,7 +168,7 @@
WrapInFunction(Bitcast(Source{{12, 34}}, dst.ast(*this), src.expr(*this, 0)));
- std::string expected = "12:34 error: no matching call to bitcast<${TO}>(${FROM})";
+ std::string expected = "12:34 error: no matching call to 'bitcast<${TO}>(${FROM})'";
expected = ReplaceAll(expected, "${FROM}", src.sem(*this)->FriendlyName());
expected = ReplaceAll(expected, "${TO}", dst.sem(*this)->FriendlyName());
diff --git a/src/tint/lang/wgsl/resolver/builtin_test.cc b/src/tint/lang/wgsl/resolver/builtin_test.cc
index 37dc276..7dfdf9f 100644
--- a/src/tint/lang/wgsl/resolver/builtin_test.cc
+++ b/src/tint/lang/wgsl/resolver/builtin_test.cc
@@ -163,12 +163,12 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(error: no matching call to select()
+ R"(error: no matching call to 'select()'
3 candidate functions:
- select(T, T, bool) -> T where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- select(vecN<T>, vecN<T>, bool) -> vecN<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
+ 'select(T, T, bool) -> T' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'select(vecN<T>, vecN<T>, bool) -> vecN<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
)");
}
@@ -179,12 +179,12 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(error: no matching call to select(i32, i32, i32)
+ R"(error: no matching call to 'select(i32, i32, i32)'
3 candidate functions:
- select(T, T, bool) -> T where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- select(vecN<T>, vecN<T>, bool) -> vecN<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
+ 'select(T, T, bool) -> T' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'select(vecN<T>, vecN<T>, bool) -> vecN<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
)");
}
@@ -197,12 +197,12 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(error: no matching call to select(mat2x2<f32>, mat2x2<f32>, bool)
+ R"(error: no matching call to 'select(mat2x2<f32>, mat2x2<f32>, bool)'
3 candidate functions:
- select(T, T, bool) -> T where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- select(vecN<T>, vecN<T>, bool) -> vecN<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
+ 'select(T, T, bool) -> T' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'select(vecN<T>, vecN<T>, bool) -> vecN<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
)");
}
@@ -213,12 +213,12 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(error: no matching call to select(f32, vec2<f32>, bool)
+ R"(error: no matching call to 'select(f32, vec2<f32>, bool)'
3 candidate functions:
- select(T, T, bool) -> T where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- select(vecN<T>, vecN<T>, bool) -> vecN<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
+ 'select(T, T, bool) -> T' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'select(vecN<T>, vecN<T>, bool) -> vecN<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
)");
}
@@ -229,12 +229,12 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(error: no matching call to select(vec2<f32>, vec3<f32>, bool)
+ R"(error: no matching call to 'select(vec2<f32>, vec3<f32>, bool)'
3 candidate functions:
- select(T, T, bool) -> T where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- select(vecN<T>, vecN<T>, bool) -> vecN<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
- select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
+ 'select(T, T, bool) -> T' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'select(vecN<T>, vecN<T>, bool) -> vecN<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
+ 'select(vecN<T>, vecN<T>, vecN<bool>) -> vecN<T>' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'i32', 'u32' or 'bool'
)");
}
@@ -268,10 +268,10 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(error: no matching call to arrayLength(ptr<private, array<i32, 4>, read_write>)
+ R"(error: no matching call to 'arrayLength(ptr<private, array<i32, 4>, read_write>)'
1 candidate function:
- arrayLength(ptr<storage, array<T>, A>) -> u32
+ 'arrayLength(ptr<storage, array<T>, A>) -> u32'
)");
}
@@ -306,7 +306,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("error: no matching call to " + std::string(param.name) + "()"));
+ HasSubstr("error: no matching call to '" + std::string(param.name) + "()'"));
}
TEST_P(ResolverBuiltinTest_FloatBuiltin_IdenticalType, OneParam_Scalar_f32) {
@@ -331,7 +331,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("error: no matching call to " + std::string(param.name) + "(f32)"));
+ HasSubstr("error: no matching call to '" + std::string(param.name) + "(f32)'"));
}
}
@@ -357,8 +357,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(vec3<f32>)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(vec3<f32>)'"));
}
}
@@ -378,8 +378,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(f32, f32)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(f32, f32)'"));
}
}
@@ -402,8 +402,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(vec3<f32>, vec3<f32>)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(vec3<f32>, vec3<f32>)'"));
}
}
@@ -423,8 +423,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(f32, f32, f32)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(f32, f32, f32)'"));
}
}
@@ -449,8 +449,8 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("error: no matching call to " + std::string(param.name) +
- "(vec3<f32>, vec3<f32>, vec3<f32>)"));
+ HasSubstr("error: no matching call to '" + std::string(param.name) +
+ "(vec3<f32>, vec3<f32>, vec3<f32>)'"));
}
}
@@ -470,8 +470,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(f32, f32, f32, f32)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(f32, f32, f32, f32)'"));
}
}
@@ -496,8 +496,8 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("error: no matching call to " + std::string(param.name) +
- "(vec3<f32>, vec3<f32>, vec3<f32>, vec3<f32>)"));
+ HasSubstr("error: no matching call to '" + std::string(param.name) +
+ "(vec3<f32>, vec3<f32>, vec3<f32>, vec3<f32>)'"));
}
}
@@ -525,7 +525,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("error: no matching call to " + std::string(param.name) + "(f16)"));
+ HasSubstr("error: no matching call to '" + std::string(param.name) + "(f16)'"));
}
}
@@ -553,8 +553,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(vec3<f16>)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(vec3<f16>)'"));
}
}
@@ -576,8 +576,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(f16, f16)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(f16, f16)'"));
}
}
@@ -602,8 +602,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(vec3<f16>, vec3<f16>)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(vec3<f16>, vec3<f16>)'"));
}
}
@@ -625,8 +625,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(f16, f16, f16)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(f16, f16, f16)'"));
}
}
@@ -653,8 +653,8 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("error: no matching call to " + std::string(param.name) +
- "(vec3<f16>, vec3<f16>, vec3<f16>)"));
+ HasSubstr("error: no matching call to '" + std::string(param.name) +
+ "(vec3<f16>, vec3<f16>, vec3<f16>)'"));
}
}
@@ -676,8 +676,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(f16, f16, f16, f16)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(f16, f16, f16, f16)'"));
}
}
@@ -704,8 +704,8 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("error: no matching call to " + std::string(param.name) +
- "(vec3<f16>, vec3<f16>, vec3<f16>, vec3<f16>)"));
+ HasSubstr("error: no matching call to '" + std::string(param.name) +
+ "(vec3<f16>, vec3<f16>, vec3<f16>, vec3<f16>)'"));
}
}
@@ -797,10 +797,10 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(error: no matching call to cross()
+ EXPECT_EQ(r()->error(), R"(error: no matching call to 'cross()'
1 candidate function:
- cross(vec3<T>, vec3<T>) -> vec3<T> where: T is abstract-float, f32 or f16
+ 'cross(vec3<T>, vec3<T>) -> vec3<T>' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -810,10 +810,10 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(error: no matching call to cross(f32, f32)
+ EXPECT_EQ(r()->error(), R"(error: no matching call to 'cross(f32, f32)'
1 candidate function:
- cross(vec3<T>, vec3<T>) -> vec3<T> where: T is abstract-float, f32 or f16
+ 'cross(vec3<T>, vec3<T>) -> vec3<T>' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -824,10 +824,10 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(error: no matching call to cross(vec3<i32>, vec3<i32>)
+ R"(error: no matching call to 'cross(vec3<i32>, vec3<i32>)'
1 candidate function:
- cross(vec3<T>, vec3<T>) -> vec3<T> where: T is abstract-float, f32 or f16
+ 'cross(vec3<T>, vec3<T>) -> vec3<T>' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -840,10 +840,10 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(error: no matching call to cross(vec4<f32>, vec4<f32>)
+ R"(error: no matching call to 'cross(vec4<f32>, vec4<f32>)'
1 candidate function:
- cross(vec3<T>, vec3<T>) -> vec3<T> where: T is abstract-float, f32 or f16
+ 'cross(vec3<T>, vec3<T>) -> vec3<T>' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -856,10 +856,10 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(error: no matching call to cross(vec3<f32>, vec3<f32>, vec3<f32>)
+ R"(error: no matching call to 'cross(vec3<f32>, vec3<f32>, vec3<f32>)'
1 candidate function:
- cross(vec3<T>, vec3<T>) -> vec3<T> where: T is abstract-float, f32 or f16
+ 'cross(vec3<T>, vec3<T>) -> vec3<T>' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -915,11 +915,12 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(error: no matching call to distance(vec3<f32>, vec3<f32>, vec3<f32>)
+ EXPECT_EQ(r()->error(),
+ R"(error: no matching call to 'distance(vec3<f32>, vec3<f32>, vec3<f32>)'
2 candidate functions:
- distance(T, T) -> T where: T is abstract-float, f32 or f16
- distance(vecN<T>, vecN<T>) -> T where: T is abstract-float, f32 or f16
+ 'distance(T, T) -> T' where: 'T' is 'abstract-float', 'f32' or 'f16'
+ 'distance(vecN<T>, vecN<T>) -> T' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -929,11 +930,11 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(error: no matching call to distance(vec3<f32>)
+ EXPECT_EQ(r()->error(), R"(error: no matching call to 'distance(vec3<f32>)'
2 candidate functions:
- distance(T, T) -> T where: T is abstract-float, f32 or f16
- distance(vecN<T>, vecN<T>) -> T where: T is abstract-float, f32 or f16
+ 'distance(T, T) -> T' where: 'T' is 'abstract-float', 'f32' or 'f16'
+ 'distance(vecN<T>, vecN<T>) -> T' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -943,11 +944,11 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(error: no matching call to distance()
+ EXPECT_EQ(r()->error(), R"(error: no matching call to 'distance()'
2 candidate functions:
- distance(T, T) -> T where: T is abstract-float, f32 or f16
- distance(vecN<T>, vecN<T>) -> T where: T is abstract-float, f32 or f16
+ 'distance(T, T) -> T' where: 'T' is 'abstract-float', 'f32' or 'f16'
+ 'distance(vecN<T>, vecN<T>) -> T' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -1089,11 +1090,11 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(error: no matching call to frexp(i32, ptr<workgroup, i32, read_write>)
+ R"(error: no matching call to 'frexp(i32, ptr<workgroup, i32, read_write>)'
2 candidate functions:
- frexp(T) -> __frexp_result_T where: T is abstract-float, f32 or f16
- frexp(vecN<T>) -> __frexp_result_vecN_T where: T is abstract-float, f32 or f16
+ 'frexp(T) -> __frexp_result_T' where: 'T' is 'abstract-float', 'f32' or 'f16'
+ 'frexp(vecN<T>) -> __frexp_result_vecN_T' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -1148,11 +1149,11 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(error: no matching call to length()
+ EXPECT_EQ(r()->error(), R"(error: no matching call to 'length()'
2 candidate functions:
- length(T) -> T where: T is abstract-float, f32 or f16
- length(vecN<T>) -> T where: T is abstract-float, f32 or f16
+ 'length(T) -> T' where: 'T' is 'abstract-float', 'f32' or 'f16'
+ 'length(vecN<T>) -> T' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -1162,11 +1163,11 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(error: no matching call to length(f32, f32)
+ EXPECT_EQ(r()->error(), R"(error: no matching call to 'length(f32, f32)'
2 candidate functions:
- length(T) -> T where: T is abstract-float, f32 or f16
- length(vecN<T>) -> T where: T is abstract-float, f32 or f16
+ 'length(T) -> T' where: 'T' is 'abstract-float', 'f32' or 'f16'
+ 'length(vecN<T>) -> T' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -1338,11 +1339,11 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(error: no matching call to modf(i32, ptr<workgroup, f32, read_write>)
+ R"(error: no matching call to 'modf(i32, ptr<workgroup, f32, read_write>)'
2 candidate functions:
- modf(T) -> __modf_result_T where: T is abstract-float, f32 or f16
- modf(vecN<T>) -> __modf_result_vecN_T where: T is abstract-float, f32 or f16
+ 'modf(T) -> __modf_result_T' where: 'T' is 'abstract-float', 'f32' or 'f16'
+ 'modf(vecN<T>) -> __modf_result_vecN_T' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -1354,11 +1355,11 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(error: no matching call to modf(f32, ptr<workgroup, i32, read_write>)
+ R"(error: no matching call to 'modf(f32, ptr<workgroup, i32, read_write>)'
2 candidate functions:
- modf(T) -> __modf_result_T where: T is abstract-float, f32 or f16
- modf(vecN<T>) -> __modf_result_vecN_T where: T is abstract-float, f32 or f16
+ 'modf(T) -> __modf_result_T' where: 'T' is 'abstract-float', 'f32' or 'f16'
+ 'modf(vecN<T>) -> __modf_result_vecN_T' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -1368,11 +1369,11 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(error: no matching call to modf(f32, f32)
+ EXPECT_EQ(r()->error(), R"(error: no matching call to 'modf(f32, f32)'
2 candidate functions:
- modf(T) -> __modf_result_T where: T is abstract-float, f32 or f16
- modf(vecN<T>) -> __modf_result_vecN_T where: T is abstract-float, f32 or f16
+ 'modf(T) -> __modf_result_T' where: 'T' is 'abstract-float', 'f32' or 'f16'
+ 'modf(vecN<T>) -> __modf_result_vecN_T' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -1384,11 +1385,11 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(error: no matching call to modf(vec2<f32>, ptr<workgroup, vec4<f32>, read_write>)
+ R"(error: no matching call to 'modf(vec2<f32>, ptr<workgroup, vec4<f32>, read_write>)'
2 candidate functions:
- modf(T) -> __modf_result_T where: T is abstract-float, f32 or f16
- modf(vecN<T>) -> __modf_result_vecN_T where: T is abstract-float, f32 or f16
+ 'modf(T) -> __modf_result_T' where: 'T' is 'abstract-float', 'f32' or 'f16'
+ 'modf(vecN<T>) -> __modf_result_vecN_T' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -1425,10 +1426,10 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(error: no matching call to normalize()
+ EXPECT_EQ(r()->error(), R"(error: no matching call to 'normalize()'
1 candidate function:
- normalize(vecN<T>) -> vecN<T> where: T is abstract-float, f32 or f16
+ 'normalize(vecN<T>) -> vecN<T>' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -1463,7 +1464,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("error: no matching call to " + std::string(param.name) + "()"));
+ HasSubstr("error: no matching call to '" + std::string(param.name) + "()'"));
}
TEST_P(ResolverBuiltinTest_IntegerBuiltin_IdenticalType, OneParams_Scalar_i32) {
@@ -1483,7 +1484,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("error: no matching call to " + std::string(param.name) + "(i32)"));
+ HasSubstr("error: no matching call to '" + std::string(param.name) + "(i32)'"));
}
}
@@ -1506,8 +1507,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(vec3<i32>)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(vec3<i32>)'"));
}
}
@@ -1528,7 +1529,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("error: no matching call to " + std::string(param.name) + "(u32)"));
+ HasSubstr("error: no matching call to '" + std::string(param.name) + "(u32)'"));
}
}
@@ -1551,8 +1552,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(vec3<u32>)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(vec3<u32>)'"));
}
}
@@ -1572,8 +1573,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(i32, i32)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(i32, i32)'"));
}
}
@@ -1596,8 +1597,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(vec3<i32>, vec3<i32>)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(vec3<i32>, vec3<i32>)'"));
}
}
@@ -1617,8 +1618,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(u32, u32)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(u32, u32)'"));
}
}
@@ -1641,8 +1642,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(vec3<u32>, vec3<u32>)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(vec3<u32>, vec3<u32>)'"));
}
}
@@ -1662,8 +1663,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(i32, i32, i32)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(i32, i32, i32)'"));
}
}
@@ -1688,8 +1689,8 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("error: no matching call to " + std::string(param.name) +
- "(vec3<i32>, vec3<i32>, vec3<i32>)"));
+ HasSubstr("error: no matching call to '" + std::string(param.name) +
+ "(vec3<i32>, vec3<i32>, vec3<i32>)'"));
}
}
@@ -1709,8 +1710,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(u32, u32, u32)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(u32, u32, u32)'"));
}
}
@@ -1735,8 +1736,8 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("error: no matching call to " + std::string(param.name) +
- "(vec3<u32>, vec3<u32>, vec3<u32>)"));
+ HasSubstr("error: no matching call to '" + std::string(param.name) +
+ "(vec3<u32>, vec3<u32>, vec3<u32>)'"));
}
}
@@ -1756,8 +1757,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(i32, i32, i32, i32)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(i32, i32, i32, i32)'"));
}
}
@@ -1782,8 +1783,8 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("error: no matching call to " + std::string(param.name) +
- "(vec3<i32>, vec3<i32>, vec3<i32>, vec3<i32>)"));
+ HasSubstr("error: no matching call to '" + std::string(param.name) +
+ "(vec3<i32>, vec3<i32>, vec3<i32>, vec3<i32>)'"));
}
}
@@ -1803,8 +1804,8 @@
// Invalid parameter count.
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " +
- std::string(param.name) + "(u32, u32, u32, u32)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" +
+ std::string(param.name) + "(u32, u32, u32, u32)'"));
}
}
@@ -1829,8 +1830,8 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("error: no matching call to " + std::string(param.name) +
- "(vec3<u32>, vec3<u32>, vec3<u32>, vec3<u32>)"));
+ HasSubstr("error: no matching call to '" + std::string(param.name) +
+ "(vec3<u32>, vec3<u32>, vec3<u32>, vec3<u32>)'"));
}
}
@@ -1942,10 +1943,10 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(error: no matching call to determinant(mat2x3<f32>)
+ EXPECT_EQ(r()->error(), R"(error: no matching call to 'determinant(mat2x3<f32>)'
1 candidate function:
- determinant(matNxN<T>) -> T where: T is abstract-float, f32 or f16
+ 'determinant(matNxN<T>) -> T' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -1957,10 +1958,10 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(error: no matching call to determinant(f32)
+ EXPECT_EQ(r()->error(), R"(error: no matching call to 'determinant(f32)'
1 candidate function:
- determinant(matNxN<T>) -> T where: T is abstract-float, f32 or f16
+ 'determinant(matNxN<T>) -> T' where: 'T' is 'abstract-float', 'f32' or 'f16'
)");
}
@@ -2026,10 +2027,10 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(error: no matching call to dot(f32, f32)
+ R"(error: no matching call to 'dot(f32, f32)'
1 candidate function:
- dot(vecN<T>, vecN<T>) -> T where: T is abstract-float, abstract-int, f32, i32, u32 or f16
+ 'dot(vecN<T>, vecN<T>) -> T' where: 'T' is 'abstract-float', 'abstract-int', 'f32', 'i32', 'u32' or 'f16'
)");
}
@@ -2079,10 +2080,10 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "error: no matching call to " + name +
- "()\n\n"
- "2 candidate functions:\n " +
- name + "(f32) -> f32\n " + name + "(vecN<f32>) -> vecN<f32>\n");
+ EXPECT_EQ(r()->error(), "error: no matching call to '" + name +
+ "()'\n\n"
+ "2 candidate functions:\n '" +
+ name + "(f32) -> f32'\n '" + name + "(vecN<f32>) -> vecN<f32>'\n");
}
INSTANTIATE_TEST_SUITE_P(ResolverTest,
@@ -2612,7 +2613,7 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " + std::string(param.name)));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" + std::string(param.name)));
}
TEST_P(ResolverBuiltinTest_DataPacking, Error_NoParams) {
@@ -2623,7 +2624,7 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " + std::string(param.name)));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" + std::string(param.name)));
}
TEST_P(ResolverBuiltinTest_DataPacking, Error_TooManyParams) {
@@ -2638,7 +2639,7 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " + std::string(param.name)));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" + std::string(param.name)));
}
INSTANTIATE_TEST_SUITE_P(
@@ -2709,7 +2710,7 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to " + std::string(param.name)));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching call to '" + std::string(param.name)));
}
INSTANTIATE_TEST_SUITE_P(
diff --git a/src/tint/lang/wgsl/resolver/builtin_validation_test.cc b/src/tint/lang/wgsl/resolver/builtin_validation_test.cc
index 9dcab3d..a6ff7e1 100644
--- a/src/tint/lang/wgsl/resolver/builtin_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/builtin_validation_test.cc
@@ -164,14 +164,14 @@
WrapInFunction(Call(Source{{56, 78}}, "mix", 1_f, 2_f, 3_f));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(56:78 error: no matching constructor for i32(f32, f32, f32)
+ EXPECT_EQ(r()->error(), R"(56:78 error: no matching constructor for 'i32(f32, f32, f32)'
2 candidate constructors:
- i32(i32) -> i32
- i32() -> i32
+ 'i32(i32) -> i32'
+ 'i32() -> i32'
1 candidate conversion:
- i32(T) -> i32 where: T is abstract-int, abstract-float, f32, f16, u32 or bool
+ 'i32(T) -> i32' where: 'T' is 'abstract-int', 'abstract-float', 'f32', 'f16', 'u32' or 'bool'
)");
}
@@ -778,10 +778,10 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(error: no matching call to workgroupUniformLoad(ptr<storage, i32, read_write>)
+ R"(error: no matching call to 'workgroupUniformLoad(ptr<storage, i32, read_write>)'
1 candidate function:
- workgroupUniformLoad(ptr<workgroup, T, read_write>) -> T
+ 'workgroupUniformLoad(ptr<workgroup, T, read_write>) -> T'
)");
}
diff --git a/src/tint/lang/wgsl/resolver/call_validation_test.cc b/src/tint/lang/wgsl/resolver/call_validation_test.cc
index 25121ae..5df9c73 100644
--- a/src/tint/lang/wgsl/resolver/call_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/call_validation_test.cc
@@ -143,7 +143,7 @@
});
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: cannot take the address of let 'z'");
+ EXPECT_EQ(r()->error(), "12:34 error: cannot take the address of 'let z'");
}
TEST_F(ResolverCallValidationTest,
@@ -519,11 +519,11 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(12:34 error: no matching call to min<i32>(abstract-int, abstract-int)
+ R"(12:34 error: no matching call to 'min<i32>(abstract-int, abstract-int)'
2 candidate functions:
- min(T, T) -> T where: T is abstract-float, abstract-int, f32, i32, u32 or f16
- min(vecN<T>, vecN<T>) -> vecN<T> where: T is abstract-float, abstract-int, f32, i32, u32 or f16
+ 'min(T, T) -> T' where: 'T' is 'abstract-float', 'abstract-int', 'f32', 'i32', 'u32' or 'f16'
+ 'min(vecN<T>, vecN<T>) -> vecN<T>' where: 'T' is 'abstract-float', 'abstract-int', 'f32', 'i32', 'u32' or 'f16'
)");
}
diff --git a/src/tint/lang/wgsl/resolver/compound_assignment_validation_test.cc b/src/tint/lang/wgsl/resolver/compound_assignment_validation_test.cc
index 578cd22..132ef50 100644
--- a/src/tint/lang/wgsl/resolver/compound_assignment_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/compound_assignment_validation_test.cc
@@ -86,7 +86,7 @@
ASSERT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching overload for operator += (i32, f32)"));
+ HasSubstr("12:34 error: no matching overload for 'operator += (i32, f32)'"));
}
TEST_F(ResolverCompoundAssignmentValidationTest, IncompatibleOp) {
@@ -103,7 +103,7 @@
ASSERT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching overload for operator |= (f32, f32)"));
+ HasSubstr("12:34 error: no matching overload for 'operator |= (f32, f32)'"));
}
TEST_F(ResolverCompoundAssignmentValidationTest, VectorScalar_Pass) {
@@ -198,7 +198,7 @@
EXPECT_THAT(
r()->error(),
- HasSubstr("12:34 error: no matching overload for operator *= (vec4<f32>, mat4x2<f32>)"));
+ HasSubstr("12:34 error: no matching overload for 'operator *= (vec4<f32>, mat4x2<f32>)'"));
}
TEST_F(ResolverCompoundAssignmentValidationTest, VectorMatrix_ResultMismatch) {
@@ -242,7 +242,7 @@
WrapInFunction(CompoundAssign(Source{{56, 78}}, Phony(), 1_i, core::BinaryOp::kAdd));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("56:78 error: no matching overload for operator += (void, i32)"));
+ HasSubstr("56:78 error: no matching overload for 'operator += (void, i32)'"));
}
TEST_F(ResolverCompoundAssignmentValidationTest, ReadOnlyBuffer) {
@@ -266,9 +266,9 @@
WrapInFunction(a, CompoundAssign(Expr(Source{{56, 78}}, "a"), 1_i, core::BinaryOp::kAdd));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(56:78 error: cannot assign to let 'a'
+ EXPECT_EQ(r()->error(), R"(56:78 error: cannot assign to 'let a'
56:78 note: 'let' variables are immutable
-12:34 note: let 'a' declared here)");
+12:34 note: 'let a' declared here)");
}
TEST_F(ResolverCompoundAssignmentValidationTest, LhsLiteral) {
@@ -288,7 +288,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
r()->error(),
- HasSubstr("error: no matching overload for operator += (atomic<i32>, atomic<i32>)"));
+ HasSubstr("error: no matching overload for 'operator += (atomic<i32>, atomic<i32>)'"));
}
} // namespace
diff --git a/src/tint/lang/wgsl/resolver/control_block_validation_test.cc b/src/tint/lang/wgsl/resolver/control_block_validation_test.cc
index a5eb482..9f38183 100644
--- a/src/tint/lang/wgsl/resolver/control_block_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/control_block_validation_test.cc
@@ -360,8 +360,8 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- "56:78 error: duplicate switch case '2'\n"
- "12:34 note: previous case declared here");
+ R"(56:78 error: duplicate switch case '2'
+12:34 note: previous case declared here)");
}
TEST_F(ResolverControlBlockValidationTest, NonUniqueCaseSelectorValueSint_Fail) {
@@ -387,8 +387,8 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- "56:78 error: duplicate switch case '-10'\n"
- "12:34 note: previous case declared here");
+ R"(56:78 error: duplicate switch case '-10'
+12:34 note: previous case declared here)");
}
TEST_F(ResolverControlBlockValidationTest, SwitchCase_Pass) {
@@ -511,8 +511,8 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- "56:78 error: duplicate switch case '10'\n"
- "12:34 note: previous case declared here");
+ R"(56:78 error: duplicate switch case '10'
+12:34 note: previous case declared here)");
}
TEST_F(ResolverControlBlockValidationTest, NonUniqueCaseSelectorSameCase_BothExpression_Fail) {
@@ -532,8 +532,8 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- "12:34 error: duplicate switch case '10'\n"
- "56:78 note: previous case declared here");
+ R"(12:34 error: duplicate switch case '10'
+56:78 note: previous case declared here)");
}
TEST_F(ResolverControlBlockValidationTest, NonUniqueCaseSelectorSame_Case_Expression_Fail) {
@@ -553,8 +553,8 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- "12:34 error: duplicate switch case '10'\n"
- "56:78 note: previous case declared here");
+ R"(12:34 error: duplicate switch case '10'
+56:78 note: previous case declared here)");
}
TEST_F(ResolverControlBlockValidationTest, Switch_OverrideCondition_Fail) {
diff --git a/src/tint/lang/wgsl/resolver/dependency_graph.cc b/src/tint/lang/wgsl/resolver/dependency_graph.cc
index 27f11ae..7e2db61 100644
--- a/src/tint/lang/wgsl/resolver/dependency_graph.cc
+++ b/src/tint/lang/wgsl/resolver/dependency_graph.cc
@@ -131,14 +131,14 @@
/// A map of global name to Global
using GlobalMap = Hashmap<Symbol, Global*, 16>;
-/// Raises an error diagnostic with the given message and source.
-void AddError(diag::List& diagnostics, const std::string& msg, const Source& source) {
- diagnostics.AddError(diag::System::Resolver, msg, source);
+/// @returns a new error diagnostic with the given source.
+diag::Diagnostic& AddError(diag::List& diagnostics, const Source& source) {
+ return diagnostics.AddError(diag::System::Resolver, source);
}
-/// Raises a note diagnostic with the given message and source.
-void AddNote(diag::List& diagnostics, const std::string& msg, const Source& source) {
- diagnostics.AddNote(diag::System::Resolver, msg, source);
+/// @returns a new note diagnostic with the given source.
+diag::Diagnostic& AddNote(diag::List& diagnostics, const Source& source) {
+ return diagnostics.AddNote(diag::System::Resolver, source);
}
/// DependencyScanner is used to traverse a module to build the list of
@@ -335,8 +335,8 @@
auto* old = scope_stack_.Set(symbol, node);
if (old != nullptr && node != old) {
auto name = symbol.Name();
- AddError(diagnostics_, "redeclaration of '" + name + "'", node->source);
- AddNote(diagnostics_, "'" + name + "' previously declared here", old->source);
+ AddError(diagnostics_, node->source) << "redeclaration of '" << name << "'";
+ AddNote(diagnostics_, old->source) << "'" << name << "' previously declared here";
}
}
@@ -355,7 +355,7 @@
return ast::TraverseAction::Descend;
});
if (!ok) {
- AddError(diagnostics_, "TraverseExpressions failed", next->source);
+ AddError(diagnostics_, next->source) << "TraverseExpressions failed";
return;
}
}
@@ -768,8 +768,8 @@
/// found in `stack`.
/// @param stack is the global dependency stack that contains a loop.
void CyclicDependencyFound(const Global* root, VectorRef<const Global*> stack) {
- StringStream msg;
- msg << "cyclic dependency found: ";
+ auto& err = AddError(diagnostics_, root->node->source);
+ err << "cyclic dependency found: ";
constexpr size_t kLoopNotStarted = ~0u;
size_t loop_start = kLoopNotStarted;
for (size_t i = 0; i < stack.Length(); i++) {
@@ -778,19 +778,18 @@
loop_start = i;
}
if (loop_start != kLoopNotStarted) {
- msg << "'" << NameOf(e->node) << "' -> ";
+ err << "'" << NameOf(e->node) << "' -> ";
}
}
- msg << "'" << NameOf(root->node) << "'";
- AddError(diagnostics_, msg.str(), root->node->source);
+ err << "'" << NameOf(root->node) << "'";
+
for (size_t i = loop_start; i < stack.Length(); i++) {
auto* from = stack[i];
auto* to = (i + 1 < stack.Length()) ? stack[i + 1] : stack[loop_start];
auto info = DepInfoFor(from, to);
- AddNote(diagnostics_,
- KindOf(from->node) + " '" + NameOf(from->node) + "' references " +
- KindOf(to->node) + " '" + NameOf(to->node) + "' here",
- info.source);
+ AddNote(diagnostics_, info.source)
+ << KindOf(from->node) + " '" << NameOf(from->node) << "' references "
+ << KindOf(to->node) << " '" << NameOf(to->node) << "' here";
}
}
diff --git a/src/tint/lang/wgsl/resolver/expression_kind_test.cc b/src/tint/lang/wgsl/resolver/expression_kind_test.cc
index 94c91c8e..1334b8b 100644
--- a/src/tint/lang/wgsl/resolver/expression_kind_test.cc
+++ b/src/tint/lang/wgsl/resolver/expression_kind_test.cc
@@ -622,34 +622,34 @@
{Def::kParameter, Use::kUnaryOp, kPass},
{Def::kStruct, Use::kAccess, R"(5:6 error: cannot use type 'STRUCT' as access
-1:2 note: struct 'STRUCT' declared here)"},
+1:2 note: 'struct STRUCT' declared here)"},
{Def::kStruct, Use::kAddressSpace,
R"(5:6 error: cannot use type 'STRUCT' as address space
-1:2 note: struct 'STRUCT' declared here)"},
+1:2 note: 'struct STRUCT' declared here)"},
{Def::kStruct, Use::kBinaryOp, R"(5:6 error: cannot use type 'STRUCT' as value
-1:2 note: struct 'STRUCT' declared here
+1:2 note: 'struct STRUCT' declared here
7:8 note: are you missing '()'?)"},
{Def::kStruct, Use::kBuiltinValue,
R"(5:6 error: cannot use type 'STRUCT' as builtin value
-1:2 note: struct 'STRUCT' declared here)"},
+1:2 note: 'struct STRUCT' declared here)"},
{Def::kStruct, Use::kFunctionReturnType, kPass},
{Def::kStruct, Use::kInterpolationSampling,
R"(5:6 error: cannot use type 'STRUCT' as interpolation sampling
-1:2 note: struct 'STRUCT' declared here)"},
+1:2 note: 'struct STRUCT' declared here)"},
{Def::kStruct, Use::kInterpolationType,
R"(5:6 error: cannot use type 'STRUCT' as interpolation type
-1:2 note: struct 'STRUCT' declared here)"},
+1:2 note: 'struct STRUCT' declared here)"},
{Def::kStruct, Use::kMemberType, kPass},
{Def::kStruct, Use::kTexelFormat, R"(5:6 error: cannot use type 'STRUCT' as texel format
-1:2 note: struct 'STRUCT' declared here)"},
+1:2 note: 'struct STRUCT' declared here)"},
{Def::kStruct, Use::kValueExpression,
R"(5:6 error: cannot use type 'STRUCT' as value
-1:2 note: struct 'STRUCT' declared here
+1:2 note: 'struct STRUCT' declared here
7:8 note: are you missing '()'?)"},
{Def::kStruct, Use::kVariableType, kPass},
{Def::kStruct, Use::kUnaryOp,
R"(5:6 error: cannot use type 'STRUCT' as value
-1:2 note: struct 'STRUCT' declared here
+1:2 note: 'struct STRUCT' declared here
7:8 note: are you missing '()'?)"},
{Def::kTexelFormat, Use::kAccess,
@@ -704,40 +704,40 @@
R"(5:6 error: cannot use type 'i32' as value
7:8 note: are you missing '()'?)"},
- {Def::kVariable, Use::kAccess, R"(5:6 error: cannot use const 'VARIABLE' as access
-1:2 note: const 'VARIABLE' declared here)"},
+ {Def::kVariable, Use::kAccess, R"(5:6 error: cannot use 'const VARIABLE' as access
+1:2 note: 'const VARIABLE' declared here)"},
{Def::kVariable, Use::kAddressSpace,
- R"(5:6 error: cannot use const 'VARIABLE' as address space
-1:2 note: const 'VARIABLE' declared here)"},
+ R"(5:6 error: cannot use 'const VARIABLE' as address space
+1:2 note: 'const VARIABLE' declared here)"},
{Def::kVariable, Use::kBinaryOp, kPass},
{Def::kVariable, Use::kBuiltinValue,
- R"(5:6 error: cannot use const 'VARIABLE' as builtin value
-1:2 note: const 'VARIABLE' declared here)"},
+ R"(5:6 error: cannot use 'const VARIABLE' as builtin value
+1:2 note: 'const VARIABLE' declared here)"},
{Def::kVariable, Use::kCallStmt,
- R"(5:6 error: cannot use const 'VARIABLE' as call target
-1:2 note: const 'VARIABLE' declared here)"},
+ R"(5:6 error: cannot use 'const VARIABLE' as call target
+1:2 note: 'const VARIABLE' declared here)"},
{Def::kVariable, Use::kCallExpr,
- R"(5:6 error: cannot use const 'VARIABLE' as call target
-1:2 note: const 'VARIABLE' declared here)"},
+ R"(5:6 error: cannot use 'const VARIABLE' as call target
+1:2 note: 'const VARIABLE' declared here)"},
{Def::kVariable, Use::kFunctionReturnType,
- R"(5:6 error: cannot use const 'VARIABLE' as type
-1:2 note: const 'VARIABLE' declared here)"},
+ R"(5:6 error: cannot use 'const VARIABLE' as type
+1:2 note: 'const VARIABLE' declared here)"},
{Def::kVariable, Use::kInterpolationSampling,
- R"(5:6 error: cannot use const 'VARIABLE' as interpolation sampling
-1:2 note: const 'VARIABLE' declared here)"},
+ R"(5:6 error: cannot use 'const VARIABLE' as interpolation sampling
+1:2 note: 'const VARIABLE' declared here)"},
{Def::kVariable, Use::kInterpolationType,
- R"(5:6 error: cannot use const 'VARIABLE' as interpolation type
-1:2 note: const 'VARIABLE' declared here)"},
+ R"(5:6 error: cannot use 'const VARIABLE' as interpolation type
+1:2 note: 'const VARIABLE' declared here)"},
{Def::kVariable, Use::kMemberType,
- R"(5:6 error: cannot use const 'VARIABLE' as type
-1:2 note: const 'VARIABLE' declared here)"},
+ R"(5:6 error: cannot use 'const VARIABLE' as type
+1:2 note: 'const VARIABLE' declared here)"},
{Def::kVariable, Use::kTexelFormat,
- R"(5:6 error: cannot use const 'VARIABLE' as texel format
-1:2 note: const 'VARIABLE' declared here)"},
+ R"(5:6 error: cannot use 'const VARIABLE' as texel format
+1:2 note: 'const VARIABLE' declared here)"},
{Def::kVariable, Use::kValueExpression, kPass},
{Def::kVariable, Use::kVariableType,
- R"(5:6 error: cannot use const 'VARIABLE' as type
-1:2 note: const 'VARIABLE' declared here)"},
+ R"(5:6 error: cannot use 'const VARIABLE' as type
+1:2 note: 'const VARIABLE' declared here)"},
{Def::kVariable, Use::kUnaryOp, kPass},
}));
diff --git a/src/tint/lang/wgsl/resolver/materialize_test.cc b/src/tint/lang/wgsl/resolver/materialize_test.cc
index 19eff8c..d156bda 100644
--- a/src/tint/lang/wgsl/resolver/materialize_test.cc
+++ b/src/tint/lang/wgsl/resolver/materialize_test.cc
@@ -440,16 +440,16 @@
std::string expect;
switch (method) {
case Method::kBuiltinArg:
- expect = "error: no matching call to min(" + data.target_type_name + ", " +
- data.abstract_type_name + ")";
+ expect = "error: no matching call to 'min(" + data.target_type_name + ", " +
+ data.abstract_type_name + ")'";
break;
case Method::kBinaryOp:
- expect = "error: no matching overload for operator + (" +
- data.target_type_name + ", " + data.abstract_type_name + ")";
+ expect = "error: no matching overload for 'operator + (" +
+ data.target_type_name + ", " + data.abstract_type_name + ")'";
break;
case Method::kCompoundAssign:
- expect = "error: no matching overload for operator += (" +
- data.target_type_name + ", " + data.abstract_type_name + ")";
+ expect = "error: no matching overload for 'operator += (" +
+ data.target_type_name + ", " + data.abstract_type_name + ")'";
break;
default:
expect = "error: cannot convert value of type '" + data.abstract_type_name +
diff --git a/src/tint/lang/wgsl/resolver/ptr_ref_validation_test.cc b/src/tint/lang/wgsl/resolver/ptr_ref_validation_test.cc
index 1895890..bbcbc13 100644
--- a/src/tint/lang/wgsl/resolver/ptr_ref_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/ptr_ref_validation_test.cc
@@ -61,7 +61,7 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:34 error: cannot take the address of let 'l')");
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot take the address of 'let l')");
}
TEST_F(ResolverPtrRefValidationTest, AddressOfConst) {
@@ -74,7 +74,7 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:34 error: cannot take the address of const 'c')");
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot take the address of 'const c')");
}
TEST_F(ResolverPtrRefValidationTest, AddressOfOverride) {
@@ -87,7 +87,7 @@
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:34 error: cannot take the address of override 'o')");
+ EXPECT_EQ(r()->error(), R"(12:34 error: cannot take the address of 'override o')");
}
TEST_F(ResolverPtrRefValidationTest, AddressOfParameter) {
@@ -112,7 +112,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(12:34 error: cannot take the address of var 't' in handle address space)");
+ R"(12:34 error: cannot take the address of 'var t' in handle address space)");
}
TEST_F(ResolverPtrRefValidationTest, AddressOfFunction) {
@@ -255,7 +255,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(12:34 error: cannot take the address of var 't' in handle address space)");
+ R"(12:34 error: cannot take the address of 'var t' in handle address space)");
}
TEST_F(ResolverPtrRefValidationTest, DerefOfLiteral) {
diff --git a/src/tint/lang/wgsl/resolver/resolver.cc b/src/tint/lang/wgsl/resolver/resolver.cc
index 2bf95e9..0beaffe 100644
--- a/src/tint/lang/wgsl/resolver/resolver.cc
+++ b/src/tint/lang/wgsl/resolver/resolver.cc
@@ -278,7 +278,7 @@
}
if (TINT_UNLIKELY(!v->initializer)) {
- AddError("'let' declaration must have an initializer", v->source);
+ AddError(v->source) << "'let' declaration must have an initializer";
return nullptr;
}
@@ -299,7 +299,7 @@
if (!ApplyAddressSpaceUsageToType(core::AddressSpace::kUndefined,
const_cast<core::type::Type*>(sem->Type()), v->source)) {
- AddNote("while instantiating 'let' " + v->name->symbol.Name(), v->source);
+ AddNote(v->source) << "while instantiating 'let' " << v->name->symbol.Name();
return nullptr;
}
@@ -346,7 +346,7 @@
ty = init->Type();
}
} else if (!ty) {
- AddError("override declaration requires a type or initializer", v->source);
+ AddError(v->source) << "override declaration requires a type or initializer";
return nullptr;
}
sem->SetType(ty);
@@ -357,7 +357,7 @@
if (!ApplyAddressSpaceUsageToType(core::AddressSpace::kUndefined,
const_cast<core::type::Type*>(ty), v->source)) {
- AddNote("while instantiating 'override' " + v->name->symbol.Name(), v->source);
+ AddNote(v->source) << "while instantiating 'override' " << v->name->symbol.Name();
return nullptr;
}
@@ -374,21 +374,20 @@
return false;
}
if (!materialized->Type()->IsAnyOf<core::type::I32, core::type::U32>()) {
- AddError("@id must be an i32 or u32 value", attr->source);
+ AddError(attr->source) << "@id must be an i32 or u32 value";
return false;
}
auto const_value = materialized->ConstantValue();
auto value = const_value->ValueAs<AInt>();
if (value < 0) {
- AddError("@id value must be non-negative", attr->source);
+ AddError(attr->source) << "@id value must be non-negative";
return false;
}
if (value > std::numeric_limits<decltype(OverrideId::value)>::max()) {
- AddError(
- "@id value must be between 0 and " +
- std::to_string(std::numeric_limits<decltype(OverrideId::value)>::max()),
- attr->source);
+ AddError(attr->source)
+ << "@id value must be between 0 and "
+ << std::numeric_limits<decltype(OverrideId::value)>::max();
return false;
}
@@ -435,7 +434,7 @@
}
if (TINT_UNLIKELY(!c->initializer)) {
- AddError("'const' declaration must have an initializer", c->source);
+ AddError(c->source) << "'const' declaration must have an initializer";
return nullptr;
}
@@ -480,7 +479,7 @@
if (!ApplyAddressSpaceUsageToType(core::AddressSpace::kUndefined,
const_cast<core::type::Type*>(ty), c->source)) {
- AddNote("while instantiating 'const' " + c->name->symbol.Name(), c->source);
+ AddNote(c->source) << "while instantiating 'const' " << c->name->symbol.Name();
return nullptr;
}
@@ -542,7 +541,7 @@
}
if (!storage_ty) {
- AddError("var declaration requires a type or initializer", var->source);
+ AddError(var->source) << "var declaration requires a type or initializer";
return nullptr;
}
@@ -568,7 +567,8 @@
if (!is_global && sem->AddressSpace() != core::AddressSpace::kFunction &&
validator_.IsValidationEnabled(var->attributes,
ast::DisabledValidation::kIgnoreAddressSpace)) {
- AddError("function-scope 'var' declaration must use 'function' address space", var->source);
+ AddError(var->source)
+ << "function-scope 'var' declaration must use 'function' address space";
return nullptr;
}
@@ -592,7 +592,7 @@
if (!ApplyAddressSpaceUsageToType(sem->AddressSpace(),
const_cast<core::type::Type*>(sem->Type()),
var->type ? var->type->source : var->source)) {
- AddNote("while instantiating 'var' " + var->name->symbol.Name(), var->source);
+ AddNote(var->source) << "while instantiating 'var' " << var->name->symbol.Name();
return nullptr;
}
@@ -721,7 +721,7 @@
b.Sem().Add(param, sem);
auto add_note = [&] {
- AddNote("while instantiating parameter " + param->name->symbol.Name(), param->source);
+ AddNote(param->source) << "while instantiating parameter " << param->name->symbol.Name();
};
if (func->IsEntryPoint()) {
@@ -895,9 +895,8 @@
increment_next_id();
}
if (ids_exhausted) {
- AddError(
- "number of 'override' variables exceeded limit of " + std::to_string(kLimit),
- decl->source);
+ AddError(decl->source)
+ << "number of 'override' variables exceeded limit of " << kLimit;
return false;
}
id = next_id;
@@ -952,12 +951,12 @@
}
auto* cond = expr->ConstantValue();
if (auto* ty = cond->Type(); !ty->Is<core::type::Bool>()) {
- AddError("const assertion condition must be a bool, got '" + ty->FriendlyName() + "'",
- assertion->condition->source);
+ AddError(assertion->condition->source)
+ << "const assertion condition must be a bool, got '" << ty->FriendlyName() << "'";
return nullptr;
}
if (!cond->ValueAs<bool>()) {
- AddError("const assertion failed", assertion->source);
+ AddError(assertion->source) << "const assertion failed";
return nullptr;
}
auto* sem = b.create<sem::Statement>(assertion, current_compound_statement_, current_function_);
@@ -1017,8 +1016,8 @@
{ // Check the parameter name is unique for the function
if (auto added = parameter_names.Add(param->name->symbol, param->source); !added) {
auto name = param->name->symbol.Name();
- AddError("redefinition of parameter '" + name + "'", param->source);
- AddNote("previous definition is here", added.value);
+ AddError(param->source) << "redefinition of parameter '" << name << "'";
+ AddNote(added.value) << "previous definition is here";
return nullptr;
}
}
@@ -1140,8 +1139,8 @@
if (auto* str = return_type->As<core::type::Struct>()) {
if (!ApplyAddressSpaceUsageToType(core::AddressSpace::kUndefined, str, decl->source)) {
- AddNote("while instantiating return type for " + decl->name->symbol.Name(),
- decl->source);
+ AddNote(decl->source) << "while instantiating return type for "
+ << decl->name->symbol.Name();
return nullptr;
}
@@ -1169,9 +1168,8 @@
if (decl->body) {
Mark(decl->body);
if (TINT_UNLIKELY(current_compound_statement_)) {
- StringStream err;
- err << "Resolver::Function() called with a current compound statement";
- AddICE(err.str(), decl->body->source);
+ AddICE("Resolver::Function() called with a current compound statement",
+ decl->body->source);
return nullptr;
}
auto* body = StatementScope(decl->body, b.create<sem::FunctionBlockStatement>(func),
@@ -1265,11 +1263,12 @@
// Error cases
[&](const ast::CaseStatement*) {
- AddError("case statement can only be used inside a switch statement", stmt->source);
+ AddError(stmt->source) << "case statement can only be used inside a switch statement";
return nullptr;
},
[&](Default) {
- AddError("unknown statement type: " + std::string(stmt->TypeInfo().name), stmt->source);
+ AddError(stmt->source)
+ << "unknown statement type: " << std::string(stmt->TypeInfo().name);
return nullptr;
});
}
@@ -1294,12 +1293,12 @@
return false;
}
if (!materialized->Type()->IsAnyOf<core::type::I32, core::type::U32>()) {
- AddError("case selector must be an i32 or u32 value", sel->source);
+ AddError(sel->source) << "case selector must be an i32 or u32 value";
return false;
}
const_value = materialized->ConstantValue();
if (!const_value) {
- AddError("case selector must be a constant expression", sel->source);
+ AddError(sel->source) << "case selector must be a constant expression";
return false;
}
}
@@ -1491,9 +1490,8 @@
if (!ast::TraverseExpressions<ast::TraverseOrder::RightToLeft>(
root, [&](const ast::Expression* expr, size_t depth) {
if (depth > kMaxExpressionDepth) {
- AddError(
- "reached max expression depth of " + std::to_string(kMaxExpressionDepth),
- expr->source);
+ AddError(expr->source)
+ << "reached max expression depth of " << kMaxExpressionDepth;
failed = true;
return ast::TraverseAction::Stop;
}
@@ -1509,7 +1507,7 @@
sorted.Push(expr);
return ast::TraverseAction::Descend;
})) {
- AddError("TraverseExpressions failed", root->source);
+ AddError(root->source) << "TraverseExpressions failed";
return nullptr;
}
@@ -1569,7 +1567,7 @@
return ast::TraverseAction::Descend;
});
if (!r) {
- AddError("TraverseExpressions failed", root->source);
+ AddError(root->source) << "TraverseExpressions failed";
return nullptr;
}
}
@@ -1630,10 +1628,9 @@
if (TINT_UNLIKELY(
address_space_expr->Value() == core::AddressSpace::kPixelLocal &&
!enabled_extensions_.Contains(wgsl::Extension::kChromiumExperimentalPixelLocal))) {
- StringStream err;
- err << "'pixel_local' address space requires the '"
- << wgsl::Extension::kChromiumExperimentalPixelLocal << "' extension enabled";
- AddError(err.str(), expr->source);
+ AddError(expr->source) << "'pixel_local' address space requires the '"
+ << wgsl::Extension::kChromiumExperimentalPixelLocal
+ << "' extension enabled";
return nullptr;
}
return address_space_expr;
@@ -1702,18 +1699,18 @@
std::string access; // the access performed for the "other" expression
};
auto make_error = [&](const sem::ValueExpression* arg, Alias&& var) {
- AddError("invalid aliased pointer argument", arg->Declaration()->source);
+ AddError(arg->Declaration()->source) << "invalid aliased pointer argument";
switch (var.type) {
case Alias::Argument:
- AddNote("aliases with another argument passed here",
- var.expr->Declaration()->source);
+ AddNote(var.expr->Declaration()->source)
+ << "aliases with another argument passed here";
break;
case Alias::ModuleScope: {
auto* func = var.expr->Stmt()->Function();
auto func_name = func->Declaration()->name->symbol.Name();
- AddNote(
- "aliases with module-scope variable " + var.access + " in '" + func_name + "'",
- var.expr->Declaration()->source);
+ AddNote(var.expr->Declaration()->source)
+ << "aliases with module-scope variable " << var.access << " in '" << func_name
+ << "'";
break;
}
}
@@ -1987,10 +1984,9 @@
if (memory_view) {
if (memory_view->Is<core::type::Pointer>() &&
!allowed_features_.features.count(wgsl::LanguageFeature::kPointerCompositeAccess)) {
- AddError(
- "pointer composite access requires the pointer_composite_access language feature, "
- "which is not allowed in the current environment",
- expr->source);
+ AddError(expr->source)
+ << "pointer composite access requires the pointer_composite_access language "
+ "feature, which is not allowed in the current environment";
return nullptr;
}
storage_ty = memory_view->StoreType();
@@ -2004,7 +2000,7 @@
return b.create<core::type::Vector>(mat->type(), mat->rows());
},
[&](Default) {
- AddError("cannot index type '" + sem_.TypeNameOf(storage_ty) + "'", expr->source);
+ AddError(expr->source) << "cannot index type '" << sem_.TypeNameOf(storage_ty) << "'";
return nullptr;
});
if (ty == nullptr) {
@@ -2013,8 +2009,8 @@
auto* idx_ty = idx->Type()->UnwrapRef();
if (!idx_ty->IsAnyOf<core::type::I32, core::type::U32>()) {
- AddError("index must be of type 'i32' or 'u32', found: '" + sem_.TypeNameOf(idx_ty) + "'",
- idx->Declaration()->source);
+ AddError(idx->Declaration()->source)
+ << "index must be of type 'i32' or 'u32', found: '" << sem_.TypeNameOf(idx_ty) << "'";
return nullptr;
}
@@ -2084,7 +2080,7 @@
auto arg_tys = tint::Transform(args, [](auto* arg) { return arg->Type()->UnwrapRef(); });
auto match = intrinsic_table_.Lookup(ty, template_args, arg_tys, args_stage);
if (match != Success) {
- AddError(match.Failure(), expr->source);
+ AddError(expr->source) << match.Failure();
return nullptr;
}
@@ -2243,7 +2239,7 @@
return arr_or_str_init(str, call_target);
},
[&](Default) {
- AddError("type is not constructible", expr->source);
+ AddError(expr->source) << "type is not constructible";
return nullptr;
});
};
@@ -2283,14 +2279,14 @@
tint::Transform(args, [](auto* arg) { return arg->Type()->UnwrapRef(); });
auto el_ty = core::type::Type::Common(arg_tys);
if (TINT_UNLIKELY(!el_ty)) {
- AddError("cannot infer common array element type from constructor arguments",
- expr->source);
+ AddError(expr->source)
+ << "cannot infer common array element type from constructor arguments";
Hashset<const core::type::Type*, 8> types;
for (size_t i = 0; i < args.Length(); i++) {
if (types.Add(args[i]->Type())) {
- AddNote("argument " + std::to_string(i) + " is of type '" +
- sem_.TypeNameOf(args[i]->Type()) + "'",
- args[i]->Declaration()->source);
+ AddNote(args[i]->Declaration()->source)
+ << "argument " << i << " is of type '"
+ << sem_.TypeNameOf(args[i]->Type()) << "'";
}
}
return nullptr;
@@ -2367,7 +2363,7 @@
auto arg_tys = tint::Transform(args, [](auto* arg) { return arg->Type()->UnwrapRef(); });
auto overload = intrinsic_table_.Lookup(fn, tmpl_args, arg_tys, arg_stage);
if (overload != Success) {
- AddError(overload.Failure(), expr->source);
+ AddError(expr->source) << overload.Failure();
return nullptr;
}
@@ -2406,7 +2402,7 @@
}
if (target->IsDeprecated()) {
- AddWarning("use of deprecated builtin", expr->source);
+ AddWarning(expr->source) << "use of deprecated builtin";
}
// If the builtin is @const, and all arguments have constant values, evaluate the builtin
@@ -2903,7 +2899,7 @@
}
if (!ApplyAddressSpaceUsageToType(address_space, store_ty, tmpl_ident->arguments[1]->source)) {
- AddNote("while instantiating " + out->FriendlyName(), ident->source);
+ AddNote(ident->source) << "while instantiating " << out->FriendlyName();
return nullptr;
}
return out;
@@ -2990,8 +2986,8 @@
auto* tmpl_ident = ident->As<ast::TemplatedIdentifier>();
if (!tmpl_ident) {
if (TINT_UNLIKELY(min_args != 0)) {
- AddError("expected '<' for '" + ident->symbol.Name() + "'",
- Source{ident->source.range.end});
+ AddError(Source{ident->source.range.end})
+ << "expected '<' for '" << ident->symbol.Name() << "'";
}
return nullptr;
}
@@ -3006,22 +3002,19 @@
}
if (min_args == max_args) {
if (TINT_UNLIKELY(ident->arguments.Length() != min_args)) {
- AddError("'" + ident->symbol.Name() + "' requires " + std::to_string(min_args) +
- " template arguments",
- ident->source);
+ AddError(ident->source) << "'" << ident->symbol.Name() << "' requires " << min_args
+ << " template arguments";
return false;
}
} else {
if (TINT_UNLIKELY(ident->arguments.Length() < min_args)) {
- AddError("'" + ident->symbol.Name() + "' requires at least " +
- std::to_string(min_args) + " template arguments",
- ident->source);
+ AddError(ident->source) << "'" << ident->symbol.Name() << "' requires at least "
+ << min_args << " template arguments";
return false;
}
if (TINT_UNLIKELY(ident->arguments.Length() > max_args)) {
- AddError("'" + ident->symbol.Name() + "' requires at most " + std::to_string(max_args) +
- " template arguments",
- ident->source);
+ AddError(ident->source) << "'" << ident->symbol.Name() << "' requires at most "
+ << max_args << " template arguments";
return false;
}
}
@@ -3047,9 +3040,7 @@
const auto& signature = builtin->Signature();
int texture_index = signature.IndexOf(core::ParameterUsage::kTexture);
if (TINT_UNLIKELY(texture_index == -1)) {
- StringStream err;
- err << "texture builtin without texture parameter";
- AddICE(err.str(), {});
+ AddICE("texture builtin without texture parameter", {});
return;
}
if (auto* user =
@@ -3287,14 +3278,14 @@
auto symbol = ident->symbol;
if (auto decl = loop_block->Decls().Get(symbol)) {
if (decl->order >= loop_block->NumDeclsAtFirstContinue()) {
- AddError("continue statement bypasses declaration of '" +
- symbol.Name() + "'",
- loop_block->FirstContinue()->source);
- AddNote("identifier '" + symbol.Name() + "' declared here",
- decl->variable->Declaration()->source);
- AddNote("identifier '" + symbol.Name() +
- "' referenced in continuing block here",
- expr->source);
+ AddError(loop_block->FirstContinue()->source)
+ << "continue statement bypasses declaration of '"
+ << symbol.Name() << "'";
+ AddNote(decl->variable->Declaration()->source)
+ << "identifier '" << symbol.Name() << "' declared here";
+ AddNote(expr->source)
+ << "identifier '" << symbol.Name()
+ << "' referenced in continuing block here";
return nullptr;
}
}
@@ -3308,9 +3299,10 @@
}
if (!current_function_ && variable->Declaration()->Is<ast::Var>()) {
// Use of a module-scope 'var' outside of a function.
- std::string desc = "var '" + ident->symbol.Name() + "' ";
- AddError(desc + "cannot be referenced at module-scope", expr->source);
- AddNote(desc + "declared here", variable->Declaration()->source);
+ AddError(expr->source)
+ << style::Keyword << "var " << style::Variable << ident->symbol.Name()
+ << style::Plain << " cannot be referenced at module-scope";
+ sem_.NoteDeclarationSource(variable->Declaration());
return nullptr;
}
}
@@ -3420,10 +3412,9 @@
if (memory_view) {
if (memory_view->Is<core::type::Pointer>() &&
!allowed_features_.features.count(wgsl::LanguageFeature::kPointerCompositeAccess)) {
- AddError(
- "pointer composite access requires the pointer_composite_access language feature, "
- "which is not allowed in the current environment",
- expr->source);
+ AddError(expr->source)
+ << "pointer composite access requires the pointer_composite_access language "
+ "feature, which is not allowed in the current environment";
return nullptr;
}
storage_ty = memory_view->StoreType();
@@ -3452,7 +3443,7 @@
}
if (member == nullptr) {
- AddError("struct member " + symbol.Name() + " not found", expr->source);
+ AddError(expr->source) << "struct member " << symbol.Name() << " not found";
return nullptr;
}
@@ -3497,20 +3488,20 @@
swizzle.Push(3u);
break;
default:
- AddError(
- "invalid vector swizzle character",
- expr->member->source.Begin() + static_cast<uint32_t>(swizzle.Length()));
+ AddError(expr->member->source.Begin() +
+ static_cast<uint32_t>(swizzle.Length()))
+ << "invalid vector swizzle character";
return nullptr;
}
if (swizzle.Back() >= vec->Width()) {
- AddError("invalid vector swizzle member", expr->member->source);
+ AddError(expr->member->source) << "invalid vector swizzle member";
return nullptr;
}
}
if (size < 1 || size > 4) {
- AddError("invalid vector swizzle size", expr->member->source);
+ AddError(expr->member->source) << "invalid vector swizzle size";
return nullptr;
}
@@ -3519,8 +3510,8 @@
auto is_xyzw = [](char c) { return c == 'x' || c == 'y' || c == 'z' || c == 'w'; };
if (!std::all_of(s.begin(), s.end(), is_rgba) &&
!std::all_of(s.begin(), s.end(), is_xyzw)) {
- AddError("invalid mixing of vector swizzle characters rgba with xyzw",
- expr->member->source);
+ AddError(expr->member->source)
+ << "invalid mixing of vector swizzle characters rgba with xyzw";
return nullptr;
}
@@ -3554,8 +3545,8 @@
},
[&](Default) {
- AddError("cannot index into expression of type '" + sem_.TypeNameOf(storage_ty) + "'",
- expr->object->source);
+ AddError(expr->object->source)
+ << "cannot index into expression of type '" << sem_.TypeNameOf(storage_ty) << "'";
return nullptr;
});
}
@@ -3581,7 +3572,7 @@
auto overload = intrinsic_table_.Lookup(expr->op, lhs->Type()->UnwrapRef(),
rhs->Type()->UnwrapRef(), stage, false);
if (overload != Success) {
- AddError(overload.Failure(), expr->source);
+ AddError(expr->source) << overload.Failure();
return nullptr;
}
@@ -3663,9 +3654,9 @@
case core::UnaryOp::kAddressOf:
if (auto* ref = expr_ty->As<core::type::Reference>()) {
if (ref->StoreType()->UnwrapRef()->is_handle()) {
- AddError("cannot take the address of " + sem_.Describe(expr) +
- " in handle address space",
- unary->expr->source);
+ AddError(unary->expr->source)
+ << "cannot take the address of " << sem_.Describe(expr)
+ << " in handle address space";
return nullptr;
}
@@ -3674,7 +3665,8 @@
if ((array && sem_.TypeOf(array->object)->UnwrapRef()->Is<core::type::Vector>()) ||
(member &&
sem_.TypeOf(member->object)->UnwrapRef()->Is<core::type::Vector>())) {
- AddError("cannot take the address of a vector component", unary->expr->source);
+ AddError(unary->expr->source)
+ << "cannot take the address of a vector component";
return nullptr;
}
@@ -3683,7 +3675,8 @@
root_ident = expr->RootIdentifier();
} else {
- AddError("cannot take the address of " + sem_.Describe(expr), unary->expr->source);
+ AddError(unary->expr->source)
+ << "cannot take the address of " << sem_.Describe(expr);
return nullptr;
}
break;
@@ -3694,8 +3687,8 @@
ptr->Access());
root_ident = expr->RootIdentifier();
} else {
- AddError("cannot dereference expression of type '" + sem_.TypeNameOf(expr_ty) + "'",
- unary->expr->source);
+ AddError(unary->expr->source)
+ << "cannot dereference expression of type '" << sem_.TypeNameOf(expr_ty) << "'";
return nullptr;
}
break;
@@ -3704,7 +3697,7 @@
stage = expr->Stage();
auto overload = intrinsic_table_.Lookup(unary->op, expr_ty->UnwrapRef(), stage);
if (overload != Success) {
- AddError(overload.Failure(), unary->source);
+ AddError(unary->source) << overload.Failure();
return nullptr;
}
ty = overload->return_type;
@@ -3755,14 +3748,14 @@
}
if (!materialized->Type()->IsAnyOf<core::type::I32, core::type::U32>()) {
- AddError("@location must be an i32 or u32 value", attr->source);
+ AddError(attr->source) << "@location must be an i32 or u32 value";
return Failure{};
}
auto const_value = materialized->ConstantValue();
auto value = const_value->ValueAs<AInt>();
if (value < 0) {
- AddError("@location value must be non-negative", attr->source);
+ AddError(attr->source) << "@location value must be non-negative";
return Failure{};
}
@@ -3779,14 +3772,14 @@
}
if (!materialized->Type()->IsAnyOf<core::type::I32, core::type::U32>()) {
- AddError("@color must be an i32 or u32 value", attr->source);
+ AddError(attr->source) << "@color must be an i32 or u32 value";
return Failure{};
}
auto const_value = materialized->ConstantValue();
auto value = const_value->ValueAs<AInt>();
if (value < 0) {
- AddError("@color value must be non-negative", attr->source);
+ AddError(attr->source) << "@color value must be non-negative";
return Failure{};
}
@@ -3802,14 +3795,14 @@
}
if (!materialized->Type()->IsAnyOf<core::type::I32, core::type::U32>()) {
- AddError("@location must be an i32 or u32 value", attr->source);
+ AddError(attr->source) << "@location must be an i32 or u32 value";
return Failure{};
}
auto const_value = materialized->ConstantValue();
auto value = const_value->ValueAs<AInt>();
if (value != 0 && value != 1) {
- AddError("@blend_src value must be zero or one", attr->source);
+ AddError(attr->source) << "@blend_src value must be zero or one";
return Failure{};
}
@@ -3825,14 +3818,14 @@
return Failure{};
}
if (!materialized->Type()->IsAnyOf<core::type::I32, core::type::U32>()) {
- AddError("@binding must be an i32 or u32 value", attr->source);
+ AddError(attr->source) << "@binding must be an i32 or u32 value";
return Failure{};
}
auto const_value = materialized->ConstantValue();
auto value = const_value->ValueAs<AInt>();
if (value < 0) {
- AddError("@binding value must be non-negative", attr->source);
+ AddError(attr->source) << "@binding value must be non-negative";
return Failure{};
}
return static_cast<uint32_t>(value);
@@ -3847,14 +3840,14 @@
return Failure{};
}
if (!materialized->Type()->IsAnyOf<core::type::I32, core::type::U32>()) {
- AddError("@group must be an i32 or u32 value", attr->source);
+ AddError(attr->source) << "@group must be an i32 or u32 value";
return Failure{};
}
auto const_value = materialized->ConstantValue();
auto value = const_value->ValueAs<AInt>();
if (value < 0) {
- AddError("@group value must be non-negative", attr->source);
+ AddError(attr->source) << "@group value must be non-negative";
return Failure{};
}
return static_cast<uint32_t>(value);
@@ -3888,13 +3881,13 @@
}
auto* ty = expr->Type();
if (!ty->IsAnyOf<core::type::I32, core::type::U32, core::type::AbstractInt>()) {
- AddError(kErrBadExpr, value->source);
+ AddError(value->source) << kErrBadExpr;
return Failure{};
}
if (expr->Stage() != core::EvaluationStage::kConstant &&
expr->Stage() != core::EvaluationStage::kOverride) {
- AddError(kErrBadExpr, value->source);
+ AddError(value->source) << kErrBadExpr;
return Failure{};
}
@@ -3904,8 +3897,8 @@
auto* common_ty = core::type::Type::Common(arg_tys);
if (!common_ty) {
- AddError("workgroup_size arguments must be of the same type, either i32 or u32",
- attr->source);
+ AddError(attr->source)
+ << "workgroup_size arguments must be of the same type, either i32 or u32";
return Failure{};
}
@@ -3921,7 +3914,7 @@
}
if (auto* value = materialized->ConstantValue()) {
if (value->ValueAs<AInt>() < 1) {
- AddError("workgroup_size argument must be at least 1", values[i]->source);
+ AddError(values[i]->source) << "workgroup_size argument must be at least 1";
return Failure{};
}
ws[i] = value->ValueAs<u32>();
@@ -3934,7 +3927,7 @@
for (size_t i = 1; i < 3; i++) {
total_size *= static_cast<uint64_t>(ws[i].value_or(1));
if (total_size > 0xffffffff) {
- AddError("total workgroup grid size cannot exceed 0xffffffff", values[i]->source);
+ AddError(values[i]->source) << "total workgroup grid size cannot exceed 0xffffffff";
return Failure{};
}
}
@@ -4013,12 +4006,12 @@
if (rule != wgsl::ChromiumDiagnosticRule::kUndefined) {
validator_.DiagnosticFilters().Set(rule, control.severity);
} else {
- StringStream ss;
- ss << "unrecognized diagnostic rule 'chromium." << name << "'\n";
+ auto& warning = AddWarning(control.rule_name->source)
+ << "unrecognized diagnostic rule 'chromium." << name << "'\n";
tint::SuggestAlternativeOptions opts;
opts.prefix = "chromium.";
- tint::SuggestAlternatives(name, wgsl::kChromiumDiagnosticRuleStrings, ss, opts);
- AddWarning(ss.str(), control.rule_name->source);
+ tint::SuggestAlternatives(name, wgsl::kChromiumDiagnosticRuleStrings,
+ warning.message, opts);
}
}
return true;
@@ -4028,10 +4021,9 @@
if (rule != wgsl::CoreDiagnosticRule::kUndefined) {
validator_.DiagnosticFilters().Set(rule, control.severity);
} else {
- StringStream ss;
- ss << "unrecognized diagnostic rule '" << name << "'\n";
- tint::SuggestAlternatives(name, wgsl::kCoreDiagnosticRuleStrings, ss);
- AddWarning(ss.str(), control.rule_name->source);
+ auto& warning = AddWarning(control.rule_name->source)
+ << "unrecognized diagnostic rule '" << name << "'\n";
+ tint::SuggestAlternatives(name, wgsl::kCoreDiagnosticRuleStrings, warning.message);
}
return true;
}
@@ -4041,9 +4033,8 @@
Mark(ext);
enabled_extensions_.Add(ext->name);
if (!allowed_features_.extensions.count(ext->name)) {
- StringStream ss;
- ss << "extension '" << ext->name << "' is not allowed in the current environment";
- AddError(ss.str(), ext->source);
+ AddError(ext->source) << "extension '" << ext->name
+ << "' is not allowed in the current environment";
return false;
}
}
@@ -4053,10 +4044,8 @@
bool Resolver::Requires(const ast::Requires* req) {
for (auto feature : req->features) {
if (!allowed_features_.features.count(feature)) {
- StringStream ss;
- ss << "language feature '" << wgsl::ToString(feature)
- << "' is not allowed in the current environment";
- AddError(ss.str(), req->source);
+ AddError(req->source) << "language feature '" << wgsl::ToString(feature)
+ << "' is not allowed in the current environment";
return false;
}
}
@@ -4111,17 +4100,16 @@
case core::EvaluationStage::kConstant: {
auto* count_val = count_sem->ConstantValue();
if (auto* ty = count_val->Type(); !ty->is_integer_scalar()) {
- AddError(
- "array count must evaluate to a constant integer expression, but is type '" +
- ty->FriendlyName() + "'",
- count_expr->source);
+ AddError(count_expr->source)
+ << "array count must evaluate to a constant integer expression, but is type '"
+ << ty->FriendlyName() << "'";
return nullptr;
}
int64_t count = count_val->ValueAs<AInt>();
if (count < 1) {
- AddError("array count (" + std::to_string(count) + ") must be greater than 0",
- count_expr->source);
+ AddError(count_expr->source)
+ << "array count (" << count << ") must be greater than 0";
return nullptr;
}
@@ -4129,9 +4117,9 @@
}
default: {
- AddError(
- "array count must evaluate to a constant integer expression or override variable",
- count_expr->source);
+ AddError(count_expr->source)
+ << "array count must evaluate to a constant integer expression "
+ "or override variable";
return nullptr;
}
}
@@ -4188,10 +4176,8 @@
if (auto const_count = el_count->As<core::type::ConstantArrayCount>()) {
size = const_count->value * stride;
if (size > std::numeric_limits<uint32_t>::max()) {
- StringStream msg;
- msg << "array byte size (0x" << std::hex << size
- << ") must not exceed 0xffffffff bytes";
- AddError(msg.str(), count_source);
+ AddError(count_source) << "array byte size (0x" << std::hex << size
+ << ") must not exceed 0xffffffff bytes";
return nullptr;
}
} else if (el_count->Is<core::type::RuntimeArrayCount>()) {
@@ -4205,9 +4191,8 @@
// https://gpuweb.github.io/gpuweb/wgsl/#limits
const size_t nest_depth = 1 + NestDepth(el_ty);
if (nest_depth > kMaxNestDepthOfCompositeType) {
- AddError("array has nesting depth of " + std::to_string(nest_depth) + ", maximum is " +
- std::to_string(kMaxNestDepthOfCompositeType),
- array_source);
+ AddError(array_source) << "array has nesting depth of " << nest_depth << ", maximum is "
+ << kMaxNestDepthOfCompositeType;
return nullptr;
}
nest_depth_.Add(out, nest_depth);
@@ -4241,9 +4226,9 @@
// https://gpuweb.github.io/gpuweb/wgsl/#limits
const size_t kMaxNumStructMembers = 16383;
if (str->members.Length() > kMaxNumStructMembers) {
- AddError("struct '" + struct_name() + "' has " + std::to_string(str->members.Length()) +
- " members, maximum is " + std::to_string(kMaxNumStructMembers),
- str->source);
+ AddError(str->source) << "struct '" << struct_name() << "' has "
+ << str->members.Length() << " members, maximum is "
+ << kMaxNumStructMembers;
return nullptr;
}
}
@@ -4283,8 +4268,8 @@
Mark(member);
Mark(member->name);
if (auto added = member_map.Add(member->name->symbol, member); !added) {
- AddError("redefinition of '" + member->name->symbol.Name() + "'", member->source);
- AddNote("previous definition is here", added.value->source);
+ AddError(member->source) << "redefinition of '" << member->name->symbol.Name() << "'";
+ AddNote(added.value->source) << "previous definition is here";
return nullptr;
}
@@ -4298,8 +4283,8 @@
// validator_.Validate member type
if (!validator_.IsPlain(type)) {
- AddError(sem_.TypeNameOf(type) + " cannot be used as the type of a structure member",
- member->source);
+ AddError(member->source)
+ << sem_.TypeNameOf(type) << " cannot be used as the type of a structure member";
return nullptr;
}
@@ -4333,13 +4318,13 @@
}
auto const_value = materialized->ConstantValue();
if (!const_value) {
- AddError("@offset must be constant expression", attr->expr->source);
+ AddError(attr->expr->source) << "@offset must be constant expression";
return false;
}
offset = const_value->ValueAs<uint64_t>();
if (offset < struct_size) {
- AddError("offsets must be in ascending order", attr->source);
+ AddError(attr->source) << "offsets must be in ascending order";
return false;
}
has_offset_attr = true;
@@ -4354,20 +4339,20 @@
return false;
}
if (!materialized->Type()->IsAnyOf<core::type::I32, core::type::U32>()) {
- AddError("@align must be an i32 or u32 value", attr->source);
+ AddError(attr->source) << "@align must be an i32 or u32 value";
return false;
}
auto const_value = materialized->ConstantValue();
if (!const_value) {
- AddError("@align must be constant expression", attr->source);
+ AddError(attr->source) << "@align must be constant expression";
return false;
}
auto value = const_value->ValueAs<AInt>();
if (value <= 0 || !tint::IsPowerOfTwo(value)) {
- AddError("@align value must be a positive, power-of-two integer",
- attr->source);
+ AddError(attr->source)
+ << "@align value must be a positive, power-of-two integer";
return false;
}
align = u32(value);
@@ -4383,27 +4368,26 @@
return false;
}
if (!materialized->Type()->IsAnyOf<core::type::U32, core::type::I32>()) {
- AddError("@size must be an i32 or u32 value", attr->source);
+ AddError(attr->source) << "@size must be an i32 or u32 value";
return false;
}
auto const_value = materialized->ConstantValue();
if (!const_value) {
- AddError("@size must be constant expression", attr->expr->source);
+ AddError(attr->expr->source) << "@size must be constant expression";
return false;
}
{
auto value = const_value->ValueAs<AInt>();
if (value <= 0) {
- AddError("@size must be a positive integer", attr->source);
+ AddError(attr->source) << "@size must be a positive integer";
return false;
}
}
auto value = const_value->ValueAs<uint64_t>();
if (value < size) {
- AddError("@size must be at least as big as the type's size (" +
- std::to_string(size) + ")",
- attr->source);
+ AddError(attr->source)
+ << "@size must be at least as big as the type's size (" << size << ")";
return false;
}
size = u32(value);
@@ -4476,16 +4460,15 @@
}
if (has_offset_attr && (has_align_attr || has_size_attr)) {
- AddError("@offset cannot be used with @align or @size", member->source);
+ AddError(member->source) << "@offset cannot be used with @align or @size";
return nullptr;
}
offset = tint::RoundUp(align, offset);
if (offset > std::numeric_limits<uint32_t>::max()) {
- StringStream msg;
- msg << "struct member offset (0x" << std::hex << offset << ") must not exceed 0x"
+ AddError(member->source)
+ << "struct member offset (0x" << std::hex << offset << ") must not exceed 0x"
<< std::hex << std::numeric_limits<uint32_t>::max() << " bytes";
- AddError(msg.str(), member->source);
return nullptr;
}
@@ -4504,9 +4487,8 @@
struct_size = tint::RoundUp(struct_align, struct_size);
if (struct_size > std::numeric_limits<uint32_t>::max()) {
- StringStream msg;
- msg << "struct size (0x" << std::hex << struct_size << ") must not exceed 0xffffffff bytes";
- AddError(msg.str(), str->source);
+ AddError(str->source) << "struct size (0x" << std::hex << struct_size
+ << ") must not exceed 0xffffffff bytes";
return nullptr;
}
if (TINT_UNLIKELY(struct_align > std::numeric_limits<uint32_t>::max())) {
@@ -4543,10 +4525,8 @@
// https://gpuweb.github.io/gpuweb/wgsl/#limits
const size_t nest_depth = 1 + members_nest_depth;
if (nest_depth > kMaxNestDepthOfCompositeType) {
- AddError("struct '" + struct_name() + "' has nesting depth of " +
- std::to_string(nest_depth) + ", maximum is " +
- std::to_string(kMaxNestDepthOfCompositeType),
- str->source);
+ AddError(str->source) << "struct '" << struct_name() << "' has nesting depth of "
+ << nest_depth << ", maximum is " << kMaxNestDepthOfCompositeType;
return nullptr;
}
nest_depth_.Add(out, nest_depth);
@@ -4789,7 +4769,7 @@
auto overload = intrinsic_table_.Lookup(stmt->op, lhs->Type()->UnwrapRef(),
rhs->Type()->UnwrapRef(), stage, true);
if (overload != Success) {
- AddError(overload.Failure(), stmt->source);
+ AddError(stmt->source) << overload.Failure();
return false;
}
@@ -4861,10 +4841,9 @@
if (decl && !ApplyAddressSpaceUsageToType(address_space,
const_cast<core::type::Type*>(member->Type()),
decl->type->source)) {
- StringStream err;
- err << "while analyzing structure member " << sem_.TypeNameOf(str) << "."
+ AddNote(member->Declaration()->source)
+ << "while analyzing structure member " << sem_.TypeNameOf(str) << "."
<< member->Name().Name();
- AddNote(err.str(), member->Declaration()->source);
return false;
}
}
@@ -4874,16 +4853,15 @@
if (auto* arr = ty->As<sem::Array>()) {
if (address_space != core::AddressSpace::kStorage) {
if (arr->Count()->Is<core::type::RuntimeArrayCount>()) {
- AddError("runtime-sized arrays can only be used in the <storage> address space",
- usage);
+ AddError(usage)
+ << "runtime-sized arrays can only be used in the <storage> address space";
return false;
}
auto count = arr->ConstantCount();
if (count.has_value() && count.value() >= kMaxArrayElementCount) {
- AddError("array count (" + std::to_string(count.value()) + ") must be less than " +
- std::to_string(kMaxArrayElementCount),
- usage);
+ AddError(usage) << "array count (" << count.value() << ") must be less than "
+ << kMaxArrayElementCount;
return false;
}
}
@@ -4892,10 +4870,8 @@
}
if (core::IsHostShareable(address_space) && !validator_.IsHostShareable(ty)) {
- StringStream err;
- err << "Type '" << sem_.TypeNameOf(ty) << "' cannot be used in address space '"
- << address_space << "' as it is non-host-shareable";
- AddError(err.str(), usage);
+ AddError(usage) << "Type '" << sem_.TypeNameOf(ty) << "' cannot be used in address space '"
+ << address_space << "' as it is non-host-shareable";
return false;
}
@@ -4964,9 +4940,8 @@
TINT_SCOPED_ASSIGNMENT(current_scoping_depth_, current_scoping_depth_ + 1);
if (current_scoping_depth_ > kMaxStatementDepth) {
- AddError("statement nesting depth / chaining length exceeds limit of " +
- std::to_string(kMaxStatementDepth),
- ast->source);
+ AddError(ast->source) << "statement nesting depth / chaining length exceeds limit of "
+ << kMaxStatementDepth;
return nullptr;
}
@@ -5004,9 +4979,8 @@
bool Resolver::CheckNotTemplated(const char* use, const ast::Identifier* ident) {
if (TINT_UNLIKELY(ident->Is<ast::TemplatedIdentifier>())) {
- AddError(
- std::string(use) + " '" + ident->symbol.Name() + "' does not take template arguments",
- ident->source);
+ AddError(ident->source) << use << " '" << ident->symbol.Name()
+ << "' does not take template arguments";
if (auto resolved = dependencies_.resolved_identifiers.Get(ident)) {
if (auto* ast_node = resolved->Node()) {
sem_.NoteDeclarationSource(ast_node);
@@ -5018,10 +4992,10 @@
}
void Resolver::ErrorInvalidAttribute(const ast::Attribute* attr, std::string_view use) {
- AddError("@" + attr->Name() + " is not valid for " + std::string(use), attr->source);
+ AddError(attr->source) << "@" << attr->Name() << " is not valid for " << std::string(use);
}
-void Resolver::AddICE(const std::string& msg, const Source& source) const {
+void Resolver::AddICE(std::string_view msg, const Source& source) const {
if (source.file) {
TINT_ICE() << source << ": " << msg;
} else {
@@ -5031,20 +5005,19 @@
err.severity = diag::Severity::InternalCompilerError;
err.system = diag::System::Resolver;
err.source = source;
- err.message = msg;
- diagnostics_.Add(std::move(err));
+ diagnostics_.Add(std::move(err)) << msg;
}
-void Resolver::AddError(const std::string& msg, const Source& source) const {
- diagnostics_.AddError(diag::System::Resolver, msg, source);
+diag::Diagnostic& Resolver::AddError(const Source& source) const {
+ return diagnostics_.AddError(diag::System::Resolver, source);
}
-void Resolver::AddWarning(const std::string& msg, const Source& source) const {
- diagnostics_.AddWarning(diag::System::Resolver, msg, source);
+diag::Diagnostic& Resolver::AddWarning(const Source& source) const {
+ return diagnostics_.AddWarning(diag::System::Resolver, source);
}
-void Resolver::AddNote(const std::string& msg, const Source& source) const {
- diagnostics_.AddNote(diag::System::Resolver, msg, source);
+diag::Diagnostic& Resolver::AddNote(const Source& source) const {
+ return diagnostics_.AddNote(diag::System::Resolver, source);
}
} // namespace tint::resolver
diff --git a/src/tint/lang/wgsl/resolver/resolver.h b/src/tint/lang/wgsl/resolver/resolver.h
index 5cf2e60..73b27ef 100644
--- a/src/tint/lang/wgsl/resolver/resolver.h
+++ b/src/tint/lang/wgsl/resolver/resolver.h
@@ -51,6 +51,7 @@
#include "src/tint/lang/wgsl/sem/struct.h"
#include "src/tint/utils/containers/bitset.h"
#include "src/tint/utils/containers/unique_vector.h"
+#include "src/tint/utils/text/styled_text.h"
// Forward declarations
namespace tint::ast {
@@ -638,16 +639,16 @@
void ErrorInvalidAttribute(const ast::Attribute* attr, std::string_view use);
/// Adds the given internal compiler error message to the diagnostics
- void AddICE(const std::string& msg, const Source& source) const;
+ void AddICE(std::string_view msg, const Source& source) const;
- /// Adds the given error message to the diagnostics
- void AddError(const std::string& msg, const Source& source) const;
+ /// @returns a new error message added to the program's diagnostics
+ diag::Diagnostic& AddError(const Source& source) const;
- /// Adds the given warning message to the diagnostics
- void AddWarning(const std::string& msg, const Source& source) const;
+ /// @returns a new warning message added to the program's diagnostics
+ diag::Diagnostic& AddWarning(const Source& source) const;
- /// Adds the given note message to the diagnostics
- void AddNote(const std::string& msg, const Source& source) const;
+ /// @returns a new note message added to the program's diagnostics
+ diag::Diagnostic& AddNote(const Source& source) const;
/// @returns the core::type::Type for the builtin type @p builtin_ty with the identifier @p
/// ident
diff --git a/src/tint/lang/wgsl/resolver/resolver_test.cc b/src/tint/lang/wgsl/resolver/resolver_test.cc
index c2392dd..4f0af3b 100644
--- a/src/tint/lang/wgsl/resolver/resolver_test.cc
+++ b/src/tint/lang/wgsl/resolver/resolver_test.cc
@@ -1751,7 +1751,7 @@
WrapInFunction(expr);
ASSERT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching overload for operator "));
+ EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching overload for 'operator "));
}
INSTANTIATE_TEST_SUITE_P(ResolverTest,
Expr_Binary_Test_Invalid,
@@ -1795,7 +1795,7 @@
ASSERT_TRUE(TypeOf(expr) == result_type);
} else {
ASSERT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("no matching overload for operator *"));
+ EXPECT_THAT(r()->error(), HasSubstr("no matching overload for 'operator *"));
}
}
auto all_dimension_values = testing::Values(2u, 3u, 4u);
@@ -1833,7 +1833,7 @@
ASSERT_TRUE(TypeOf(expr) == result_type);
} else {
ASSERT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching overload for operator * "));
+ EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching overload for 'operator * "));
}
}
INSTANTIATE_TEST_SUITE_P(ResolverTest,
@@ -2117,7 +2117,7 @@
WrapInFunction(der);
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching overload for operator ! (vec4<f32>)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching overload for 'operator ! (vec4<f32>)"));
}
TEST_F(ResolverTest, UnaryOp_Complement) {
@@ -2127,7 +2127,7 @@
WrapInFunction(der);
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching overload for operator ~ (vec4<f32>)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching overload for 'operator ~ (vec4<f32>)"));
}
TEST_F(ResolverTest, UnaryOp_Negation) {
@@ -2137,7 +2137,7 @@
WrapInFunction(der);
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("error: no matching overload for operator - (u32)"));
+ EXPECT_THAT(r()->error(), HasSubstr("error: no matching overload for 'operator - (u32)"));
}
TEST_F(ResolverTest, TextureSampler_TextureSample) {
@@ -2419,7 +2419,7 @@
});
ASSERT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "error: cannot take the address of var 's' in handle address space");
+ EXPECT_EQ(r()->error(), "error: cannot take the address of 'var s' in handle address space");
}
TEST_F(ResolverTest, ModuleDependencyOrderedDeclarations) {
diff --git a/src/tint/lang/wgsl/resolver/sem_helper.cc b/src/tint/lang/wgsl/resolver/sem_helper.cc
index e364a91..25eeef5 100644
--- a/src/tint/lang/wgsl/resolver/sem_helper.cc
+++ b/src/tint/lang/wgsl/resolver/sem_helper.cc
@@ -35,6 +35,8 @@
#include "src/tint/lang/wgsl/sem/type_expression.h"
#include "src/tint/lang/wgsl/sem/value_expression.h"
#include "src/tint/utils/rtti/switch.h"
+#include "src/tint/utils/text/styled_text.h"
+#include "src/tint/utils/text/text_style.h"
namespace tint::resolver {
@@ -68,69 +70,71 @@
auto* type = ty_expr->Type();
if (auto* incomplete = type->As<IncompleteType>(); TINT_UNLIKELY(incomplete)) {
- AddError("expected '<' for '" + std::string(ToString(incomplete->builtin)) + "'",
- expr->Declaration()->source.End());
+ AddError(expr->Declaration()->source.End())
+ << "expected " << style::Code << "<" << style::Plain << " for " << style::Type
+ << incomplete->builtin << style::Plain;
return nullptr;
}
return ty_expr;
}
-std::string SemHelper::Describe(const sem::Expression* expr) const {
- return Switch(
+StyledText SemHelper::Describe(const sem::Expression* expr) const {
+ StyledText text;
+
+ Switch(
expr, //
[&](const sem::VariableUser* var_expr) {
auto* variable = var_expr->Variable()->Declaration();
auto name = variable->name->symbol.Name();
- auto* kind = Switch(
- variable, //
- [&](const ast::Var*) { return "var"; }, //
- [&](const ast::Let*) { return "let"; }, //
- [&](const ast::Const*) { return "const"; }, //
- [&](const ast::Parameter*) { return "parameter"; }, //
- [&](const ast::Override*) { return "override"; }, //
- [&](Default) { return "variable"; });
- return std::string(kind) + " '" + name + "'";
+ Switch(
+ variable, //
+ [&](const ast::Var*) { text << style::Keyword << "var"; }, //
+ [&](const ast::Let*) { text << style::Keyword << "let"; }, //
+ [&](const ast::Const*) { text << style::Keyword << "const"; }, //
+ [&](const ast::Parameter*) { text << "parameter"; }, //
+ [&](const ast::Override*) { text << style::Keyword << "override"; }, //
+ [&](Default) { text << "variable"; });
+ text << " " << style::Variable << name << style::Plain;
},
[&](const sem::ValueExpression* val_expr) {
- auto type = val_expr->Type()->FriendlyName();
- return "value of type '" + type + "'";
+ text << "value of type " << style::Type << val_expr->Type()->FriendlyName();
},
[&](const sem::TypeExpression* ty_expr) {
- auto name = ty_expr->Type()->FriendlyName();
- return "type '" + name + "'";
+ text << "type " << style::Type << ty_expr->Type()->FriendlyName();
},
[&](const sem::FunctionExpression* fn_expr) {
auto* fn = fn_expr->Function()->Declaration();
- auto name = fn->name->symbol.Name();
- return "function '" + name + "'";
+ text << "function " << style::Function << fn->name->symbol.Name();
},
[&](const sem::BuiltinEnumExpression<wgsl::BuiltinFn>* fn) {
- return "builtin function '" + tint::ToString(fn->Value()) + "'";
+ text << "builtin function " << style::Function << fn->Value();
},
[&](const sem::BuiltinEnumExpression<core::Access>* access) {
- return "access '" + tint::ToString(access->Value()) + "'";
+ text << "access " << style::Enum << access->Value();
},
[&](const sem::BuiltinEnumExpression<core::AddressSpace>* addr) {
- return "address space '" + tint::ToString(addr->Value()) + "'";
+ text << "address space " << style::Enum << addr->Value();
},
[&](const sem::BuiltinEnumExpression<core::BuiltinValue>* builtin) {
- return "builtin value '" + tint::ToString(builtin->Value()) + "'";
+ text << "builtin value " << style::Enum << builtin->Value();
},
[&](const sem::BuiltinEnumExpression<core::InterpolationSampling>* fmt) {
- return "interpolation sampling '" + tint::ToString(fmt->Value()) + "'";
+ text << "interpolation sampling " << style::Enum << fmt->Value();
},
[&](const sem::BuiltinEnumExpression<core::InterpolationType>* fmt) {
- return "interpolation type '" + tint::ToString(fmt->Value()) + "'";
+ text << "interpolation type " << style::Enum << fmt->Value();
},
[&](const sem::BuiltinEnumExpression<core::TexelFormat>* fmt) {
- return "texel format '" + tint::ToString(fmt->Value()) + "'";
+ text << "texel format " << style::Enum << fmt->Value();
},
[&](const UnresolvedIdentifier* ui) {
auto name = ui->Identifier()->identifier->symbol.Name();
- return "unresolved identifier '" + name + "'";
+ text << "unresolved identifier " << style::Code << name;
}, //
TINT_ICE_ON_NO_MATCH);
+
+ return text << style::Plain;
}
void SemHelper::ErrorUnexpectedExprKind(
@@ -140,7 +144,7 @@
if (auto* ui = expr->As<UnresolvedIdentifier>()) {
auto* ident = ui->Identifier();
auto name = ident->identifier->symbol.Name();
- AddError("unresolved " + std::string(wanted) + " '" + name + "'", ident->source);
+ AddError(ident->source) << "unresolved " << wanted << " " << style::Code << name;
if (!suggestions.IsEmpty()) {
// Filter out suggestions that have a leading underscore.
Vector<std::string_view, 8> filtered;
@@ -149,15 +153,13 @@
filtered.Push(str);
}
}
- StringStream msg;
- tint::SuggestAlternatives(name, filtered.Slice(), msg);
- AddNote(msg.str(), ident->source);
+ auto& note = AddNote(ident->source);
+ tint::SuggestAlternatives(name, filtered.Slice(), note.message);
}
return;
}
- AddError("cannot use " + Describe(expr) + " as " + std::string(wanted),
- expr->Declaration()->source);
+ AddError(expr->Declaration()->source) << "cannot use " << Describe(expr) << " as " << wanted;
NoteDeclarationSource(expr->Declaration());
}
@@ -166,7 +168,8 @@
if (auto* ident = expr->Declaration()->As<ast::IdentifierExpression>()) {
if (expr->IsAnyOf<sem::FunctionExpression, sem::TypeExpression,
sem::BuiltinEnumExpression<wgsl::BuiltinFn>>()) {
- AddNote("are you missing '()'?", ident->source.End());
+ AddNote(ident->source.End())
+ << "are you missing " << style::Code << "()" << style::Plain << "?";
}
}
}
@@ -188,40 +191,48 @@
Switch(
node,
[&](const ast::Struct* n) {
- AddNote("struct '" + n->name->symbol.Name() + "' declared here", n->source);
+ AddNote(n->source) << style::Keyword << "struct " << style::Type
+ << n->name->symbol.Name() << style::Plain << " declared here";
},
[&](const ast::Alias* n) {
- AddNote("alias '" + n->name->symbol.Name() + "' declared here", n->source);
+ AddNote(n->source) << style::Keyword << "alias " << style::Type
+ << n->name->symbol.Name() << style::Plain << " declared here";
},
[&](const ast::Var* n) {
- AddNote("var '" + n->name->symbol.Name() + "' declared here", n->source);
+ AddNote(n->source) << style::Keyword << "var " << style::Variable
+ << n->name->symbol.Name() << style::Plain << " declared here";
},
[&](const ast::Let* n) {
- AddNote("let '" + n->name->symbol.Name() + "' declared here", n->source);
+ AddNote(n->source) << style::Keyword << "let " << style::Variable
+ << n->name->symbol.Name() << style::Plain << " declared here";
},
[&](const ast::Override* n) {
- AddNote("override '" + n->name->symbol.Name() + "' declared here", n->source);
+ AddNote(n->source) << style::Keyword << "override " << style::Variable
+ << n->name->symbol.Name() << style::Plain << " declared here";
},
[&](const ast::Const* n) {
- AddNote("const '" + n->name->symbol.Name() + "' declared here", n->source);
+ AddNote(n->source) << style::Keyword << "const " << style::Variable
+ << n->name->symbol.Name() << style::Plain << " declared here";
},
[&](const ast::Parameter* n) {
- AddNote("parameter '" + n->name->symbol.Name() + "' declared here", n->source);
+ AddNote(n->source) << "parameter " << style::Variable << n->name->symbol.Name()
+ << style::Plain << " declared here";
},
[&](const ast::Function* n) {
- AddNote("function '" + n->name->symbol.Name() + "' declared here", n->source);
+ AddNote(n->source) << "function " << style::Function << n->name->symbol.Name()
+ << style::Plain << " declared here";
});
}
-void SemHelper::AddError(const std::string& msg, const Source& source) const {
- builder_->Diagnostics().AddError(diag::System::Resolver, msg, source);
+diag::Diagnostic& SemHelper::AddError(const Source& source) const {
+ return builder_->Diagnostics().AddError(diag::System::Resolver, source);
}
-void SemHelper::AddWarning(const std::string& msg, const Source& source) const {
- builder_->Diagnostics().AddWarning(diag::System::Resolver, msg, source);
+diag::Diagnostic& SemHelper::AddWarning(const Source& source) const {
+ return builder_->Diagnostics().AddWarning(diag::System::Resolver, source);
}
-void SemHelper::AddNote(const std::string& msg, const Source& source) const {
- builder_->Diagnostics().AddNote(diag::System::Resolver, msg, source);
+diag::Diagnostic& SemHelper::AddNote(const Source& source) const {
+ return builder_->Diagnostics().AddNote(diag::System::Resolver, source);
}
} // namespace tint::resolver
diff --git a/src/tint/lang/wgsl/resolver/sem_helper.h b/src/tint/lang/wgsl/resolver/sem_helper.h
index ad63ac2..fd7b700 100644
--- a/src/tint/lang/wgsl/resolver/sem_helper.h
+++ b/src/tint/lang/wgsl/resolver/sem_helper.h
@@ -40,6 +40,7 @@
#include "src/tint/lang/wgsl/sem/type_expression.h"
#include "src/tint/utils/containers/map.h"
#include "src/tint/utils/diagnostic/diagnostic.h"
+#include "src/tint/utils/text/styled_text.h"
namespace tint::resolver {
@@ -287,17 +288,17 @@
/// @param expr the expression to describe
/// @return a string that describes @p expr. Useful for diagnostics.
- std::string Describe(const sem::Expression* expr) const;
+ StyledText Describe(const sem::Expression* expr) const;
private:
- /// Adds the given error message to the diagnostics
- void AddError(const std::string& msg, const Source& source) const;
+ /// @returns a new error diagnostics
+ diag::Diagnostic& AddError(const Source& source) const;
- /// Adds the given warning message to the diagnostics
- void AddWarning(const std::string& msg, const Source& source) const;
+ /// @returns a new warning diagnostics
+ diag::Diagnostic& AddWarning(const Source& source) const;
- /// Adds the given note message to the diagnostics
- void AddNote(const std::string& msg, const Source& source) const;
+ /// @returns a new note diagnostics
+ diag::Diagnostic& AddNote(const Source& source) const;
ProgramBuilder* builder_;
};
diff --git a/src/tint/lang/wgsl/resolver/type_validation_test.cc b/src/tint/lang/wgsl/resolver/type_validation_test.cc
index 0264afc..f89f25c 100644
--- a/src/tint/lang/wgsl/resolver/type_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/type_validation_test.cc
@@ -493,9 +493,9 @@
GlobalVar("b", ty.array(ty.f32(), Add("size", 1_i)), core::AddressSpace::kWorkgroup);
WrapInFunction(Assign(Source{{12, 34}}, "a", "b"));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(),
- "12:34 error: cannot assign 'array<f32, [unnamed override-expression]>' to "
- "'array<f32, [unnamed override-expression]>'");
+ EXPECT_EQ(
+ r()->error(),
+ R"(12:34 error: cannot assign 'array<f32, [unnamed override-expression]>' to 'array<f32, [unnamed override-expression]>')");
}
TEST_F(ResolverTypeValidationTest, ArraySize_NamedOverride_Param) {
@@ -536,8 +536,8 @@
core::AddressSpace::kPrivate);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(12:34 error: var 'size' cannot be referenced at module-scope
-note: var 'size' declared here)");
+ R"(12:34 error: 'var size' cannot be referenced at module-scope
+note: 'var size' declared here)");
}
TEST_F(ResolverTypeValidationTest, ArraySize_FunctionConst) {
@@ -1511,7 +1511,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
R"(12:34 error: type 'A' does not take template arguments
-56:78 note: alias 'A' declared here)");
+56:78 note: 'alias A' declared here)");
}
INSTANTIATE_TEST_SUITE_P(BuiltinTypes,
@@ -1564,7 +1564,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
R"(12:34 error: type 'S' does not take template arguments
-56:78 note: struct 'S' declared here)");
+56:78 note: 'struct S' declared here)");
}
TEST_F(ResolverUntemplatedTypeUsedWithTemplateArgs, Struct_Ctor) {
@@ -1576,7 +1576,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), R"(12:34 error: type 'S' does not take template arguments
-note: struct 'S' declared here)");
+note: 'struct S' declared here)");
}
TEST_F(ResolverUntemplatedTypeUsedWithTemplateArgs, AliasedArray_Type) {
@@ -1589,7 +1589,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
R"(12:34 error: type 'A' does not take template arguments
-note: alias 'A' declared here)");
+note: 'alias A' declared here)");
}
TEST_F(ResolverUntemplatedTypeUsedWithTemplateArgs, AliasedArray_Ctor) {
@@ -1601,7 +1601,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), R"(12:34 error: type 'A' does not take template arguments
-note: alias 'A' declared here)");
+note: 'alias A' declared here)");
}
} // namespace TypeDoesNotTakeTemplateArgs
diff --git a/src/tint/lang/wgsl/resolver/uniformity.cc b/src/tint/lang/wgsl/resolver/uniformity.cc
index c86127a..818e5e1 100644
--- a/src/tint/lang/wgsl/resolver/uniformity.cc
+++ b/src/tint/lang/wgsl/resolver/uniformity.cc
@@ -1829,9 +1829,8 @@
auto* control_flow = TraceBackAlongPathUntil(
non_uniform_source, [](Node* node) { return node->affects_control_flow; });
if (control_flow) {
- diagnostics_.AddNote(diag::System::Resolver,
- "control flow depends on possibly non-uniform value",
- control_flow->ast->source);
+ diagnostics_.AddNote(diag::System::Resolver, control_flow->ast->source)
+ << "control flow depends on possibly non-uniform value";
// TODO(jrprice): There are cases where the function with uniformity requirements is not
// actually inside this control flow construct, for example:
// - A conditional interrupt (e.g. break), with a barrier elsewhere in the loop
@@ -1876,58 +1875,52 @@
non_uniform_source->ast,
[&](const ast::IdentifierExpression* ident) {
auto* var = sem_.GetVal(ident)->UnwrapLoad()->As<sem::VariableUser>()->Variable();
- StringStream ss;
if (auto* param = var->As<sem::Parameter>()) {
auto* func = param->Owner()->As<sem::Function>();
- ss << param_type(param) << "'" << NameFor(ident) << "' of '" << NameFor(func)
- << "' may be non-uniform";
+ diagnostics_.AddNote(diag::System::Resolver, ident->source)
+ << param_type(param) << "'" << NameFor(ident) << "' of '" << NameFor(func)
+ << "' may be non-uniform";
} else {
- ss << "reading from " << var_type(var) << "'" << NameFor(ident)
- << "' may result in a non-uniform value";
+ diagnostics_.AddNote(diag::System::Resolver, ident->source)
+ << "reading from " << var_type(var) << "'" << NameFor(ident)
+ << "' may result in a non-uniform value";
}
- diagnostics_.AddNote(diag::System::Resolver, ss.str(), ident->source);
},
[&](const ast::Variable* v) {
auto* var = sem_.Get(v);
- StringStream ss;
- ss << "reading from " << var_type(var) << "'" << NameFor(v)
- << "' may result in a non-uniform value";
- diagnostics_.AddNote(diag::System::Resolver, ss.str(), v->source);
+ diagnostics_.AddNote(diag::System::Resolver, v->source)
+ << "reading from " << var_type(var) << "'" << NameFor(v)
+ << "' may result in a non-uniform value";
},
[&](const ast::CallExpression* c) {
auto target_name = NameFor(c->target);
switch (non_uniform_source->type) {
case Node::kFunctionCallReturnValue: {
- diagnostics_.AddNote(
- diag::System::Resolver,
- "return value of '" + target_name + "' may be non-uniform", c->source);
+ diagnostics_.AddNote(diag::System::Resolver, c->source)
+ << "return value of '" + target_name + "' may be non-uniform";
break;
}
case Node::kFunctionCallArgumentContents: {
auto* arg = c->args[non_uniform_source->arg_index];
auto* var = sem_.GetVal(arg)->RootIdentifier();
- StringStream ss;
- ss << "reading from " << var_type(var) << "'" << NameFor(var)
- << "' may result in a non-uniform value";
- diagnostics_.AddNote(diag::System::Resolver, ss.str(),
- var->Declaration()->source);
+ diagnostics_.AddNote(diag::System::Resolver, var->Declaration()->source)
+ << "reading from " << var_type(var) << "'" << NameFor(var)
+ << "' may result in a non-uniform value";
break;
}
case Node::kFunctionCallArgumentValue: {
auto* arg = c->args[non_uniform_source->arg_index];
// TODO(jrprice): Which output? (return value vs another pointer argument).
- diagnostics_.AddNote(diag::System::Resolver,
- "passing non-uniform pointer to '" + target_name +
- "' may produce a non-uniform output",
- arg->source);
+ diagnostics_.AddNote(diag::System::Resolver, arg->source)
+ << "passing non-uniform pointer to '" << target_name
+ << "' may produce a non-uniform output";
break;
}
case Node::kFunctionCallPointerArgumentResult: {
- diagnostics_.AddNote(
- diag::System::Resolver,
- "contents of pointer may become non-uniform after calling '" +
- target_name + "'",
- c->args[non_uniform_source->arg_index]->source);
+ diagnostics_.AddNote(diag::System::Resolver,
+ c->args[non_uniform_source->arg_index]->source)
+ << "contents of pointer may become non-uniform after calling '"
+ << target_name << "'";
break;
}
default: {
@@ -1937,8 +1930,8 @@
}
},
[&](const ast::Expression* e) {
- diagnostics_.AddNote(diag::System::Resolver,
- "result of expression may be non-uniform", e->source);
+ diagnostics_.AddNote(diag::System::Resolver, e->source)
+ << "result of expression may be non-uniform";
}, //
TINT_ICE_ON_NO_MATCH);
}
diff --git a/src/tint/lang/wgsl/resolver/validator.cc b/src/tint/lang/wgsl/resolver/validator.cc
index 18f23cc..bf18b93 100644
--- a/src/tint/lang/wgsl/resolver/validator.cc
+++ b/src/tint/lang/wgsl/resolver/validator.cc
@@ -135,8 +135,8 @@
}
// Helper to stringify a pipeline IO attribute.
-std::string AttrToStr(const ast::Attribute* attr) {
- return "@" + attr->Name();
+StyledText AttrToStr(const ast::Attribute* attr) {
+ return StyledText{} << "@" << attr->Name();
}
template <typename CALLBACK>
@@ -180,34 +180,29 @@
Validator::~Validator() = default;
-void Validator::AddError(const std::string& msg, const Source& source) const {
- diagnostics_.AddError(diag::System::Resolver, msg, source);
+diag::Diagnostic& Validator::AddError(const Source& source) const {
+ return diagnostics_.AddError(diag::System::Resolver, source);
}
-void Validator::AddWarning(const std::string& msg, const Source& source) const {
- diagnostics_.AddWarning(diag::System::Resolver, msg, source);
+diag::Diagnostic& Validator::AddWarning(const Source& source) const {
+ return diagnostics_.AddWarning(diag::System::Resolver, source);
}
-void Validator::AddNote(const std::string& msg, const Source& source) const {
- diagnostics_.AddNote(diag::System::Resolver, msg, source);
+diag::Diagnostic& Validator::AddNote(const Source& source) const {
+ return diagnostics_.AddNote(diag::System::Resolver, source);
}
-bool Validator::AddDiagnostic(wgsl::DiagnosticRule rule,
- const std::string& msg,
- const Source& source) const {
+diag::Diagnostic* Validator::MaybeAddDiagnostic(wgsl::DiagnosticRule rule,
+ const Source& source) const {
auto severity = diagnostic_filters_.Get(rule);
if (severity != wgsl::DiagnosticSeverity::kOff) {
diag::Diagnostic d{};
d.severity = ToSeverity(severity);
d.system = diag::System::Resolver;
d.source = source;
- d.message = msg;
- diagnostics_.Add(std::move(d));
- if (severity == wgsl::DiagnosticSeverity::kError) {
- return false;
- }
+ return &diagnostics_.Add(std::move(d));
}
- return true;
+ return nullptr;
}
// https://gpuweb.github.io/gpuweb/wgsl/#plain-types-section
@@ -316,11 +311,10 @@
for (auto pair : incompatible) {
if (enabled_extensions_.Contains(pair.first) && enabled_extensions_.Contains(pair.second)) {
- std::string a{ToString(pair.first)};
- std::string b{ToString(pair.second)};
- AddError("extension '" + a + "' cannot be used with extension '" + b + "'",
- source_of(pair.first));
- AddNote("'" + b + "' enabled here", source_of(pair.second));
+ AddError(source_of(pair.first))
+ << "extension '" << pair.first << "' cannot be used with extension '" << pair.second
+ << "'";
+ AddNote(source_of(pair.second)) << "'" << pair.second << "' enabled here";
return false;
}
}
@@ -332,7 +326,7 @@
// https://gpuweb.github.io/gpuweb/wgsl/#atomic-types
// T must be either u32 or i32.
if (!s->Type()->IsAnyOf<core::type::U32, core::type::I32>()) {
- AddError("atomic only supports i32 or u32 types", a->arguments[0]->source);
+ AddError(a->arguments[0]->source) << "atomic only supports i32 or u32 types";
return false;
}
return true;
@@ -340,7 +334,7 @@
bool Validator::Pointer(const ast::TemplatedIdentifier* a, const core::type::Pointer* s) const {
if (s->AddressSpace() == core::AddressSpace::kUndefined) {
- AddError("ptr missing address space", a->source);
+ AddError(a->source) << "ptr missing address space";
return false;
}
@@ -350,15 +344,15 @@
// * For the storage address space, the access mode is optional, and defaults to read.
// * For other address spaces, the access mode must not be written.
if (s->AddressSpace() != core::AddressSpace::kStorage) {
- AddError("only pointers in <storage> address space may specify an access mode",
- a->source);
+ AddError(a->source)
+ << "only pointers in <storage> address space may specify an access mode";
return false;
}
}
if (auto* store_ty = s->StoreType(); !IsStorable(store_ty)) {
- AddError(sem_.TypeNameOf(store_ty) + " cannot be used as the store type of a pointer",
- a->arguments[1]->source);
+ AddError(a->arguments[1]->source)
+ << sem_.TypeNameOf(store_ty) + " cannot be used as the store type of a pointer";
return false;
}
@@ -371,42 +365,39 @@
case core::Access::kRead:
if (!allowed_features_.features.count(
wgsl::LanguageFeature::kReadonlyAndReadwriteStorageTextures)) {
- AddError(
+ AddError(source) <<
+
"read-only storage textures require the "
"readonly_and_readwrite_storage_textures language feature, which is not "
- "allowed in the current environment",
- source);
+ "allowed in the current environment";
return false;
}
break;
case core::Access::kReadWrite:
if (!allowed_features_.features.count(
wgsl::LanguageFeature::kReadonlyAndReadwriteStorageTextures)) {
- AddError(
- "read-write storage textures require the "
- "readonly_and_readwrite_storage_textures language feature, which is not "
- "allowed in the current environment",
- source);
+ AddError(source)
+ << "read-write storage textures require the "
+ "readonly_and_readwrite_storage_textures language feature, which is not "
+ "allowed in the current environment";
return false;
}
break;
case core::Access::kWrite:
break;
case core::Access::kUndefined:
- AddError("storage texture missing access control", source);
+ AddError(source) << "storage texture missing access control";
return false;
}
if (!IsValidStorageTextureDimension(t->dim())) {
- AddError("cube dimensions for storage textures are not supported", source);
+ AddError(source) << "cube dimensions for storage textures are not supported";
return false;
}
if (!IsValidStorageTextureTexelFormat(t->texel_format())) {
- AddError(
- "image format must be one of the texel formats specified for storage "
- "textues in https://gpuweb.github.io/gpuweb/wgsl/#texel-formats",
- source);
+ AddError(source) << "image format must be one of the texel formats specified for storage "
+ "textues in https://gpuweb.github.io/gpuweb/wgsl/#texel-formats";
return false;
}
return true;
@@ -414,7 +405,7 @@
bool Validator::SampledTexture(const core::type::SampledTexture* t, const Source& source) const {
if (!t->type()->UnwrapRef()->IsAnyOf<core::type::F32, core::type::I32, core::type::U32>()) {
- AddError("texture_2d<type>: type must be f32, i32 or u32", source);
+ AddError(source) << "texture_2d<type>: type must be f32, i32 or u32";
return false;
}
@@ -424,12 +415,12 @@
bool Validator::MultisampledTexture(const core::type::MultisampledTexture* t,
const Source& source) const {
if (t->dim() != core::type::TextureDimension::k2d) {
- AddError("only 2d multisampled textures are supported", source);
+ AddError(source) << "only 2d multisampled textures are supported";
return false;
}
if (!t->type()->UnwrapRef()->IsAnyOf<core::type::F32, core::type::I32, core::type::U32>()) {
- AddError("texture_multisampled_2d<type>: type must be f32, i32 or u32", source);
+ AddError(source) << "texture_multisampled_2d<type>: type must be f32, i32 or u32";
return false;
}
@@ -440,9 +431,8 @@
const core::type::Type* from,
const Source& source) const {
if (core::type::Type::ConversionRank(from, to) == core::type::Type::kNoConversion) {
- AddError("cannot convert value of type '" + sem_.TypeNameOf(from) + "' to type '" +
- sem_.TypeNameOf(to) + "'",
- source);
+ AddError(source) << "cannot convert value of type '" << sem_.TypeNameOf(from)
+ << "' to type '" << sem_.TypeNameOf(to) << "'";
return false;
}
return true;
@@ -456,10 +446,9 @@
// Value type has to match storage type
if (storage_ty != value_type) {
- StringStream s;
- s << "cannot initialize " << v->Kind() << " of type '" << sem_.TypeNameOf(storage_ty)
- << "' with value of type '" << sem_.TypeNameOf(initializer_ty) << "'";
- AddError(s.str(), v->source);
+ AddError(v->source) << "cannot initialize " << v->Kind() << " of type '"
+ << sem_.TypeNameOf(storage_ty) << "' with value of type '"
+ << sem_.TypeNameOf(initializer_ty) << "'";
return false;
}
@@ -501,16 +490,16 @@
}
auto note_usage = [&] {
- AddNote("'" + store_ty->FriendlyName() + "' used in address space '" +
- tint::ToString(address_space) + "' here",
- source);
+ AddNote(source) << "'" << store_ty->FriendlyName() << "' used in address space '"
+ << address_space << "' here";
};
// Among three host-shareable address spaces, f16 is supported in "uniform" and
// "storage" address space, but not "push_constant" address space yet.
if (Is<core::type::F16>(store_ty->DeepestElement()) &&
address_space == core::AddressSpace::kPushConstant) {
- AddError("using f16 types in 'push_constant' address space is not implemented yet", source);
+ AddError(source)
+ << "using f16 types in 'push_constant' address space is not implemented yet";
return false;
}
@@ -521,7 +510,7 @@
// Recurse into the member type.
if (!AddressSpaceLayout(m->Type(), address_space, m->Declaration()->type->source)) {
- AddNote("see layout of struct:\n" + str->Layout(), str->Declaration()->source);
+ AddNote(str->Declaration()->source) << "see layout of struct:\n" << str->Layout();
note_usage();
return false;
}
@@ -530,20 +519,19 @@
if (m->Offset() % required_align != 0 &&
!enabled_extensions_.Contains(
wgsl::Extension::kChromiumInternalRelaxedUniformLayout)) {
- AddError("the offset of a struct member of type '" +
- m->Type()->UnwrapRef()->FriendlyName() + "' in address space '" +
- tint::ToString(address_space) + "' must be a multiple of " +
- std::to_string(required_align) + " bytes, but '" + member_name_of(m) +
- "' is currently at offset " + std::to_string(m->Offset()) +
- ". Consider setting @align(" + std::to_string(required_align) +
- ") on this member",
- m->Declaration()->source);
+ AddError(m->Declaration()->source)
+ << "the offset of a struct member of type '"
+ << m->Type()->UnwrapRef()->FriendlyName() << "' in address space '"
+ << address_space << "' must be a multiple of " << required_align
+ << " bytes, but '" << member_name_of(m) << "' is currently at offset "
+ << m->Offset() << ". Consider setting @align(" << required_align
+ << ") on this member";
- AddNote("see layout of struct:\n" + str->Layout(), str->Declaration()->source);
+ AddNote(str->Declaration()->source) << "see layout of struct:\n" << str->Layout();
if (auto* member_str = m->Type()->As<sem::Struct>()) {
- AddNote("and layout of struct member:\n" + member_str->Layout(),
- member_str->Declaration()->source);
+ AddNote(member_str->Declaration()->source) << "and layout of struct member:\n"
+ << member_str->Layout();
}
note_usage();
@@ -558,20 +546,21 @@
if (prev_to_curr_offset % 16 != 0 &&
!enabled_extensions_.Contains(
wgsl::Extension::kChromiumInternalRelaxedUniformLayout)) {
- AddError(
- "uniform storage requires that the number of bytes between the start of "
- "the previous member of type struct and the current member be a multiple "
- "of 16 bytes, but there are currently " +
- std::to_string(prev_to_curr_offset) + " bytes between '" +
- member_name_of(prev_member) + "' and '" + member_name_of(m) +
- "'. Consider setting @align(16) on this member",
- m->Declaration()->source);
+ AddError(m->Declaration()->source)
+ << "uniform storage requires that the number of bytes between the start of "
+ "the previous member of type struct and the current member be a "
+ "multiple of 16 bytes, but there are currently "
+ << prev_to_curr_offset << " bytes between '" << member_name_of(prev_member)
+ << "' and '" << member_name_of(m)
+ << "'. Consider setting @align(16) on this member";
- AddNote("see layout of struct:\n" + str->Layout(), str->Declaration()->source);
+ AddNote(str->Declaration()->source) << "see layout of struct:\n"
+ << str->Layout();
auto* prev_member_str = prev_member->Type()->As<sem::Struct>();
- AddNote("and layout of previous member struct:\n" + prev_member_str->Layout(),
- prev_member_str->Declaration()->source);
+ AddNote(prev_member_str->Declaration()->source)
+ << "and layout of previous member struct:\n"
+ << prev_member_str->Layout();
note_usage();
return false;
}
@@ -596,7 +585,7 @@
if (arr->Stride() % 16 != 0) {
// Since WGSL has no stride attribute, try to provide a useful hint for how the
// shader author can resolve the issue.
- std::string hint;
+ std::string_view hint;
if (arr->ElemType()->Is<core::type::Scalar>()) {
hint = "Consider using a vector or struct as the element type instead.";
} else if (auto* vec = arr->ElemType()->As<core::type::Vector>();
@@ -609,12 +598,10 @@
"Consider wrapping the element type in a struct and using the @size "
"attribute.";
}
- AddError(
- "uniform storage requires that array elements are aligned to 16 bytes, but "
- "array element of type '" +
- arr->ElemType()->FriendlyName() + "' has a stride of " +
- std::to_string(arr->Stride()) + " bytes. " + hint,
- source);
+ AddError(source) << "uniform storage requires that array elements are aligned to "
+ "16 bytes, but array element of type '"
+ << arr->ElemType()->FriendlyName() << "' has a stride of "
+ << arr->Stride() << " bytes. " << hint;
return false;
}
}
@@ -636,8 +623,8 @@
if (IsValidationEnabled(var->attributes,
ast::DisabledValidation::kIgnoreAddressSpace)) {
if (!local->Type()->UnwrapRef()->IsConstructible()) {
- AddError("function-scope 'var' must have a constructible type",
- var->type ? var->type->source : var->source);
+ AddError(var->type ? var->type->source : var->source)
+ << "function-scope 'var' must have a constructible type";
return false;
}
}
@@ -663,16 +650,16 @@
[&](const ast::Var* var) {
if (auto* init = global->Initializer();
init && init->Stage() > core::EvaluationStage::kOverride) {
- AddError("module-scope 'var' initializer must be a constant or override-expression",
- init->Declaration()->source);
+ AddError(init->Declaration()->source)
+ << "module-scope 'var' initializer must be a constant or "
+ "override-expression";
return false;
}
if (!var->declared_address_space && !global->Type()->UnwrapRef()->is_handle()) {
- AddError(
- "module-scope 'var' declarations that are not of texture or sampler types must "
- "provide an address space",
- decl->source);
+ AddError(decl->source) << "module-scope 'var' declarations that are not of texture "
+ "or sampler types must "
+ "provide an address space";
return false;
}
@@ -687,7 +674,7 @@
}
if (global->AddressSpace() == core::AddressSpace::kFunction) {
- AddError("module-scope 'var' must not use address space 'function'", decl->source);
+ AddError(decl->source) << "module-scope 'var' must not use address space 'function'";
return false;
}
@@ -698,7 +685,8 @@
// https://gpuweb.github.io/gpuweb/wgsl/#resource-interface
// Each resource variable must be declared with both group and binding attributes.
if (!decl->HasBindingPoint()) {
- AddError("resource variables require @group and @binding attributes", decl->source);
+ AddError(decl->source)
+ << "resource variables require @group and @binding attributes";
return false;
}
break;
@@ -709,8 +697,8 @@
if (binding_attr || group_attr) {
// https://gpuweb.github.io/gpuweb/wgsl/#attribute-binding
// Must only be applied to a resource variable
- AddError("non-resource variables must not have @group or @binding attributes",
- decl->source);
+ AddError(decl->source)
+ << "non-resource variables must not have @group or @binding attributes";
return false;
}
}
@@ -724,7 +712,8 @@
auto* store_ty = v->Type()->UnwrapRef();
if (!IsStorable(store_ty)) {
- AddError(sem_.TypeNameOf(store_ty) + " cannot be used as the type of a var", var->source);
+ AddError(var->source) << sem_.TypeNameOf(store_ty)
+ << " cannot be used as the type of a var";
return false;
}
@@ -732,9 +721,8 @@
// https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables
// If the store type is a texture type or a sampler type, then the variable declaration must
// not have a address space attribute. The address space will always be handle.
- AddError("variables of type '" + sem_.TypeNameOf(store_ty) +
- "' must not specifiy an address space",
- var->source);
+ AddError(var->source) << "variables of type '" << sem_.TypeNameOf(store_ty)
+ << "' must not specifiy an address space";
return false;
}
@@ -744,8 +732,8 @@
// * For the storage address space, the access mode is optional, and defaults to read.
// * For other address spaces, the access mode must not be written.
if (v->AddressSpace() != core::AddressSpace::kStorage) {
- AddError("only variables in <storage> address space may specify an access mode",
- var->source);
+ AddError(var->source)
+ << "only variables in <storage> address space may specify an access mode";
return false;
}
}
@@ -759,10 +747,10 @@
// https://gpuweb.github.io/gpuweb/wgsl/#var-and-let
// Optionally has an initializer expression, if the variable is in the private or
// function address spaces.
- AddError("var of address space '" + tint::ToString(v->AddressSpace()) +
- "' cannot have an initializer. var initializers are only supported "
- "for the address spaces 'private' and 'function'",
- var->source);
+ AddError(var->source)
+ << "var of address space '" << v->AddressSpace()
+ << "' cannot have an initializer. var initializers are only supported for "
+ "the address spaces 'private' and 'function'";
return false;
}
}
@@ -775,7 +763,7 @@
if (IsValidationEnabled(var->attributes, ast::DisabledValidation::kIgnoreAddressSpace) &&
(v->AddressSpace() == core::AddressSpace::kIn ||
v->AddressSpace() == core::AddressSpace::kOut)) {
- AddError("invalid use of input/output address space", var->source);
+ AddError(var->source) << "invalid use of input/output address space";
return false;
}
return true;
@@ -786,8 +774,8 @@
auto* storage_ty = v->Type()->UnwrapRef();
if (!(storage_ty->IsConstructible() || storage_ty->Is<core::type::Pointer>())) {
- AddError(sem_.TypeNameOf(storage_ty) + " cannot be used as the type of a 'let'",
- decl->source);
+ AddError(decl->source) << sem_.TypeNameOf(storage_ty)
+ << " cannot be used as the type of a 'let'";
return false;
}
return true;
@@ -799,25 +787,24 @@
auto* storage_ty = v->Type()->UnwrapRef();
if (auto* init = v->Initializer(); init && init->Stage() > core::EvaluationStage::kOverride) {
- AddError("'override' initializer must be an override-expression",
- init->Declaration()->source);
+ AddError(init->Declaration()->source)
+ << "'override' initializer must be an override-expression";
return false;
}
if (auto id = v->Attributes().override_id) {
if (auto var = override_ids.Get(*id); var && *var != v) {
auto* attr = ast::GetAttribute<ast::IdAttribute>(v->Declaration()->attributes);
- AddError("@id values must be unique", attr->source);
- AddNote("a override with an ID of " + std::to_string(id->value) +
- " was previously declared here:",
- ast::GetAttribute<ast::IdAttribute>((*var)->Declaration()->attributes)->source);
+ AddError(attr->source) << "@id values must be unique";
+ AddNote(ast::GetAttribute<ast::IdAttribute>((*var)->Declaration()->attributes)->source)
+ << "a override with an ID of " << id->value << " was previously declared here:";
return false;
}
}
if (!storage_ty->Is<core::type::Scalar>()) {
- AddError(sem_.TypeNameOf(storage_ty) + " cannot be used as the type of a 'override'",
- decl->source);
+ AddError(decl->source) << sem_.TypeNameOf(storage_ty)
+ << " cannot be used as the type of a 'override'";
return false;
}
@@ -855,10 +842,8 @@
break;
}
if (!ok) {
- StringStream ss;
- ss << "function parameter of pointer type cannot be in '" << sc
- << "' address space";
- AddError(ss.str(), decl->source);
+ AddError(decl->source) << "function parameter of pointer type cannot be in '" << sc
+ << "' address space";
return false;
}
}
@@ -866,13 +851,13 @@
if (IsPlain(var->Type())) {
if (!var->Type()->IsConstructible()) {
- AddError("type of function parameter must be constructible", decl->type->source);
+ AddError(decl->type->source) << "type of function parameter must be constructible";
return false;
}
} else if (!var->Type()
->IsAnyOf<core::type::Texture, core::type::Sampler, core::type::Pointer>()) {
- AddError("type of function parameter cannot be " + sem_.TypeNameOf(var->Type()),
- decl->source);
+ AddError(decl->source) << "type of function parameter cannot be "
+ << sem_.TypeNameOf(var->Type());
return false;
}
@@ -898,9 +883,8 @@
}
auto* vec = type->As<core::type::Vector>();
if (!(vec && vec->Width() == 4 && vec->type()->Is<core::type::F32>())) {
- StringStream err;
- err << "store type of @builtin(" << builtin << ") must be 'vec4<f32>'";
- AddError(err.str(), attr->source);
+ AddError(attr->source)
+ << "store type of @builtin(" << builtin << ") must be 'vec4<f32>'";
return false;
}
break;
@@ -915,9 +899,8 @@
}
if (!(type->is_unsigned_integer_vector() &&
type->As<core::type::Vector>()->Width() == 3)) {
- StringStream err;
- err << "store type of @builtin(" << builtin << ") must be 'vec3<u32>'";
- AddError(err.str(), attr->source);
+ AddError(attr->source)
+ << "store type of @builtin(" << builtin << ") must be 'vec3<u32>'";
return false;
}
break;
@@ -927,9 +910,7 @@
is_stage_mismatch = true;
}
if (!type->Is<core::type::F32>()) {
- StringStream err;
- err << "store type of @builtin(" << builtin << ") must be 'f32'";
- AddError(err.str(), attr->source);
+ AddError(attr->source) << "store type of @builtin(" << builtin << ") must be 'f32'";
return false;
}
break;
@@ -939,9 +920,8 @@
is_stage_mismatch = true;
}
if (!type->Is<core::type::Bool>()) {
- StringStream err;
- err << "store type of @builtin(" << builtin << ") must be 'bool'";
- AddError(err.str(), attr->source);
+ AddError(attr->source)
+ << "store type of @builtin(" << builtin << ") must be 'bool'";
return false;
}
break;
@@ -951,9 +931,7 @@
is_stage_mismatch = true;
}
if (!type->Is<core::type::U32>()) {
- StringStream err;
- err << "store type of @builtin(" << builtin << ") must be 'u32'";
- AddError(err.str(), attr->source);
+ AddError(attr->source) << "store type of @builtin(" << builtin << ") must be 'u32'";
return false;
}
break;
@@ -964,9 +942,7 @@
is_stage_mismatch = true;
}
if (!type->Is<core::type::U32>()) {
- StringStream err;
- err << "store type of @builtin(" << builtin << ") must be 'u32'";
- AddError(err.str(), attr->source);
+ AddError(attr->source) << "store type of @builtin(" << builtin << ") must be 'u32'";
return false;
}
break;
@@ -975,9 +951,7 @@
is_stage_mismatch = true;
}
if (!type->Is<core::type::U32>()) {
- StringStream err;
- err << "store type of @builtin(" << builtin << ") must be 'u32'";
- AddError(err.str(), attr->source);
+ AddError(attr->source) << "store type of @builtin(" << builtin << ") must be 'u32'";
return false;
}
break;
@@ -987,31 +961,25 @@
is_stage_mismatch = true;
}
if (!type->Is<core::type::U32>()) {
- StringStream err;
- err << "store type of @builtin(" << builtin << ") must be 'u32'";
- AddError(err.str(), attr->source);
+ AddError(attr->source) << "store type of @builtin(" << builtin << ") must be 'u32'";
return false;
}
break;
case core::BuiltinValue::kSubgroupInvocationId:
case core::BuiltinValue::kSubgroupSize:
if (!enabled_extensions_.Contains(wgsl::Extension::kChromiumExperimentalSubgroups)) {
- StringStream err;
- err << "use of @builtin(" << builtin
+ AddError(attr->source)
+ << "use of @builtin(" << builtin
<< ") attribute requires enabling extension 'chromium_experimental_subgroups'";
- AddError(err.str(), attr->source);
return false;
}
if (!type->Is<core::type::U32>()) {
- StringStream err;
- err << "store type of @builtin(" << builtin << ") must be 'u32'";
- AddError(err.str(), attr->source);
+ AddError(attr->source) << "store type of @builtin(" << builtin << ") must be 'u32'";
return false;
}
if (stage != ast::PipelineStage::kNone && stage != ast::PipelineStage::kCompute) {
- StringStream err;
- err << "@builtin(" << builtin << ") is only valid as a compute shader input";
- AddError(err.str(), attr->source);
+ AddError(attr->source)
+ << "@builtin(" << builtin << ") is only valid as a compute shader input";
return false;
}
break;
@@ -1020,10 +988,8 @@
}
if (is_stage_mismatch) {
- StringStream err;
- err << "@builtin(" << builtin << ") cannot be used for " << stage_name.str() << " shader "
- << (is_input ? "input" : "output");
- AddError(err.str(), attr->source);
+ AddError(attr->source) << "@builtin(" << builtin << ") cannot be used for "
+ << stage_name.str() << " shader " << (is_input ? "input" : "output");
return false;
}
@@ -1034,7 +1000,7 @@
const core::type::Type* storage_ty,
const ast::PipelineStage stage) const {
if (stage == ast::PipelineStage::kCompute) {
- AddError(AttrToStr(attr) + " cannot be used by compute shaders", attr->source);
+ AddError(attr->source) << AttrToStr(attr) << " cannot be used by compute shaders";
return false;
}
@@ -1046,13 +1012,13 @@
}
if (type->is_integer_scalar_or_vector() && i_type->Value() != core::InterpolationType::kFlat) {
- AddError("interpolation type must be 'flat' for integral user-defined IO types",
- attr->source);
+ AddError(attr->source)
+ << "interpolation type must be 'flat' for integral user-defined IO types";
return false;
}
if (attr->sampling && i_type->Value() == core::InterpolationType::kFlat) {
- AddError("flat interpolation attribute must not have a sampling parameter", attr->source);
+ AddError(attr->source) << "flat interpolation attribute must not have a sampling parameter";
return false;
}
@@ -1062,7 +1028,7 @@
bool Validator::InvariantAttribute(const ast::InvariantAttribute* attr,
const ast::PipelineStage stage) const {
if (stage == ast::PipelineStage::kCompute) {
- AddError(AttrToStr(attr) + " cannot be used by compute shaders", attr->source);
+ AddError(attr->source) << AttrToStr(attr) << " cannot be used by compute shaders";
return false;
}
return true;
@@ -1076,15 +1042,15 @@
attr, //
[&](const ast::WorkgroupAttribute*) {
if (decl->PipelineStage() != ast::PipelineStage::kCompute) {
- AddError("@workgroup_size is only valid for compute stages", attr->source);
+ AddError(attr->source) << "@workgroup_size is only valid for compute stages";
return false;
}
return true;
},
[&](const ast::MustUseAttribute*) {
if (func->ReturnType()->Is<core::type::Void>()) {
- AddError("@must_use can only be applied to functions that return a value",
- attr->source);
+ AddError(attr->source)
+ << "@must_use can only be applied to functions that return a value";
return false;
}
return true;
@@ -1096,16 +1062,15 @@
}
if (decl->params.Length() > kMaxFunctionParameters) {
- AddError("function declares " + std::to_string(decl->params.Length()) +
- " parameters, maximum is " + std::to_string(kMaxFunctionParameters),
- decl->source);
+ AddError(decl->source) << "function declares " << decl->params.Length()
+ << " parameters, maximum is " << kMaxFunctionParameters;
return false;
}
if (!func->ReturnType()->Is<core::type::Void>()) {
if (!func->ReturnType()->IsConstructible()) {
- AddError("function return type must be a constructible type",
- decl->return_type->source);
+ AddError(decl->return_type->source)
+ << "function return type must be a constructible type";
return false;
}
@@ -1115,7 +1080,7 @@
behaviors = sem_.Get(last)->Behaviors();
}
if (behaviors.Contains(sem::Behavior::kNext)) {
- AddError("missing return at end of function", decl->source);
+ AddError(decl->source) << "missing return at end of function";
return false;
}
} else if (TINT_UNLIKELY(IsValidationEnabled(
@@ -1183,18 +1148,17 @@
auto builtin = sem_.Get(builtin_attr)->Value();
if (pipeline_io_attribute) {
- AddError("multiple entry point IO attributes", attr->source);
- AddNote("previously consumed " + AttrToStr(pipeline_io_attribute),
- pipeline_io_attribute->source);
+ AddError(attr->source) << "multiple entry point IO attributes";
+ AddNote(pipeline_io_attribute->source)
+ << "previously consumed " << AttrToStr(pipeline_io_attribute);
return false;
}
pipeline_io_attribute = attr;
if (builtins.Contains(builtin)) {
- StringStream err;
- err << "@builtin(" << builtin << ") appears multiple times as pipeline "
+ AddError(decl->source)
+ << "@builtin(" << builtin << ") appears multiple times as pipeline "
<< (param_or_ret == ParamOrRetType::kParameter ? "input" : "output");
- AddError(err.str(), decl->source);
return false;
}
@@ -1209,9 +1173,9 @@
[&](const ast::LocationAttribute* loc_attr) {
location_attribute = loc_attr;
if (pipeline_io_attribute) {
- AddError("multiple entry point IO attributes", attr->source);
- AddNote("previously consumed " + AttrToStr(pipeline_io_attribute),
- pipeline_io_attribute->source);
+ AddError(attr->source) << "multiple entry point IO attributes";
+ AddNote(pipeline_io_attribute->source)
+ << "previously consumed " << AttrToStr(pipeline_io_attribute);
return false;
}
pipeline_io_attribute = attr;
@@ -1236,9 +1200,9 @@
[&](const ast::ColorAttribute* col_attr) {
color_attribute = col_attr;
if (pipeline_io_attribute) {
- AddError("multiple entry point IO attributes", attr->source);
- AddNote("previously consumed " + AttrToStr(pipeline_io_attribute),
- pipeline_io_attribute->source);
+ AddError(attr->source) << "multiple entry point IO attributes";
+ AddNote(pipeline_io_attribute->source)
+ << "previously consumed " << AttrToStr(pipeline_io_attribute);
return false;
}
pipeline_io_attribute = attr;
@@ -1269,17 +1233,16 @@
if (IsValidationEnabled(attrs, ast::DisabledValidation::kEntryPointParameter)) {
if (is_struct_member && ty->Is<core::type::Struct>()) {
- AddError("nested structures cannot be used for entry point IO", source);
+ AddError(source) << "nested structures cannot be used for entry point IO";
return false;
}
if (!ty->Is<core::type::Struct>() && !pipeline_io_attribute) {
- std::string err = "missing entry point IO attribute";
+ auto& err = AddError(source) << "missing entry point IO attribute";
if (!is_struct_member) {
- err += (param_or_ret == ParamOrRetType::kParameter ? " on parameter"
+ err << (param_or_ret == ParamOrRetType::kParameter ? " on parameter"
: " on return type");
}
- AddError(err, source);
return false;
}
@@ -1287,18 +1250,16 @@
if (ty->is_integer_scalar_or_vector() && !interpolate_attribute) {
if (decl->PipelineStage() == ast::PipelineStage::kVertex &&
param_or_ret == ParamOrRetType::kReturnType) {
- AddError(
- "integral user-defined vertex outputs must have a flat interpolation "
- "attribute",
- source);
+ AddError(source) << "integral user-defined vertex outputs must have a "
+ "flat interpolation "
+ "attribute";
return false;
}
if (decl->PipelineStage() == ast::PipelineStage::kFragment &&
param_or_ret == ParamOrRetType::kParameter) {
- AddError(
- "integral user-defined fragment inputs must have a flat interpolation "
- "attribute",
- source);
+ AddError(source) << "integral user-defined fragment inputs must have "
+ "a flat interpolation "
+ "attribute";
return false;
}
}
@@ -1309,8 +1270,8 @@
// should restrict targets with @blend_src to location 0 for easy translation
// in the backend writers.
if (location.value_or(1) != 0) {
- AddError("@blend_src can only be used with @location(0)",
- blend_src_attribute->source);
+ AddError(blend_src_attribute->source)
+ << "@blend_src can only be used with @location(0)";
return false;
}
}
@@ -1322,11 +1283,11 @@
}
if (first_blend_src && first_location_without_blend_src) {
- AddError(
- "use of @blend_src requires all the output @location attributes of the entry "
- "point to be paired with a @blend_src attribute",
- first_location_without_blend_src->source);
- AddNote("use of @blend_src here", first_blend_src->source);
+ AddError(first_location_without_blend_src->source)
+ << "use of @blend_src requires all the output @location "
+ "attributes of the entry "
+ "point to be paired with a @blend_src attribute";
+ AddNote(first_blend_src->source) << "use of @blend_src here";
return false;
}
@@ -1335,38 +1296,36 @@
first_nonzero_location = location_attribute;
}
if (first_nonzero_location && first_blend_src) {
- AddError("pipeline cannot use both a @blend_src and non-zero @location",
- first_blend_src->source);
- AddNote("non-zero @location declared here", first_nonzero_location->source);
+ AddError(first_blend_src->source)
+ << "pipeline cannot use both a @blend_src and non-zero @location";
+ AddNote(first_nonzero_location->source) << "non-zero @location declared here";
return false;
}
std::pair<uint32_t, uint32_t> location_and_blend_src(location.value(),
blend_src.value_or(0));
if (!locations_and_blend_srcs.Add(location_and_blend_src)) {
- StringStream err;
- err << "@location(" << location.value() << ") ";
+ auto& err = AddError(location_attribute->source)
+ << "@location(" << location.value() << ") ";
if (blend_src_attribute) {
err << "@blend_src(" << blend_src.value() << ") ";
}
err << "appears multiple times";
- AddError(err.str(), location_attribute->source);
return false;
}
}
if (color_attribute && !colors.Add(color.value())) {
- StringStream err;
- err << "@color(" << color.value() << ") appears multiple times";
- AddError(err.str(), color_attribute->source);
+ AddError(color_attribute->source)
+ << "@color(" << color.value() << ") appears multiple times";
return false;
}
if (interpolate_attribute) {
if (!pipeline_io_attribute ||
!pipeline_io_attribute->Is<ast::LocationAttribute>()) {
- AddError("@interpolate can only be used with @location",
- interpolate_attribute->source);
+ AddError(interpolate_attribute->source)
+ << "@interpolate can only be used with @location";
return false;
}
}
@@ -1380,8 +1339,8 @@
}
}
if (!has_position) {
- AddError("@invariant must be applied to a position builtin",
- invariant_attribute->source);
+ AddError(invariant_attribute->source)
+ << "@invariant must be applied to a position builtin";
return false;
}
}
@@ -1407,8 +1366,8 @@
member->Declaration()->source, param_or_ret,
/*is_struct_member*/ true, member->Attributes().location,
member->Attributes().blend_src, member->Attributes().color)) {
- AddNote("while analyzing entry point '" + decl->name->symbol.Name() + "'",
- decl->source);
+ AddNote(decl->source)
+ << "while analyzing entry point '" << decl->name->symbol.Name() << "'";
return false;
}
}
@@ -1459,16 +1418,16 @@
}
}
if (!found) {
- AddError("a vertex shader must include the 'position' builtin in its return type",
- decl->source);
+ AddError(decl->source)
+ << "a vertex shader must include the 'position' builtin in its return type";
return false;
}
}
if (decl->PipelineStage() == ast::PipelineStage::kCompute) {
if (!ast::HasAttribute<ast::WorkgroupAttribute>(decl->attributes)) {
- AddError("a compute shader must include 'workgroup_size' in its attributes",
- decl->source);
+ AddError(decl->source)
+ << "a compute shader must include 'workgroup_size' in its attributes";
return false;
}
}
@@ -1495,12 +1454,11 @@
// resource interface of a given shader must not have the same group and binding values,
// when considered as a pair of values.
auto func_name = decl->name->symbol.Name();
- AddError(
- "entry point '" + func_name +
- "' references multiple variables that use the same resource binding @group(" +
- std::to_string(bp->group) + "), @binding(" + std::to_string(bp->binding) + ")",
- var_decl->source);
- AddNote("first resource binding usage declared here", added.value->source);
+ AddError(var_decl->source) << "entry point '" << func_name
+ << "' references multiple variables that use the same "
+ "resource binding @group("
+ << bp->group << "), @binding(" << bp->binding << ")";
+ AddNote(added.value->source) << "first resource binding usage declared here";
return false;
}
}
@@ -1529,14 +1487,14 @@
return "<unknown>";
};
- AddError(std::string(constraint) + " requires " + stage_name(latest_stage) +
- ", but expression is " + stage_name(expr->Stage()),
- expr->Declaration()->source);
+ AddError(expr->Declaration()->source)
+ << constraint << " requires " << stage_name(latest_stage) << ", but expression is "
+ << stage_name(expr->Stage());
if (auto* stmt = expr->Stmt()) {
if (auto* decl = As<ast::VariableDeclStatement>(stmt->Declaration())) {
if (decl->variable->Is<ast::Const>()) {
- AddNote("consider changing 'const' to 'let'", decl->source);
+ AddNote(decl->source) << "consider changing 'const' to 'let'";
}
}
}
@@ -1548,9 +1506,12 @@
bool Validator::Statements(VectorRef<const ast::Statement*> stmts) const {
for (auto* stmt : stmts) {
if (!sem_.Get(stmt)->IsReachable()) {
- if (!AddDiagnostic(wgsl::ChromiumDiagnosticRule::kUnreachableCode,
- "code is unreachable", stmt->source)) {
- return false;
+ if (auto* d = MaybeAddDiagnostic(wgsl::ChromiumDiagnosticRule::kUnreachableCode,
+ stmt->source)) {
+ *d << "code is unreachable";
+ if (d->severity >= diag::Severity::Error) {
+ return false;
+ }
}
break;
}
@@ -1561,14 +1522,14 @@
bool Validator::BreakStatement(const sem::Statement* stmt,
sem::Statement* current_statement) const {
if (!stmt->FindFirstParent<sem::LoopBlockStatement, sem::CaseStatement>()) {
- AddError("break statement must be in a loop or switch case", stmt->Declaration()->source);
+ AddError(stmt->Declaration()->source) << "break statement must be in a loop or switch case";
return false;
}
if (ClosestContinuing(/*stop_at_loop*/ true, /* stop_at_switch */ true, current_statement) !=
nullptr) {
- AddError(
- "`break` must not be used to exit from a continuing block. Use `break-if` instead.",
- stmt->Declaration()->source);
+ AddError(stmt->Declaration()->source)
+ << "`break` must not be used to exit from a continuing block. Use "
+ "`break-if` instead.";
return false;
}
return true;
@@ -1578,16 +1539,16 @@
sem::Statement* current_statement) const {
if (auto* continuing = ClosestContinuing(/*stop_at_loop*/ true, /* stop_at_switch */ false,
current_statement)) {
- AddError("continuing blocks must not contain a continue statement",
- stmt->Declaration()->source);
+ AddError(stmt->Declaration()->source)
+ << "continuing blocks must not contain a continue statement";
if (continuing != stmt->Declaration() && continuing != stmt->Parent()->Declaration()) {
- AddNote("see continuing block here", continuing->source);
+ AddNote(continuing->source) << "see continuing block here";
}
return false;
}
if (!stmt->FindFirstParent<sem::LoopBlockStatement>()) {
- AddError("continue statement must be in a loop", stmt->Declaration()->source);
+ AddError(stmt->Declaration()->source) << "continue statement must be in a loop";
return false;
}
@@ -1608,23 +1569,23 @@
Switch(
call->Target(), //
[&](const sem::Function* fn) {
- AddError("ignoring return value of function '" +
- fn->Declaration()->name->symbol.Name() + "' annotated with @must_use",
- call->Declaration()->source);
+ AddError(call->Declaration()->source)
+ << "ignoring return value of function '"
+ << fn->Declaration()->name->symbol.Name() + "' annotated with @must_use";
sem_.NoteDeclarationSource(fn->Declaration());
},
[&](const sem::BuiltinFn* b) {
- AddError("ignoring return value of builtin '" + tint::ToString(b->Fn()) + "'",
- call->Declaration()->source);
+ AddError(call->Declaration()->source)
+ << "ignoring return value of builtin '" << b->Fn() << "'";
},
[&](const sem::ValueConversion*) {
- AddError("value conversion evaluated but not used", call->Declaration()->source);
+ AddError(call->Declaration()->source) << "value conversion evaluated but not used";
},
[&](const sem::ValueConstructor*) {
- AddError("value constructor evaluated but not used", call->Declaration()->source);
+ AddError(call->Declaration()->source) << "value constructor evaluated but not used";
},
[&](Default) {
- AddError("return value of call not used", call->Declaration()->source);
+ AddError(call->Declaration()->source) << "return value of call not used";
});
return false;
}
@@ -1634,7 +1595,7 @@
bool Validator::LoopStatement(const sem::LoopStatement* stmt) const {
if (stmt->Behaviors().Empty()) {
- AddError("loop does not exit", stmt->Declaration()->source.Begin());
+ AddError(stmt->Declaration()->source.Begin()) << "loop does not exit";
return false;
}
return true;
@@ -1642,14 +1603,14 @@
bool Validator::ForLoopStatement(const sem::ForLoopStatement* stmt) const {
if (stmt->Behaviors().Empty()) {
- AddError("for-loop does not exit", stmt->Declaration()->source.Begin());
+ AddError(stmt->Declaration()->source.Begin()) << "for-loop does not exit";
return false;
}
if (auto* cond = stmt->Condition()) {
auto* cond_ty = cond->Type()->UnwrapRef();
if (!cond_ty->Is<core::type::Bool>()) {
- AddError("for-loop condition must be bool, got " + sem_.TypeNameOf(cond_ty),
- stmt->Condition()->Declaration()->source);
+ AddError(stmt->Condition()->Declaration()->source)
+ << "for-loop condition must be bool, got " << sem_.TypeNameOf(cond_ty);
return false;
}
}
@@ -1658,14 +1619,14 @@
bool Validator::WhileStatement(const sem::WhileStatement* stmt) const {
if (stmt->Behaviors().Empty()) {
- AddError("while does not exit", stmt->Declaration()->source.Begin());
+ AddError(stmt->Declaration()->source.Begin()) << "while does not exit";
return false;
}
if (auto* cond = stmt->Condition()) {
auto* cond_ty = cond->Type()->UnwrapRef();
if (!cond_ty->Is<core::type::Bool>()) {
- AddError("while condition must be bool, got " + sem_.TypeNameOf(cond_ty),
- stmt->Condition()->Declaration()->source);
+ AddError(stmt->Condition()->Declaration()->source)
+ << "while condition must be bool, got " << sem_.TypeNameOf(cond_ty);
return false;
}
}
@@ -1676,8 +1637,8 @@
sem::Statement* current_statement) const {
auto* cond_ty = stmt->Condition()->Type()->UnwrapRef();
if (!cond_ty->Is<core::type::Bool>()) {
- AddError("break-if statement condition must be bool, got " + sem_.TypeNameOf(cond_ty),
- stmt->Condition()->Declaration()->source);
+ AddError(stmt->Condition()->Declaration()->source)
+ << "break-if statement condition must be bool, got " << sem_.TypeNameOf(cond_ty);
return false;
}
@@ -1687,24 +1648,24 @@
}
if (auto* continuing = s->As<sem::LoopContinuingBlockStatement>()) {
if (continuing->Declaration()->statements.Back() != stmt->Declaration()) {
- AddError("break-if must be the last statement in a continuing block",
- stmt->Declaration()->source);
- AddNote("see continuing block here", s->Declaration()->source);
+ AddError(stmt->Declaration()->source)
+ << "break-if must be the last statement in a continuing block";
+ AddNote(s->Declaration()->source) << "see continuing block here";
return false;
}
return true;
}
}
- AddError("break-if must be in a continuing block", stmt->Declaration()->source);
+ AddError(stmt->Declaration()->source) << "break-if must be in a continuing block";
return false;
}
bool Validator::IfStatement(const sem::IfStatement* stmt) const {
auto* cond_ty = stmt->Condition()->Type()->UnwrapRef();
if (!cond_ty->Is<core::type::Bool>()) {
- AddError("if statement condition must be bool, got " + sem_.TypeNameOf(cond_ty),
- stmt->Condition()->Declaration()->source);
+ AddError(stmt->Condition()->Declaration()->source)
+ << "if statement condition must be bool, got " << sem_.TypeNameOf(cond_ty);
return false;
}
return true;
@@ -1728,9 +1689,8 @@
// If the called function does not return a value, a function call statement should be
// used instead.
auto* builtin = call->Target()->As<sem::BuiltinFn>();
- auto name = tint::ToString(builtin->Fn());
- AddError("builtin function '" + name + "' does not return a value",
- call->Declaration()->source);
+ AddError(call->Declaration()->source)
+ << "builtin function '" << builtin->Fn() << "' does not return a value";
return false;
}
}
@@ -1753,35 +1713,32 @@
return true;
}
auto index = static_cast<size_t>(signed_index);
- std::string name{core::ToString(usage)};
auto* arg = call->Arguments()[index];
if (auto values = arg->ConstantValue()) {
if (auto* vector = values->Type()->As<core::type::Vector>()) {
for (size_t i = 0; i < vector->Width(); i++) {
auto value = values->Index(i)->ValueAs<AInt>();
if (value < min || value > max) {
- AddError("each component of the " + name + " argument must be at least " +
- std::to_string(min) + " and at most " + std::to_string(max) +
- ". " + name + " component " + std::to_string(i) + " is " +
- std::to_string(value),
- arg->Declaration()->source);
+ AddError(arg->Declaration()->source)
+ << "each component of the " << usage << " argument must be at least "
+ << min << " and at most " << max << ". " << usage << " component " << i
+ << " is " << value;
return false;
}
}
} else {
auto value = values->ValueAs<AInt>();
if (value < min || value > max) {
- AddError("the " + name + " argument must be at least " + std::to_string(min) +
- " and at most " + std::to_string(max) + ". " + name + " is " +
- std::to_string(value),
- arg->Declaration()->source);
+ AddError(arg->Declaration()->source)
+ << "the " << usage << " argument must be at least " << min
+ << " and at most " << max << ". " << usage << " is " << value;
return false;
}
}
return true;
}
- AddError("the " + name + " argument must be a const-expression",
- arg->Declaration()->source);
+ AddError(arg->Declaration()->source)
+ << "the " << usage << " argument must be a const-expression";
return false;
};
@@ -1802,9 +1759,9 @@
auto* ty = ptr->StoreType();
if (ty->Is<core::type::Atomic>() || atomic_composite_info_.Contains(ty)) {
- AddError(
- "workgroupUniformLoad must not be called with an argument that contains an atomic type",
- arg->Declaration()->source);
+ AddError(arg->Declaration()->source)
+ << "workgroupUniformLoad must not be called with an argument that "
+ "contains an atomic type";
return false;
}
@@ -1820,8 +1777,8 @@
TINT_ASSERT(call->Arguments().Length() == 2);
auto* laneArg = call->Arguments()[1];
if (!laneArg->ConstantValue()) {
- AddError("the sourceLaneIndex argument of subgroupBroadcast must be a const-expression",
- laneArg->Declaration()->source);
+ AddError(laneArg->Declaration()->source)
+ << "the sourceLaneIndex argument of subgroupBroadcast must be a const-expression";
return false;
}
@@ -1837,9 +1794,9 @@
const auto extension = builtin->RequiredExtension();
if (extension != wgsl::Extension::kUndefined) {
if (!enabled_extensions_.Contains(extension)) {
- AddError("cannot call built-in function '" + std::string(builtin->str()) +
- "' without extension " + tint::ToString(extension),
- call->Declaration()->source);
+ AddError(call->Declaration()->source)
+ << "cannot call built-in function '" << builtin->Fn() << "' without extension "
+ << extension;
return false;
}
}
@@ -1847,10 +1804,10 @@
const auto feature = builtin->RequiredLanguageFeature();
if (feature != wgsl::LanguageFeature::kUndefined) {
if (!allowed_features_.features.count(feature)) {
- AddError("built-in function '" + std::string(builtin->str()) + "' requires the " +
- std::string(wgsl::ToString(feature)) +
- " language feature, which is not allowed in the current environment",
- call->Declaration()->source);
+ AddError(call->Declaration()->source)
+ << "built-in function '" << builtin->Fn() << "' requires the "
+ << wgsl::ToString(feature)
+ << " language feature, which is not allowed in the current environment";
return false;
}
}
@@ -1861,7 +1818,7 @@
bool Validator::CheckF16Enabled(const Source& source) const {
// Validate if f16 type is allowed.
if (!enabled_extensions_.Contains(wgsl::Extension::kF16)) {
- AddError("f16 type used without 'f16' extension enabled", source);
+ AddError(source) << "f16 type used without 'f16' extension enabled";
return false;
}
return true;
@@ -1874,24 +1831,24 @@
auto name = sym.Name();
if (!current_statement) { // Function call at module-scope.
- AddError("functions cannot be called at module-scope", decl->source);
+ AddError(decl->source) << "functions cannot be called at module-scope";
return false;
}
if (target->Declaration()->IsEntryPoint()) {
// https://www.w3.org/TR/WGSL/#function-restriction
// An entry point must never be the target of a function call.
- AddError("entry point functions cannot be the target of a function call", decl->source);
+ AddError(decl->source) << "entry point functions cannot be the target of a function call";
return false;
}
if (decl->args.Length() != target->Parameters().Length()) {
bool more = decl->args.Length() > target->Parameters().Length();
- AddError("too " + (more ? std::string("many") : std::string("few")) +
- " arguments in call to '" + name + "', expected " +
- std::to_string(target->Parameters().Length()) + ", got " +
- std::to_string(call->Arguments().Length()),
- decl->source);
+ AddError(decl->source) << "too "
+ << (more ? std::string("many") : std::string("few")) +
+ " arguments in call to '"
+ << name << "', expected " << target->Parameters().Length()
+ << ", got " << call->Arguments().Length();
return false;
}
@@ -1902,10 +1859,10 @@
auto* arg_type = sem_.TypeOf(arg_expr)->UnwrapRef();
if (param_type != arg_type) {
- AddError("type mismatch for argument " + std::to_string(i + 1) + " in call to '" +
- name + "', expected '" + sem_.TypeNameOf(param_type) + "', got '" +
- sem_.TypeNameOf(arg_type) + "'",
- arg_expr->source);
+ AddError(arg_expr->source)
+ << "type mismatch for argument " << (i + 1) << " in call to '" << name
+ << "', expected '" << sem_.TypeNameOf(param_type) << "', got '"
+ << sem_.TypeNameOf(arg_type) << "'";
return false;
}
@@ -1931,10 +1888,8 @@
if (root_store_type != arg_store_type &&
IsValidationEnabled(param->Declaration()->attributes,
ast::DisabledValidation::kIgnoreInvalidPointerArgument)) {
- AddError(
- "arguments of pointer type must not point to a subset of the originating "
- "variable",
- arg_expr->source);
+ AddError(arg_expr->source) << "arguments of pointer type must not point to a "
+ "subset of the originating variable";
return false;
}
}
@@ -1951,7 +1906,7 @@
// https://gpuweb.github.io/gpuweb/wgsl/#function-call-expr
// If the called function does not return a value, a function call
// statement should be used instead.
- AddError("function '" + name + "' does not return a value", decl->source);
+ AddError(decl->source) << "function '" << name << "' does not return a value";
return false;
}
}
@@ -1962,28 +1917,26 @@
bool Validator::StructureInitializer(const ast::CallExpression* ctor,
const core::type::Struct* struct_type) const {
if (!struct_type->IsConstructible()) {
- AddError("structure constructor has non-constructible type", ctor->source);
+ AddError(ctor->source) << "structure constructor has non-constructible type";
return false;
}
if (ctor->args.Length() > 0) {
if (ctor->args.Length() != struct_type->Members().Length()) {
std::string fm = ctor->args.Length() < struct_type->Members().Length() ? "few" : "many";
- AddError("structure constructor has too " + fm + " inputs: expected " +
- std::to_string(struct_type->Members().Length()) + ", found " +
- std::to_string(ctor->args.Length()),
- ctor->source);
+ AddError(ctor->source)
+ << "structure constructor has too " << fm << " inputs: expected "
+ << struct_type->Members().Length() << ", found " << ctor->args.Length();
return false;
}
for (auto* member : struct_type->Members()) {
auto* value = ctor->args[member->Index()];
auto* value_ty = sem_.TypeOf(value);
if (member->Type() != value_ty->UnwrapRef()) {
- AddError(
- "type in structure constructor does not match struct member type: expected '" +
- sem_.TypeNameOf(member->Type()) + "', found '" + sem_.TypeNameOf(value_ty) +
- "'",
- value->source);
+ AddError(value->source)
+ << "type in structure constructor does not match struct member type: expected '"
+ << sem_.TypeNameOf(member->Type()) << "', found '" << sem_.TypeNameOf(value_ty)
+ << "'";
return false;
}
}
@@ -1999,27 +1952,26 @@
auto* value_ty = sem_.TypeOf(value)->UnwrapRef();
if (core::type::Type::ConversionRank(value_ty, elem_ty) ==
core::type::Type::kNoConversion) {
- AddError("'" + sem_.TypeNameOf(value_ty) +
- "' cannot be used to construct an array of '" + sem_.TypeNameOf(elem_ty) +
- "'",
- value->source);
+ AddError(value->source)
+ << "'" << sem_.TypeNameOf(value_ty) + "' cannot be used to construct an array of '"
+ << sem_.TypeNameOf(elem_ty) << "'";
return false;
}
}
auto* c = array_type->Count();
if (c->Is<core::type::RuntimeArrayCount>()) {
- AddError("cannot construct a runtime-sized array", ctor->source);
+ AddError(ctor->source) << "cannot construct a runtime-sized array";
return false;
}
if (c->IsAnyOf<sem::NamedOverrideArrayCount, sem::UnnamedOverrideArrayCount>()) {
- AddError("cannot construct an array that has an override-expression count", ctor->source);
+ AddError(ctor->source) << "cannot construct an array that has an override-expression count";
return false;
}
if (!elem_ty->IsConstructible()) {
- AddError("array constructor has non-constructible element type", ctor->source);
+ AddError(ctor->source) << "array constructor has non-constructible element type";
return false;
}
@@ -2031,9 +1983,8 @@
const auto count = c->As<core::type::ConstantArrayCount>()->value;
if (!values.IsEmpty() && (values.Length() != count)) {
std::string fm = values.Length() < count ? "few" : "many";
- AddError("array constructor has too " + fm + " elements: expected " +
- std::to_string(count) + ", found " + std::to_string(values.Length()),
- ctor->source);
+ AddError(ctor->source) << "array constructor has too " << fm << " elements: expected "
+ << count << ", found " << values.Length();
return false;
}
return true;
@@ -2041,7 +1992,7 @@
bool Validator::Vector(const core::type::Type* el_ty, const Source& source) const {
if (!el_ty->Is<core::type::Scalar>()) {
- AddError("vector element type must be 'bool', 'f32', 'f16', 'i32' or 'u32'", source);
+ AddError(source) << "vector element type must be 'bool', 'f32', 'f16', 'i32' or 'u32'";
return false;
}
return true;
@@ -2049,7 +2000,7 @@
bool Validator::Matrix(const core::type::Type* el_ty, const Source& source) const {
if (!el_ty->is_float_scalar()) {
- AddError("matrix element type must be 'f32' or 'f16'", source);
+ AddError(source) << "matrix element type must be 'f32' or 'f16'";
return false;
}
return true;
@@ -2059,12 +2010,12 @@
auto backtrace = [&](const sem::Function* func, const sem::Function* entry_point) {
if (func != entry_point) {
TraverseCallChain(entry_point, func, [&](const sem::Function* f) {
- AddNote("called by function '" + f->Declaration()->name->symbol.Name() + "'",
- f->Declaration()->source);
+ AddNote(f->Declaration()->source)
+ << "called by function '" << f->Declaration()->name->symbol.Name() << "'";
});
- AddNote(
- "called by entry point '" + entry_point->Declaration()->name->symbol.Name() + "'",
- entry_point->Declaration()->source);
+ AddNote(entry_point->Declaration()->source)
+ << "called by entry point '" << entry_point->Declaration()->name->symbol.Name()
+ << "'";
}
};
@@ -2077,11 +2028,9 @@
break;
}
}
- StringStream msg;
- msg << "var with '" << var->AddressSpace() << "' address space cannot be used by "
- << stage << " pipeline stage";
- AddError(msg.str(), source);
- AddNote("variable is declared here", var->Declaration()->source);
+ AddError(source) << "var with '" << var->AddressSpace()
+ << "' address space cannot be used by " << stage << " pipeline stage";
+ AddNote(var->Declaration()->source) << "variable is declared here";
backtrace(func, entry_point);
return false;
};
@@ -2105,10 +2054,8 @@
for (auto* builtin : func->DirectlyCalledBuiltins()) {
if (!builtin->SupportedStages().Contains(stage)) {
auto* call = func->FindDirectCallTo(builtin);
- StringStream err;
- err << "built-in cannot be used by " << stage << " pipeline stage";
- AddError(err.str(),
- call ? call->Declaration()->source : func->Declaration()->source);
+ AddError(call ? call->Declaration()->source : func->Declaration()->source)
+ << "built-in cannot be used by " << stage << " pipeline stage";
backtrace(func, entry_point);
return false;
}
@@ -2119,9 +2066,8 @@
auto check_no_discards = [&](const sem::Function* func, const sem::Function* entry_point) {
if (auto* discard = func->DiscardStatement()) {
auto stage = entry_point->Declaration()->PipelineStage();
- StringStream err;
- err << "discard statement cannot be used in " << stage << " pipeline stage";
- AddError(err.str(), discard->Declaration()->source);
+ AddError(discard->Declaration()->source)
+ << "discard statement cannot be used in " << stage << " pipeline stage";
backtrace(func, entry_point);
return false;
}
@@ -2176,13 +2122,13 @@
auto* el_ty = arr->ElemType();
if (!IsPlain(el_ty)) {
- AddError(sem_.TypeNameOf(el_ty) + " cannot be used as an element type of an array",
- el_source);
+ AddError(el_source) << sem_.TypeNameOf(el_ty)
+ << " cannot be used as an element type of an array";
return false;
}
if (!IsFixedFootprint(el_ty)) {
- AddError("an array element type cannot contain a runtime-sized array", el_source);
+ AddError(el_source) << "an array element type cannot contain a runtime-sized array";
return false;
}
@@ -2204,10 +2150,9 @@
// Arrays decorated with the stride attribute must have a stride that is
// at least the size of the element type, and be a multiple of the
// element type's alignment value.
- AddError(
- "arrays decorated with the stride attribute must have a stride that is at least the "
- "size of the element type, and be a multiple of the element type's alignment value",
- attr->source);
+ AddError(attr->source)
+ << "arrays decorated with the stride attribute must have a stride that is at least the "
+ "size of the element type, and be a multiple of the element type's alignment value";
return false;
}
return true;
@@ -2219,7 +2164,7 @@
bool Validator::Structure(const sem::Struct* str, ast::PipelineStage stage) const {
if (str->Members().IsEmpty()) {
- AddError("structures must have at least one member", str->Declaration()->source);
+ AddError(str->Declaration()->source) << "structures must have at least one member";
return false;
}
@@ -2229,8 +2174,8 @@
if (auto* r = member->Type()->As<sem::Array>()) {
if (r->Count()->Is<core::type::RuntimeArrayCount>()) {
if (member != str->Members().Back()) {
- AddError("runtime arrays may only appear as the last member of a struct",
- member->Declaration()->source);
+ AddError(member->Declaration()->source)
+ << "runtime arrays may only appear as the last member of a struct";
return false;
}
}
@@ -2240,9 +2185,8 @@
return false;
}
} else if (!IsFixedFootprint(member->Type())) {
- AddError(
- "a struct that contains a runtime array cannot be nested inside another struct",
- member->Declaration()->source);
+ AddError(member->Declaration()->source)
+ << "a struct that contains a runtime array cannot be nested inside another struct";
return false;
}
@@ -2291,10 +2235,9 @@
},
[&](const ast::StructMemberSizeAttribute*) {
if (!member->Type()->HasCreationFixedFootprint()) {
- AddError(
- "@size can only be applied to members where the member's type size can "
- "be fully determined at shader creation time",
- attr->source);
+ AddError(attr->source)
+ << "@size can only be applied to members where the member's type size "
+ "can be fully determined at shader creation time";
return false;
}
return true;
@@ -2306,8 +2249,8 @@
}
if (invariant_attribute && !has_position) {
- AddError("@invariant must be applied to a position builtin",
- invariant_attribute->source);
+ AddError(invariant_attribute->source)
+ << "@invariant must be applied to a position builtin";
return false;
}
@@ -2316,14 +2259,15 @@
// restrict targets with index attributes to location 0 for easy translation in the
// backend writers.
if (member->Attributes().location.value_or(1) != 0) {
- AddError("@blend_src can only be used with @location(0)",
- blend_src_attribute->source);
+ AddError(blend_src_attribute->source)
+ << "@blend_src can only be used with @location(0)";
return false;
}
}
if (interpolate_attribute && !location_attribute) {
- AddError("@interpolate can only be used with @location", interpolate_attribute->source);
+ AddError(interpolate_attribute->source)
+ << "@interpolate can only be used with @location";
return false;
}
@@ -2333,13 +2277,12 @@
std::optional<uint32_t> blend_src = member->Attributes().blend_src;
if (!locations_and_blend_srcs.Add(std::make_pair(location, blend_src))) {
- StringStream err;
- err << "@location(" << location << ") ";
+ auto& err = AddError(location_attribute->source)
+ << "@location(" << location << ") ";
if (blend_src) {
err << "@blend_src(" << blend_src.value() << ") ";
}
err << "appears multiple times";
- AddError(err.str(), location_attribute->source);
return false;
}
}
@@ -2347,9 +2290,8 @@
if (color_attribute) {
uint32_t color = member->Attributes().color.value();
if (!colors.Add(color)) {
- StringStream err;
- err << "@color(" << color << ") appears multiple times";
- AddError(err.str(), color_attribute->source);
+ AddError(color_attribute->source)
+ << "@color(" << color << ") appears multiple times";
return false;
}
}
@@ -2363,17 +2305,16 @@
ast::PipelineStage stage,
const Source& source) const {
if (stage == ast::PipelineStage::kCompute) {
- AddError(AttrToStr(attr) + " cannot be used by compute shaders", attr->source);
+ AddError(attr->source) << AttrToStr(attr) << " cannot be used by compute shaders";
return false;
}
if (!type->is_numeric_scalar_or_vector()) {
std::string invalid_type = sem_.TypeNameOf(type);
- AddError("cannot apply @location to declaration of type '" + invalid_type + "'", source);
- AddNote(
- "@location must only be applied to declarations of numeric scalar or numeric vector "
- "type",
- attr->source);
+ AddError(source) << "cannot apply @location to declaration of type '" << invalid_type
+ << "'";
+ AddNote(attr->source) << "@location must only be applied to declarations of numeric scalar "
+ "or numeric vector type";
return false;
}
@@ -2386,9 +2327,8 @@
const Source& source,
const std::optional<bool> is_input) const {
if (!enabled_extensions_.Contains(wgsl::Extension::kChromiumExperimentalFramebufferFetch)) {
- AddError(
- "use of @color requires enabling extension 'chromium_experimental_framebuffer_fetch'",
- attr->source);
+ AddError(attr->source) << "use of @color requires enabling extension "
+ "'chromium_experimental_framebuffer_fetch'";
return false;
}
@@ -2396,16 +2336,15 @@
stage != ast::PipelineStage::kNone && stage != ast::PipelineStage::kFragment;
bool is_output = !is_input.value_or(true);
if (is_stage_non_fragment || is_output) {
- AddError("@color can only be used for fragment shader input", attr->source);
+ AddError(attr->source) << "@color can only be used for fragment shader input";
return false;
}
if (!type->is_numeric_scalar_or_vector()) {
std::string invalid_type = sem_.TypeNameOf(type);
- AddError("cannot apply @color to declaration of type '" + invalid_type + "'", source);
- AddNote(
- "@color must only be applied to declarations of numeric scalar or numeric vector type",
- attr->source);
+ AddError(source) << "cannot apply @color to declaration of type '" << invalid_type << "'";
+ AddNote(attr->source) << "@color must only be applied to declarations of numeric scalar or "
+ "numeric vector type";
return false;
}
@@ -2416,10 +2355,8 @@
ast::PipelineStage stage,
const std::optional<bool> is_input) const {
if (!enabled_extensions_.Contains(wgsl::Extension::kChromiumInternalDualSourceBlending)) {
- AddError(
- "use of @blend_src requires enabling extension "
- "'chromium_internal_dual_source_blending'",
- attr->source);
+ AddError(attr->source) << "use of @blend_src requires enabling extension "
+ "'chromium_internal_dual_source_blending'";
return false;
}
@@ -2427,7 +2364,7 @@
stage != ast::PipelineStage::kNone && stage != ast::PipelineStage::kFragment;
bool is_output = is_input.value_or(false);
if (is_stage_non_fragment || is_output) {
- AddError(AttrToStr(attr) + " can only be used for fragment shader output", attr->source);
+ AddError(attr->source) << AttrToStr(attr) << " can only be used for fragment shader output";
return false;
}
@@ -2439,18 +2376,18 @@
const core::type::Type* ret_type,
sem::Statement* current_statement) const {
if (func_type->UnwrapRef() != ret_type) {
- AddError("return statement type must match its function return type, returned '" +
- sem_.TypeNameOf(ret_type) + "', expected '" + sem_.TypeNameOf(func_type) + "'",
- ret->source);
+ AddError(ret->source)
+ << "return statement type must match its function return type, returned '"
+ << sem_.TypeNameOf(ret_type) << "', expected '" << sem_.TypeNameOf(func_type) << "'";
return false;
}
auto* sem = sem_.Get(ret);
if (auto* continuing = ClosestContinuing(/*stop_at_loop*/ false, /* stop_at_switch */ false,
current_statement)) {
- AddError("continuing blocks must not contain a return statement", ret->source);
+ AddError(ret->source) << "continuing blocks must not contain a return statement";
if (continuing != sem->Declaration() && continuing != sem->Parent()->Declaration()) {
- AddNote("see continuing block here", continuing->source);
+ AddNote(continuing->source) << "see continuing block here";
}
return false;
}
@@ -2460,16 +2397,15 @@
bool Validator::SwitchStatement(const ast::SwitchStatement* s) {
if (s->body.Length() > kMaxSwitchCaseSelectors) {
- AddError("switch statement has " + std::to_string(s->body.Length()) +
- " case selectors, max is " + std::to_string(kMaxSwitchCaseSelectors),
- s->source);
+ AddError(s->source) << "switch statement has " << s->body.Length()
+ << " case selectors, max is " << kMaxSwitchCaseSelectors;
return false;
}
auto* cond_ty = sem_.TypeOf(s->condition);
if (!cond_ty->is_integer_scalar()) {
- AddError("switch statement selector expression must be of a scalar integer type",
- s->condition->source);
+ AddError(s->condition->source)
+ << "switch statement selector expression must be of a scalar integer type";
return false;
}
@@ -2482,10 +2418,10 @@
if (selector->IsDefault()) {
if (default_selector != nullptr) {
// More than one default clause
- AddError("switch statement must have exactly one default clause",
- selector->Declaration()->source);
+ AddError(selector->Declaration()->source)
+ << "switch statement must have exactly one default clause";
- AddNote("previous default case", default_selector->Declaration()->source);
+ AddNote(default_selector->Declaration()->source) << "previous default case";
return false;
}
default_selector = selector;
@@ -2494,21 +2430,22 @@
auto* decl_ty = selector->Value()->Type();
if (cond_ty != decl_ty) {
- AddError(
- "the case selector values must have the same type as the selector expression.",
- selector->Declaration()->source);
+ AddError(selector->Declaration()->source)
+ << "the case selector values must have the same type as the "
+ "selector expression.";
return false;
}
auto value = selector->Value()->ValueAs<u32>();
if (auto added = selectors.Add(value, selector->Declaration()->source); !added) {
- AddError("duplicate switch case '" +
- (decl_ty->IsAnyOf<core::type::I32, core::type::AbstractNumeric>()
- ? std::to_string(i32(value))
- : std::to_string(value)) +
- "'",
- selector->Declaration()->source);
- AddNote("previous case declared here", added.value);
+ auto& err = AddError(selector->Declaration()->source)
+ << "duplicate switch case " << style::Literal;
+ if (decl_ty->IsAnyOf<core::type::I32, core::type::AbstractNumeric>()) {
+ err << i32(value);
+ } else {
+ err << value;
+ }
+ AddNote(added.value) << "previous case declared here";
return false;
}
}
@@ -2516,7 +2453,7 @@
if (default_selector == nullptr) {
// No default clause
- AddError("switch statement must have a default clause", s->source);
+ AddError(s->source) << "switch statement must have a default clause";
return false;
}
@@ -2543,10 +2480,9 @@
if (!ty->IsConstructible() &&
!ty->IsAnyOf<core::type::Pointer, core::type::Texture, core::type::Sampler,
core::type::AbstractNumeric>()) {
- AddError("cannot assign '" + sem_.TypeNameOf(rhs_ty) +
- "' to '_'. '_' can only be assigned a constructible, pointer, texture or "
- "sampler type",
- rhs->source);
+ AddError(rhs->source) << "cannot assign '" << sem_.TypeNameOf(rhs_ty)
+ << "' to '_'. '_' can only be assigned a constructible, pointer, "
+ "texture or sampler type";
return false;
}
return true; // RHS can be anything.
@@ -2559,7 +2495,7 @@
auto* lhs_ref = lhs_ty->As<core::type::Reference>();
if (!lhs_ref) {
// LHS is not a reference, so it has no storage.
- AddError("cannot assign to " + sem_.Describe(lhs_sem), lhs->source);
+ AddError(lhs->source) << "cannot assign to " << sem_.Describe(lhs_sem);
auto* expr = lhs;
while (expr) {
@@ -2571,22 +2507,25 @@
Switch(
user->Variable()->Declaration(), //
[&](const ast::Let* v) {
- AddNote("'let' variables are immutable",
- user->Declaration()->source);
+ AddNote(user->Declaration()->source)
+ << style::Variable << "let" << style::Plain
+ << " variables are immutable";
sem_.NoteDeclarationSource(v);
},
[&](const ast::Const* v) {
- AddNote("'const' variables are immutable",
- user->Declaration()->source);
+ AddNote(user->Declaration()->source)
+ << style::Variable << "const" << style::Plain
+ << " variables are immutable";
sem_.NoteDeclarationSource(v);
},
[&](const ast::Override* v) {
- AddNote("'override' variables are immutable",
- user->Declaration()->source);
+ AddNote(user->Declaration()->source)
+ << style::Variable << "override" << style::Plain
+ << " variables are immutable";
sem_.NoteDeclarationSource(v);
},
[&](const ast::Parameter* v) {
- AddNote("parameters are immutable", user->Declaration()->source);
+ AddNote(user->Declaration()->source) << "parameters are immutable";
sem_.NoteDeclarationSource(v);
});
}
@@ -2602,18 +2541,17 @@
// Value type has to match storage type
if (storage_ty != value_type) {
- AddError(
- "cannot assign '" + sem_.TypeNameOf(rhs_ty) + "' to '" + sem_.TypeNameOf(lhs_ty) + "'",
- a->source);
+ AddError(a->source) << "cannot assign " << style::Type << sem_.TypeNameOf(rhs_ty)
+ << style::Plain << " to " << style::Type << sem_.TypeNameOf(lhs_ty);
return false;
}
if (!storage_ty->IsConstructible()) {
- AddError("storage type of assignment must be constructible", a->source);
+ AddError(a->source) << "storage type of assignment must be constructible";
return false;
}
if (lhs_ref->Access() == core::Access::kRead) {
- AddError("cannot store into a read-only type '" + sem_.RawTypeNameOf(lhs_ty) + "'",
- a->source);
+ AddError(a->source) << "cannot store into a read-only type " << style::Type
+ << sem_.RawTypeNameOf(lhs_ty) << style::Plain;
return false;
}
return true;
@@ -2632,8 +2570,8 @@
[&](const ast::Let*) { return "cannot modify 'let'"; },
[&](const ast::Override*) { return "cannot modify 'override'"; });
if (err) {
- AddError(err, lhs->source);
- AddNote("'" + v->name->symbol.Name() + "' is declared here:", v->source);
+ AddError(lhs->source) << err;
+ AddNote(v->source) << "'" << v->name->symbol.Name() << "' is declared here:";
return false;
}
}
@@ -2642,18 +2580,19 @@
auto* lhs_ref = lhs_ty->As<core::type::Reference>();
if (!lhs_ref) {
// LHS is not a reference, so it has no storage.
- AddError("cannot modify value of type '" + sem_.TypeNameOf(lhs_ty) + "'", lhs->source);
+ AddError(lhs->source) << "cannot modify value of type '" << sem_.TypeNameOf(lhs_ty) << "'";
return false;
}
if (!lhs_ref->StoreType()->is_integer_scalar()) {
const std::string kind = inc->increment ? "increment" : "decrement";
- AddError(kind + " statement can only be applied to an integer scalar", lhs->source);
+ AddError(lhs->source) << kind << " statement can only be applied to an integer scalar";
return false;
}
if (lhs_ref->Access() == core::Access::kRead) {
- AddError("cannot modify read-only type '" + sem_.RawTypeNameOf(lhs_ty) + "'", inc->source);
+ AddError(inc->source) << "cannot modify read-only type '" << sem_.RawTypeNameOf(lhs_ty)
+ << "'";
return false;
}
return true;
@@ -2669,8 +2608,8 @@
} else {
auto added = seen.Add(&d->TypeInfo(), d->source);
if (!added && !d->Is<ast::InternalAttribute>()) {
- AddError("duplicate " + d->Name() + " attribute", d->source);
- AddNote("first attribute declared here", added.value);
+ AddError(d->source) << "duplicate " << d->Name() << " attribute";
+ AddNote(added.value) << "first attribute declared here";
return false;
}
}
@@ -2689,17 +2628,10 @@
auto diag_added = diagnostics.Add(std::make_pair(category, name), dc);
if (!diag_added && diag_added.value->severity != dc->severity) {
- {
- StringStream ss;
- ss << "conflicting diagnostic " << use;
- AddError(ss.str(), dc->rule_name->source);
- }
- {
- StringStream ss;
- ss << "severity of '" << dc->rule_name->String() << "' set to '" << dc->severity
- << "' here";
- AddNote(ss.str(), diag_added.value->rule_name->source);
- }
+ AddError(dc->rule_name->source) << "conflicting diagnostic " << use;
+ AddNote(diag_added.value->rule_name->source)
+ << "severity of '" << dc->rule_name->String() << "' set to '" << dc->severity
+ << "' here";
return false;
}
}
@@ -2733,10 +2665,9 @@
}
void Validator::RaiseArrayWithOverrideCountError(const Source& source) const {
- AddError(
- "array with an 'override' element count can only be used as the store type of a "
- "'var<workgroup>'",
- source);
+ AddError(source)
+ << "array with an 'override' element count can only be used as the store type of a "
+ "'var<workgroup>'";
}
std::string Validator::VectorPretty(uint32_t size, const core::type::Type* element_type) const {
@@ -2759,18 +2690,16 @@
for (auto* member : str->Members()) {
using Allowed = std::tuple<core::type::I32, core::type::U32, core::type::F32>;
if (TINT_UNLIKELY(!member->Type()->TypeInfo().IsAnyOfTuple<Allowed>())) {
- AddError(
- "struct members used in the 'pixel_local' address space can only be of "
- "the type 'i32', 'u32' or 'f32'",
- member->Declaration()->source);
- AddNote("struct '" + str->Name().Name() +
- "' used in the 'pixel_local' address space here",
- source);
+ AddError(member->Declaration()->source)
+ << "struct members used in the 'pixel_local' address "
+ "space can only be of the type 'i32', 'u32' or 'f32'";
+ AddNote(source) << "struct '" << str->Name().Name()
+ << "' used in the 'pixel_local' address space here";
return false;
}
}
} else if (TINT_UNLIKELY(!store_ty->TypeInfo().Is<core::type::Struct>())) {
- AddError("'pixel_local' variable only support struct storage types", source);
+ AddError(source) << "'pixel_local' variable only support struct storage types";
return false;
}
break;
@@ -2779,18 +2708,16 @@
wgsl::Extension::kChromiumExperimentalPushConstant) &&
IsValidationEnabled(attributes,
ast::DisabledValidation::kIgnoreAddressSpace))) {
- AddError(
- "use of variable address space 'push_constant' requires enabling extension "
- "'chromium_experimental_push_constant'",
- source);
+ AddError(source) << "use of variable address space 'push_constant' requires "
+ "enabling extension 'chromium_experimental_push_constant'";
return false;
}
break;
case core::AddressSpace::kStorage:
if (TINT_UNLIKELY(access == core::Access::kWrite)) {
// The access mode for the storage address space can only be 'read' or 'read_write'.
- AddError("access mode 'write' is not valid for the 'storage' address space",
- source);
+ AddError(source)
+ << "access mode 'write' is not valid for the 'storage' address space";
return false;
}
break;
@@ -2799,13 +2726,13 @@
}
auto atomic_error = [&]() -> const char* {
+ StyledText err;
if (address_space != core::AddressSpace::kStorage &&
address_space != core::AddressSpace::kWorkgroup) {
return "atomic variables must have <storage> or <workgroup> address space";
}
if (address_space == core::AddressSpace::kStorage && access != core::Access::kReadWrite) {
- return "atomic variables in <storage> address space must have read_write access "
- "mode";
+ return "atomic variables in <storage> address space must have read_write access mode";
}
return nullptr;
};
@@ -2813,9 +2740,9 @@
auto check_sub_atomics = [&] {
if (auto atomic_use = atomic_composite_info_.Get(store_ty)) {
if (auto* err = atomic_error()) {
- AddError(err, source);
- AddNote("atomic sub-type of '" + sem_.TypeNameOf(store_ty) + "' is declared here",
- **atomic_use);
+ AddError(source) << err;
+ AddNote(**atomic_use)
+ << "atomic sub-type of '" << sem_.TypeNameOf(store_ty) << "' is declared here";
return false;
}
}
@@ -2826,7 +2753,7 @@
store_ty, //
[&](const core::type::Atomic*) {
if (auto* err = atomic_error()) {
- AddError(err, source);
+ AddError(source) << err;
return false;
}
return true;
@@ -2855,29 +2782,28 @@
continue;
}
- std::string s{core::ToString(space)};
-
- AddError("entry point '" + ep->Declaration()->name->symbol.Name() +
- "' uses two different '" + s + "' variables.",
- ep->Declaration()->source);
- AddNote("first '" + s + "' variable declaration is here", var->Declaration()->source);
+ AddError(ep->Declaration()->source)
+ << "entry point '" << ep->Declaration()->name->symbol.Name()
+ << "' uses two different '" << space << "' variables.";
+ AddNote(var->Declaration()->source)
+ << "first '" << space << "' variable declaration is here";
if (func != ep) {
TraverseCallChain(ep, func, [&](const sem::Function* f) {
- AddNote("called by function '" + f->Declaration()->name->symbol.Name() + "'",
- f->Declaration()->source);
+ AddNote(f->Declaration()->source)
+ << "called by function '" << f->Declaration()->name->symbol.Name() << "'";
});
- AddNote("called by entry point '" + ep->Declaration()->name->symbol.Name() + "'",
- ep->Declaration()->source);
+ AddNote(ep->Declaration()->source)
+ << "called by entry point '" << ep->Declaration()->name->symbol.Name() << "'";
}
- AddNote("second '" + s + "' variable declaration is here",
- seen_var->Declaration()->source);
+ AddNote(seen_var->Declaration()->source)
+ << "second '" << space << "' variable declaration is here";
if (seen_func != ep) {
TraverseCallChain(ep, seen_func, [&](const sem::Function* f) {
- AddNote("called by function '" + f->Declaration()->name->symbol.Name() + "'",
- f->Declaration()->source);
+ AddNote(f->Declaration()->source)
+ << "called by function '" << f->Declaration()->name->symbol.Name() << "'";
});
- AddNote("called by entry point '" + ep->Declaration()->name->symbol.Name() + "'",
- ep->Declaration()->source);
+ AddNote(ep->Declaration()->source)
+ << "called by entry point '" << ep->Declaration()->name->symbol.Name() << "'";
}
return false;
}
diff --git a/src/tint/lang/wgsl/resolver/validator.h b/src/tint/lang/wgsl/resolver/validator.h
index a33b702..0fa3bd9 100644
--- a/src/tint/lang/wgsl/resolver/validator.h
+++ b/src/tint/lang/wgsl/resolver/validator.h
@@ -42,6 +42,7 @@
#include "src/tint/utils/containers/vector.h"
#include "src/tint/utils/diagnostic/source.h"
#include "src/tint/utils/math/hash.h"
+#include "src/tint/utils/text/styled_text.h"
// Forward declarations
namespace tint::ast {
@@ -125,29 +126,23 @@
Hashset<TypeAndAddressSpace, 8>& valid_type_storage_layouts);
~Validator();
- /// Adds the given error message to the diagnostics
- /// @param msg the error message
+ /// @returns an error diagnostic
/// @param source the error source
- void AddError(const std::string& msg, const Source& source) const;
+ diag::Diagnostic& AddError(const Source& source) const;
- /// Adds the given warning message to the diagnostics
- /// @param msg the warning message
+ /// @returns an warning diagnostic
/// @param source the warning source
- void AddWarning(const std::string& msg, const Source& source) const;
+ diag::Diagnostic& AddWarning(const Source& source) const;
- /// Adds the given note message to the diagnostics
- /// @param msg the note message
+ /// @returns an note diagnostic
/// @param source the note source
- void AddNote(const std::string& msg, const Source& source) const;
+ diag::Diagnostic& AddNote(const Source& source) const;
- /// Adds the given message to the diagnostics with current severity for the given rule.
+ /// Adds a diagnostic with current severity for the given rule.
/// @param rule the diagnostic trigger rule
- /// @param msg the diagnostic message
/// @param source the diagnostic source
- /// @returns false if the diagnostic is an error for the given trigger rule
- bool AddDiagnostic(wgsl::DiagnosticRule rule,
- const std::string& msg,
- const Source& source) const;
+ /// @returns the diagnostic, if the diagnostic level isn't disabled
+ diag::Diagnostic* MaybeAddDiagnostic(wgsl::DiagnosticRule rule, const Source& source) const;
/// @returns the diagnostic filter stack
DiagnosticFilterStack& DiagnosticFilters() { return diagnostic_filters_; }
diff --git a/src/tint/lang/wgsl/resolver/value_constructor_validation_test.cc b/src/tint/lang/wgsl/resolver/value_constructor_validation_test.cc
index 027b471..0fb486e 100644
--- a/src/tint/lang/wgsl/resolver/value_constructor_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/value_constructor_validation_test.cc
@@ -478,7 +478,8 @@
WrapInFunction(a);
ASSERT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for f32(f32, f32)"));
+ EXPECT_THAT(r()->error(),
+ HasSubstr("12:34 error: no matching constructor for 'f32(f32, f32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, ConversionConstructorInvalid_InvalidConstructor) {
@@ -487,7 +488,7 @@
ASSERT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for f32(array<f32, 4>)"));
+ HasSubstr("12:34 error: no matching constructor for 'f32(array<f32, 4>)"));
}
} // namespace ConversionConstructTest
@@ -1062,7 +1063,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec2<f32>(i32, f32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec2<f32>(i32, f32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec2F16_Error_ScalarArgumentTypeMismatch) {
@@ -1072,7 +1073,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec2<f16>(f16, f32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec2<f16>(f16, f32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec2U32_Error_ScalarArgumentTypeMismatch) {
@@ -1080,7 +1081,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec2<u32>(u32, i32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec2<u32>(u32, i32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec2I32_Error_ScalarArgumentTypeMismatch) {
@@ -1088,7 +1089,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec2<i32>(u32, i32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec2<i32>(u32, i32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec2Bool_Error_ScalarArgumentTypeMismatch) {
@@ -1096,7 +1097,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec2<bool>(bool, i32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec2<bool>(bool, i32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec2_Error_Vec3ArgumentCardinalityTooLarge) {
@@ -1104,7 +1105,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec2<f32>(vec3<f32>)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec2<f32>(vec3<f32>)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec2_Error_Vec4ArgumentCardinalityTooLarge) {
@@ -1112,7 +1113,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec2<f32>(vec4<f32>)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec2<f32>(vec4<f32>)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec2_Error_TooManyArgumentsScalar) {
@@ -1120,7 +1121,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec2<f32>(f32, f32, f32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec2<f32>(f32, f32, f32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec2_Error_TooManyArgumentsVector) {
@@ -1129,7 +1130,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec2<f32>(vec2<f32>, vec2<f32>)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec2<f32>(vec2<f32>, vec2<f32>)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec2_Error_TooManyArgumentsVectorAndScalar) {
@@ -1137,7 +1138,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec2<f32>(vec2<f32>, f32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec2<f32>(vec2<f32>, f32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec2_Error_InvalidArgumentType) {
@@ -1145,7 +1146,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec2<f32>(mat2x2<f32>)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec2<f32>(mat2x2<f32>)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec2_Success_ZeroValue) {
@@ -1319,7 +1320,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec3<f32>(f32, f32, i32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec3<f32>(f32, f32, i32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec3F16_Error_ScalarArgumentTypeMismatch) {
@@ -1329,7 +1330,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec3<f16>(f16, f16, f32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec3<f16>(f16, f16, f32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec3U32_Error_ScalarArgumentTypeMismatch) {
@@ -1337,7 +1338,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec3<u32>(u32, i32, u32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec3<u32>(u32, i32, u32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec3I32_Error_ScalarArgumentTypeMismatch) {
@@ -1345,15 +1346,16 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec3<i32>(i32, u32, i32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec3<i32>(i32, u32, i32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec3Bool_Error_ScalarArgumentTypeMismatch) {
WrapInFunction(Call<vec3<bool>>(Source{{12, 34}}, false, 1_i, true));
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec3<bool>(bool, i32, bool)"));
+ EXPECT_THAT(
+ r()->error(),
+ HasSubstr("12:34 error: no matching constructor for 'vec3<bool>(bool, i32, bool)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Error_Vec4ArgumentCardinalityTooLarge) {
@@ -1361,7 +1363,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec3<f32>(vec4<f32>)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec3<f32>(vec4<f32>)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Error_TooFewArgumentsScalar) {
@@ -1369,7 +1371,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec3<f32>(f32, f32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec3<f32>(f32, f32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Error_TooManyArgumentsScalar) {
@@ -1378,7 +1380,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec3<f32>(f32, f32, f32, f32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec3<f32>(f32, f32, f32, f32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Error_TooFewArgumentsVec2) {
@@ -1386,7 +1388,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec3<f32>(vec2<f32>)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec3<f32>(vec2<f32>)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Error_TooManyArgumentsVec2) {
@@ -1395,7 +1397,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec3<f32>(vec2<f32>, vec2<f32>)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec3<f32>(vec2<f32>, vec2<f32>)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Error_TooManyArgumentsVec2AndScalar) {
@@ -1404,7 +1406,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec3<f32>(vec2<f32>, f32, f32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec3<f32>(vec2<f32>, f32, f32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Error_TooManyArgumentsVec3) {
@@ -1412,7 +1414,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec3<f32>(vec3<f32>, f32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec3<f32>(vec3<f32>, f32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Error_InvalidArgumentType) {
@@ -1420,7 +1422,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec3<f32>(mat2x2<f32>)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec3<f32>(mat2x2<f32>)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec3_Success_ZeroValue) {
@@ -1642,7 +1644,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec4<f32>(f32, f32, i32, f32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec4<f32>(f32, f32, i32, f32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec4F16_Error_ScalarArgumentTypeMismatch) {
@@ -1653,7 +1655,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec4<f16>(f16, f16, f32, f16)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec4<f16>(f16, f16, f32, f16)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec4U32_Error_ScalarArgumentTypeMismatch) {
@@ -1662,7 +1664,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec4<u32>(u32, u32, i32, u32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec4<u32>(u32, u32, i32, u32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec4I32_Error_ScalarArgumentTypeMismatch) {
@@ -1671,7 +1673,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec4<i32>(i32, i32, u32, i32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec4<i32>(i32, i32, u32, i32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec4Bool_Error_ScalarArgumentTypeMismatch) {
@@ -1680,7 +1682,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec4<bool>(bool, bool, i32, bool)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec4<bool>(bool, bool, i32, bool)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooFewArgumentsScalar) {
@@ -1688,7 +1690,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec4<f32>(f32, f32, f32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec4<f32>(f32, f32, f32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooManyArgumentsScalar) {
@@ -1697,7 +1699,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec4<f32>(f32, f32, f32, f32, f32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec4<f32>(f32, f32, f32, f32, f32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooFewArgumentsVec2AndScalar) {
@@ -1705,7 +1707,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec4<f32>(vec2<f32>, f32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec4<f32>(vec2<f32>, f32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooManyArgumentsVec2AndScalars) {
@@ -1714,7 +1716,8 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec4<f32>(vec2<f32>, f32, f32, f32)"));
+ HasSubstr(
+ "12:34 error: no matching constructor for 'vec4<f32>(vec2<f32>, f32, f32, f32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooManyArgumentsVec2Vec2Scalar) {
@@ -1723,7 +1726,8 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec4<f32>(vec2<f32>, vec2<f32>, f32)"));
+ HasSubstr(
+ "12:34 error: no matching constructor for 'vec4<f32>(vec2<f32>, vec2<f32>, f32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooManyArgumentsVec2Vec2Vec2) {
@@ -1731,10 +1735,8 @@
Call<vec4<f32>>(Source{{12, 34}}, Call<vec2<f32>>(), Call<vec2<f32>>(), Call<vec2<f32>>()));
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(
- r()->error(),
- HasSubstr(
- "12:34 error: no matching constructor for vec4<f32>(vec2<f32>, vec2<f32>, vec2<f32>)"));
+ EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for "
+ "'vec4<f32>(vec2<f32>, vec2<f32>, vec2<f32>)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooFewArgumentsVec3) {
@@ -1742,7 +1744,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec4<f32>(vec3<f32>)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec4<f32>(vec3<f32>)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooManyArgumentsVec3AndScalars) {
@@ -1751,7 +1753,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec4<f32>(vec3<f32>, f32, f32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec4<f32>(vec3<f32>, f32, f32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooManyArgumentsVec3AndVec2) {
@@ -1760,7 +1762,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec4<f32>(vec3<f32>, vec2<f32>)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec4<f32>(vec3<f32>, vec2<f32>)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooManyArgumentsVec2AndVec3) {
@@ -1769,7 +1771,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec4<f32>(vec2<f32>, vec3<f32>)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec4<f32>(vec2<f32>, vec3<f32>)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_TooManyArgumentsVec3AndVec3) {
@@ -1778,7 +1780,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec4<f32>(vec3<f32>, vec3<f32>)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec4<f32>(vec3<f32>, vec3<f32>)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Error_InvalidArgumentType) {
@@ -1786,7 +1788,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec4<f32>(mat2x2<f32>)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec4<f32>(mat2x2<f32>)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vec4_Success_ZeroValue) {
@@ -1966,7 +1968,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec3<f32>(f32, f32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec3<f32>(f32, f32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, NestedVectorConstructors_Success) {
@@ -1989,7 +1991,8 @@
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for vec2<f32>(u32)"));
+ EXPECT_THAT(r()->error(),
+ HasSubstr("12:34 error: no matching constructor for 'vec2<f32>(u32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vector_Alias_Argument_Success) {
@@ -2012,7 +2015,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec2<f32>(f32, u32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec2<f32>(f32, u32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vector_ElementTypeAlias_Success) {
@@ -2035,7 +2038,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("12:34 error: no matching constructor for vec3<u32>(vec2<f32>, f32)"));
+ HasSubstr("12:34 error: no matching constructor for 'vec3<u32>(vec2<f32>, f32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, Vector_ArgumentElementTypeAlias_Success) {
@@ -2339,7 +2342,7 @@
Expr(Source{{1, 3}}, 2_u)));
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("1:1 error: no matching constructor for vec2(i32, u32)"));
+ EXPECT_THAT(r()->error(), HasSubstr("1:1 error: no matching constructor for 'vec2(i32, u32)'"));
}
TEST_F(ResolverValueConstructorValidationTest, CannotInferVec3ElementTypeFromScalarsMismatch) {
@@ -2350,7 +2353,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("1:1 error: no matching constructor for vec3(i32, u32, i32)"));
+ HasSubstr("1:1 error: no matching constructor for 'vec3(i32, u32, i32)'"));
}
TEST_F(ResolverValueConstructorValidationTest,
@@ -2361,7 +2364,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("1:1 error: no matching constructor for vec3(i32, vec2<f32>)"));
+ HasSubstr("1:1 error: no matching constructor for 'vec3(i32, vec2<f32>)'"));
}
TEST_F(ResolverValueConstructorValidationTest, CannotInferVec4ElementTypeFromScalarsMismatch) {
@@ -2373,7 +2376,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("1:1 error: no matching constructor for vec4(i32, i32, f32, i32)"));
+ HasSubstr("1:1 error: no matching constructor for 'vec4(i32, i32, f32, i32)'"));
}
TEST_F(ResolverValueConstructorValidationTest,
@@ -2384,7 +2387,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("1:1 error: no matching constructor for vec4(i32, vec3<u32>)"));
+ HasSubstr("1:1 error: no matching constructor for 'vec4(i32, vec3<u32>)'"));
}
TEST_F(ResolverValueConstructorValidationTest, CannotInferVec4ElementTypeFromVec2AndVec2Mismatch) {
@@ -2394,7 +2397,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
- HasSubstr("1:1 error: no matching constructor for vec4(vec2<i32>, vec2<u32>)"));
+ HasSubstr("1:1 error: no matching constructor for 'vec4(vec2<i32>, vec2<u32>)'"));
}
} // namespace VectorConstructor
@@ -2458,8 +2461,8 @@
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for " +
- MatrixStr(param) + "(" + args_tys.str() + ")"));
+ EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for '" +
+ MatrixStr(param) + "(" + args_tys.str() + ")'"));
}
TEST_P(MatrixConstructorTest, ElementConstructor_Error_TooFewArguments) {
@@ -2486,8 +2489,8 @@
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for " +
- MatrixStr(param) + "(" + args_tys.str() + ")"));
+ EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for '" +
+ MatrixStr(param) + "(" + args_tys.str() + ")'"));
}
TEST_P(MatrixConstructorTest, ColumnConstructor_Error_TooManyArguments) {
@@ -2515,8 +2518,8 @@
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for " +
- MatrixStr(param) + "(" + args_tys.str() + ")"));
+ EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for '" +
+ MatrixStr(param) + "(" + args_tys.str() + ")'"));
}
TEST_P(MatrixConstructorTest, ElementConstructor_Error_TooManyArguments) {
@@ -2543,8 +2546,8 @@
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for " +
- MatrixStr(param) + "(" + args_tys.str() + ")"));
+ EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for '" +
+ MatrixStr(param) + "(" + args_tys.str() + ")'"));
}
TEST_P(MatrixConstructorTest, ColumnConstructor_Error_InvalidArgumentType) {
@@ -2571,8 +2574,8 @@
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for " +
- MatrixStr(param) + "(" + args_tys.str() + ")"));
+ EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for '" +
+ MatrixStr(param) + "(" + args_tys.str() + ")'"));
}
TEST_P(MatrixConstructorTest, ElementConstructor_Error_InvalidArgumentType) {
@@ -2598,8 +2601,8 @@
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for " +
- MatrixStr(param) + "(" + args_tys.str() + ")"));
+ EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for '" +
+ MatrixStr(param) + "(" + args_tys.str() + ")'"));
}
TEST_P(MatrixConstructorTest, ColumnConstructor_Error_TooFewRowsInVectorArgument) {
@@ -2636,8 +2639,8 @@
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for " +
- MatrixStr(param) + "(" + args_tys.str() + ")"));
+ EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for '" +
+ MatrixStr(param) + "(" + args_tys.str() + ")'"));
}
TEST_P(MatrixConstructorTest, ColumnConstructor_Error_TooManyRowsInVectorArgument) {
@@ -2673,8 +2676,8 @@
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for " +
- MatrixStr(param) + "(" + args_tys.str() + ")"));
+ EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for '" +
+ MatrixStr(param) + "(" + args_tys.str() + ")'"));
}
TEST_P(MatrixConstructorTest, ZeroValue_Success) {
@@ -2759,8 +2762,8 @@
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for " +
- MatrixStr(param) + "(" + args_tys.str() + ")"));
+ EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for '" +
+ MatrixStr(param) + "(" + args_tys.str() + ")'"));
}
TEST_P(MatrixConstructorTest, ElementTypeAlias_Success) {
@@ -2794,7 +2797,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
r()->error(),
- HasSubstr("12:34 error: no matching constructor for mat2x2<f32>(vec2<u32>, vec2<f32>)"));
+ HasSubstr("12:34 error: no matching constructor for 'mat2x2<f32>(vec2<u32>, vec2<f32>)'"));
}
TEST_P(MatrixConstructorTest, ArgumentTypeAlias_Success) {
@@ -2840,8 +2843,8 @@
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
- EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for " +
- MatrixStr(param) + "(" + args_tys.str() + ")"));
+ EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for '" +
+ MatrixStr(param) + "(" + args_tys.str() + ")'"));
}
TEST_P(MatrixConstructorTest, ArgumentElementTypeAlias_Success) {
@@ -2903,7 +2906,7 @@
Enable(wgsl::Extension::kF16);
StringStream err;
- err << "12:34 error: no matching constructor for mat" << param.columns << "x" << param.rows
+ err << "12:34 error: no matching constructor for 'mat" << param.columns << "x" << param.rows
<< "(";
Vector<const ast::Expression*, 8> args;
@@ -2934,7 +2937,7 @@
Enable(wgsl::Extension::kF16);
StringStream err;
- err << "12:34 error: no matching constructor for mat" << param.columns << "x" << param.rows
+ err << "12:34 error: no matching constructor for 'mat" << param.columns << "x" << param.rows
<< "(";
Vector<const ast::Expression*, 16> args;
@@ -2951,7 +2954,7 @@
}
}
- err << ")";
+ err << ")'";
auto matrix_type = ty.mat<Infer>(param.columns, param.rows);
WrapInFunction(Call(Source{{12, 34}}, matrix_type, std::move(args)));
diff --git a/src/tint/lang/wgsl/resolver/variable_test.cc b/src/tint/lang/wgsl/resolver/variable_test.cc
index d3d9f10..6f70683 100644
--- a/src/tint/lang/wgsl/resolver/variable_test.cc
+++ b/src/tint/lang/wgsl/resolver/variable_test.cc
@@ -1312,7 +1312,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), R"(12:34 error: variable 'a' does not take template arguments
-56:78 note: var 'a' declared here)");
+56:78 note: 'var a' declared here)");
}
TEST_F(ResolverVariableTest, GlobalConst_UseTemplatedIdent) {
@@ -1330,7 +1330,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), R"(12:34 error: variable 'a' does not take template arguments
-56:78 note: const 'a' declared here)");
+56:78 note: 'const a' declared here)");
}
TEST_F(ResolverVariableTest, GlobalOverride_UseTemplatedIdent) {
@@ -1348,7 +1348,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), R"(12:34 error: variable 'a' does not take template arguments
-56:78 note: override 'a' declared here)");
+56:78 note: 'override a' declared here)");
}
TEST_F(ResolverVariableTest, Param_UseTemplatedIdent) {
@@ -1380,7 +1380,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), R"(12:34 error: variable 'a' does not take template arguments
-56:78 note: var 'a' declared here)");
+56:78 note: 'var a' declared here)");
}
TEST_F(ResolverVariableTest, Let_UseTemplatedIdent) {
@@ -1397,7 +1397,7 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), R"(12:34 error: variable 'a' does not take template arguments
-56:78 note: let 'a' declared here)");
+56:78 note: 'let a' declared here)");
}
} // namespace
diff --git a/src/tint/lang/wgsl/resolver/variable_validation_test.cc b/src/tint/lang/wgsl/resolver/variable_validation_test.cc
index f333b64..10bc7ec 100644
--- a/src/tint/lang/wgsl/resolver/variable_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/variable_validation_test.cc
@@ -101,8 +101,8 @@
GlobalVar("b", ty.i32(), core::AddressSpace::kPrivate, Expr(Source{{56, 78}}, "a"));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(56:78 error: var 'a' cannot be referenced at module-scope
-12:34 note: var 'a' declared here)");
+ EXPECT_EQ(r()->error(), R"(56:78 error: 'var a' cannot be referenced at module-scope
+12:34 note: 'var a' declared here)");
}
TEST_F(ResolverVariableValidationTest, OverrideNoInitializerNoType) {
diff --git a/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc b/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc
index 622f73f..8ad212a 100644
--- a/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc
@@ -338,7 +338,7 @@
void ASTPrinter::EmitImageFormat(StringStream& out, const core::TexelFormat fmt) {
switch (fmt) {
case core::TexelFormat::kUndefined:
- diagnostics_.AddError(diag::System::Writer, "unknown image format");
+ diagnostics_.AddError(diag::System::Writer, Source{}) << "unknown image format";
break;
default:
out << fmt;
diff --git a/src/tint/utils/cli/cli.cc b/src/tint/utils/cli/cli.cc
index b6dc911..6b00638 100644
--- a/src/tint/utils/cli/cli.cc
+++ b/src/tint/utils/cli/cli.cc
@@ -174,8 +174,8 @@
return Failure{err};
}
} else if (!parse_options.ignore_unknown) {
- StringStream err;
- err << "unknown flag: " << arg << std::endl;
+ StyledText err;
+ err << "unknown flag: " << arg << "\n";
auto names = options_by_name.Keys();
auto alternatives =
Transform(names, [&](const std::string& s) { return std::string_view(s); });
@@ -183,7 +183,7 @@
opts.prefix = "--";
opts.list_possible_values = false;
SuggestAlternatives(arg, alternatives.Slice(), err, opts);
- return Failure{err.str()};
+ return Failure{err.Plain()};
}
}
diff --git a/src/tint/utils/diagnostic/BUILD.bazel b/src/tint/utils/diagnostic/BUILD.bazel
index 5cd5f48..568132a 100644
--- a/src/tint/utils/diagnostic/BUILD.bazel
+++ b/src/tint/utils/diagnostic/BUILD.bazel
@@ -41,28 +41,11 @@
srcs = [
"diagnostic.cc",
"formatter.cc",
- "printer.cc",
"source.cc",
- ] + select({
- ":_not_tint_build_is_linux__and__not_tint_build_is_mac__and__not_tint_build_is_win_": [
- "printer_other.cc",
- ],
- "//conditions:default": [],
- }) + select({
- ":tint_build_is_linux_or_tint_build_is_mac": [
- "printer_posix.cc",
- ],
- "//conditions:default": [],
- }) + select({
- ":tint_build_is_win": [
- "printer_windows.cc",
- ],
- "//conditions:default": [],
- }),
+ ],
hdrs = [
"diagnostic.h",
"formatter.h",
- "printer.h",
"source.h",
],
deps = [
@@ -84,7 +67,6 @@
srcs = [
"diagnostic_test.cc",
"formatter_test.cc",
- "printer_test.cc",
"source_test.cc",
],
deps = [
@@ -103,50 +85,3 @@
visibility = ["//visibility:public"],
)
-alias(
- name = "tint_build_is_linux",
- actual = "//src/tint:tint_build_is_linux_true",
-)
-
-alias(
- name = "_not_tint_build_is_linux_",
- actual = "//src/tint:tint_build_is_linux_false",
-)
-
-alias(
- name = "tint_build_is_mac",
- actual = "//src/tint:tint_build_is_mac_true",
-)
-
-alias(
- name = "_not_tint_build_is_mac_",
- actual = "//src/tint:tint_build_is_mac_false",
-)
-
-alias(
- name = "tint_build_is_win",
- actual = "//src/tint:tint_build_is_win_true",
-)
-
-alias(
- name = "_not_tint_build_is_win_",
- actual = "//src/tint:tint_build_is_win_false",
-)
-
-selects.config_setting_group(
- name = "tint_build_is_linux_or_tint_build_is_mac",
- match_any = [
- "tint_build_is_linux",
- "tint_build_is_mac",
- ],
-)
-
-selects.config_setting_group(
- name = "_not_tint_build_is_linux__and__not_tint_build_is_mac__and__not_tint_build_is_win_",
- match_all = [
- ":_not_tint_build_is_linux_",
- ":_not_tint_build_is_mac_",
- ":_not_tint_build_is_win_",
- ],
-)
-
diff --git a/src/tint/utils/diagnostic/BUILD.cmake b/src/tint/utils/diagnostic/BUILD.cmake
index 37b0742..c0c2bc6 100644
--- a/src/tint/utils/diagnostic/BUILD.cmake
+++ b/src/tint/utils/diagnostic/BUILD.cmake
@@ -43,8 +43,6 @@
utils/diagnostic/diagnostic.h
utils/diagnostic/formatter.cc
utils/diagnostic/formatter.h
- utils/diagnostic/printer.cc
- utils/diagnostic/printer.h
utils/diagnostic/source.cc
utils/diagnostic/source.h
)
@@ -60,24 +58,6 @@
tint_utils_traits
)
-if((NOT TINT_BUILD_IS_LINUX) AND (NOT TINT_BUILD_IS_MAC) AND (NOT TINT_BUILD_IS_WIN))
- tint_target_add_sources(tint_utils_diagnostic lib
- "utils/diagnostic/printer_other.cc"
- )
-endif((NOT TINT_BUILD_IS_LINUX) AND (NOT TINT_BUILD_IS_MAC) AND (NOT TINT_BUILD_IS_WIN))
-
-if(TINT_BUILD_IS_LINUX OR TINT_BUILD_IS_MAC)
- tint_target_add_sources(tint_utils_diagnostic lib
- "utils/diagnostic/printer_posix.cc"
- )
-endif(TINT_BUILD_IS_LINUX OR TINT_BUILD_IS_MAC)
-
-if(TINT_BUILD_IS_WIN)
- tint_target_add_sources(tint_utils_diagnostic lib
- "utils/diagnostic/printer_windows.cc"
- )
-endif(TINT_BUILD_IS_WIN)
-
################################################################################
# Target: tint_utils_diagnostic_test
# Kind: test
@@ -85,7 +65,6 @@
tint_add_target(tint_utils_diagnostic_test test
utils/diagnostic/diagnostic_test.cc
utils/diagnostic/formatter_test.cc
- utils/diagnostic/printer_test.cc
utils/diagnostic/source_test.cc
)
diff --git a/src/tint/utils/diagnostic/BUILD.gn b/src/tint/utils/diagnostic/BUILD.gn
index 4bc6b72..ccb2594 100644
--- a/src/tint/utils/diagnostic/BUILD.gn
+++ b/src/tint/utils/diagnostic/BUILD.gn
@@ -48,8 +48,6 @@
"diagnostic.h",
"formatter.cc",
"formatter.h",
- "printer.cc",
- "printer.h",
"source.cc",
"source.h",
]
@@ -63,25 +61,12 @@
"${tint_src_dir}/utils/text",
"${tint_src_dir}/utils/traits",
]
-
- if (!tint_build_is_linux && !tint_build_is_mac && !tint_build_is_win) {
- sources += [ "printer_other.cc" ]
- }
-
- if (tint_build_is_linux || tint_build_is_mac) {
- sources += [ "printer_posix.cc" ]
- }
-
- if (tint_build_is_win) {
- sources += [ "printer_windows.cc" ]
- }
}
if (tint_build_unittests) {
tint_unittests_source_set("unittests") {
sources = [
"diagnostic_test.cc",
"formatter_test.cc",
- "printer_test.cc",
"source_test.cc",
]
deps = [
diff --git a/src/tint/utils/diagnostic/diagnostic.cc b/src/tint/utils/diagnostic/diagnostic.cc
index 404d9fa..2a21caa 100644
--- a/src/tint/utils/diagnostic/diagnostic.cc
+++ b/src/tint/utils/diagnostic/diagnostic.cc
@@ -30,6 +30,7 @@
#include <unordered_map>
#include "src/tint/utils/diagnostic/formatter.h"
+#include "src/tint/utils/text/styled_text.h"
namespace tint::diag {
@@ -69,7 +70,7 @@
std::string List::Str() const {
diag::Formatter::Style style;
style.print_newline_at_end = false;
- return Formatter{style}.Format(*this);
+ return Formatter{style}.Format(*this).Plain();
}
} // namespace tint::diag
diff --git a/src/tint/utils/diagnostic/diagnostic.h b/src/tint/utils/diagnostic/diagnostic.h
index ac5c42a..69f77d2 100644
--- a/src/tint/utils/diagnostic/diagnostic.h
+++ b/src/tint/utils/diagnostic/diagnostic.h
@@ -35,6 +35,7 @@
#include "src/tint/utils/containers/vector.h"
#include "src/tint/utils/diagnostic/source.h"
+#include "src/tint/utils/text/styled_text.h"
#include "src/tint/utils/traits/traits.h"
namespace tint::diag {
@@ -85,12 +86,19 @@
/// @return this diagnostic
Diagnostic& operator=(const Diagnostic&);
+ /// Appends @p msg to the diagnostic's message
+ template <typename T>
+ Diagnostic& operator<<(T&& msg) {
+ message << std::forward<T>(msg);
+ return *this;
+ }
+
/// severity is the severity of the diagnostic message.
Severity severity = Severity::Error;
/// source is the location of the diagnostic.
Source source;
/// message is the text associated with the diagnostic.
- std::string message;
+ StyledText message;
/// system is the Tint system that raised the diagnostic.
System system;
/// A shared pointer to a Source::File. Only used if the diagnostic Source
@@ -171,80 +179,56 @@
/// Adds the note message with the given Source to the end of this list.
/// @param system the system raising the note message
- /// @param note_msg the note message
/// @param source the source of the note diagnostic
/// @returns a reference to the new diagnostic.
/// @note The returned reference must not be used after the list is mutated again.
- diag::Diagnostic& AddNote(System system, std::string_view note_msg, const Source& source) {
+ diag::Diagnostic& AddNote(System system, const Source& source) {
diag::Diagnostic note{};
note.severity = diag::Severity::Note;
note.system = system;
note.source = source;
- note.message = note_msg;
return Add(std::move(note));
}
/// Adds the warning message with the given Source to the end of this list.
/// @param system the system raising the warning message
- /// @param warning_msg the warning message
/// @param source the source of the warning diagnostic
/// @returns a reference to the new diagnostic.
/// @note The returned reference must not be used after the list is mutated again.
- diag::Diagnostic& AddWarning(System system,
- std::string_view warning_msg,
- const Source& source) {
+ diag::Diagnostic& AddWarning(System system, const Source& source) {
diag::Diagnostic warning{};
warning.severity = diag::Severity::Warning;
warning.system = system;
warning.source = source;
- warning.message = warning_msg;
return Add(std::move(warning));
}
- /// Adds the error message without a source to the end of this list.
- /// @param system the system raising the error message
- /// @param err_msg the error message
- /// @returns a reference to the new diagnostic.
- /// @note The returned reference must not be used after the list is mutated again.
- diag::Diagnostic& AddError(System system, std::string_view err_msg) {
- diag::Diagnostic error{};
- error.severity = diag::Severity::Error;
- error.system = system;
- error.message = err_msg;
- return Add(std::move(error));
- }
-
/// Adds the error message with the given Source to the end of this list.
/// @param system the system raising the error message
- /// @param err_msg the error message
/// @param source the source of the error diagnostic
/// @returns a reference to the new diagnostic.
/// @note The returned reference must not be used after the list is mutated again.
- diag::Diagnostic& AddError(System system, std::string_view err_msg, const Source& source) {
+ diag::Diagnostic& AddError(System system, const Source& source) {
diag::Diagnostic error{};
error.severity = diag::Severity::Error;
error.system = system;
error.source = source;
- error.message = err_msg;
return Add(std::move(error));
}
/// Adds an internal compiler error message to the end of this list.
/// @param system the system raising the error message
- /// @param err_msg the error message
/// @param source the source of the internal compiler error
/// @param file the Source::File owned by this diagnostic
/// @returns a reference to the new diagnostic.
/// @note The returned reference must not be used after the list is mutated again.
diag::Diagnostic& AddIce(System system,
- std::string_view err_msg,
const Source& source,
std::shared_ptr<Source::File> file) {
diag::Diagnostic ice{};
ice.severity = diag::Severity::InternalCompilerError;
ice.system = system;
ice.source = source;
- ice.message = err_msg;
ice.owned_file = std::move(file);
return Add(std::move(ice));
}
diff --git a/src/tint/utils/diagnostic/formatter.cc b/src/tint/utils/diagnostic/formatter.cc
index a256a8a..664c4f8 100644
--- a/src/tint/utils/diagnostic/formatter.cc
+++ b/src/tint/utils/diagnostic/formatter.cc
@@ -33,13 +33,16 @@
#include <vector>
#include "src/tint/utils/diagnostic/diagnostic.h"
-#include "src/tint/utils/diagnostic/printer.h"
+#include "src/tint/utils/macros/defer.h"
#include "src/tint/utils/text/string_stream.h"
+#include "src/tint/utils/text/styled_text.h"
+#include "src/tint/utils/text/styled_text_printer.h"
+#include "src/tint/utils/text/text_style.h"
namespace tint::diag {
namespace {
-const char* to_str(Severity severity) {
+const char* ToString(Severity severity) {
switch (severity) {
case Severity::Note:
return "note";
@@ -55,7 +58,7 @@
return "";
}
-std::string to_str(const Source::Location& location) {
+std::string ToString(const Source::Location& location) {
StringStream ss;
if (location.line > 0) {
ss << location.line;
@@ -68,138 +71,84 @@
} // namespace
-/// State holds the internal formatter state for a format() call.
-struct Formatter::State {
- /// Constructs a State associated with the given printer.
- /// @param p the printer to write formatted messages to.
- explicit State(Printer* p) : printer(p) {}
- ~State() { flush(); }
-
- /// SetStyle sets the current style to new_style, flushing any pending messages to the printer
- /// if the style changed.
- /// @param new_style the new style to apply for future written messages.
- void SetStyle(const diag::Style& new_style) {
- if (style.color != new_style.color || style.bold != new_style.bold) {
- flush();
- style = new_style;
- }
- }
-
- /// flush writes any pending messages to the printer, clearing the buffer.
- void flush() {
- auto str = stream.str();
- if (str.length() > 0) {
- printer->Write(str, style);
- StringStream reset;
- stream.swap(reset);
- }
- }
-
- /// operator<< queues msg to be written to the printer.
- /// @param msg the value or string to write to the printer
- /// @returns this State so that calls can be chained
- template <typename T>
- State& operator<<(T&& msg) {
- stream << std::forward<T>(msg);
- return *this;
- }
-
- /// Newline queues a newline to be written to the printer.
- void Newline() { stream << std::endl; }
-
- /// repeat queues the character c to be written to the printer n times.
- /// @param c the character to print `n` times
- /// @param n the number of times to print character `c`
- void repeat(char c, size_t n) { stream.repeat(c, n); }
-
- private:
- Printer* printer;
- diag::Style style;
- StringStream stream;
-};
-
Formatter::Formatter() {}
Formatter::Formatter(const Style& style) : style_(style) {}
-void Formatter::Format(const List& list, Printer* printer) const {
- State state{printer};
+StyledText Formatter::Format(const List& list) const {
+ StyledText text;
bool first = true;
for (auto diag : list) {
- state.SetStyle({});
if (!first) {
- state.Newline();
+ text << "\n";
}
- Format(diag, state);
+ Format(diag, text);
first = false;
}
if (style_.print_newline_at_end) {
- state.Newline();
+ text << "\n";
}
+
+ return text;
}
-void Formatter::Format(const Diagnostic& diag, State& state) const {
+void Formatter::Format(const Diagnostic& diag, StyledText& text) const {
auto const& src = diag.source;
auto const& rng = src.range;
- state.SetStyle({Color::kDefault, true});
+ text << style::Plain;
+ TINT_DEFER(text << style::Plain);
- struct TextAndColor {
+ struct TextAndStyle {
std::string text;
- Color color;
- bool bold = false;
+ TextStyle style = {};
};
- std::vector<TextAndColor> prefix;
- prefix.reserve(6);
+ Vector<TextAndStyle, 6> prefix;
if (style_.print_file && src.file != nullptr) {
if (rng.begin.line > 0) {
- prefix.emplace_back(
- TextAndColor{src.file->path + ":" + to_str(rng.begin), Color::kDefault});
+ prefix.Push(TextAndStyle{src.file->path + ":" + ToString(rng.begin)});
} else {
- prefix.emplace_back(TextAndColor{src.file->path, Color::kDefault});
+ prefix.Push(TextAndStyle{src.file->path});
}
} else if (rng.begin.line > 0) {
- prefix.emplace_back(TextAndColor{to_str(rng.begin), Color::kDefault});
+ prefix.Push(TextAndStyle{ToString(rng.begin)});
}
- Color severity_color = Color::kDefault;
- switch (diag.severity) {
- case Severity::Note:
- break;
- case Severity::Warning:
- severity_color = Color::kYellow;
- break;
- case Severity::Error:
- severity_color = Color::kRed;
- break;
- case Severity::Fatal:
- case Severity::InternalCompilerError:
- severity_color = Color::kMagenta;
- break;
- }
if (style_.print_severity) {
- prefix.emplace_back(TextAndColor{to_str(diag.severity), severity_color, true});
- }
-
- for (size_t i = 0; i < prefix.size(); i++) {
- if (i > 0) {
- state << " ";
+ TextStyle style;
+ switch (diag.severity) {
+ case Severity::Note:
+ break;
+ case Severity::Warning:
+ style = style::Warning + style::Bold;
+ break;
+ case Severity::Error:
+ style = style::Error + style::Bold;
+ break;
+ case Severity::Fatal:
+ case Severity::InternalCompilerError:
+ style = style::Fatal + style::Bold;
+ break;
}
- state.SetStyle({prefix[i].color, prefix[i].bold});
- state << prefix[i].text;
+ prefix.Push(TextAndStyle{ToString(diag.severity), style});
}
- state.SetStyle({Color::kDefault, true});
- if (!prefix.empty()) {
- state << ": ";
+ for (size_t i = 0; i < prefix.Length(); i++) {
+ if (i > 0) {
+ text << " ";
+ }
+ text << prefix[i].style << prefix[i].text;
}
- state << diag.message;
+
+ if (!prefix.IsEmpty()) {
+ text << style::Plain << ": ";
+ }
+ text << style::Bold << diag.message;
if (style_.print_line && src.file && rng.begin.line > 0) {
- state.Newline();
- state.SetStyle({Color::kDefault, false});
+ text << style::Plain << "\n";
for (size_t line_num = rng.begin.line;
(line_num <= rng.end.line) && (line_num <= src.file->content.lines.size());
@@ -210,16 +159,16 @@
bool is_ascii = true;
for (auto c : line) {
if (c == '\t') {
- state.repeat(' ', style_.tab_width);
+ text.Repeat(' ', style_.tab_width);
} else {
- state << c;
+ text << c;
}
if (c & 0x80) {
is_ascii = false;
}
}
- state.Newline();
+ text << style::Plain << "\n";
// If the line contains non-ascii characters, then we cannot assume that
// a single utf8 code unit represents a single glyph, so don't attempt to
@@ -228,7 +177,7 @@
continue;
}
- state.SetStyle({Color::kCyan, false});
+ text << style::Squiggle;
// Count the number of glyphs in the line span.
// start and end use 1-based indexing.
@@ -244,33 +193,24 @@
if (line_num == rng.begin.line && line_num == rng.end.line) {
// Single line
- state.repeat(' ', num_glyphs(1, rng.begin.column));
- state.repeat('^',
- std::max<size_t>(num_glyphs(rng.begin.column, rng.end.column), 1));
+ text.Repeat(' ', num_glyphs(1, rng.begin.column));
+ text.Repeat('^', std::max<size_t>(num_glyphs(rng.begin.column, rng.end.column), 1));
} else if (line_num == rng.begin.line) {
// Start of multi-line
- state.repeat(' ', num_glyphs(1, rng.begin.column));
- state.repeat('^', num_glyphs(rng.begin.column, line_len + 1));
+ text.Repeat(' ', num_glyphs(1, rng.begin.column));
+ text.Repeat('^', num_glyphs(rng.begin.column, line_len + 1));
} else if (line_num == rng.end.line) {
// End of multi-line
- state.repeat('^', num_glyphs(1, rng.end.column));
+ text.Repeat('^', num_glyphs(1, rng.end.column));
} else {
// Middle of multi-line
- state.repeat('^', num_glyphs(1, line_len + 1));
+ text.Repeat('^', num_glyphs(1, line_len + 1));
}
- state.Newline();
+ text << style::Plain << "\n";
}
-
- state.SetStyle({});
}
}
-std::string Formatter::Format(const List& list) const {
- StringPrinter printer;
- Format(list, &printer);
- return printer.str();
-}
-
Formatter::~Formatter() = default;
} // namespace tint::diag
diff --git a/src/tint/utils/diagnostic/formatter.h b/src/tint/utils/diagnostic/formatter.h
index 63da5e2..b744ff6 100644
--- a/src/tint/utils/diagnostic/formatter.h
+++ b/src/tint/utils/diagnostic/formatter.h
@@ -30,12 +30,17 @@
#include <string>
+// Forward declaration
+namespace tint {
+class StyledTextPrinter;
+class StyledText;
+} // namespace tint
namespace tint::diag {
-
class Diagnostic;
class List;
-class Printer;
+} // namespace tint::diag
+namespace tint::diag {
/// Formatter are used to print a list of diagnostics messages.
class Formatter {
public:
@@ -62,18 +67,14 @@
~Formatter();
- /// @param list the list of diagnostic messages to format
- /// @param printer the printer used to display the formatted diagnostics
- void Format(const List& list, Printer* printer) const;
-
/// @return the list of diagnostics `list` formatted to a string.
/// @param list the list of diagnostic messages to format
- std::string Format(const List& list) const;
+ StyledText Format(const List& list) const;
private:
struct State;
- void Format(const Diagnostic& diag, State& state) const;
+ void Format(const Diagnostic& diag, StyledText& text) const;
const Style style_;
};
diff --git a/src/tint/utils/diagnostic/formatter_test.cc b/src/tint/utils/diagnostic/formatter_test.cc
index 44e63dc1..6d77367 100644
--- a/src/tint/utils/diagnostic/formatter_test.cc
+++ b/src/tint/utils/diagnostic/formatter_test.cc
@@ -31,6 +31,7 @@
#include "gtest/gtest.h"
#include "src/tint/utils/diagnostic/diagnostic.h"
+#include "src/tint/utils/text/styled_text.h"
namespace tint::diag {
namespace {
@@ -106,7 +107,7 @@
TEST_F(DiagFormatterTest, Simple) {
Formatter fmt{{false, false, false, false}};
- auto got = fmt.Format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err});
+ auto got = fmt.Format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err}).Plain();
auto* expect = R"(1:14: purr
2:14: grrr
3:16: hiss)";
@@ -115,7 +116,7 @@
TEST_F(DiagFormatterTest, SimpleNewlineAtEnd) {
Formatter fmt{{false, false, false, true}};
- auto got = fmt.Format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err});
+ auto got = fmt.Format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err}).Plain();
auto* expect = R"(1:14: purr
2:14: grrr
3:16: hiss
@@ -126,14 +127,14 @@
TEST_F(DiagFormatterTest, SimpleNoSource) {
Formatter fmt{{false, false, false, false}};
auto diag = Diag(Severity::Note, Source{}, "no source!", System::Test);
- auto got = fmt.Format(List{diag});
+ auto got = fmt.Format(List{diag}).Plain();
auto* expect = "no source!";
ASSERT_EQ(expect, got);
}
TEST_F(DiagFormatterTest, WithFile) {
Formatter fmt{{true, false, false, false}};
- auto got = fmt.Format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err});
+ auto got = fmt.Format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err}).Plain();
auto* expect = R"(file.name:1:14: purr
file.name:2:14: grrr
file.name:3:16: hiss)";
@@ -142,7 +143,7 @@
TEST_F(DiagFormatterTest, WithSeverity) {
Formatter fmt{{false, true, false, false}};
- auto got = fmt.Format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err});
+ auto got = fmt.Format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err}).Plain();
auto* expect = R"(1:14 note: purr
2:14 warning: grrr
3:16 error: hiss)";
@@ -151,7 +152,7 @@
TEST_F(DiagFormatterTest, WithLine) {
Formatter fmt{{false, false, true, false}};
- auto got = fmt.Format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err});
+ auto got = fmt.Format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err}).Plain();
auto* expect = R"(1:14: purr
the cat says meow
^
@@ -169,7 +170,7 @@
TEST_F(DiagFormatterTest, UnicodeWithLine) {
Formatter fmt{{false, false, true, false}};
- auto got = fmt.Format(List{utf8_diag_note, utf8_diag_warn, utf8_diag_err});
+ auto got = fmt.Format(List{utf8_diag_note, utf8_diag_warn, utf8_diag_err}).Plain();
auto* expect =
"1:15: purr\n"
"the \xf0\x9f\x90\xb1 says meow\n"
@@ -184,7 +185,7 @@
TEST_F(DiagFormatterTest, BasicWithFileSeverityLine) {
Formatter fmt{{true, true, true, false}};
- auto got = fmt.Format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err});
+ auto got = fmt.Format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err}).Plain();
auto* expect = R"(file.name:1:14 note: purr
the cat says meow
^
@@ -204,7 +205,7 @@
auto multiline = Diag(Severity::Warning, Source{Source::Range{{2, 9}, {4, 15}}, &ascii_file},
"multiline", System::Test);
Formatter fmt{{false, false, true, false}};
- auto got = fmt.Format(List{multiline});
+ auto got = fmt.Format(List{multiline}).Plain();
auto* expect = R"(2:9: multiline
the dog says woof
^^^^^^^^^^
@@ -220,7 +221,7 @@
auto multiline = Diag(Severity::Warning, Source{Source::Range{{2, 9}, {4, 15}}, &utf8_file},
"multiline", System::Test);
Formatter fmt{{false, false, true, false}};
- auto got = fmt.Format(List{multiline});
+ auto got = fmt.Format(List{multiline}).Plain();
auto* expect =
"2:9: multiline\n"
"the \xf0\x9f\x90\x95 says woof\n"
@@ -231,7 +232,7 @@
TEST_F(DiagFormatterTest, BasicWithFileSeverityLineTab4) {
Formatter fmt{{true, true, true, false, 4u}};
- auto got = fmt.Format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err});
+ auto got = fmt.Format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err}).Plain();
auto* expect = R"(file.name:1:14 note: purr
the cat says meow
^
@@ -251,7 +252,7 @@
auto multiline = Diag(Severity::Warning, Source{Source::Range{{2, 9}, {4, 15}}, &ascii_file},
"multiline", System::Test);
Formatter fmt{{false, false, true, false, 4u}};
- auto got = fmt.Format(List{multiline});
+ auto got = fmt.Format(List{multiline}).Plain();
auto* expect = R"(2:9: multiline
the dog says woof
^^^^^^^^^^^^
@@ -265,7 +266,7 @@
TEST_F(DiagFormatterTest, ICE) {
Formatter fmt{{}};
- auto got = fmt.Format(List{ascii_diag_ice});
+ auto got = fmt.Format(List{ascii_diag_ice}).Plain();
auto* expect = R"(file.name:4:16 internal compiler error: unreachable
the snail says ???
^^^
@@ -276,7 +277,7 @@
TEST_F(DiagFormatterTest, Fatal) {
Formatter fmt{{}};
- auto got = fmt.Format(List{ascii_diag_fatal});
+ auto got = fmt.Format(List{ascii_diag_fatal}).Plain();
auto* expect = R"(file.name:4:16 fatal: nothing
the snail says ???
^^^
@@ -288,8 +289,8 @@
TEST_F(DiagFormatterTest, RangeOOB) {
Formatter fmt{{true, true, true, true}};
diag::List list;
- list.AddError(System::Test, "oob", Source{{{10, 20}, {30, 20}}, &ascii_file});
- auto got = fmt.Format(list);
+ list.AddError(System::Test, Source{{{10, 20}, {30, 20}}, &ascii_file}) << "oob";
+ auto got = fmt.Format(list).Plain();
auto* expect = R"(file.name:10:20 error: oob
)";
diff --git a/src/tint/utils/diagnostic/printer.cc b/src/tint/utils/diagnostic/printer.cc
deleted file mode 100644
index 819dc58..0000000
--- a/src/tint/utils/diagnostic/printer.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/utils/diagnostic/printer.h"
-
-#include <string>
-
-namespace tint::diag {
-
-Printer::~Printer() = default;
-
-StringPrinter::StringPrinter() = default;
-StringPrinter::~StringPrinter() = default;
-
-std::string StringPrinter::str() const {
- return stream.str();
-}
-
-void StringPrinter::Write(const std::string& str, const Style&) {
- stream << str;
-}
-
-} // namespace tint::diag
diff --git a/src/tint/utils/diagnostic/printer.h b/src/tint/utils/diagnostic/printer.h
deleted file mode 100644
index 2b361b8..0000000
--- a/src/tint/utils/diagnostic/printer.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef SRC_TINT_UTILS_DIAGNOSTIC_PRINTER_H_
-#define SRC_TINT_UTILS_DIAGNOSTIC_PRINTER_H_
-
-#include <memory>
-#include <sstream>
-#include <string>
-
-namespace tint::diag {
-
-class List;
-
-/// Color is an enumerator of colors used by Style.
-enum class Color {
- kDefault,
- kBlack,
- kRed,
- kGreen,
- kYellow,
- kBlue,
- kMagenta,
- kCyan,
- kWhite,
-};
-
-/// Style describes how a diagnostic message should be printed.
-struct Style {
- /// The foreground text color
- Color color = Color::kDefault;
- /// If true the text will be displayed with a strong weight
- bool bold = false;
-};
-
-/// Printers are used to print formatted diagnostic messages to a stream.
-class Printer {
- public:
- /// @returns a diagnostic Printer
- /// @param out the file to print to.
- /// @param use_colors if true, the printer will use colors if `out` is a terminal and supports
- /// them.
- static std::unique_ptr<Printer> Create(FILE* out, bool use_colors);
-
- virtual ~Printer();
-
- /// writes the string str to the printer with the given style.
- /// @param str the string to write to the printer
- /// @param style the style used to print `str`
- virtual void Write(const std::string& str, const Style& style) = 0;
-};
-
-/// StringPrinter is an implementation of Printer that writes to a std::string.
-class StringPrinter : public Printer {
- public:
- StringPrinter();
- ~StringPrinter() override;
-
- /// @returns the printed string.
- std::string str() const;
-
- void Write(const std::string& str, const Style&) override;
-
- private:
- std::stringstream stream;
-};
-
-} // namespace tint::diag
-
-#endif // SRC_TINT_UTILS_DIAGNOSTIC_PRINTER_H_
diff --git a/src/tint/utils/diagnostic/printer_other.cc b/src/tint/utils/diagnostic/printer_other.cc
deleted file mode 100644
index b311e5a..0000000
--- a/src/tint/utils/diagnostic/printer_other.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// GEN_BUILD:CONDITION((!tint_build_is_linux) && (!tint_build_is_mac) && (!tint_build_is_win))
-
-#include <cstring>
-
-#include "src/tint/utils/diagnostic/printer.h"
-
-namespace tint::diag {
-namespace {
-
-class PrinterOther : public Printer {
- public:
- explicit PrinterOther(FILE* f) : file(f) {}
-
- void Write(const std::string& str, const Style&) override {
- fwrite(str.data(), 1, str.size(), file);
- }
-
- private:
- FILE* file;
-};
-
-} // namespace
-
-std::unique_ptr<Printer> Printer::Create(FILE* out, bool) {
- return std::make_unique<PrinterOther>(out);
-}
-
-} // namespace tint::diag
diff --git a/src/tint/utils/diagnostic/printer_posix.cc b/src/tint/utils/diagnostic/printer_posix.cc
deleted file mode 100644
index 156c3ce..0000000
--- a/src/tint/utils/diagnostic/printer_posix.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// GEN_BUILD:CONDITION(tint_build_is_linux || tint_build_is_mac)
-
-#include <unistd.h>
-
-#include <cstring>
-
-#include "src/tint/utils/diagnostic/printer.h"
-
-namespace tint::diag {
-namespace {
-
-bool supports_colors(FILE* f) {
- if (!isatty(fileno(f))) {
- return false;
- }
-
- const char* cterm = getenv("TERM");
- if (cterm == nullptr) {
- return false;
- }
-
- std::string term = getenv("TERM");
- if (term != "cygwin" && term != "linux" && term != "rxvt-unicode-256color" &&
- term != "rxvt-unicode" && term != "screen-256color" && term != "screen" &&
- term != "tmux-256color" && term != "tmux" && term != "xterm-256color" &&
- term != "xterm-color" && term != "xterm") {
- return false;
- }
-
- return true;
-}
-
-class PrinterPosix : public Printer {
- public:
- PrinterPosix(FILE* f, bool colors) : file(f), use_colors(colors && supports_colors(f)) {}
-
- void Write(const std::string& str, const Style& style) override {
- WriteColor(style.color, style.bold);
- fwrite(str.data(), 1, str.size(), file);
- WriteColor(Color::kDefault, false);
- }
-
- private:
- constexpr const char* ColorCode(Color color, bool bold) {
- switch (color) {
- case Color::kDefault:
- return bold ? "\u001b[1m" : "\u001b[0m";
- case Color::kBlack:
- return bold ? "\u001b[30;1m" : "\u001b[30m";
- case Color::kRed:
- return bold ? "\u001b[31;1m" : "\u001b[31m";
- case Color::kGreen:
- return bold ? "\u001b[32;1m" : "\u001b[32m";
- case Color::kYellow:
- return bold ? "\u001b[33;1m" : "\u001b[33m";
- case Color::kBlue:
- return bold ? "\u001b[34;1m" : "\u001b[34m";
- case Color::kMagenta:
- return bold ? "\u001b[35;1m" : "\u001b[35m";
- case Color::kCyan:
- return bold ? "\u001b[36;1m" : "\u001b[36m";
- case Color::kWhite:
- return bold ? "\u001b[37;1m" : "\u001b[37m";
- }
- return ""; // unreachable
- }
-
- void WriteColor(Color color, bool bold) {
- if (use_colors) {
- auto* code = ColorCode(color, bold);
- fwrite(code, 1, strlen(code), file);
- }
- }
-
- FILE* const file;
- const bool use_colors;
-};
-
-} // namespace
-
-std::unique_ptr<Printer> Printer::Create(FILE* out, bool use_colors) {
- return std::make_unique<PrinterPosix>(out, use_colors);
-}
-
-} // namespace tint::diag
diff --git a/src/tint/utils/diagnostic/printer_test.cc b/src/tint/utils/diagnostic/printer_test.cc
deleted file mode 100644
index aeb1fa2..0000000
--- a/src/tint/utils/diagnostic/printer_test.cc
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/utils/diagnostic/printer.h"
-
-#include "gtest/gtest.h"
-
-namespace tint::diag {
-namespace {
-
-// Actually verifying that the expected colors are printed is exceptionally
-// difficult as:
-// a) The color emission varies by OS.
-// b) The logic checks to see if the printer is writing to a terminal, making
-// mocking hard.
-// c) Actually probing what gets written to a FILE* is notoriously tricky.
-//
-// The least we can do is to exersice the code - which is what we do here.
-// The test will print each of the colors, and can be examined with human
-// eyeballs.
-// This can be enabled or disabled with ENABLE_PRINTER_TESTS
-#define ENABLE_PRINTER_TESTS 0
-#if ENABLE_PRINTER_TESTS
-
-using PrinterTest = testing::Test;
-
-TEST_F(PrinterTest, WithColors) {
- auto printer = Printer::Create(stdout, true);
- printer->Write("Default", Style{Color::kDefault, false});
- printer->Write("Black", Style{Color::kBlack, false});
- printer->Write("Red", Style{Color::kRed, false});
- printer->Write("Green", Style{Color::kGreen, false});
- printer->Write("Yellow", Style{Color::kYellow, false});
- printer->Write("Blue", Style{Color::kBlue, false});
- printer->Write("Magenta", Style{Color::kMagenta, false});
- printer->Write("Cyan", Style{Color::kCyan, false});
- printer->Write("White", Style{Color::kWhite, false});
- printf("\n");
-}
-
-TEST_F(PrinterTest, BoldWithColors) {
- auto printer = Printer::Create(stdout, true);
- printer->Write("Default", Style{Color::kDefault, true});
- printer->Write("Black", Style{Color::kBlack, true});
- printer->Write("Red", Style{Color::kRed, true});
- printer->Write("Green", Style{Color::kGreen, true});
- printer->Write("Yellow", Style{Color::kYellow, true});
- printer->Write("Blue", Style{Color::kBlue, true});
- printer->Write("Magenta", Style{Color::kMagenta, true});
- printer->Write("Cyan", Style{Color::kCyan, true});
- printer->Write("White", Style{Color::kWhite, true});
- printf("\n");
-}
-
-TEST_F(PrinterTest, WithoutColors) {
- auto printer = Printer::Create(stdout, false);
- printer->Write("Default", Style{Color::kDefault, false});
- printer->Write("Black", Style{Color::kBlack, false});
- printer->Write("Red", Style{Color::kRed, false});
- printer->Write("Green", Style{Color::kGreen, false});
- printer->Write("Yellow", Style{Color::kYellow, false});
- printer->Write("Blue", Style{Color::kBlue, false});
- printer->Write("Magenta", Style{Color::kMagenta, false});
- printer->Write("Cyan", Style{Color::kCyan, false});
- printer->Write("White", Style{Color::kWhite, false});
- printf("\n");
-}
-
-TEST_F(PrinterTest, BoldWithoutColors) {
- auto printer = Printer::Create(stdout, false);
- printer->Write("Default", Style{Color::kDefault, true});
- printer->Write("Black", Style{Color::kBlack, true});
- printer->Write("Red", Style{Color::kRed, true});
- printer->Write("Green", Style{Color::kGreen, true});
- printer->Write("Yellow", Style{Color::kYellow, true});
- printer->Write("Blue", Style{Color::kBlue, true});
- printer->Write("Magenta", Style{Color::kMagenta, true});
- printer->Write("Cyan", Style{Color::kCyan, true});
- printer->Write("White", Style{Color::kWhite, true});
- printf("\n");
-}
-
-#endif // ENABLE_PRINTER_TESTS
-} // namespace
-} // namespace tint::diag
diff --git a/src/tint/utils/diagnostic/printer_windows.cc b/src/tint/utils/diagnostic/printer_windows.cc
deleted file mode 100644
index 485e9a9..0000000
--- a/src/tint/utils/diagnostic/printer_windows.cc
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// GEN_BUILD:CONDITION(tint_build_is_win)
-
-#include <cstring>
-
-#include "src/tint/utils/diagnostic/printer.h"
-
-#define WIN32_LEAN_AND_MEAN 1
-#include <Windows.h>
-
-namespace tint::diag {
-namespace {
-
-struct ConsoleInfo {
- HANDLE handle = INVALID_HANDLE_VALUE;
- WORD default_attributes = 0;
- operator bool() const { return handle != INVALID_HANDLE_VALUE; }
-};
-
-ConsoleInfo ConsoleInfoFor(FILE* file) {
- if (file == nullptr) {
- return {};
- }
-
- ConsoleInfo console{};
- if (file == stdout) {
- console.handle = GetStdHandle(STD_OUTPUT_HANDLE);
- } else if (file == stderr) {
- console.handle = GetStdHandle(STD_ERROR_HANDLE);
- } else {
- return {};
- }
-
- CONSOLE_SCREEN_BUFFER_INFO info{};
- if (GetConsoleScreenBufferInfo(console.handle, &info) == 0) {
- return {};
- }
-
- console.default_attributes = info.wAttributes;
- return console;
-}
-
-class PrinterWindows : public Printer {
- public:
- PrinterWindows(FILE* f, bool use_colors)
- : file(f), console(ConsoleInfoFor(use_colors ? f : nullptr)) {}
-
- void Write(const std::string& str, const Style& style) override {
- WriteColor(style.color, style.bold);
- fwrite(str.data(), 1, str.size(), file);
- WriteColor(Color::kDefault, false);
- }
-
- private:
- WORD Attributes(Color color, bool bold) {
- switch (color) {
- case Color::kDefault:
- return console.default_attributes;
- case Color::kBlack:
- return 0;
- case Color::kRed:
- return FOREGROUND_RED | (bold ? FOREGROUND_INTENSITY : 0);
- case Color::kGreen:
- return FOREGROUND_GREEN | (bold ? FOREGROUND_INTENSITY : 0);
- case Color::kYellow:
- return FOREGROUND_RED | FOREGROUND_GREEN | (bold ? FOREGROUND_INTENSITY : 0);
- case Color::kBlue:
- return FOREGROUND_BLUE | (bold ? FOREGROUND_INTENSITY : 0);
- case Color::kMagenta:
- return FOREGROUND_RED | FOREGROUND_BLUE | (bold ? FOREGROUND_INTENSITY : 0);
- case Color::kCyan:
- return FOREGROUND_GREEN | FOREGROUND_BLUE | (bold ? FOREGROUND_INTENSITY : 0);
- case Color::kWhite:
- return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE |
- (bold ? FOREGROUND_INTENSITY : 0);
- }
- return 0; // unreachable
- }
-
- void WriteColor(Color color, bool bold) {
- if (console) {
- SetConsoleTextAttribute(console.handle, Attributes(color, bold));
- fflush(file);
- }
- }
-
- FILE* const file;
- const ConsoleInfo console;
-};
-
-} // namespace
-
-std::unique_ptr<Printer> Printer::Create(FILE* out, bool use_colors) {
- return std::make_unique<PrinterWindows>(out, use_colors);
-}
-
-} // namespace tint::diag
diff --git a/src/tint/utils/result/result.cc b/src/tint/utils/result/result.cc
index 016e2fb..a3ecfc3 100644
--- a/src/tint/utils/result/result.cc
+++ b/src/tint/utils/result/result.cc
@@ -32,7 +32,7 @@
Failure::Failure() = default;
Failure::Failure(std::string_view err) {
- reason.AddError(diag::System::Unknown, err, Source{});
+ reason.AddError(diag::System::Unknown, Source{}) << err;
}
Failure::Failure(diag::Diagnostic diagnostic) : reason(diag::List{std::move(diagnostic)}) {}
diff --git a/src/tint/utils/templates/intrinsic_table_data.tmpl.inc b/src/tint/utils/templates/intrinsic_table_data.tmpl.inc
index c7a8ba5..0308082 100644
--- a/src/tint/utils/templates/intrinsic_table_data.tmpl.inc
+++ b/src/tint/utils/templates/intrinsic_table_data.tmpl.inc
@@ -285,19 +285,17 @@
{{- end }}
return Build{{$name}}(state, ty{{range .TemplateParams}}, {{.GetName}}{{end}});
},
-/* string */ [](MatchState*{{if .TemplateParams}} state{{end}}) -> std::string {
+/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {
{{- range .TemplateParams }}
{{- template "DeclareLocalTemplateParamName" . }}
{{- end }}
{{- if .DisplayName }}
- StringStream ss;
- ss{{range SplitDisplayName .DisplayName}} << {{.}}{{end}};
- return ss.str();
+ out {{range SplitDisplayName .DisplayName}} << style::Type << {{.}}{{end}};
{{- else if .TemplateParams }}
- return "{{.Name}}<"{{template "AppendTemplateParamNames" .TemplateParams}} + ">";
+ out << style::Type << "{{.Name}}" << style::Code << "<"{{template "AppendTemplateParamNames" .TemplateParams}} << style::Code << ">";
{{- else }}
- return "{{.Name}}";
+ out << style::Type << "{{.Name}}";
{{- end }}
}
};
@@ -319,18 +317,15 @@
{{- end }}
return nullptr;
},
-/* string */ [](MatchState*) -> std::string {
- StringStream ss;
- // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+/* print */ [](MatchState*, StyledText& out) {
+ // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
- ss
-{{- range .Types -}}
-{{- if IsFirstIn . $.Types }} << k{{PascalCase .Name}}Matcher.string(nullptr)
-{{- else if IsLastIn . $.Types }} << " or " << k{{PascalCase .Name}}Matcher.string(nullptr)
-{{- else }} << ", " << k{{PascalCase .Name}}Matcher.string(nullptr)
+{{ range .Types -}}
+{{- if IsFirstIn . $.Types }} k{{PascalCase .Name}}Matcher.print(nullptr, out);
+{{- else if IsLastIn . $.Types }} out << TextStyle{} << " or "; k{{PascalCase .Name}}Matcher.print(nullptr, out);
+{{- else }} out << TextStyle{} << ", "; k{{PascalCase .Name}}Matcher.print(nullptr, out);
{{- end -}}
-{{- end -}};
- return ss.str();
+{{- end -}}
}
};
{{ end -}}
@@ -364,15 +359,14 @@
}
},
{{- end }}
-/* string */ [](MatchState*) -> std::string {
- return "
+/* print */ [](MatchState*, StyledText& out) {
+ out
{{- range .Options -}}
-{{- if IsFirstIn . $.Options }}{{.Name}}
-{{- else if IsLastIn . $.Options }} or {{.Name}}
-{{- else }}, {{.Name}}
+{{- if IsFirstIn . $.Options }}<< style::Enum << "{{.Name}}"
+{{- else if IsLastIn . $.Options }}<< TextStyle{} << " or " << style::Enum << "{{.Name}}"
+{{- else }}<< TextStyle{} << ", " << style::Enum << "{{.Name}}"
{{- end -}}
-{{- end -}}
-";
+{{- end -}};
}
};
{{ end -}}
@@ -444,12 +438,13 @@
{{- /* ------------------------------------------------------------------ */ -}}
{{- define "DeclareLocalTemplateParamName" -}}
{{- /* ------------------------------------------------------------------ */ -}}
+ StyledText {{.Name}};
{{- if IsTemplateTypeParam . }}
- const std::string {{.Name}} = state->TypeName();
+ state->PrintType({{.Name}});
{{- else if IsTemplateNumberParam . }}
- const std::string {{.Name}} = state->NumName();
+ state->PrintNum({{.Name}});
{{- else if IsTemplateEnumParam . }}
- const std::string {{.Name}} = state->NumName();
+ state->PrintNum({{.Name}});
{{- end -}}
{{- end -}}
@@ -484,9 +479,9 @@
{{- define "AppendTemplateParamNames" -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- range $i, $ := . -}}
-{{- if $i }} + ", " + {{.Name}}
-{{- else }} + {{.Name}}
-{{- end -}}
+{{- if $i }} << style::Code << ", " << style::Type << {{.Name}}
+{{- else }} << style::Type << {{.Name}}
+{{- end -}}
{{- end -}}
{{- end -}}
diff --git a/src/tint/utils/text/string.cc b/src/tint/utils/text/string.cc
index 0812dad..374176e 100644
--- a/src/tint/utils/text/string.cc
+++ b/src/tint/utils/text/string.cc
@@ -30,6 +30,7 @@
#include "src/tint/utils/containers/transform.h"
#include "src/tint/utils/containers/vector.h"
#include "src/tint/utils/text/string.h"
+#include "src/tint/utils/text/styled_text.h"
namespace tint {
@@ -64,7 +65,7 @@
void SuggestAlternatives(std::string_view got,
Slice<const std::string_view> strings,
- StringStream& ss,
+ StyledText& ss,
const SuggestAlternativeOptions& options /* = {} */) {
// If the string typed was within kSuggestionDistance of one of the possible enum values,
// suggest that. Don't bother with suggestions if the string was extremely long.
diff --git a/src/tint/utils/text/string.h b/src/tint/utils/text/string.h
index 6ae2894..6ccd38d 100644
--- a/src/tint/utils/text/string.h
+++ b/src/tint/utils/text/string.h
@@ -35,6 +35,11 @@
#include "src/tint/utils/containers/vector.h"
#include "src/tint/utils/text/string_stream.h"
+/// Forward declaration
+namespace tint {
+class StyledText;
+}
+
namespace tint {
/// @param str the string to apply replacements to
@@ -124,7 +129,7 @@
/// @param options options for the suggestion
void SuggestAlternatives(std::string_view got,
Slice<const std::string_view> strings,
- StringStream& ss,
+ StyledText& ss,
const SuggestAlternativeOptions& options = {});
/// @param str the input string
diff --git a/src/tint/utils/text/string_test.cc b/src/tint/utils/text/string_test.cc
index b14aaac..da6e242 100644
--- a/src/tint/utils/text/string_test.cc
+++ b/src/tint/utils/text/string_test.cc
@@ -29,6 +29,7 @@
#include "gmock/gmock.h"
#include "src/tint/utils/text/string_stream.h"
+#include "src/tint/utils/text/styled_text.h"
#include "src/tint/utils/containers/transform.h" // Used by ToStringList()
@@ -95,33 +96,33 @@
TEST(StringTest, SuggestAlternatives) {
{
std::string_view alternatives[] = {"hello world", "Hello World"};
- StringStream ss;
+ StyledText ss;
SuggestAlternatives("hello wordl", alternatives, ss);
- EXPECT_EQ(ss.str(), R"(Did you mean 'hello world'?
+ EXPECT_EQ(ss.Plain(), R"(Did you mean 'hello world'?
Possible values: 'hello world', 'Hello World')");
}
{
std::string_view alternatives[] = {"foobar", "something else"};
- StringStream ss;
+ StyledText ss;
SuggestAlternatives("hello world", alternatives, ss);
- EXPECT_EQ(ss.str(), R"(Possible values: 'foobar', 'something else')");
+ EXPECT_EQ(ss.Plain(), R"(Possible values: 'foobar', 'something else')");
}
{
std::string_view alternatives[] = {"hello world", "Hello World"};
- StringStream ss;
+ StyledText ss;
SuggestAlternativeOptions opts;
opts.prefix = "$";
SuggestAlternatives("hello wordl", alternatives, ss, opts);
- EXPECT_EQ(ss.str(), R"(Did you mean '$hello world'?
+ EXPECT_EQ(ss.Plain(), R"(Did you mean '$hello world'?
Possible values: '$hello world', '$Hello World')");
}
{
std::string_view alternatives[] = {"hello world", "Hello World"};
- StringStream ss;
+ StyledText ss;
SuggestAlternativeOptions opts;
opts.list_possible_values = false;
SuggestAlternatives("hello world", alternatives, ss, opts);
- EXPECT_EQ(ss.str(), R"(Did you mean 'hello world'?)");
+ EXPECT_EQ(ss.Plain(), R"(Did you mean 'hello world'?)");
}
}