about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-07-09 16:33:36 +0200
committerGitHub <noreply@github.com>2023-07-09 16:33:36 +0200
commita46589f76b269d24d24e0f2d2762d40bb764ae9e (patch)
tree0baf7bfc512f324a65f3ebddbb2f6036c3941ada
parent6a20f681d558431831a33cf6068b4b536837bbce (diff)
parent92b5d0c4cb1f369442beb79f87aa6114987e7956 (diff)
downloadrust-a46589f76b269d24d24e0f2d2762d40bb764ae9e.tar.gz
rust-a46589f76b269d24d24e0f2d2762d40bb764ae9e.zip
Rollup merge of #113273 - hi-rustin:rustin-patch-opt-level, r=Kobzol
Use String or Int to set the opt level

Address https://github.com/rust-lang/rust/pull/112756/files#r1249345725

Use String or Int to set the opt level.

r? ``@jyn514``
-rw-r--r--config.example.toml14
-rw-r--r--src/bootstrap/config.rs73
-rw-r--r--src/bootstrap/config/tests.rs5
3 files changed, 76 insertions, 16 deletions
diff --git a/config.example.toml b/config.example.toml
index 0c65b25fe13..367f95b156f 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -400,10 +400,20 @@ changelog-seen = 2
 # =============================================================================
 [rust]
 
-# Whether or not to optimize the compiler and standard library.
+# Whether or not to optimize when compiling the compiler and standard library,
+# and what level of optimization to use.
 # WARNING: Building with optimize = false is NOT SUPPORTED. Due to bootstrapping,
 # building without optimizations takes much longer than optimizing. Further, some platforms
 # fail to build without this optimization (c.f. #65352).
+# The valid options are:
+# true - Enable optimizations.
+# false - Disable optimizations.
+# 0 - Disable optimizations.
+# 1 - Basic optimizations.
+# 2 - Some optimizations.
+# 3 - All optimizations.
+# "s" - Optimize for binary size.
+# "z" - Optimize for binary size, but also turn off loop vectorization.
 #optimize = true
 
 # Indicates that the build should be configured for debugging Rust. A
@@ -757,7 +767,7 @@ changelog-seen = 2
 # This option will override the same option under [build] section.
 #profiler = build.profiler (bool)
 
-# This option supports enable `rpath` in each target independently, 
+# This option supports enable `rpath` in each target independently,
 # and will override the same option under [rust] section. It only works on Unix platforms
 #rpath = rust.rpath (bool)
 
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 5f5f7ea25fb..28ae46efefe 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -875,11 +875,10 @@ impl Default for StringOrBool {
     }
 }
 
-#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
-#[serde(untagged)]
+#[derive(Clone, Debug, PartialEq, Eq)]
 pub enum RustOptimize {
-    #[serde(deserialize_with = "deserialize_and_validate_opt_level")]
     String(String),
+    Int(u8),
     Bool(bool),
 }
 
@@ -889,26 +888,74 @@ impl Default for RustOptimize {
     }
 }
 
-fn deserialize_and_validate_opt_level<'de, D>(d: D) -> Result<String, D::Error>
-where
-    D: serde::de::Deserializer<'de>,
-{
-    let v = String::deserialize(d)?;
-    if ["0", "1", "2", "3", "s", "z"].iter().find(|x| **x == v).is_some() {
-        Ok(v)
-    } else {
-        Err(format!(r#"unrecognized option for rust optimize: "{}", expected one of "0", "1", "2", "3", "s", "z""#, v)).map_err(serde::de::Error::custom)
+impl<'de> Deserialize<'de> for RustOptimize {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        deserializer.deserialize_any(OptimizeVisitor)
+    }
+}
+
+struct OptimizeVisitor;
+
+impl<'de> serde::de::Visitor<'de> for OptimizeVisitor {
+    type Value = RustOptimize;
+
+    fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        formatter.write_str(r#"one of: 0, 1, 2, 3, "s", "z", true, false"#)
+    }
+
+    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
+    where
+        E: serde::de::Error,
+    {
+        if ["s", "z"].iter().find(|x| **x == value).is_some() {
+            Ok(RustOptimize::String(value.to_string()))
+        } else {
+            Err(format_optimize_error_msg(value)).map_err(serde::de::Error::custom)
+        }
+    }
+
+    fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
+    where
+        E: serde::de::Error,
+    {
+        if matches!(value, 0..=3) {
+            Ok(RustOptimize::Int(value as u8))
+        } else {
+            Err(format_optimize_error_msg(value)).map_err(serde::de::Error::custom)
+        }
+    }
+
+    fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
+    where
+        E: serde::de::Error,
+    {
+        Ok(RustOptimize::Bool(value))
     }
 }
 
+fn format_optimize_error_msg(v: impl std::fmt::Display) -> String {
+    format!(
+        r#"unrecognized option for rust optimize: "{}", expected one of 0, 1, 2, 3, "s", "z", true, false"#,
+        v
+    )
+}
+
 impl RustOptimize {
     pub(crate) fn is_release(&self) -> bool {
-        if let RustOptimize::Bool(true) | RustOptimize::String(_) = &self { true } else { false }
+        match &self {
+            RustOptimize::Bool(true) | RustOptimize::String(_) => true,
+            RustOptimize::Int(i) => *i > 0,
+            RustOptimize::Bool(false) => false,
+        }
     }
 
     pub(crate) fn get_opt_level(&self) -> Option<String> {
         match &self {
             RustOptimize::String(s) => Some(s.clone()),
+            RustOptimize::Int(i) => Some(i.to_string()),
             RustOptimize::Bool(_) => None,
         }
     }
diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs
index 732df54cdac..c340bb2982a 100644
--- a/src/bootstrap/config/tests.rs
+++ b/src/bootstrap/config/tests.rs
@@ -184,7 +184,10 @@ fn rust_optimize() {
     assert_eq!(parse("").rust_optimize.is_release(), true);
     assert_eq!(parse("rust.optimize = false").rust_optimize.is_release(), false);
     assert_eq!(parse("rust.optimize = true").rust_optimize.is_release(), true);
-    assert_eq!(parse("rust.optimize = \"1\"").rust_optimize.get_opt_level(), Some("1".to_string()));
+    assert_eq!(parse("rust.optimize = 0").rust_optimize.is_release(), false);
+    assert_eq!(parse("rust.optimize = 1").rust_optimize.is_release(), true);
+    assert_eq!(parse("rust.optimize = 1").rust_optimize.get_opt_level(), Some("1".to_string()));
+    assert_eq!(parse("rust.optimize = \"s\"").rust_optimize.is_release(), true);
     assert_eq!(parse("rust.optimize = \"s\"").rust_optimize.get_opt_level(), Some("s".to_string()));
 }