Change:
It would be nice if we could speed up stage1 library builds by building it with less opts and no debuginfo. had the idea to control this with something like <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
i'm going to use as a separate more broad issue for - i'll repurpose this to just be for (which is a lot simpler to add)
mentoring instructions: add this option to the struct, then around , set
Can we confirm before we land this support that this is actually a significant win in practice? I recall historically having issues with optimize = false equivalents where the net effect is broken and slower tests - I would prefer to avoid landing support we don't want to actually support :)
this is especially useful in combination with - optimizing only rustc and not std should be a speedup even if we include the time taken for tests.
claim
Maybe we should just generalize the config value to a number/boolean, instead of adding a new attribute?

Discussion:
assert_eq!(target, compiler.host); } <del> if self.config.rust_optimize { </del> <ins> if self.config.rust_optimize.is_release() { </ins> // FIXME: cargo bench/install do not accept `--release` if cmd != "bench" && cmd != "install" { cargo.arg("--release");

} let profile_var = |name: &str| { <del> let profile = if self.config.rust_optimize { "RELEASE" } else { "DEV" }; </del> <ins> let profile = if self.config.rust_optimize.is_release() { "RELEASE" } else { "DEV" }; </ins> format!("CARGO_PROFILE_{}_{}", profile, name) };

} }; cargo.env(profile_var("DEBUG"), debuginfo_level.to_string()); <ins> if let Some(opt_level) = &self.config.rust_optimize.get_opt_level() { cargo.env(profile_var("OPT_LEVEL"), opt_level); } </ins> if !self.config.dry_run() && self.cc.borrow()[&target].args().iter().any(|arg| arg == "-gz") { rustflags.arg("-Clink-arg=-gz");

pub llvm_use_libcxx: bool, // rust codegen options <del> pub rust_optimize: bool, </del> <ins> pub rust_optimize: RustOptimize, </ins> pub rust_codegen_units: Option<u32>, pub rust_codegen_units_std: Option<u32>, pub rust_debug_assertions: bool,

} } <ins> #[derive(Clone, Debug, Deserialize, PartialEq, Eq)] #[serde(untagged)] pub enum RustOptimize { #[serde(deserialize_with = "deserialize_and_validate_opt_level")] String(String), Bool(bool), } impl Default for RustOptimize { fn default() -> RustOptimize { RustOptimize::Bool(false) } } 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 RustOptimize { pub(crate) fn is_release(&self) -> bool { if let RustOptimize::Bool(true) | RustOptimize::String(_) = &self { true } else { false } } pub(crate) fn get_opt_level(&self) -> Option<String> { match &self { RustOptimize::String(s) => Some(s.clone()), RustOptimize::Bool(_) => None, } } } </ins> #[derive(Deserialize)] #[serde(untagged)] enum StringOrInt<'a> { String(&'a str), Int(i64), } define_config! { /// TOML representation of how the Rust build is configured. struct Rust { <del> optimize: Option<bool> = "optimize", </del> <ins> optimize: Option<RustOptimize> = "optimize", </ins> debug: Option<bool> = "debug", codegen_units: Option<u32> = "codegen-units", codegen_units_std: Option<u32> = "codegen-units-std",

config.ninja_in_file = true; config.llvm_static_stdcpp = false; config.backtrace = true; <del> config.rust_optimize = true; </del> <ins> config.rust_optimize = RustOptimize::Bool(true); </ins> config.rust_optimize_tests = true; config.submodules = None; config.docs = true;

config.llvm_assertions = llvm_assertions.unwrap_or(false); config.llvm_tests = llvm_tests.unwrap_or(false); config.llvm_plugins = llvm_plugins.unwrap_or(false); <del> config.rust_optimize = optimize.unwrap_or(true); </del> <ins> config.rust_optimize = optimize.unwrap_or(RustOptimize::Bool(true)); </ins> let default = debug == Some(true); config.rust_debug_assertions = debug_assertions.unwrap_or(default);

} Config::parse_inner(&["check".to_owned()], get_toml); } <ins> #[test] 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 = "s"").rust_optimize.get_opt_level(), Some("s".to_string())); } #[test] #[should_panic] fn invalid_rust_optimize() { parse("rust.optimize = "a""); } </ins>

/// Component directory that Cargo will produce output into (e.g. /// release/debug) fn cargo_dir(&self) -> &'static str { <del> if self.config.rust_optimize { "release" } else { "debug" } </del> <ins> if self.config.rust_optimize.is_release() { "release" } else { "debug" } </ins> } fn tools_dir(&self, compiler: Compiler) -> PathBuf {

cargo.arg("-p").arg("clippy_dev"); // clippy_dev gets confused if it can't find `clippy/Cargo.toml` cargo.current_dir(&builder.src.join("src").join("tools").join("clippy")); <del> if builder.config.rust_optimize { </del> <ins> if builder.config.rust_optimize.is_release() { </ins> cargo.env("PROFILE", "release"); } else { cargo.env("PROFILE", "debug");