about summary refs log tree commit diff
path: root/src/build_helper
diff options
context:
space:
mode:
authorWeihang Lo <me@weihanglo.tw>2025-01-24 19:08:32 -0500
committerWeihang Lo <me@weihanglo.tw>2025-01-24 19:08:32 -0500
commit5f8bcec6c8e006f0b73b9bff076299f77d6c166c (patch)
tree9d5166dddf3489a2ef0163e6089f4c1939d8d863 /src/build_helper
parent1e9b0177da38e3f421a3b9b1942f1777d166e06a (diff)
downloadrust-5f8bcec6c8e006f0b73b9bff076299f77d6c166c.tar.gz
rust-5f8bcec6c8e006f0b73b9bff076299f77d6c166c.zip
fix(bootstrap): deserialize null as `f64::NAN`
When doing optimized build through opt-dist,
I've often run into errors like `invalid type: null, expected f64`.
This is likely because some f64 fields might actually bet set null.
Unfortunately, serde_json doesn't handle null <-> NaN well.

This commit addresses it by having a custom deserialize method, so
null is always be deserialized to `f64:NAN`.

See:

* https://rust-lang.zulipchat.com/#narrow/channel/242791-t-infra/topic/opt-dist.3A.20.60invalid.20type.3A.20null.2C.20expect.20f64.60.20failure
* https://github.com/serde-rs/json/issues/202
Diffstat (limited to 'src/build_helper')
-rw-r--r--src/build_helper/src/metrics.rs8
1 files changed, 8 insertions, 0 deletions
diff --git a/src/build_helper/src/metrics.rs b/src/build_helper/src/metrics.rs
index 2d0c66a8f33..538c33e9b15 100644
--- a/src/build_helper/src/metrics.rs
+++ b/src/build_helper/src/metrics.rs
@@ -16,6 +16,7 @@ pub struct JsonInvocation {
     //
     // This is necessary to easily correlate this invocation with logs or other data.
     pub start_time: u64,
+    #[serde(deserialize_with = "null_as_f64_nan")]
     pub duration_including_children_sec: f64,
     pub children: Vec<JsonNode>,
 }
@@ -28,6 +29,7 @@ pub enum JsonNode {
         type_: String,
         debug_repr: String,
 
+        #[serde(deserialize_with = "null_as_f64_nan")]
         duration_excluding_children_sec: f64,
         system_stats: JsonStepSystemStats,
 
@@ -88,5 +90,11 @@ pub struct JsonInvocationSystemStats {
 #[derive(Serialize, Deserialize)]
 #[serde(rename_all = "snake_case")]
 pub struct JsonStepSystemStats {
+    #[serde(deserialize_with = "null_as_f64_nan")]
     pub cpu_utilization_percent: f64,
 }
+
+fn null_as_f64_nan<'de, D: serde::Deserializer<'de>>(d: D) -> Result<f64, D::Error> {
+    use serde::Deserialize as _;
+    Option::<f64>::deserialize(d).map(|f| f.unwrap_or(f64::NAN))
+}