From 91fe2d0ed7a8f79a64216c7328b2bea11a3bc9ea Mon Sep 17 00:00:00 2001 From: Roc Yu Date: Wed, 22 Dec 2021 15:37:49 -0500 Subject: [PATCH 01/11] Clean up NestedAttributesExt trait/implementation --- src/librustdoc/clean/types.rs | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index cb4896fbfd23d..fc26b82c974f8 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -879,20 +879,25 @@ impl AttributesExt for [ast::Attribute] { } crate trait NestedAttributesExt { - /// Returns `true` if the attribute list contains a specific `Word` - fn has_word(self, word: Symbol) -> bool; + /// Returns `true` if the attribute list contains a specific `word` + fn has_word(self, word: Symbol) -> bool + where + Self: std::marker::Sized, + { + ::get_word_attr(self, word).is_some() + } + + /// Returns `Some(attr)` if the attribute list contains 'attr' + /// corresponding to a specific `word` fn get_word_attr(self, word: Symbol) -> Option; } -impl + IntoIterator> - NestedAttributesExt for I +impl NestedAttributesExt for I +where + I: IntoIterator, { - fn has_word(self, word: Symbol) -> bool { - self.into_iter().any(|attr| attr.is_word() && attr.has_name(word)) - } - - fn get_word_attr(mut self, word: Symbol) -> Option { - self.find(|attr| attr.is_word() && attr.has_name(word)) + fn get_word_attr(self, word: Symbol) -> Option { + self.into_iter().find(|attr| attr.is_word() && attr.has_name(word)) } } From 1773e8318f0ff7a928867df0d56c9d58b9b906e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alper=20=C3=87ugun?= Date: Mon, 27 Dec 2021 12:28:11 +0100 Subject: [PATCH 02/11] Add another implementation example to Debug trait --- library/core/src/fmt/mod.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 6fc3cd0b7c4ad..2d4f477ca0189 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -570,11 +570,26 @@ impl Display for Arguments<'_> { /// There are a number of helper methods on the [`Formatter`] struct to help you with manual /// implementations, such as [`debug_struct`]. /// +/// [`debug_struct`]: Formatter::debug_struct +/// +/// For custom cases, it's also possible to implement `Debug` using the [`write!`] macro: +/// ``` +/// # use std::fmt; +/// # struct Point { +/// # x: i32, +/// # y: i32, +/// # } +/// +/// impl fmt::Debug for Point { +/// fn fmt(&self, f: &mut fmt::Formatter <'_>) -> fmt::Result { +/// write!(f, "Point [{} {}]", self.x, self.y) +/// } +/// } +/// ``` +/// /// `Debug` implementations using either `derive` or the debug builder API /// on [`Formatter`] support pretty-printing using the alternate flag: `{:#?}`. /// -/// [`debug_struct`]: Formatter::debug_struct -/// /// Pretty-printing with `#?`: /// /// ``` From cc18120425a5c571a968d850c75cc935a8321136 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Thu, 30 Dec 2021 16:42:06 -0500 Subject: [PATCH 03/11] Set font size proportional to user's font size According to MDN (https://developer.mozilla.org/en-US/docs/Web/CSS/font-size), > To maximize accessibility, it is generally best to use values that > are relative to the user's default font size. > Defining font sizes in px is not accessible, because the user cannot > change the font size in some browsers. Note that changing font size (in browser or OS settings) is distinct from the zoom functionality triggered with Ctrl/Cmd-+. Zoom functionality increases the size of everything on the page, effectively applying a multiplier to all pixel sizes. Font size changes apply to just text. For relative font sizes, we could use `em`, as we do in several places already. However that has a problem of "compounding" (see MDN article for details). The compounding problem is nicely solved by `rem`, which make font sizes relative to the root element, not the parent element. Since we were using a hodge-podge of pixel sizes, em, rem, and percentage sizes before, this change switching everything to rem, while keeping the same size relative to our old default of 16px. 16px is still the default on most browsers, for users that haven't set a larger or smaller font size. --- src/librustdoc/html/static/css/rustdoc.css | 111 +++++++++++---------- 1 file changed, 58 insertions(+), 53 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index e5c667a37c669..d82c65398b835 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -108,7 +108,7 @@ html { /* General structure and fonts */ body { - font: 16px/1.4 "Source Serif 4", NanumBarunGothic, serif; + font: 1rem/1.4 "Source Serif 4", NanumBarunGothic, serif; margin: 0; position: relative; @@ -118,13 +118,13 @@ body { } h1 { - font-size: 1.5em; + font-size: 1.5rem; } h2 { - font-size: 1.4em; + font-size: 1.4rem; } h3 { - font-size: 1.3em; + font-size: 1.3rem; } h1, h2, h3, h4, h5, h6 { font-weight: 500; @@ -160,10 +160,10 @@ h2, border-bottom: 1px solid; } h3.code-header { - font-size: 1.1em; + font-size: 1.1rem; } h4.code-header { - font-size: 1em; + font-size: 1rem; } h3.code-header, h4.code-header { font-weight: 600; @@ -206,7 +206,7 @@ div.impl-items > div:not(.docblock):not(.item-info), } .content ul.crate a.crate { - font-size: 16px/1.6; + font-size: 1rem/1.6; } ol, ul { @@ -317,7 +317,7 @@ li { nav.sub { position: relative; - font-size: 16px; + font-size: 1rem; text-transform: uppercase; } @@ -423,7 +423,7 @@ nav.sub { .sidebar .location { border: 1px solid; - font-size: 17px; + font-size: 1.0625rem; margin: 30px 10px 20px 10px; text-align: center; word-wrap: break-word; @@ -432,7 +432,7 @@ nav.sub { } .sidebar .version { - font-size: 15px; + font-size: 0.9375rem; text-align: center; border-bottom: 1px solid; overflow-wrap: break-word; @@ -470,7 +470,7 @@ nav.sub { overflow: hidden; line-height: 15px; padding: 7px 5px; - font-size: 14px; + font-size: 0.875rem; font-weight: 300; transition: border 500ms ease-out; } @@ -479,7 +479,7 @@ nav.sub { border-top: 1px solid; border-bottom: 1px solid; text-align: center; - font-size: 17px; + font-size: 1.0625rem; margin-bottom: 5px; font-weight: inherit; padding: 0; @@ -579,18 +579,18 @@ nav.sub { white-space: pre-wrap; } -.top-doc .docblock h2 { font-size: 1.3em; } -.top-doc .docblock h3 { font-size: 1.15em; } +.top-doc .docblock h2 { font-size: 1.3rem; } +.top-doc .docblock h3 { font-size: 1.15rem; } .top-doc .docblock h4, .top-doc .docblock h5 { - font-size: 1.1em; + font-size: 1.1rem; } .top-doc .docblock h6 { - font-size: 1em; + font-size: 1rem; } -.docblock h5 { font-size: 1em; } -.docblock h6 { font-size: 0.95em; } +.docblock h5 { font-size: 1rem; } +.docblock h6 { font-size: 0.95rem; } .docblock { margin-left: 24px; @@ -605,7 +605,7 @@ nav.sub { .content .out-of-band { flex-grow: 0; text-align: right; - font-size: 23px; + font-size: 1.4375rem; margin: 0px; padding: 0 0 0 12px; font-weight: normal; @@ -646,7 +646,7 @@ nav.sub { .content td { vertical-align: top; } .content td:first-child { padding-right: 20px; } .content td p:first-child { margin-top: 0; } -.content td h1, .content td h2 { margin-left: 0; font-size: 1.1em; } +.content td h1, .content td h2 { margin-left: 0; font-size: 1.1rem; } .content tr:first-child td { border-top: 0; } .docblock table { @@ -687,7 +687,7 @@ nav.sub { .content .multi-column li { width: 100%; display: inline-block; } .content > .methods > .method { - font-size: 1em; + font-size: 1rem; position: relative; } /* Shift "where ..." part of method or fn definition down a line */ @@ -695,7 +695,7 @@ nav.sub { .content .fn .where, .content .where.fmt-newline { display: block; - font-size: 0.8em; + font-size: 0.8rem; } .content .methods > div:not(.notable-traits):not(.method) { @@ -718,7 +718,7 @@ nav.sub { } .content .item-info code { - font-size: 90%; + font-size: 0.81rem; } .content .item-info { @@ -732,7 +732,7 @@ nav.sub { .content .item-info::before { content: '⬑'; - font-size: 25px; + font-size: 1.5625rem; position: absolute; top: -6px; left: -19px; @@ -835,7 +835,7 @@ h2.small-section-header > .anchor { position: absolute; top: 0; right: 0; - font-size: 17px; + font-size: 1.0625rem; font-weight: normal; } @@ -905,7 +905,7 @@ h2.small-section-header > .anchor { border-radius: 1px; margin-top: 5px; padding: 10px 16px; - font-size: 17px; + font-size: 1.0625rem; transition: border-color 300ms ease; transition: border-radius 300ms ease-in-out; transition: box-shadow 300ms ease-in-out; @@ -1000,7 +1000,7 @@ body.blur > :not(#help) { #help span.top, #help span.bottom { text-align: center; display: block; - font-size: 18px; + font-size: 1.125rem; } #help span.top { @@ -1030,7 +1030,7 @@ body.blur > :not(#help) { .stab { padding: 3px; margin-bottom: 5px; - font-size: 90%; + font-size: 0.9rem; font-weight: normal; } .stab p { @@ -1038,7 +1038,7 @@ body.blur > :not(#help) { } .stab .emoji { - font-size: 1.2em; + font-size: 1.2rem; } /* Black one-pixel outline around emoji shapes */ @@ -1054,7 +1054,7 @@ body.blur > :not(#help) { .import-item .stab { border-radius: 3px; display: inline-block; - font-size: 80%; + font-size: 0.8rem; line-height: 1.2; margin-bottom: 0; margin-left: .3em; @@ -1080,7 +1080,7 @@ body.blur > :not(#help) { .impl-items .srclink, .impl .srclink, .methods .srclink { /* Override header settings otherwise it's too bold */ - font-size: 17px; + font-size: 1.0625rem; font-weight: normal; } @@ -1089,7 +1089,7 @@ body.blur > :not(#help) { } .has-srclink { - font-size: 16px; + font-size: 1rem; margin-bottom: 12px; /* Push the src link out to the right edge consistently */ justify-content: space-between; @@ -1120,7 +1120,7 @@ a.test-arrow { position: absolute; padding: 5px 10px 5px 10px; border-radius: 5px; - font-size: 130%; + font-size: 1.3rem; top: 5px; right: 5px; z-index: 1; @@ -1155,19 +1155,19 @@ a.test-arrow:hover{ .out-of-band > span.since { position: initial; - font-size: 20px; + font-size: 1.25rem; margin-right: 5px; } h3.variant { font-weight: 600; - font-size: 1.1em; + font-size: 1.1rem; margin-bottom: 10px; border-bottom: none; } .sub-variant h4 { - font-size: 1em; + font-size: 1rem; font-weight: 400; border-bottom: none; margin-top: 0; @@ -1227,7 +1227,7 @@ h3.variant { padding: 5px 3px 3px 3px; border-radius: 6px; margin-left: 5px; - font-size: 16px; + font-size: 1rem; } .tooltip.ignore::after { @@ -1260,7 +1260,7 @@ h3.variant { .tooltip.compile_fail, .tooltip.should_panic, .tooltip.ignore { font-weight: bold; - font-size: 20px; + font-size: 1.25rem; } .notable-traits-tooltip { @@ -1279,7 +1279,7 @@ h3.variant { border-radius: 6px; margin-left: 5px; z-index: 10; - font-size: 16px; + font-size: 1rem; cursor: default; position: absolute; border: 1px solid; @@ -1299,14 +1299,14 @@ h3.variant { .notable-traits .notable { margin: 0; margin-bottom: 13px; - font-size: 19px; + font-size: 1.1875rem; font-weight: 600; } .notable-traits .docblock code.content{ margin: 0; padding: 0; - font-size: 20px; + font-size: 1.25rem; } /* Example code has the "Run" button that needs to be positioned relative to the pre */ @@ -1344,7 +1344,7 @@ pre.rust { float: left; width: 33.3%; text-align: center; - font-size: 18px; + font-size: 1.125rem; cursor: pointer; border: 0; border-top: 2px solid; @@ -1357,7 +1357,7 @@ pre.rust { #titles > button > div.count { display: inline-block; - font-size: 16px; + font-size: 1rem; } .notable-traits { @@ -1384,7 +1384,7 @@ pre.rust { left: 0; cursor: pointer; font-weight: bold; - font-size: 1.2em; + font-size: 1.2rem; border-bottom: 1px solid; display: flex; height: 40px; @@ -1398,7 +1398,7 @@ pre.rust { overflow: auto; } #source-sidebar > .title { - font-size: 1.5em; + font-size: 1.5rem; text-align: center; border-bottom: 1px solid; margin-bottom: 6px; @@ -1426,6 +1426,9 @@ pre.rust { #theme-picker, #settings-menu, #help-button, #copy-path { padding: 4px; + /* Rare exception to specifying font sizes in rem. Since these are acting + as icons, it's okay to specify their sizes in pixels. */ + font-size: 16px; width: 27px; height: 29px; border: 1px solid; @@ -1437,7 +1440,9 @@ pre.rust { right: 30px; font-family: "Fira Sans", Arial, sans-serif; text-align: center; - font-size: 17px; + /* Rare exception to specifying font sizes in rem. Since this is acting + as an icon, it's okay to specify their sizes in pixels. */ + font-size: 16px; padding-top: 2px; } @@ -1499,7 +1504,7 @@ kbd { border: 0; border-collapse: collapse; border-spacing: 0; - font-size: 16px; + font-size: 1rem; } .table-display tr td:first-child { @@ -1511,11 +1516,11 @@ kbd { } .table-display .out-of-band { position: relative; - font-size: 19px; + font-size: 1.1875rem; display: block; } #implementors-list > .impl-items .table-display .out-of-band { - font-size: 17px; + font-size: 1.0625rem; } .table-display td:hover .anchor { @@ -1557,7 +1562,7 @@ div.name.expand + .children { div.name::before { content: "\25B6"; padding-left: 4px; - font-size: 0.7em; + font-size: 0.7rem; position: absolute; left: -16px; top: 4px; @@ -1624,7 +1629,7 @@ details.rustdoc-toggle.top-doc > summary::before, details.rustdoc-toggle.non-exhaustive > summary, details.rustdoc-toggle.non-exhaustive > summary::before { font-family: 'Fira Sans'; - font-size: 16px; + font-size: 1rem; } details.non-exhaustive { @@ -1768,7 +1773,7 @@ details.rustdoc-toggle[open] > summary.hideme::after { min-height: 39px; background: inherit; text-align: left; - font-size: 24px; + font-size: 1.5rem; } .sidebar .location:empty { @@ -1909,7 +1914,7 @@ details.rustdoc-toggle[open] > summary.hideme::after { } .show-it > .block.items > ul > li > a { - font-size: 21px; + font-size: 1.3125rem; } /* Because of ios, we need to actually have a full height sidebar title so the From 4145877731e9f38a4640d2dfeed7b123d81d061a Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Mon, 3 Jan 2022 12:55:42 +0000 Subject: [PATCH 04/11] Explicitly pass `PATH` to the Windows exe resolver --- library/std/src/sys/windows/process.rs | 31 ++++++++++------ library/std/src/sys/windows/process/tests.rs | 39 +++++++++----------- 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index e84dfbce4a754..5ad570427978e 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -268,7 +268,7 @@ impl Command { } else { None }; - let program = resolve_exe(&self.program, child_paths)?; + let program = resolve_exe(&self.program, || env::var_os("PATH"), child_paths)?; let mut cmd_str = make_command_line(program.as_os_str(), &self.args, self.force_quotes_enabled)?; cmd_str.push(0); // add null terminator @@ -362,7 +362,11 @@ impl fmt::Debug for Command { // Therefore this functions first assumes `.exe` was intended. // It falls back to the plain file name if a full path is given and the extension is omitted // or if only a file name is given and it already contains an extension. -fn resolve_exe<'a>(exe_path: &'a OsStr, child_paths: Option<&OsStr>) -> io::Result { +fn resolve_exe<'a>( + exe_path: &'a OsStr, + parent_paths: impl FnOnce() -> Option, + child_paths: Option<&OsStr>, +) -> io::Result { // Early return if there is no filename. if exe_path.is_empty() || path::has_trailing_slash(exe_path) { return Err(io::Error::new_const( @@ -406,7 +410,7 @@ fn resolve_exe<'a>(exe_path: &'a OsStr, child_paths: Option<&OsStr>) -> io::Resu let has_extension = exe_path.bytes().contains(&b'.'); // Search the directories given by `search_paths`. - let result = search_paths(child_paths, |mut path| { + let result = search_paths(parent_paths, child_paths, |mut path| { path.push(&exe_path); if !has_extension { path.set_extension(EXE_EXTENSION); @@ -423,15 +427,20 @@ fn resolve_exe<'a>(exe_path: &'a OsStr, child_paths: Option<&OsStr>) -> io::Resu // Calls `f` for every path that should be used to find an executable. // Returns once `f` returns the path to an executable or all paths have been searched. -fn search_paths(child_paths: Option<&OsStr>, mut f: F) -> Option +fn search_paths( + parent_paths: Paths, + child_paths: Option<&OsStr>, + mut exists: Exists, +) -> Option where - F: FnMut(PathBuf) -> Option, + Paths: FnOnce() -> Option, + Exists: FnMut(PathBuf) -> Option, { // 1. Child paths // This is for consistency with Rust's historic behaviour. if let Some(paths) = child_paths { for path in env::split_paths(paths).filter(|p| !p.as_os_str().is_empty()) { - if let Some(path) = f(path) { + if let Some(path) = exists(path) { return Some(path); } } @@ -440,7 +449,7 @@ where // 2. Application path if let Ok(mut app_path) = env::current_exe() { app_path.pop(); - if let Some(path) = f(app_path) { + if let Some(path) = exists(app_path) { return Some(path); } } @@ -450,7 +459,7 @@ where unsafe { if let Ok(Some(path)) = super::fill_utf16_buf( |buf, size| c::GetSystemDirectoryW(buf, size), - |buf| f(PathBuf::from(OsString::from_wide(buf))), + |buf| exists(PathBuf::from(OsString::from_wide(buf))), ) { return Some(path); } @@ -458,7 +467,7 @@ where { if let Ok(Some(path)) = super::fill_utf16_buf( |buf, size| c::GetWindowsDirectoryW(buf, size), - |buf| f(PathBuf::from(OsString::from_wide(buf))), + |buf| exists(PathBuf::from(OsString::from_wide(buf))), ) { return Some(path); } @@ -466,9 +475,9 @@ where } // 5. Parent paths - if let Some(parent_paths) = env::var_os("PATH") { + if let Some(parent_paths) = parent_paths() { for path in env::split_paths(&parent_paths).filter(|p| !p.as_os_str().is_empty()) { - if let Some(path) = f(path) { + if let Some(path) = exists(path) { return Some(path); } } diff --git a/library/std/src/sys/windows/process/tests.rs b/library/std/src/sys/windows/process/tests.rs index 6159a679c0e69..f1221767af30e 100644 --- a/library/std/src/sys/windows/process/tests.rs +++ b/library/std/src/sys/windows/process/tests.rs @@ -136,51 +136,46 @@ fn windows_exe_resolver() { use super::resolve_exe; use crate::io; + let env_paths = || env::var_os("PATH"); + // Test a full path, with and without the `exe` extension. let mut current_exe = env::current_exe().unwrap(); - assert!(resolve_exe(current_exe.as_ref(), None).is_ok()); + assert!(resolve_exe(current_exe.as_ref(), env_paths, None).is_ok()); current_exe.set_extension(""); - assert!(resolve_exe(current_exe.as_ref(), None).is_ok()); + assert!(resolve_exe(current_exe.as_ref(), env_paths, None).is_ok()); // Test lone file names. - assert!(resolve_exe(OsStr::new("cmd"), None).is_ok()); - assert!(resolve_exe(OsStr::new("cmd.exe"), None).is_ok()); - assert!(resolve_exe(OsStr::new("cmd.EXE"), None).is_ok()); - assert!(resolve_exe(OsStr::new("fc"), None).is_ok()); + assert!(resolve_exe(OsStr::new("cmd"), env_paths, None).is_ok()); + assert!(resolve_exe(OsStr::new("cmd.exe"), env_paths, None).is_ok()); + assert!(resolve_exe(OsStr::new("cmd.EXE"), env_paths, None).is_ok()); + assert!(resolve_exe(OsStr::new("fc"), env_paths, None).is_ok()); // Invalid file names should return InvalidInput. - assert_eq!(resolve_exe(OsStr::new(""), None).unwrap_err().kind(), io::ErrorKind::InvalidInput); assert_eq!( - resolve_exe(OsStr::new("\0"), None).unwrap_err().kind(), + resolve_exe(OsStr::new(""), env_paths, None).unwrap_err().kind(), + io::ErrorKind::InvalidInput + ); + assert_eq!( + resolve_exe(OsStr::new("\0"), env_paths, None).unwrap_err().kind(), io::ErrorKind::InvalidInput ); // Trailing slash, therefore there's no file name component. assert_eq!( - resolve_exe(OsStr::new(r"C:\Path\to\"), None).unwrap_err().kind(), + resolve_exe(OsStr::new(r"C:\Path\to\"), env_paths, None).unwrap_err().kind(), io::ErrorKind::InvalidInput ); - /* FIXME: fix and re-enable these tests before making changes to the resolver. - /* Some of the following tests may need to be changed if you are deliberately changing the behaviour of `resolve_exe`. */ - let paths = env::var_os("PATH").unwrap(); - env::set_var("PATH", ""); - - assert_eq!(resolve_exe(OsStr::new("rustc"), None).unwrap_err().kind(), io::ErrorKind::NotFound); - - let child_paths = Some(paths.as_os_str()); - assert!(resolve_exe(OsStr::new("rustc"), child_paths).is_ok()); + let empty_paths = || None; // The resolver looks in system directories even when `PATH` is empty. - assert!(resolve_exe(OsStr::new("cmd.exe"), None).is_ok()); + assert!(resolve_exe(OsStr::new("cmd.exe"), empty_paths, None).is_ok()); // The application's directory is also searched. let current_exe = env::current_exe().unwrap(); - assert!(resolve_exe(current_exe.file_name().unwrap().as_ref(), None).is_ok()); - - */ + assert!(resolve_exe(current_exe.file_name().unwrap().as_ref(), empty_paths, None).is_ok()); } From 10e3d92306ad4022cff547aa1e02b13cdfab816d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 22 Dec 2021 06:41:26 +1100 Subject: [PATCH 05/11] Label more build steps. Currently the output of a command like `./x.py build --stage 0 library/std` is this: ``` Updating only changed submodules Submodules updated in 0.02 seconds extracting [...] Compiling [...] Finished dev [unoptimized] target(s) in 17.53s Building stage0 std artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu) Compling [...] Finished release [optimized + debuginfo] target(s) in 21.99s Copying stage0 std from stage0 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu) Build completed successfully in 0:00:51 ``` I find the part before the "Building stage0 std artifacts" a bit confusing. After this commit, it looks like this: ``` Updating only changed submodules Submodules updated in 0.02 seconds extracting [...] Building rustbuild Compiling [...] Finished dev [unoptimized] target(s) in 17.53s Building stage0 std artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu) Compling [...] Finished release [optimized + debuginfo] target(s) in 21.99s Copying stage0 std from stage0 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu) Build completed successfully in 0:00:51 ``` The "Building rustbuild" label makes it clear what the first cargo build invocation is for. The indentation of the "Submodules updated" line indicates it is a sub-step of a parent task. --- src/bootstrap/bootstrap.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 5a33073e6b022..5235a6b818053 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -974,6 +974,7 @@ def bootstrap_binary(self): def build_bootstrap(self): """Build bootstrap""" + print("Building rustbuild") build_dir = os.path.join(self.build_dir, "bootstrap") if self.clean and os.path.exists(build_dir): shutil.rmtree(build_dir) @@ -1133,7 +1134,7 @@ def update_submodules(self): recorded_submodules[data[3]] = data[2] for module in filtered_submodules: self.update_submodule(module[0], module[1], recorded_submodules) - print("Submodules updated in %.2f seconds" % (time() - start_time)) + print(" Submodules updated in %.2f seconds" % (time() - start_time)) def set_dist_environment(self, url): """Set download URL for normal environment""" From 2e74ca18e43cbaa11300f24cfa0571d7c44d175e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 22 Dec 2021 10:29:49 +1100 Subject: [PATCH 06/11] Tweak the usage messages for `x.py build` and `x.py check`. They're a bit out of date, and overly complicated. --- src/bootstrap/flags.rs | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 2fddda74a28e9..9180c5f03af68 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -401,26 +401,19 @@ To learn more about a subcommand, run `./x.py -h`", "\n Arguments: This subcommand accepts a number of paths to directories to the crates - and/or artifacts to compile. For example: - - ./x.py build library/core - ./x.py build library/core library/proc_macro - ./x.py build library/std --stage 1 - - If no arguments are passed then the complete artifacts for that stage are - also compiled. + and/or artifacts to compile. For example, for a quick build of a usable + compiler: - ./x.py build - ./x.py build --stage 1 + ./x.py build --stage 1 library/std - For a quick build of a usable compiler, you can pass: + This will build a compiler and standard library from the local source code. + Once this is done, build/$ARCH/stage1 contains a usable compiler. - ./x.py build --stage 1 library/test + If no arguments are passed then the default artifacts for that stage are + compiled. For example: - This will first build everything once (like `--stage 0` without further - arguments would), and then use the compiler built in stage 0 to build - library/test and its dependencies. - Once this is done, build/$ARCH/stage1 contains a usable compiler.", + ./x.py build --stage 0 + ./x.py build ", ); } "check" | "c" => { @@ -430,14 +423,9 @@ Arguments: This subcommand accepts a number of paths to directories to the crates and/or artifacts to compile. For example: - ./x.py check library/core - ./x.py check library/core library/proc_macro + ./x.py check library/std - If no arguments are passed then the complete artifacts are compiled: std, test, and rustc. Note - also that since we use `cargo check`, by default this will automatically enable incremental - compilation, so there's no need to pass it separately, though it won't hurt. We also completely - ignore the stage passed, as there's no way to compile in non-stage 0 without actually building - the compiler.", + If no arguments are passed then many artifacts are checked.", ); } "clippy" => { From 6152d15e7c06910a3fe1e7621f624ceaa9d010a8 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 3 Jan 2022 16:32:52 -0800 Subject: [PATCH 07/11] Extract init_env_logger to crate --- Cargo.lock | 14 ++++-- compiler/rustc_driver/Cargo.toml | 6 +-- compiler/rustc_driver/src/lib.rs | 57 +++-------------------- compiler/rustc_log/Cargo.toml | 16 +++++++ compiler/rustc_log/src/lib.rs | 78 ++++++++++++++++++++++++++++++++ 5 files changed, 114 insertions(+), 57 deletions(-) create mode 100644 compiler/rustc_log/Cargo.toml create mode 100644 compiler/rustc_log/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index a912eee97dbf2..17f7d2ca15a90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3808,7 +3808,6 @@ dependencies = [ name = "rustc_driver" version = "0.0.0" dependencies = [ - "atty", "libc", "rustc_ast", "rustc_ast_pretty", @@ -3822,6 +3821,7 @@ dependencies = [ "rustc_hir_pretty", "rustc_interface", "rustc_lint", + "rustc_log", "rustc_metadata", "rustc_middle", "rustc_parse", @@ -3833,8 +3833,6 @@ dependencies = [ "rustc_target", "rustc_typeck", "tracing", - "tracing-subscriber", - "tracing-tree", "winapi", ] @@ -4077,6 +4075,16 @@ dependencies = [ "libc", ] +[[package]] +name = "rustc_log" +version = "0.0.0" +dependencies = [ + "atty", + "tracing", + "tracing-subscriber", + "tracing-tree", +] + [[package]] name = "rustc_macros" version = "0.1.0" diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml index 2383a000687fa..872f946bf7d91 100644 --- a/compiler/rustc_driver/Cargo.toml +++ b/compiler/rustc_driver/Cargo.toml @@ -8,10 +8,8 @@ crate-type = ["dylib"] [dependencies] libc = "0.2" -atty = "0.2" tracing = { version = "0.1.28" } -tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] } -tracing-tree = "0.2.0" +rustc_log = { path = "../rustc_log" } rustc_middle = { path = "../rustc_middle" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_target = { path = "../rustc_target" } @@ -40,4 +38,4 @@ winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] [features] llvm = ['rustc_interface/llvm'] -max_level_info = ['tracing/max_level_info'] +max_level_info = ['rustc_log/max_level_info'] diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 12e0b7a4977e1..3d58b27f83922 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -24,6 +24,7 @@ use rustc_feature::find_gated_cfg; use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; use rustc_interface::{interface, Queries}; use rustc_lint::LintStore; +use rustc_log::stdout_isatty; use rustc_metadata::locator; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; @@ -514,14 +515,6 @@ impl Compilation { #[derive(Copy, Clone)] pub struct RustcDefaultCalls; -fn stdout_isatty() -> bool { - atty::is(atty::Stream::Stdout) -} - -fn stderr_isatty() -> bool { - atty::is(atty::Stream::Stderr) -} - fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) { let upper_cased_code = code.to_ascii_uppercase(); let normalised = if upper_cased_code.starts_with('E') { @@ -1254,54 +1247,18 @@ pub fn install_ice_hook() { /// This allows tools to enable rust logging without having to magically match rustc's /// tracing crate version. pub fn init_rustc_env_logger() { - init_env_logger("RUSTC_LOG") + if let Err(error) = rustc_log::init_rustc_env_logger() { + early_error(ErrorOutputType::default(), &error.to_string()); + } } /// This allows tools to enable rust logging without having to magically match rustc's /// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var /// other than `RUSTC_LOG`. pub fn init_env_logger(env: &str) { - use tracing_subscriber::{ - filter::{self, EnvFilter, LevelFilter}, - layer::SubscriberExt, - }; - - let filter = match std::env::var(env) { - Ok(env) => EnvFilter::new(env), - _ => EnvFilter::default().add_directive(filter::Directive::from(LevelFilter::WARN)), - }; - - let color_logs = match std::env::var(String::from(env) + "_COLOR") { - Ok(value) => match value.as_ref() { - "always" => true, - "never" => false, - "auto" => stderr_isatty(), - _ => early_error( - ErrorOutputType::default(), - &format!( - "invalid log color value '{}': expected one of always, never, or auto", - value - ), - ), - }, - Err(std::env::VarError::NotPresent) => stderr_isatty(), - Err(std::env::VarError::NotUnicode(_value)) => early_error( - ErrorOutputType::default(), - "non-Unicode log color value: expected one of always, never, or auto", - ), - }; - - let layer = tracing_tree::HierarchicalLayer::default() - .with_writer(io::stderr) - .with_indent_lines(true) - .with_ansi(color_logs) - .with_targets(true) - .with_indent_amount(2); - #[cfg(parallel_compiler)] - let layer = layer.with_thread_ids(true).with_thread_names(true); - - let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer); - tracing::subscriber::set_global_default(subscriber).unwrap(); + if let Err(error) = rustc_log::init_env_logger(env) { + early_error(ErrorOutputType::default(), &error.to_string()); + } } #[cfg(all(unix, any(target_env = "gnu", target_os = "macos")))] diff --git a/compiler/rustc_log/Cargo.toml b/compiler/rustc_log/Cargo.toml new file mode 100644 index 0000000000000..5b03794622464 --- /dev/null +++ b/compiler/rustc_log/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "rustc_log" +version = "0.0.0" +edition = "2021" + +[lib] +doctest = false + +[dependencies] +atty = "0.2" +tracing = "0.1.28" +tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] } +tracing-tree = "0.2.0" + +[features] +max_level_info = ['tracing/max_level_info'] diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs new file mode 100644 index 0000000000000..498c8cf9c5e9a --- /dev/null +++ b/compiler/rustc_log/src/lib.rs @@ -0,0 +1,78 @@ +//! This crate allows tools to enable rust logging without having to magically +//! match rustc's tracing crate version. + +use std::env::{self, VarError}; +use std::fmt::{self, Display}; +use std::io; +use tracing_subscriber::filter::{Directive, EnvFilter, LevelFilter}; +use tracing_subscriber::layer::SubscriberExt; + +pub fn init_rustc_env_logger() -> Result<(), Error> { + init_env_logger("RUSTC_LOG") +} + +/// In contrast to `init_rustc_env_logger` this allows you to choose an env var +/// other than `RUSTC_LOG`. +pub fn init_env_logger(env: &str) -> Result<(), Error> { + let filter = match env::var(env) { + Ok(env) => EnvFilter::new(env), + _ => EnvFilter::default().add_directive(Directive::from(LevelFilter::WARN)), + }; + + let color_logs = match env::var(String::from(env) + "_COLOR") { + Ok(value) => match value.as_ref() { + "always" => true, + "never" => false, + "auto" => stderr_isatty(), + _ => return Err(Error::InvalidColorValue(value)), + }, + Err(VarError::NotPresent) => stderr_isatty(), + Err(VarError::NotUnicode(_value)) => return Err(Error::NonUnicodeColorValue), + }; + + let layer = tracing_tree::HierarchicalLayer::default() + .with_writer(io::stderr) + .with_indent_lines(true) + .with_ansi(color_logs) + .with_targets(true) + .with_indent_amount(2); + #[cfg(parallel_compiler)] + let layer = layer.with_thread_ids(true).with_thread_names(true); + + let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer); + tracing::subscriber::set_global_default(subscriber).unwrap(); + + Ok(()) +} + +pub fn stdout_isatty() -> bool { + atty::is(atty::Stream::Stdout) +} + +pub fn stderr_isatty() -> bool { + atty::is(atty::Stream::Stderr) +} + +#[derive(Debug)] +pub enum Error { + InvalidColorValue(String), + NonUnicodeColorValue, +} + +impl std::error::Error for Error {} + +impl Display for Error { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::InvalidColorValue(value) => write!( + formatter, + "invalid log color value '{}': expected one of always, never, or auto", + value, + ), + Error::NonUnicodeColorValue => write!( + formatter, + "non-Unicode log color value: expected one of always, never, or auto", + ), + } + } +} From dd5ee326bc565b19421ac952c23203f9ec63140c Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 3 Jan 2022 20:23:59 -0800 Subject: [PATCH 08/11] Justify why rustc_log exists --- compiler/rustc_log/src/lib.rs | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index 498c8cf9c5e9a..44c76a7379bda 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -1,5 +1,42 @@ //! This crate allows tools to enable rust logging without having to magically //! match rustc's tracing crate version. +//! +//! For example if someone is working on rustc_ast and wants to write some +//! minimal code against it to run in a debugger, with access to the `debug!` +//! logs emitted by rustc_ast, that can be done by writing: +//! +//! ```toml +//! [dependencies] +//! rustc_ast = { path = "../rust/compiler/rustc_ast" } +//! rustc_log = { path = "../rust/compiler/rustc_log" } +//! rustc_span = { path = "../rust/compiler/rustc_span" } +//! ``` +//! +//! ```ignore +//! fn main() { +//! rustc_log::init_rustc_env_logger().unwrap(); +//! +//! let edition = rustc_span::edition::Edition::Edition2021; +//! rustc_span::create_session_globals_then(edition, || { +//! /* ... */ +//! }); +//! } +//! ``` +//! +//! Now `RUSTC_LOG=debug cargo run` will run your minimal main.rs and show +//! rustc's debug logging. In a workflow like this, one might also add +//! `std::env::set_var("RUSTC_LOG", "debug")` to the top of main so that `cargo +//! run` by itself is sufficient to get logs. +//! +//! The reason rustc_log is a tiny separate crate, as opposed to exposing the +//! same things in rustc_driver only, is to enable the above workflow. If you +//! had to depend on rustc_driver in order to turn on rustc's debug logs, that's +//! an enormously bigger dependency tree; every change you make to rustc_ast (or +//! whichever piece of the compiler you are interested in) would involve +//! rebuilding all the rest of rustc up to rustc_driver in order to run your +//! main.rs. Whereas by depending only on rustc_log and the few crates you are +//! debugging, you can make changes inside those crates and quickly run main.rs +//! to read the debug logs. use std::env::{self, VarError}; use std::fmt::{self, Display}; From ffbeebbf7a6dc5fba40b439fc0ebe80ac72af309 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 3 Jan 2022 22:01:35 -0800 Subject: [PATCH 09/11] Make rustc_log doc test runnable --- Cargo.lock | 1 + compiler/rustc_log/Cargo.toml | 6 +++--- compiler/rustc_log/src/lib.rs | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 17f7d2ca15a90..eed6cb2751647 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4080,6 +4080,7 @@ name = "rustc_log" version = "0.0.0" dependencies = [ "atty", + "rustc_span", "tracing", "tracing-subscriber", "tracing-tree", diff --git a/compiler/rustc_log/Cargo.toml b/compiler/rustc_log/Cargo.toml index 5b03794622464..1b2cde605556d 100644 --- a/compiler/rustc_log/Cargo.toml +++ b/compiler/rustc_log/Cargo.toml @@ -3,14 +3,14 @@ name = "rustc_log" version = "0.0.0" edition = "2021" -[lib] -doctest = false - [dependencies] atty = "0.2" tracing = "0.1.28" tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] } tracing-tree = "0.2.0" +[dev-dependencies] +rustc_span = { path = "../rustc_span" } + [features] max_level_info = ['tracing/max_level_info'] diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index 44c76a7379bda..f5e7435d36e36 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -12,7 +12,7 @@ //! rustc_span = { path = "../rust/compiler/rustc_span" } //! ``` //! -//! ```ignore +//! ``` //! fn main() { //! rustc_log::init_rustc_env_logger().unwrap(); //! From 4df1a5561adc0ee6e1635df825d34026e04530b1 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 4 Jan 2022 14:25:20 -0800 Subject: [PATCH 10/11] Touch up Debug example from PR 92322 --- library/core/src/fmt/mod.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 2d4f477ca0189..8a2a64f8dc97f 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -572,16 +572,20 @@ impl Display for Arguments<'_> { /// /// [`debug_struct`]: Formatter::debug_struct /// -/// For custom cases, it's also possible to implement `Debug` using the [`write!`] macro: +/// Types that do not wish to use the standard suite of debug representations +/// provided by the `Formatter` trait (`debug_struct`, `debug_tuple`, +/// `debut_list`, `debug_set`, `debug_map`) can do something totally custom by +/// manually writing an arbitrary representation to the `Formatter`. +/// /// ``` /// # use std::fmt; /// # struct Point { /// # x: i32, /// # y: i32, /// # } -/// +/// # /// impl fmt::Debug for Point { -/// fn fmt(&self, f: &mut fmt::Formatter <'_>) -> fmt::Result { +/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// write!(f, "Point [{} {}]", self.x, self.y) /// } /// } From e5684238159e4fe7f333c9118a321cdfeeb8990a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 5 Jan 2022 10:41:22 +0100 Subject: [PATCH 11/11] update Miri --- Cargo.lock | 13 ++----------- src/tools/miri | 2 +- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1fe03a06c7974..97907b45f449d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -368,7 +368,7 @@ version = "0.1.0" dependencies = [ "directories", "rustc-workspace-hack", - "rustc_version 0.3.3", + "rustc_version", "serde", "serde_json", "vergen", @@ -2276,7 +2276,7 @@ dependencies = [ "measureme 9.1.2", "rand 0.8.4", "rustc-workspace-hack", - "rustc_version 0.4.0", + "rustc_version", "shell-escape", "smallvec", ] @@ -4577,15 +4577,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "rustc_version" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" -dependencies = [ - "semver 0.11.0", -] - [[package]] name = "rustc_version" version = "0.4.0" diff --git a/src/tools/miri b/src/tools/miri index d307e6c1970d1..824816c973a3f 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit d307e6c1970d1edb63d6a08d332e0acdb72c5cc5 +Subproject commit 824816c973a3fd0596ae3a9a38c6fb6299b913b8