about summary refs log tree commit diff
path: root/src/librustdoc
diff options
context:
space:
mode:
authorTshepang Mbambo <tshepang@gmail.com>2025-05-15 11:47:11 +0200
committerGitHub <noreply@github.com>2025-05-15 11:47:11 +0200
commita3ce646c3ca97632d4c3a637704d8153d8feb0bf (patch)
tree7b32415cdda158f9c51d195f0f03921c86d8892a /src/librustdoc
parentd016ed87c371be960e05db843c0bac33a3f85ac9 (diff)
parent1fd536c5fb7616f08973dd33074efb94e82eea44 (diff)
downloadrust-a3ce646c3ca97632d4c3a637704d8153d8feb0bf.tar.gz
rust-a3ce646c3ca97632d4c3a637704d8153d8feb0bf.zip
Merge pull request #2388 from rust-lang/rustc-pull
Rustc pull update
Diffstat (limited to 'src/librustdoc')
-rw-r--r--src/librustdoc/clean/render_macro_matchers.rs2
-rw-r--r--src/librustdoc/clean/types.rs6
-rw-r--r--src/librustdoc/config.rs6
-rw-r--r--src/librustdoc/doctest.rs44
-rw-r--r--src/librustdoc/doctest/tests.rs22
-rw-r--r--src/librustdoc/html/static/css/noscript.css2
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css52
-rw-r--r--src/librustdoc/html/templates/page.html2
-rw-r--r--src/librustdoc/lib.rs25
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs21
10 files changed, 88 insertions, 94 deletions
diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs
index e967fd40609..d684e6f8650 100644
--- a/src/librustdoc/clean/render_macro_matchers.rs
+++ b/src/librustdoc/clean/render_macro_matchers.rs
@@ -167,7 +167,7 @@ fn print_tts(printer: &mut Printer<'_>, tts: &TokenStream) {
 }
 
 fn usually_needs_space_between_keyword_and_open_delim(symbol: Symbol, span: Span) -> bool {
-    let ident = Ident { name: symbol, span };
+    let ident = Ident::new(symbol, span);
     let is_keyword = ident.is_used_keyword() || ident.is_unused_keyword();
     if !is_keyword {
         // An identifier that is not a keyword usually does not need a space
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index bbe11bf56af..15890fff0c3 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -786,7 +786,11 @@ impl Item {
                             // because it isn't public API.
                             None
                         }
-                        _ => Some(rustc_hir_pretty::attribute_to_string(&tcx, attr)),
+                        _ => Some({
+                            let mut s = rustc_hir_pretty::attribute_to_string(&tcx, attr);
+                            assert_eq!(s.pop(), Some('\n'));
+                            s
+                        }),
                     }
                 } else if attr.has_any_name(ALLOWED_ATTRIBUTES) {
                     Some(
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 4ef73ff48ed..f93aa8ffd0d 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -174,7 +174,7 @@ pub(crate) struct Options {
     pub(crate) expanded_args: Vec<String>,
 
     /// Arguments to be used when compiling doctests.
-    pub(crate) doctest_compilation_args: Vec<String>,
+    pub(crate) doctest_build_args: Vec<String>,
 }
 
 impl fmt::Debug for Options {
@@ -802,7 +802,7 @@ impl Options {
         let scrape_examples_options = ScrapeExamplesOptions::new(matches, dcx);
         let with_examples = matches.opt_strs("with-examples");
         let call_locations = crate::scrape_examples::load_call_locations(with_examples, dcx);
-        let doctest_compilation_args = matches.opt_strs("doctest-compilation-args");
+        let doctest_build_args = matches.opt_strs("doctest-build-arg");
 
         let unstable_features =
             rustc_feature::UnstableFeatures::from_environment(crate_name.as_deref());
@@ -851,7 +851,7 @@ impl Options {
             scrape_examples_options,
             unstable_features,
             expanded_args: args,
-            doctest_compilation_args,
+            doctest_build_args,
         };
         let render_options = RenderOptions {
             output,
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 0cdf2f92a89..ef70b862185 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -51,46 +51,6 @@ pub(crate) struct GlobalTestOptions {
     pub(crate) args_file: PathBuf,
 }
 
-/// Function used to split command line arguments just like a shell would.
-fn split_args(args: &str) -> Vec<String> {
-    let mut out = Vec::new();
-    let mut iter = args.chars();
-    let mut current = String::new();
-
-    while let Some(c) = iter.next() {
-        if c == '\\' {
-            if let Some(c) = iter.next() {
-                // If it's escaped, even a quote or a whitespace will be ignored.
-                current.push(c);
-            }
-        } else if c == '"' || c == '\'' {
-            while let Some(new_c) = iter.next() {
-                if new_c == c {
-                    break;
-                } else if new_c == '\\' {
-                    if let Some(c) = iter.next() {
-                        // If it's escaped, even a quote will be ignored.
-                        current.push(c);
-                    }
-                } else {
-                    current.push(new_c);
-                }
-            }
-        } else if " \n\t\r".contains(c) {
-            if !current.is_empty() {
-                out.push(current.clone());
-                current.clear();
-            }
-        } else {
-            current.push(c);
-        }
-    }
-    if !current.is_empty() {
-        out.push(current);
-    }
-    out
-}
-
 pub(crate) fn generate_args_file(file_path: &Path, options: &RustdocOptions) -> Result<(), String> {
     let mut file = File::create(file_path)
         .map_err(|error| format!("failed to create args file: {error:?}"))?;
@@ -119,9 +79,7 @@ pub(crate) fn generate_args_file(file_path: &Path, options: &RustdocOptions) ->
         content.push(format!("-Z{unstable_option_str}"));
     }
 
-    for compilation_args in &options.doctest_compilation_args {
-        content.extend(split_args(compilation_args));
-    }
+    content.extend(options.doctest_build_args.clone());
 
     let content = content.join("\n");
 
diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs
index 49add73e9d6..618c2041b43 100644
--- a/src/librustdoc/doctest/tests.rs
+++ b/src/librustdoc/doctest/tests.rs
@@ -382,28 +382,6 @@ fn main() {
 }
 
 #[test]
-fn check_split_args() {
-    fn compare(input: &str, expected: &[&str]) {
-        let output = super::split_args(input);
-        let expected = expected.iter().map(|s| s.to_string()).collect::<Vec<_>>();
-        assert_eq!(expected, output, "test failed for {input:?}");
-    }
-
-    compare("'a' \"b\"c", &["a", "bc"]);
-    compare("'a' \"b \"c d", &["a", "b c", "d"]);
-    compare("'a' \"b\\\"c\"", &["a", "b\"c"]);
-    compare("'a\"'", &["a\""]);
-    compare("\"a'\"", &["a'"]);
-    compare("\\ a", &[" a"]);
-    compare("\\\\", &["\\"]);
-    compare("a'", &["a"]);
-    compare("a          ", &["a"]);
-    compare("a          b", &["a", "b"]);
-    compare("a\n\t \rb", &["a", "b"]);
-    compare("a\n\t1 \rb", &["a", "1", "b"]);
-}
-
-#[test]
 fn comment_in_attrs() {
     // If there is an inline code comment after attributes, we need to ensure that
     // a backline will be added to prevent generating code "inside" it (and thus generating)
diff --git a/src/librustdoc/html/static/css/noscript.css b/src/librustdoc/html/static/css/noscript.css
index 477a79d63e9..a3c6bf98161 100644
--- a/src/librustdoc/html/static/css/noscript.css
+++ b/src/librustdoc/html/static/css/noscript.css
@@ -43,6 +43,7 @@ nav.sub {
 	--settings-button-border-focus: #717171;
 	--sidebar-background-color: #f5f5f5;
 	--sidebar-background-color-hover: #e0e0e0;
+	--sidebar-border-color: #ddd;
 	--code-block-background-color: #f5f5f5;
 	--scrollbar-track-background-color: #dcdcdc;
 	--scrollbar-thumb-background-color: rgba(36, 37, 39, 0.6);
@@ -149,6 +150,7 @@ nav.sub {
 		--settings-button-border-focus: #ffb900;
 		--sidebar-background-color: #505050;
 		--sidebar-background-color-hover: #676767;
+		--sidebar-border-color: #2A2A2A;
 		--code-block-background-color: #2A2A2A;
 		--scrollbar-track-background-color: #717171;
 		--scrollbar-thumb-background-color: rgba(32, 34, 37, .6);
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index f838f3f1106..a81d5c9c49b 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1,4 +1,6 @@
-/* When static files are updated, their suffixes need to be updated.
+/* ignore-tidy-filelength */
+/*
+	When static files are updated, their suffixes need to be updated.
 	1. In the top directory run:
 		./x.py doc --stage 1 library/core
 	2. Find the directory containing files named with updated suffixes:
@@ -496,12 +498,13 @@ img {
 	top: 0;
 	left: 0;
 	z-index: var(--desktop-sidebar-z-index);
+	/* resize indicator: hide this when on touch or mobile */
+	border-right: solid 1px var(--sidebar-border-color);
 }
 
 .rustdoc.src .sidebar {
 	flex-basis: 50px;
 	width: 50px;
-	border-right: 1px solid;
 	overflow-x: hidden;
 	/* The sidebar is by default hidden  */
 	overflow-y: hidden;
@@ -515,12 +518,27 @@ img {
 .sidebar-resizer {
 	touch-action: none;
 	width: 9px;
-	cursor: col-resize;
+	cursor: ew-resize;
 	z-index: calc(var(--desktop-sidebar-z-index) + 1);
 	position: fixed;
 	height: 100%;
-	/* make sure there's a 1px gap between the scrollbar and resize handle */
-	left: calc(var(--desktop-sidebar-width) + 1px);
+	left: var(--desktop-sidebar-width);
+	display: flex;
+	align-items: center;
+	justify-content: flex-start;
+	color: var(--right-side-color);
+}
+.sidebar-resizer::before {
+	content: "";
+	border-right: dotted 2px currentColor;
+	width: 2px;
+	height: 12px;
+}
+.sidebar-resizer::after {
+	content: "";
+	border-right: dotted 2px currentColor;
+	width: 2px;
+	height: 16px;
 }
 
 .rustdoc.src .sidebar-resizer {
@@ -543,11 +561,12 @@ img {
 }
 
 .sidebar-resizing * {
-	cursor: col-resize !important;
+	cursor: ew-resize !important;
 }
 
 .sidebar-resizing .sidebar {
 	position: fixed;
+	border-right: solid 2px var(--sidebar-resizer-active);
 }
 .sidebar-resizing > body {
 	padding-left: var(--resizing-sidebar-width);
@@ -561,8 +580,9 @@ img {
 	margin: 0;
 	/* when active or hovered, place resizer glow on top of the sidebar (right next to, or even
 	   on top of, the scrollbar) */
-	left: var(--desktop-sidebar-width);
+	left: calc(var(--desktop-sidebar-width) - 1px);
 	border-left: solid 1px var(--sidebar-resizer-hover);
+	color: var(--sidebar-resizer-hover);
 }
 
 .src-sidebar-expanded .rustdoc.src .sidebar-resizer:hover,
@@ -578,21 +598,20 @@ img {
 		/* too easy to hit the resizer while trying to hit the [-] toggle */
 		display: none !important;
 	}
+	.sidebar {
+		/* resize indicator: hide this when on touch or mobile */
+		border-right: none;
+	}
 }
 
 .sidebar-resizer.active {
 	/* make the resize tool bigger when actually resizing, to avoid :hover styles on other stuff
 		while resizing */
 	padding: 0 140px;
-	width: 2px;
+	width: calc(140px + 140px + 9px + 2px);
 	margin-left: -140px;
 	border-left: none;
-}
-.sidebar-resizer.active::before {
-	border-left: solid 2px var(--sidebar-resizer-active);
-	display: block;
-	height: 100%;
-	content: "";
+	color: var(--sidebar-resizer-active);
 }
 
 .sidebar, .mobile-topbar, .sidebar-menu-toggle,
@@ -2509,6 +2528,8 @@ in src-script.js and main.js
 		/* Reduce height slightly to account for mobile topbar. */
 		height: calc(100vh - 45px);
 		width: 200px;
+		/* resize indicator: hide this when on touch or mobile */
+		border-right: none;
 	}
 
 	/* The source view uses a different design for the sidebar toggle, and doesn't have a topbar,
@@ -2897,6 +2918,7 @@ by default.
 	--settings-button-border-focus: #717171;
 	--sidebar-background-color: #f5f5f5;
 	--sidebar-background-color-hover: #e0e0e0;
+	--sidebar-border-color: #ddd;
 	--code-block-background-color: #f5f5f5;
 	--scrollbar-track-background-color: #dcdcdc;
 	--scrollbar-thumb-background-color: rgba(36, 37, 39, 0.6);
@@ -3002,6 +3024,7 @@ by default.
 	--settings-button-border-focus: #ffb900;
 	--sidebar-background-color: #505050;
 	--sidebar-background-color-hover: #676767;
+	--sidebar-border-color: #999;
 	--code-block-background-color: #2A2A2A;
 	--scrollbar-track-background-color: #717171;
 	--scrollbar-thumb-background-color: rgba(32, 34, 37, .6);
@@ -3114,6 +3137,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 	--settings-button-border-focus: #e0e0e0;
 	--sidebar-background-color: #14191f;
 	--sidebar-background-color-hover: rgba(70, 70, 70, 0.33);
+	--sidebar-border-color: #5c6773;
 	--code-block-background-color: #191f26;
 	--scrollbar-track-background-color: transparent;
 	--scrollbar-thumb-background-color: #5c6773;
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
index 5ef376f4acb..7af99e7097c 100644
--- a/src/librustdoc/html/templates/page.html
+++ b/src/librustdoc/html/templates/page.html
@@ -114,7 +114,7 @@
         {% endif %}
         {{ sidebar|safe }}
     </nav> {# #}
-    <div class="sidebar-resizer"></div> {# #}
+    <div class="sidebar-resizer" title="Drag to resize sidebar"></div> {# #}
     <main>
         {% if page.css_class != "src" %}<div class="width-limiter">{% endif %}
             {# defined in storage.js to avoid duplicating complex UI across every page #}
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index bca40b8117b..b4210e7b518 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -73,9 +73,11 @@ extern crate tikv_jemalloc_sys as jemalloc_sys;
 
 use std::env::{self, VarError};
 use std::io::{self, IsTerminal};
+use std::path::Path;
 use std::process;
 
 use rustc_errors::DiagCtxtHandle;
+use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_interface::interface;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{ErrorOutputType, RustcOptGroup, make_crate_type_option};
@@ -654,9 +656,9 @@ fn opts() -> Vec<RustcOptGroup> {
             Unstable,
             Multi,
             "",
-            "doctest-compilation-args",
-            "",
-            "add arguments to be used when compiling doctests",
+            "doctest-build-arg",
+            "One argument (of possibly many) to be used when compiling doctests",
+            "ARG",
         ),
         opt(
             Unstable,
@@ -904,6 +906,10 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
                 rustc_interface::passes::write_dep_info(tcx);
             }
 
+            if let Some(metrics_dir) = &sess.opts.unstable_opts.metrics_dir {
+                dump_feature_usage_metrics(tcx, metrics_dir);
+            }
+
             if run_check {
                 // Since we're in "check" mode, no need to generate anything beyond this point.
                 return;
@@ -923,3 +929,16 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
         })
     })
 }
+
+fn dump_feature_usage_metrics(tcxt: TyCtxt<'_>, metrics_dir: &Path) {
+    let hash = tcxt.crate_hash(LOCAL_CRATE);
+    let crate_name = tcxt.crate_name(LOCAL_CRATE);
+    let metrics_file_name = format!("unstable_feature_usage_metrics-{crate_name}-{hash}.json");
+    let metrics_path = metrics_dir.join(metrics_file_name);
+    if let Err(error) = tcxt.features().dump_feature_usage_metrics(metrics_path) {
+        // FIXME(yaahc): once metrics can be enabled by default we will want "failure to emit
+        // default metrics" to only produce a warning when metrics are enabled by default and emit
+        // an error only when the user manually enables metrics
+        tcxt.dcx().err(format!("cannot emit feature usage metrics: {error}"));
+    }
+}
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 36f5889dcf4..f3e2138d1a5 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -496,12 +496,21 @@ impl<'tcx> LinkCollector<'_, 'tcx> {
 
         // Try looking for methods and associated items.
         // NB: `path_root` could be empty when resolving in the root namespace (e.g. `::std`).
-        let (path_root, item_str) = path_str.rsplit_once("::").ok_or_else(|| {
-            // If there's no `::`, it's not an associated item.
-            // So we can be sure that `rustc_resolve` was accurate when it said it wasn't resolved.
-            debug!("found no `::`, assuming {path_str} was correctly not in scope");
-            UnresolvedPath { item_id, module_id, partial_res: None, unresolved: path_str.into() }
-        })?;
+        let (path_root, item_str) = match path_str.rsplit_once("::") {
+            Some(res @ (_path_root, item_str)) if !item_str.is_empty() => res,
+            _ => {
+                // If there's no `::`, or the `::` is at the end (e.g. `String::`) it's not an
+                // associated item. So we can be sure that `rustc_resolve` was accurate when it
+                // said it wasn't resolved.
+                debug!("`::` missing or at end, assuming {path_str} was not in scope");
+                return Err(UnresolvedPath {
+                    item_id,
+                    module_id,
+                    partial_res: None,
+                    unresolved: path_str.into(),
+                });
+            }
+        };
         let item_name = Symbol::intern(item_str);
 
         // FIXME(#83862): this arbitrarily gives precedence to primitives over modules to support