tint/resolver: Error when quantizeToF16 value is unrepresentable

...as a F16, for const-eval.

Fixed: tint:1744
Change-Id: I5eff05c6bc4727cbdfefb546602f3ee194d22612
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/108640
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Auto-Submit: Ben Clayton <bclayton@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/resolver/const_eval.cc b/src/tint/resolver/const_eval.cc
index a7f5d7d..6400798 100644
--- a/src/tint/resolver/const_eval.cc
+++ b/src/tint/resolver/const_eval.cc
@@ -2615,19 +2615,13 @@
 
 ConstEval::Result ConstEval::quantizeToF16(const sem::Type* ty,
                                            utils::VectorRef<const sem::Constant*> args,
-                                           const Source&) {
-    auto transform = [&](const sem::Constant* c) {
-        auto conv = CheckedConvert<f32>(f16(c->As<f32>()));
+                                           const Source& source) {
+    auto transform = [&](const sem::Constant* c) -> ImplResult {
+        auto value = c->As<f32>();
+        auto conv = CheckedConvert<f32>(f16(value));
         if (!conv) {
-            // https://www.w3.org/TR/WGSL/#quantizeToF16-builtin
-            // If e is outside the finite range of binary16, then the result is any value of type
-            // f32
-            switch (conv.Failure()) {
-                case ConversionFailure::kExceedsNegativeLimit:
-                    return CreateElement(builder, c->Type(), f16(f16::kLowestValue));
-                case ConversionFailure::kExceedsPositiveLimit:
-                    return CreateElement(builder, c->Type(), f16(f16::kHighestValue));
-            }
+            AddError(OverflowErrorMessage(value, "f16"), source);
+            return utils::Failure;
         }
         return CreateElement(builder, c->Type(), conv.Get());
     };
diff --git a/src/tint/resolver/const_eval_builtin_test.cc b/src/tint/resolver/const_eval_builtin_test.cc
index a85f4b6..a7a43ae 100644
--- a/src/tint/resolver/const_eval_builtin_test.cc
+++ b/src/tint/resolver/const_eval_builtin_test.cc
@@ -1916,7 +1916,6 @@
                      testing::ValuesIn(Unpack2x16unormCases())));
 
 std::vector<Case> QuantizeToF16Cases() {
-    (void)E({Vec(0_f, 0_f)}, "");  // Currently unused, but will be soon.
     return {
         C({0_f}, 0_f),    //
         C({-0_f}, -0_f),  //
@@ -1945,12 +1944,6 @@
         C({0x0.06b7p-14_f}, 0x0.068p-14_f),    //
         C({-0x0.06b7p-14_f}, -0x0.068p-14_f),  //
 
-        // Value out of f16 range
-        C({65504.003_f}, 65504_f),     //
-        C({-65504.003_f}, -65504_f),   //
-        C({0x1.234p56_f}, 65504_f),    //
-        C({-0x4.321p65_f}, -65504_f),  //
-
         // Vector tests
         C({Vec(0_f, -0_f)}, Vec(0_f, -0_f)),  //
         C({Vec(1_f, -1_f)}, Vec(1_f, -1_f)),  //
@@ -1963,8 +1956,16 @@
         C({Vec(0x0.034p-14_f, -0x0.034p-14_f, 0x0.068p-14_f, -0x0.068p-14_f)},
           Vec(0x0.034p-14_f, -0x0.034p-14_f, 0x0.068p-14_f, -0x0.068p-14_f)),
 
-        C({Vec(65504.003_f, 0x1.234p56_f)}, Vec(65504_f, 65504_f)),
-        C({Vec(-0x1.234p56_f, -65504.003_f)}, Vec(-65504_f, -65504_f)),
+        // Value out of f16 range
+        E({65504.003_f}, "12:34 error: value 65504.00390625 cannot be represented as 'f16'"),
+        E({-65504.003_f}, "12:34 error: value -65504.00390625 cannot be represented as 'f16'"),
+        E({0x1.234p56_f}, "12:34 error: value 81979586966978560 cannot be represented as 'f16'"),
+        E({0x4.321p65_f},
+          "12:34 error: value 1.5478871919272394752e+20 cannot be represented as 'f16'"),
+        E({Vec(65504.003_f, 0_f)},
+          "12:34 error: value 65504.00390625 cannot be represented as 'f16'"),
+        E({Vec(0_f, -0x4.321p65_f)},
+          "12:34 error: value -1.5478871919272394752e+20 cannot be represented as 'f16'"),
     };
 }
 INSTANTIATE_TEST_SUITE_P(  //