diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 59f66c55572af..30a56badeb52e 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1576,7 +1576,7 @@ fn add_rpath_args( let target_triple = sess.opts.target_triple.triple(); let mut get_install_prefix_lib_path = || { let install_prefix = option_env!("CFG_PREFIX").expect("CFG_PREFIX"); - let tlib = filesearch::relative_target_lib_path(&sess.sysroot, target_triple); + let tlib = rustc_target::target_rustlib_path(&sess.sysroot, target_triple).join("lib"); let mut path = PathBuf::from(install_prefix); path.push(&tlib); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 59488fc80a5e2..fd29053433e55 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -423,8 +423,7 @@ pub fn get_codegen_sysroot( .iter() .chain(sysroot_candidates.iter()) .map(|sysroot| { - let libdir = filesearch::relative_target_lib_path(&sysroot, &target); - sysroot.join(libdir).with_file_name("codegen-backends") + filesearch::make_target_lib_path(&sysroot, &target).with_file_name("codegen-backends") }) .find(|f| { info!("codegen backend candidate: {}", f.display()); diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index 2df326628e787..6fe6a555f1af8 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -1,6 +1,5 @@ pub use self::FileMatch::*; -use std::borrow::Cow; use std::env; use std::fs; use std::path::{Path, PathBuf}; @@ -91,26 +90,21 @@ impl<'a> FileSearch<'a> { // Returns a list of directories where target-specific tool binaries are located. pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec { - let mut p = PathBuf::from(self.sysroot); - p.push(find_libdir(self.sysroot).as_ref()); - p.push(RUST_LIB_DIR); - p.push(&self.triple); - p.push("bin"); + let rustlib_path = rustc_target::target_rustlib_path(self.sysroot, &self.triple); + let p = std::array::IntoIter::new([ + Path::new(&self.sysroot), + Path::new(&rustlib_path), + Path::new("bin"), + ]) + .collect::(); if self_contained { vec![p.clone(), p.join("self-contained")] } else { vec![p] } } } -pub fn relative_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf { - let mut p = PathBuf::from(find_libdir(sysroot).as_ref()); - assert!(p.is_relative()); - p.push(RUST_LIB_DIR); - p.push(target_triple); - p.push("lib"); - p -} - pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf { - sysroot.join(&relative_target_lib_path(sysroot, target_triple)) + let rustlib_path = rustc_target::target_rustlib_path(sysroot, target_triple); + std::array::IntoIter::new([sysroot, Path::new(&rustlib_path), Path::new("lib")]) + .collect::() } // This function checks if sysroot is found using env::args().next(), and if it @@ -157,11 +151,13 @@ pub fn get_or_default_sysroot() -> PathBuf { return None; } + // Pop off `bin/rustc`, obtaining the suspected sysroot. p.pop(); p.pop(); - let mut libdir = PathBuf::from(&p); - libdir.push(find_libdir(&p).as_ref()); - if libdir.exists() { Some(p) } else { None } + // Look for the target rustlib directory in the suspected sysroot. + let mut rustlib_path = rustc_target::target_rustlib_path(&p, "dummy"); + rustlib_path.pop(); // pop off the dummy target. + if rustlib_path.exists() { Some(p) } else { None } } None => None, } @@ -171,37 +167,3 @@ pub fn get_or_default_sysroot() -> PathBuf { // use env::current_exe() to imply sysroot. from_env_args_next().unwrap_or_else(from_current_exe) } - -// The name of the directory rustc expects libraries to be located. -fn find_libdir(sysroot: &Path) -> Cow<'static, str> { - // FIXME: This is a quick hack to make the rustc binary able to locate - // Rust libraries in Linux environments where libraries might be installed - // to lib64/lib32. This would be more foolproof by basing the sysroot off - // of the directory where `librustc_driver` is located, rather than - // where the rustc binary is. - // If --libdir is set during configuration to the value other than - // "lib" (i.e., non-default), this value is used (see issue #16552). - - #[cfg(target_pointer_width = "64")] - const PRIMARY_LIB_DIR: &str = "lib64"; - - #[cfg(target_pointer_width = "32")] - const PRIMARY_LIB_DIR: &str = "lib32"; - - const SECONDARY_LIB_DIR: &str = "lib"; - - match option_env!("CFG_LIBDIR_RELATIVE") { - None | Some("lib") => { - if sysroot.join(PRIMARY_LIB_DIR).join(RUST_LIB_DIR).exists() { - PRIMARY_LIB_DIR.into() - } else { - SECONDARY_LIB_DIR.into() - } - } - Some(libdir) => libdir.into(), - } -} - -// The name of rustc's own place to organize libraries. -// Used to be "rustc", now the default is "rustlib" -const RUST_LIB_DIR: &str = "rustlib"; diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index 6702538874705..48ace9b65b678 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -15,6 +15,8 @@ #![feature(associated_type_bounds)] #![feature(exhaustive_patterns)] +use std::path::{Path, PathBuf}; + #[macro_use] extern crate rustc_macros; @@ -29,3 +31,52 @@ pub mod spec; /// This is a hack to allow using the `HashStable_Generic` derive macro /// instead of implementing everything in `rustc_middle`. pub trait HashStableContext {} + +/// The name of rustc's own place to organize libraries. +/// +/// Used to be `rustc`, now the default is `rustlib`. +const RUST_LIB_DIR: &str = "rustlib"; + +/// Returns a `rustlib` path for this particular target, relative to the provided sysroot. +/// +/// For example: `target_sysroot_path("/usr", "x86_64-unknown-linux-gnu")` => +/// `"lib*/rustlib/x86_64-unknown-linux-gnu"`. +pub fn target_rustlib_path(sysroot: &Path, target_triple: &str) -> PathBuf { + let libdir = find_libdir(sysroot); + std::array::IntoIter::new([ + Path::new(libdir.as_ref()), + Path::new(RUST_LIB_DIR), + Path::new(target_triple), + ]) + .collect::() +} + +/// The name of the directory rustc expects libraries to be located. +fn find_libdir(sysroot: &Path) -> std::borrow::Cow<'static, str> { + // FIXME: This is a quick hack to make the rustc binary able to locate + // Rust libraries in Linux environments where libraries might be installed + // to lib64/lib32. This would be more foolproof by basing the sysroot off + // of the directory where `librustc_driver` is located, rather than + // where the rustc binary is. + // If --libdir is set during configuration to the value other than + // "lib" (i.e., non-default), this value is used (see issue #16552). + + #[cfg(target_pointer_width = "64")] + const PRIMARY_LIB_DIR: &str = "lib64"; + + #[cfg(target_pointer_width = "32")] + const PRIMARY_LIB_DIR: &str = "lib32"; + + const SECONDARY_LIB_DIR: &str = "lib"; + + match option_env!("CFG_LIBDIR_RELATIVE") { + None | Some("lib") => { + if sysroot.join(PRIMARY_LIB_DIR).join(RUST_LIB_DIR).exists() { + PRIMARY_LIB_DIR.into() + } else { + SECONDARY_LIB_DIR.into() + } + } + Some(libdir) => libdir.into(), + } +} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 27ca6a23a96bc..4bffd6e8ddd35 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1897,15 +1897,15 @@ impl Target { Ok(base) } - /// Search RUST_TARGET_PATH for a JSON file specifying the given target - /// triple. If none is found, look for a file called `target.json` inside - /// the sysroot under the target-triple's `rustlib` directory. - /// Note that it could also just be a bare filename already, so also - /// check for that. If one of the hardcoded targets we know about, just - /// return it directly. + /// Search for a JSON file specifying the given target triple. /// - /// The error string could come from any of the APIs called, including - /// filesystem access and JSON decoding. + /// If none is found in `$RUST_TARGET_PATH`, look for a file called `target.json` inside the + /// sysroot under the target-triple's `rustlib` directory. Note that it could also just be a + /// bare filename already, so also check for that. If one of the hardcoded targets we know + /// about, just return it directly. + /// + /// The error string could come from any of the APIs called, including filesystem access and + /// JSON decoding. pub fn search(target_triple: &TargetTriple, sysroot: &PathBuf) -> Result { use rustc_serialize::json; use std::env; @@ -1942,8 +1942,13 @@ impl Target { // Additionally look in the sysroot under `lib/rustlib//target.json` // as a fallback. - let p = - sysroot.join("lib").join("rustlib").join(&target_triple).join("target.json"); + let rustlib_path = crate::target_rustlib_path(&sysroot, &target_triple); + let p = std::array::IntoIter::new([ + Path::new(sysroot), + Path::new(&rustlib_path), + Path::new("target.json"), + ]) + .collect::(); if p.is_file() { return load_file(&p); } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 33aa42b137a23..bca7a8cfcee09 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1606,7 +1606,6 @@ impl Type { } } RawPointer(..) => Some(PrimitiveType::RawPointer), - BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference), BareFunction(..) => Some(PrimitiveType::Fn), Never => Some(PrimitiveType::Never), _ => None, @@ -1665,13 +1664,7 @@ impl Type { } crate fn is_primitive(&self) -> bool { - match self { - Self::Primitive(_) => true, - Self::BorrowedRef { ref type_, .. } | Self::RawPointer(_, ref type_) => { - type_.is_primitive() - } - _ => false, - } + self.primitive_type().is_some() } crate fn projection(&self) -> Option<(&Type, DefId, Symbol)> { diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index f631f627fc255..51392ca119189 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -24,6 +24,7 @@ crate fn render_with_highlighting( playground_button: Option<&str>, tooltip: Option<(Option, &str)>, edition: Edition, + extra_content: Option, ) { debug!("highlighting: ================\n{}\n==============", src); if let Some((edition_info, class)) = tooltip { @@ -39,13 +40,21 @@ crate fn render_with_highlighting( ); } - write_header(out, class); + write_header(out, class, extra_content); write_code(out, &src, edition); write_footer(out, playground_button); } -fn write_header(out: &mut Buffer, class: Option<&str>) { - writeln!(out, "
", class.unwrap_or_default());
+fn write_header(out: &mut Buffer, class: Option<&str>, extra_content: Option) {
+    write!(out, "
"); + if let Some(extra) = extra_content { + out.push_buffer(extra); + } + if let Some(class) = class { + writeln!(out, "
", class);
+    } else {
+        writeln!(out, "
");
+    }
 }
 
 fn write_code(out: &mut Buffer, src: &str, edition: Edition) {
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index dc29add933314..99e96fdcf1eb4 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -34,6 +34,12 @@ crate struct Page<'a> {
     crate static_extra_scripts: &'a [&'a str],
 }
 
+impl<'a> Page<'a> {
+    crate fn get_static_root_path(&self) -> &str {
+        self.static_root_path.unwrap_or(self.root_path)
+    }
+}
+
 crate fn render(
     layout: &Layout,
     page: &Page<'_>,
@@ -41,7 +47,7 @@ crate fn render(
     t: T,
     style_files: &[StylePath],
 ) -> String {
-    let static_root_path = page.static_root_path.unwrap_or(page.root_path);
+    let static_root_path = page.get_static_root_path();
     format!(
         "\
 \
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 509f173055775..c2b40ab34e255 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -315,6 +315,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> {
             playground_button.as_deref(),
             tooltip,
             edition,
+            None,
         );
         Some(Event::Html(s.into_inner().into()))
     }
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index e0c1fd06e7b6c..4e17dc8d3a7d0 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -215,7 +215,7 @@ impl<'tcx> Context<'tcx> {
                 &self.shared.layout,
                 &page,
                 |buf: &mut _| print_sidebar(self, it, buf),
-                |buf: &mut _| print_item(self, it, buf),
+                |buf: &mut _| print_item(self, it, buf, &page),
                 &self.shared.style_files,
             )
         } else {
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 4b7664f28a149..7ccc313cc5905 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -22,9 +22,10 @@ use crate::formats::{AssocItemRender, Impl, RenderMode};
 use crate::html::escape::Escape;
 use crate::html::format::{print_abi_with_space, print_where_clause, Buffer, PrintWithSpace};
 use crate::html::highlight;
+use crate::html::layout::Page;
 use crate::html::markdown::MarkdownSummaryLine;
 
-pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer) {
+pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, page: &Page<'_>) {
     debug_assert!(!item.is_stripped());
     // Write the breadcrumb trail header for the top
     buf.write_str("

"); @@ -74,7 +75,16 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer) } } write!(buf, "{}", item.type_(), item.name.as_ref().unwrap()); - write!(buf, ""); + write!( + buf, + "", + static_root_path = page.get_static_root_path(), + suffix = page.resource_suffix, + ); buf.write_str(""); // in-band buf.write_str(""); @@ -1016,6 +1026,7 @@ fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Mac None, None, it.span(cx.tcx()).inner().edition(), + None, ); }); document(w, cx, it, None) diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index c493801d9907f..d0518cb6862fe 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -207,6 +207,7 @@ pub(super) fn write_shared( } write_toolchain("brush.svg", static_files::BRUSH_SVG)?; write_toolchain("wheel.svg", static_files::WHEEL_SVG)?; + write_toolchain("clipboard.svg", static_files::CLIPBOARD_SVG)?; write_toolchain("down-arrow.svg", static_files::DOWN_ARROW_SVG)?; let mut themes: Vec<&String> = themes.iter().collect(); diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 14e2d65d94ef8..57c33f94918d7 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -169,16 +169,17 @@ where /// adding line numbers to the left-hand side. fn print_src(buf: &mut Buffer, s: &str, edition: Edition) { let lines = s.lines().count(); + let mut line_numbers = Buffer::empty_from(buf); let mut cols = 0; let mut tmp = lines; while tmp > 0 { cols += 1; tmp /= 10; } - buf.write_str("
");
+    line_numbers.write_str("
");
     for i in 1..=lines {
-        writeln!(buf, "{0:1$}", i, cols);
+        writeln!(line_numbers, "{0:1$}", i, cols);
     }
-    buf.write_str("
"); - highlight::render_with_highlighting(s, buf, None, None, None, edition); + line_numbers.write_str("
"); + highlight::render_with_highlighting(s, buf, None, None, None, edition, Some(line_numbers)); } diff --git a/src/librustdoc/html/static/clipboard.svg b/src/librustdoc/html/static/clipboard.svg new file mode 100644 index 0000000000000..8adbd99630488 --- /dev/null +++ b/src/librustdoc/html/static/clipboard.svg @@ -0,0 +1 @@ + diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index a03d20c053dfd..dc65e14ab37b8 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1252,15 +1252,31 @@ function hideThemeButtonState() { document.execCommand('copy'); document.body.removeChild(el); - but.textContent = '✓'; + // There is always one children, but multiple childNodes. + but.children[0].style.display = 'none'; + + var tmp; + if (but.childNodes.length < 2) { + tmp = document.createTextNode('✓'); + but.appendChild(tmp); + } else { + onEachLazy(but.childNodes, function(e) { + if (e.nodeType === Node.TEXT_NODE) { + tmp = e; + return true; + } + }); + tmp.textContent = '✓'; + } if (reset_button_timeout !== null) { window.clearTimeout(reset_button_timeout); } function reset_button() { - but.textContent = '⎘'; + tmp.textContent = ''; reset_button_timeout = null; + but.children[0].style.display = ""; } reset_button_timeout = window.setTimeout(reset_button, 1000); diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 42a85fcce030a..aaa2525644f11 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -206,7 +206,6 @@ li { max-width: none; overflow: visible; margin-left: 0px; - min-width: 70em; } nav.sub { @@ -357,7 +356,7 @@ nav.sub { padding-left: 0; } -.rustdoc:not(.source) .example-wrap { +.rustdoc .example-wrap { display: inline-flex; margin-bottom: 10px; } @@ -370,8 +369,6 @@ nav.sub { .example-wrap > pre.line-number { overflow: initial; border: 1px solid; - border-top-left-radius: 5px; - border-bottom-left-radius: 5px; padding: 13px 8px; text-align: right; } @@ -381,7 +378,7 @@ nav.sub { overflow-x: auto; } -.rustdoc:not(.source) .example-wrap > pre { +.rustdoc .example-wrap > pre { margin: 0; } @@ -395,15 +392,14 @@ nav.sub { table-layout: fixed; } -.content pre.line-numbers { - float: left; - border: none; +.content > .example-wrap pre.line-numbers { position: relative; - -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; + border-top-left-radius: 5px; + border-bottom-left-radius: 5px; } .line-numbers span { cursor: pointer; @@ -1321,11 +1317,12 @@ h4 > .notable-traits { } #copy-path { - height: 30px; - font-size: 18px; margin-left: 10px; - padding: 0 6px; - width: 28px; + padding: 0; + padding-left: 2px; +} +#copy-path> img { + margin-bottom: 2px; } #theme-choices { diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css index aace0b3c037ca..aafb7f6300ea4 100644 --- a/src/librustdoc/html/static/themes/ayu.css +++ b/src/librustdoc/html/static/themes/ayu.css @@ -53,7 +53,7 @@ span code { .docblock code, .docblock-short code { background-color: #191f26; } -pre { +pre, .rustdoc.source .example-wrap { color: #e6e1cf; background-color: #191f26; } @@ -509,7 +509,7 @@ kbd { color: #fff; } -#theme-picker > img, #settings-menu > img { +#theme-picker > img, #settings-menu > img, #copy-path > img { filter: invert(100); } diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index c23e95ce107a9..715605d7b3785 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -26,7 +26,7 @@ h4:not(.method):not(.type):not(.tymethod) { .docblock code, .docblock-short code { background-color: #2A2A2A; } -pre { +pre, .rustdoc.source .example-wrap { background-color: #2A2A2A; } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 9330972121073..60ed889879387 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -28,7 +28,7 @@ h4:not(.method):not(.type):not(.tymethod) { .docblock code, .docblock-short code { background-color: #F5F5F5; } -pre { +pre, .rustdoc.source .example-wrap { background-color: #F5F5F5; } diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index 2b73bd5d52ee6..1abb1f7294a18 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -41,6 +41,9 @@ crate static BRUSH_SVG: &[u8] = include_bytes!("static/brush.svg"); /// The file contents of `wheel.svg`, the icon used for the settings button. crate static WHEEL_SVG: &[u8] = include_bytes!("static/wheel.svg"); +/// The file contents of `clipboard.svg`, the icon used for the "copy path" button. +crate static CLIPBOARD_SVG: &[u8] = include_bytes!("static/clipboard.svg"); + /// The file contents of `down-arrow.svg`, the icon used for the crate choice combobox. crate static DOWN_ARROW_SVG: &[u8] = include_bytes!("static/down-arrow.svg"); diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml new file mode 100644 index 0000000000000..f11c41e8bd552 --- /dev/null +++ b/src/test/rustdoc-gui/source-code-page.goml @@ -0,0 +1,13 @@ +goto: file://|DOC_PATH|/../src/test_docs/lib.rs.html +// Check that we can click on the line number. +click: (40, 224) // This is the position of the span for line 4. +// Unfortunately, "#4" isn't a valid query selector, so we have to go around that limitation +// by instead getting the nth span. +assert: (".line-numbers > span:nth-child(4)", "class", "line-highlighted") +// We now check that the good spans are highlighted +goto: file://|DOC_PATH|/../src/test_docs/lib.rs.html#4-6 +assert-false: (".line-numbers > span:nth-child(3)", "class", "line-highlighted") +assert: (".line-numbers > span:nth-child(4)", "class", "line-highlighted") +assert: (".line-numbers > span:nth-child(5)", "class", "line-highlighted") +assert: (".line-numbers > span:nth-child(6)", "class", "line-highlighted") +assert-false: (".line-numbers > span:nth-child(7)", "class", "line-highlighted")