From b787d723fc489ef50bd6cf32464fc638a1773fda Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 1 Dec 2020 15:36:14 +0100 Subject: [PATCH 01/19] Fix SGX CI Broken in #79038 --- library/std/tests/env.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/std/tests/env.rs b/library/std/tests/env.rs index 0e55ec648c9c5..76056637a4cf9 100644 --- a/library/std/tests/env.rs +++ b/library/std/tests/env.rs @@ -1,6 +1,5 @@ use std::env::*; use std::ffi::{OsStr, OsString}; -use std::path::PathBuf; use rand::distributions::Alphanumeric; use rand::{thread_rng, Rng}; @@ -92,6 +91,8 @@ fn env_home_dir() { cfg_if::cfg_if! { if #[cfg(unix)] { + use std::path::PathBuf; + let oldhome = var_to_os_string(var("HOME")); set_var("HOME", "/home/MountainView"); @@ -109,6 +110,8 @@ fn env_home_dir() { if let Some(oldhome) = oldhome { set_var("HOME", oldhome); } } else if #[cfg(windows)] { + use std::path::PathBuf; + let oldhome = var_to_os_string(var("HOME")); let olduserprofile = var_to_os_string(var("USERPROFILE")); From 4eb76fcc8eb37e69962d27d990ba693fa612c17a Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Tue, 1 Dec 2020 23:09:03 +0100 Subject: [PATCH 02/19] Use more std:: instead of core:: in docs for consistency, add more intra doc links --- library/core/src/fmt/mod.rs | 2 +- library/core/src/future/pending.rs | 2 +- library/core/src/future/poll_fn.rs | 6 +++--- library/core/src/future/ready.rs | 2 +- library/core/src/panic.rs | 2 +- library/core/src/task/ready.rs | 19 +++++++++++-------- library/std/src/primitive_docs.rs | 4 ++-- 7 files changed, 20 insertions(+), 17 deletions(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 4ed62a620c4df..0c65c1c9eb7e9 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -403,7 +403,7 @@ impl<'a> Arguments<'a> { /// ```rust /// #![feature(fmt_as_str)] /// - /// use core::fmt::Arguments; + /// use std::fmt::Arguments; /// /// fn write_str(_: &str) { /* ... */ } /// diff --git a/library/core/src/future/pending.rs b/library/core/src/future/pending.rs index ab162638a1cfe..560dd25ecff42 100644 --- a/library/core/src/future/pending.rs +++ b/library/core/src/future/pending.rs @@ -21,7 +21,7 @@ pub struct Pending { /// # Examples /// /// ```no_run -/// use core::future; +/// use std::future; /// /// # async fn run() { /// let future = future::pending(); diff --git a/library/core/src/future/poll_fn.rs b/library/core/src/future/poll_fn.rs index af63e1bb097b8..9ae118e29f110 100644 --- a/library/core/src/future/poll_fn.rs +++ b/library/core/src/future/poll_fn.rs @@ -3,7 +3,7 @@ use crate::future::Future; use crate::pin::Pin; use crate::task::{Context, Poll}; -/// Creates a future that wraps a function returning `Poll`. +/// Creates a future that wraps a function returning [`Poll`]. /// /// Polling the future delegates to the wrapped function. /// @@ -13,7 +13,7 @@ use crate::task::{Context, Poll}; /// #![feature(future_poll_fn)] /// # async fn run() { /// use core::future::poll_fn; -/// use core::task::{Context, Poll}; +/// use std::task::{Context, Poll}; /// /// fn read_line(_cx: &mut Context<'_>) -> Poll { /// Poll::Ready("Hello, World!".into()) @@ -31,7 +31,7 @@ where PollFn { f } } -/// A Future that wraps a function returning `Poll`. +/// A Future that wraps a function returning [`Poll`]. /// /// This `struct` is created by [`poll_fn()`]. See its /// documentation for more. diff --git a/library/core/src/future/ready.rs b/library/core/src/future/ready.rs index e98f5c570bf3c..b0c7fbb1d7a76 100644 --- a/library/core/src/future/ready.rs +++ b/library/core/src/future/ready.rs @@ -33,7 +33,7 @@ impl Future for Ready { /// # Examples /// /// ``` -/// use core::future; +/// use std::future; /// /// # async fn run() { /// let a = future::ready(1); diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index 34a974b827158..03bb849509ad4 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -189,7 +189,7 @@ impl<'a> Location<'a> { /// # Examples /// /// ``` - /// use core::panic::Location; + /// use std::panic::Location; /// /// /// Returns the [`Location`] at which it is called. /// #[track_caller] diff --git a/library/core/src/task/ready.rs b/library/core/src/task/ready.rs index e221aaf3fd6d6..cbf6990001589 100644 --- a/library/core/src/task/ready.rs +++ b/library/core/src/task/ready.rs @@ -1,15 +1,18 @@ -/// Extracts the successful type of a `Poll`. +/// Extracts the successful type of a [`Poll`]. /// -/// This macro bakes in propagation of `Pending` signals by returning early. +/// This macro bakes in propagation of [`Pending`] signals by returning early. +/// +/// [`Poll`]: crate::task::Poll +/// [`Pending`]: crate::task::Poll::Pending /// /// # Examples /// /// ``` /// #![feature(ready_macro)] /// -/// use core::task::{ready, Context, Poll}; -/// use core::future::{self, Future}; -/// use core::pin::Pin; +/// use std::task::{ready, Context, Poll}; +/// use std::future::{self, Future}; +/// use std::pin::Pin; /// /// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> { /// let mut fut = future::ready(42); @@ -28,9 +31,9 @@ /// ``` /// # #![feature(ready_macro)] /// # -/// # use core::task::{Context, Poll}; -/// # use core::future::{self, Future}; -/// # use core::pin::Pin; +/// # use std::task::{Context, Poll}; +/// # use std::future::{self, Future}; +/// # use std::pin::Pin; /// # /// # pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> { /// # let mut fut = future::ready(42); diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 83a282c8cd6b5..55171ef2292d7 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -198,7 +198,7 @@ mod prim_bool {} /// words, they can't return `!` from every code path. As an example, this code doesn't compile: /// /// ```compile_fail -/// use core::ops::Add; +/// use std::ops::Add; /// /// fn foo() -> impl Add { /// unimplemented!() @@ -208,7 +208,7 @@ mod prim_bool {} /// But this code does: /// /// ``` -/// use core::ops::Add; +/// use std::ops::Add; /// /// fn foo() -> impl Add { /// if true { From 88c6cf88842fa6a321f2630ea154d0267969466d Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 1 Dec 2020 23:18:46 -0500 Subject: [PATCH 03/19] Pass around Symbols instead of Idents in doctree The span was unused. --- src/librustdoc/clean/mod.rs | 15 ++++++--------- src/librustdoc/doctree.rs | 8 ++++---- src/librustdoc/visit_ast.rs | 18 +++++++++--------- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d294d8f02a80f..dc53f09faba93 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1989,16 +1989,13 @@ impl Clean for hir::BareFnTy<'_> { } } -impl Clean> for (&hir::Item<'_>, Option) { +impl Clean> for (&hir::Item<'_>, Option) { fn clean(&self, cx: &DocContext<'_>) -> Vec { use hir::ItemKind; let (item, renamed) = self; let def_id = cx.tcx.hir().local_def_id(item.hir_id).to_def_id(); - let mut name = match renamed { - Some(ident) => ident.name, - None => cx.tcx.hir().name(item.hir_id), - }; + let mut name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id)); cx.with_param_env(def_id, || { let kind = match item.kind { ItemKind::Static(ty, mutability, body_id) => StaticItem(Static { @@ -2291,7 +2288,7 @@ impl Clean> for doctree::Import<'_> { } } -impl Clean for (&hir::ForeignItem<'_>, Option) { +impl Clean for (&hir::ForeignItem<'_>, Option) { fn clean(&self, cx: &DocContext<'_>) -> Item { let (item, renamed) = self; cx.with_param_env(cx.tcx.hir().local_def_id(item.hir_id).to_def_id(), || { @@ -2325,7 +2322,7 @@ impl Clean for (&hir::ForeignItem<'_>, Option) { Item::from_hir_id_and_parts( item.hir_id, - Some(renamed.unwrap_or(item.ident).name), + Some(renamed.unwrap_or(item.ident.name)), kind, cx, ) @@ -2333,10 +2330,10 @@ impl Clean for (&hir::ForeignItem<'_>, Option) { } } -impl Clean for (&hir::MacroDef<'_>, Option) { +impl Clean for (&hir::MacroDef<'_>, Option) { fn clean(&self, cx: &DocContext<'_>) -> Item { let (item, renamed) = self; - let name = renamed.unwrap_or(item.ident).name; + let name = renamed.unwrap_or(item.ident.name); let tts = item.ast.body.inner_tokens().trees().collect::>(); // Extract the spans of all matchers. They represent the "interface" of the macro. let matchers = tts.chunks(4).map(|arm| arm[0].span()).collect::>(); diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 3961870a1bfad..ee9a698185799 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -3,7 +3,7 @@ crate use self::StructType::*; use rustc_ast as ast; -use rustc_span::{self, symbol::Ident, Span, Symbol}; +use rustc_span::{self, Span, Symbol}; use rustc_hir as hir; @@ -16,9 +16,9 @@ crate struct Module<'hir> { crate mods: Vec>, crate id: hir::HirId, // (item, renamed) - crate items: Vec<(&'hir hir::Item<'hir>, Option)>, - crate foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option)>, - crate macros: Vec<(&'hir hir::MacroDef<'hir>, Option)>, + crate items: Vec<(&'hir hir::Item<'hir>, Option)>, + crate foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option)>, + crate macros: Vec<(&'hir hir::MacroDef<'hir>, Option)>, crate is_crate: bool, } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 4028293076df9..f9cb1d586b102 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -10,7 +10,7 @@ use rustc_hir::Node; use rustc_middle::middle::privacy::AccessLevel; use rustc_middle::ty::TyCtxt; use rustc_span::source_map::Spanned; -use rustc_span::symbol::{kw, sym, Ident, Symbol}; +use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{self, Span}; use std::mem; @@ -116,7 +116,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { &mut self, id: hir::HirId, res: Res, - renamed: Option, + renamed: Option, glob: bool, om: &mut Module<'tcx>, please_inline: bool, @@ -226,11 +226,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { fn visit_item( &mut self, item: &'tcx hir::Item<'_>, - renamed: Option, + renamed: Option, om: &mut Module<'tcx>, ) { debug!("visiting item {:?}", item); - let ident = renamed.unwrap_or(item.ident); + let name = renamed.unwrap_or(item.ident.name); if item.vis.node.is_pub() { let def_id = self.cx.tcx.hir().local_def_id(item.hir_id); @@ -266,7 +266,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } _ => false, }); - let ident = if is_glob { None } else { Some(ident) }; + let ident = if is_glob { None } else { Some(name) }; if self.maybe_inline_local( item.hir_id, path.res, @@ -280,7 +280,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } om.imports.push(Import { - name: ident.name, + name, id: item.hir_id, vis: &item.vis, attrs: &item.attrs, @@ -296,7 +296,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { &item.vis, item.hir_id, m, - Some(ident.name), + Some(name), )); } hir::ItemKind::Fn(..) @@ -312,7 +312,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { hir::ItemKind::Const(..) => { // Underscore constants do not correspond to a nameable item and // so are never useful in documentation. - if ident.name != kw::Underscore { + if name != kw::Underscore { om.items.push((item, renamed)); } } @@ -329,7 +329,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { fn visit_foreign_item( &mut self, item: &'tcx hir::ForeignItem<'_>, - renamed: Option, + renamed: Option, om: &mut Module<'tcx>, ) { // If inlining we only want to include public functions. From 500979828a376c4118b3c48df1642f8fea1d1c40 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 1 Dec 2020 22:32:56 -0800 Subject: [PATCH 04/19] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index bfca1cd22bf51..63d0fe43449ad 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit bfca1cd22bf514d5f2b6c1089b0ded0ba7dfaa6e +Subproject commit 63d0fe43449adcb316d34d98a982b597faca4178 From 67a67d827abfe506977938efaeb5c38b3ea94bf6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 2 Dec 2020 13:49:33 +0100 Subject: [PATCH 05/19] disable a ptr equality test on Miri --- library/alloc/tests/str.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs index b13019146568c..04077f88414c8 100644 --- a/library/alloc/tests/str.rs +++ b/library/alloc/tests/str.rs @@ -1978,9 +1978,13 @@ fn const_str_ptr() { const B: &'static [u8; 2] = &A; const C: *const u8 = B as *const u8; - unsafe { + #[cfg(not(miri))] // Miri does not deduplicate consts (https://github.com/rust-lang/miri/issues/131) + { let foo = &A as *const u8; assert_eq!(foo, C); + } + + unsafe { assert_eq!(from_utf8_unchecked(&A), "hi"); assert_eq!(*C, A[0]); assert_eq!(*(&B[0] as *const u8), A[0]); From 7e74b72d135c072c49dd0273b9582b4a51eb7a93 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 2 Dec 2020 14:09:36 +0100 Subject: [PATCH 06/19] break formatting so rustfmt is happy --- library/alloc/tests/str.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs index 04077f88414c8..604835e6cc4a6 100644 --- a/library/alloc/tests/str.rs +++ b/library/alloc/tests/str.rs @@ -1978,7 +1978,8 @@ fn const_str_ptr() { const B: &'static [u8; 2] = &A; const C: *const u8 = B as *const u8; - #[cfg(not(miri))] // Miri does not deduplicate consts (https://github.com/rust-lang/miri/issues/131) + // Miri does not deduplicate consts (https://github.com/rust-lang/miri/issues/131) + #[cfg(not(miri))] { let foo = &A as *const u8; assert_eq!(foo, C); From 4e7a2dcabb0aa42f297284ead946d5787027d035 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 2 Dec 2020 10:07:29 -0500 Subject: [PATCH 07/19] Use `item_name` instead of pretty printing Pretty printing would add a `r#` prefix to raw identifiers, which was not correct. In general I think this change makes sense - pretty-printing is for showing to the *user*, `item_name` is suitable to pass to resolve. --- src/librustdoc/passes/collect_intra_doc_links.rs | 13 +++++++++---- src/test/rustdoc/intra-doc/raw-ident-self.rs | 13 +++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 src/test/rustdoc/intra-doc/raw-ident-self.rs diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 3dcc0f240a3f8..551c086a8d4e3 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -847,12 +847,17 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { // FIXME(jynelson): this shouldn't go through stringification, rustdoc should just use the DefId directly let self_name = self_id.and_then(|self_id| { + use ty::TyKind; if matches!(self.cx.tcx.def_kind(self_id), DefKind::Impl) { - // using `ty.to_string()` directly has issues with shortening paths + // using `ty.to_string()` (or any variant) has issues with raw idents let ty = self.cx.tcx.type_of(self_id); - let name = ty::print::with_crate_prefix(|| ty.to_string()); - debug!("using type_of(): {}", name); - Some(name) + let name = match ty.kind() { + TyKind::Adt(def, _) => Some(self.cx.tcx.item_name(def.did).to_string()), + other if other.is_primitive() => Some(ty.to_string()), + _ => None, + }; + debug!("using type_of(): {:?}", name); + name } else { let name = self.cx.tcx.opt_item_name(self_id).map(|sym| sym.to_string()); debug!("using item_name(): {:?}", name); diff --git a/src/test/rustdoc/intra-doc/raw-ident-self.rs b/src/test/rustdoc/intra-doc/raw-ident-self.rs new file mode 100644 index 0000000000000..d289797f14652 --- /dev/null +++ b/src/test/rustdoc/intra-doc/raw-ident-self.rs @@ -0,0 +1,13 @@ +#![deny(broken_intra_doc_links)] +pub mod r#impl { + pub struct S; + + impl S { + /// See [Self::b]. + // @has raw_ident_self/impl/struct.S.html + // @has - '//a[@href="../../raw_ident_self/impl/struct.S.html#method.b"]' 'Self::b' + pub fn a() {} + + pub fn b() {} + } +} From 908bf5a310b7265a3e7c1d1fa021e3b10aa67293 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 2 Dec 2020 23:39:05 +0300 Subject: [PATCH 08/19] rustc_metadata: Remove some dead code --- compiler/rustc_metadata/src/rmeta/decoder.rs | 17 ----------------- .../src/rmeta/decoder/cstore_impl.rs | 12 ++++-------- compiler/rustc_middle/src/middle/cstore.rs | 2 -- src/librustdoc/core.rs | 1 - 4 files changed, 4 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index f53a40278062c..c571ed7b61262 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1592,23 +1592,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.def_path_hash_unlocked(index, &mut def_path_hashes) } - fn all_def_path_hashes_and_def_ids(&self) -> Vec<(DefPathHash, DefId)> { - let mut def_path_hashes = self.def_path_hash_cache.lock(); - let mut def_index_to_data = |index| { - (self.def_path_hash_unlocked(index, &mut def_path_hashes), self.local_def_id(index)) - }; - if let Some(data) = &self.root.proc_macro_data { - std::iter::once(CRATE_DEF_INDEX) - .chain(data.macros.decode(self)) - .map(def_index_to_data) - .collect() - } else { - (0..self.num_def_ids()) - .map(|index| def_index_to_data(DefIndex::from_usize(index))) - .collect() - } - } - /// Get the `DepNodeIndex` corresponding this crate. The result of this /// method is cached in the `dep_node_index` field. fn get_crate_dep_node_index(&self, tcx: TyCtxt<'tcx>) -> DepNodeIndex { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 2ffd239b2f06c..b7f2288521790 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -456,6 +456,10 @@ impl CStore { pub fn module_expansion_untracked(&self, def_id: DefId, sess: &Session) -> ExpnId { self.get_crate_data(def_id.krate).module_expansion(def_id.index, sess) } + + pub fn num_def_ids(&self, cnum: CrateNum) -> usize { + self.get_crate_data(cnum).num_def_ids() + } } impl CrateStore for CStore { @@ -498,14 +502,6 @@ impl CrateStore for CStore { self.get_crate_data(def.krate).def_path_hash(def.index) } - fn all_def_path_hashes_and_def_ids(&self, cnum: CrateNum) -> Vec<(DefPathHash, DefId)> { - self.get_crate_data(cnum).all_def_path_hashes_and_def_ids() - } - - fn num_def_ids(&self, cnum: CrateNum) -> usize { - self.get_crate_data(cnum).num_def_ids() - } - // See `CrateMetadataRef::def_path_hash_to_def_id` for more details fn def_path_hash_to_def_id( &self, diff --git a/compiler/rustc_middle/src/middle/cstore.rs b/compiler/rustc_middle/src/middle/cstore.rs index bd7121ca1d70f..6d2c43874bc0f 100644 --- a/compiler/rustc_middle/src/middle/cstore.rs +++ b/compiler/rustc_middle/src/middle/cstore.rs @@ -189,8 +189,6 @@ pub trait CrateStore { fn def_kind(&self, def: DefId) -> DefKind; fn def_path(&self, def: DefId) -> DefPath; fn def_path_hash(&self, def: DefId) -> DefPathHash; - fn all_def_path_hashes_and_def_ids(&self, cnum: CrateNum) -> Vec<(DefPathHash, DefId)>; - fn num_def_ids(&self, cnum: CrateNum) -> usize; fn def_path_hash_to_def_id( &self, cnum: CrateNum, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index b63acdc114e89..97117ab13415a 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -13,7 +13,6 @@ use rustc_hir::{ }; use rustc_interface::interface; use rustc_middle::hir::map::Map; -use rustc_middle::middle::cstore::CrateStore; use rustc_middle::middle::privacy::AccessLevels; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; use rustc_resolve as resolve; From 56c64f871ec25468c55345645713032b615326b1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 29 Nov 2020 22:34:41 +0100 Subject: [PATCH 09/19] Add lint pass for doc keyword --- compiler/rustc_lint/src/internal.rs | 46 ++++++++++++++++++++++++++++- compiler/rustc_lint/src/lib.rs | 3 ++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index c2d98b8e4ad37..b226572703256 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -10,7 +10,7 @@ use rustc_hir::{GenericArg, HirId, MutTy, Mutability, Path, PathSegment, QPath, use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; use rustc_span::hygiene::{ExpnKind, MacroKind}; -use rustc_span::symbol::{sym, Ident, Symbol}; +use rustc_span::symbol::{kw, sym, Ident, Symbol}; declare_tool_lint! { pub rustc::DEFAULT_HASH_TYPES, @@ -267,3 +267,47 @@ impl EarlyLintPass for LintPassImpl { } } } + +declare_tool_lint! { + pub rustc::EXISTING_DOC_KEYWORD, + Deny, + "Check that documented keywords in std and core actually exist", + report_in_external_macro: true +} + +declare_lint_pass!(ExistingDocKeyword => [EXISTING_DOC_KEYWORD]); + +fn is_doc_keyword(s: Symbol) -> bool { + s <= kw::Union +} + +impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword { + fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) { + for attr in item.attrs { + if !attr.has_name(sym::doc) { + continue; + } + if let Some(list) = attr.meta_item_list() { + for nested in list { + if nested.has_name(sym::keyword) { + let v = nested + .value_str() + .expect("#[doc(keyword = \"...\")] expected a value!"); + if is_doc_keyword(v) { + return; + } + cx.struct_span_lint(EXISTING_DOC_KEYWORD, attr.span, |lint| { + lint.build(&format!( + "Found non-existing keyword `{}` used in \ + `#[doc(keyword = \"...\")]`", + v, + )) + .help("only existing keywords are allowed in core/std") + .emit(); + }); + } + } + } + } + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 81549be4b0915..80ef855c3859e 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -463,6 +463,8 @@ fn register_internals(store: &mut LintStore) { store.register_early_pass(|| box DefaultHashTypes::new()); store.register_lints(&LintPassImpl::get_lints()); store.register_early_pass(|| box LintPassImpl); + store.register_lints(&ExistingDocKeyword::get_lints()); + store.register_late_pass(|| box ExistingDocKeyword); store.register_lints(&TyTyKind::get_lints()); store.register_late_pass(|| box TyTyKind); store.register_group( @@ -475,6 +477,7 @@ fn register_internals(store: &mut LintStore) { LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO), LintId::of(TY_PASS_BY_REFERENCE), LintId::of(USAGE_OF_QUALIFIED_TY), + LintId::of(EXISTING_DOC_KEYWORD), ], ); } From 0105e4a54b2ccbfbd62b0d07f636520b39094f5e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 3 Dec 2020 14:05:58 +0100 Subject: [PATCH 10/19] Add test for EXISTING_DOC_KEYWORD internal lint --- .../internal-lints/existing_doc_keyword.rs | 9 +++++++++ .../internal-lints/existing_doc_keyword.stderr | 11 +++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/test/ui-fulldeps/internal-lints/existing_doc_keyword.rs create mode 100644 src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr diff --git a/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.rs b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.rs new file mode 100644 index 0000000000000..2b4a65b4a4c50 --- /dev/null +++ b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.rs @@ -0,0 +1,9 @@ +// compile-flags: -Z unstable-options + +#![feature(rustc_private)] +#![feature(doc_keyword)] + +#![crate_type = "lib"] + +#[doc(keyword = "tadam")] //~ ERROR +mod tadam {} diff --git a/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr new file mode 100644 index 0000000000000..6fc288ae43453 --- /dev/null +++ b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr @@ -0,0 +1,11 @@ +error: Found non-existing keyword `tadam` used in `#[doc(keyword = "...")]` + --> $DIR/existing_doc_keyword.rs:8:1 + | +LL | #[doc(keyword = "tadam")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[deny(rustc::existing_doc_keyword)]` on by default + = help: only existing keywords are allowed in core/std + +error: aborting due to previous error + From 50eb3a89f8e2a4c1d809d2b0170b0063b9338d6d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 3 Dec 2020 15:32:41 +0100 Subject: [PATCH 11/19] Only deny doc_keyword in std and set it as "allow" by default --- compiler/rustc_lint/src/internal.rs | 2 +- library/std/src/lib.rs | 1 + .../ui-fulldeps/internal-lints/existing_doc_keyword.rs | 2 ++ .../internal-lints/existing_doc_keyword.stderr | 8 ++++++-- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index b226572703256..af5972c6c81c7 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -270,7 +270,7 @@ impl EarlyLintPass for LintPassImpl { declare_tool_lint! { pub rustc::EXISTING_DOC_KEYWORD, - Deny, + Allow, "Check that documented keywords in std and core actually exist", report_in_external_macro: true } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 83eb847697dd4..6c240cb4c3ed9 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -212,6 +212,7 @@ all(target_vendor = "fortanix", target_env = "sgx"), feature(slice_index_methods, coerce_unsized, sgx_platform) )] +#![deny(rustc::existing_doc_keyword)] #![cfg_attr(all(test, target_vendor = "fortanix", target_env = "sgx"), feature(fixed_size_array))] // std is implemented with unstable features, many of which are internal // compiler details that will never be stable diff --git a/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.rs b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.rs index 2b4a65b4a4c50..053712a4b4ee6 100644 --- a/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.rs +++ b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.rs @@ -5,5 +5,7 @@ #![crate_type = "lib"] +#![deny(rustc::existing_doc_keyword)] + #[doc(keyword = "tadam")] //~ ERROR mod tadam {} diff --git a/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr index 6fc288ae43453..bac44f338b74c 100644 --- a/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr +++ b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr @@ -1,10 +1,14 @@ error: Found non-existing keyword `tadam` used in `#[doc(keyword = "...")]` - --> $DIR/existing_doc_keyword.rs:8:1 + --> $DIR/existing_doc_keyword.rs:10:1 | LL | #[doc(keyword = "tadam")] | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[deny(rustc::existing_doc_keyword)]` on by default +note: the lint level is defined here + --> $DIR/existing_doc_keyword.rs:8:9 + | +LL | #![deny(rustc::existing_doc_keyword)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: only existing keywords are allowed in core/std error: aborting due to previous error From ff0ebd27a4436729b68cdf5180cfbb0c16c803a0 Mon Sep 17 00:00:00 2001 From: Vishnunarayan K I Date: Thu, 3 Dec 2020 21:09:39 +0530 Subject: [PATCH 12/19] move interpret::MemoryKind::Heap to const eval --- compiler/rustc_mir/src/const_eval/machine.rs | 27 ++++++++++++++++++- compiler/rustc_mir/src/interpret/intern.rs | 27 +++++++++++-------- compiler/rustc_mir/src/interpret/machine.rs | 8 +++--- compiler/rustc_mir/src/interpret/memory.rs | 5 ---- .../rustc_mir/src/transform/const_prop.rs | 2 ++ 5 files changed, 48 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_mir/src/const_eval/machine.rs b/compiler/rustc_mir/src/const_eval/machine.rs index 275496647d948..187f6fab5181f 100644 --- a/compiler/rustc_mir/src/const_eval/machine.rs +++ b/compiler/rustc_mir/src/const_eval/machine.rs @@ -7,6 +7,7 @@ use std::collections::hash_map::Entry; use std::hash::Hash; use rustc_data_structures::fx::FxHashMap; +use std::fmt; use rustc_ast::Mutability; use rustc_hir::def_id::DefId; @@ -179,6 +180,28 @@ impl interpret::AllocMap for FxHashMap { crate type CompileTimeEvalContext<'mir, 'tcx> = InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>; +#[derive(Debug, PartialEq, Eq, Copy, Clone)] +pub enum MemoryKind { + Heap, +} + +impl fmt::Display for MemoryKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + MemoryKind::Heap => write!(f, "heap allocation"), + } + } +} + +impl interpret::MayLeak for MemoryKind { + #[inline(always)] + fn may_leak(self) -> bool { + match self { + MemoryKind::Heap => false, + } + } +} + impl interpret::MayLeak for ! { #[inline(always)] fn may_leak(self) -> bool { @@ -222,6 +245,8 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, 'tcx> { compile_time_machine!(<'mir, 'tcx>); + type MemoryKind = MemoryKind; + type MemoryExtra = MemoryExtra; fn find_mir_or_eval_fn( @@ -317,7 +342,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, let ptr = ecx.memory.allocate( Size::from_bytes(size as u64), align, - interpret::MemoryKind::ConstHeap, + interpret::MemoryKind::Machine(MemoryKind::Heap), ); ecx.write_scalar(Scalar::Ptr(ptr), dest)?; } diff --git a/compiler/rustc_mir/src/interpret/intern.rs b/compiler/rustc_mir/src/interpret/intern.rs index db996f72128a7..01d58c47e3ab9 100644 --- a/compiler/rustc_mir/src/interpret/intern.rs +++ b/compiler/rustc_mir/src/interpret/intern.rs @@ -25,19 +25,20 @@ use rustc_target::abi::Size; use rustc_ast::Mutability; use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, Scalar, ValueVisitor}; +use crate::const_eval; -pub trait CompileTimeMachine<'mir, 'tcx> = Machine< +pub trait CompileTimeMachine<'mir, 'tcx, T> = Machine< 'mir, 'tcx, - MemoryKind = !, + MemoryKind = T, PointerTag = (), ExtraFnVal = !, FrameExtra = (), AllocExtra = (), - MemoryMap = FxHashMap, Allocation)>, + MemoryMap = FxHashMap, Allocation)>, >; -struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> { +struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>> { /// The ectx from which we intern. ecx: &'rt mut InterpCx<'mir, 'tcx, M>, /// Previously encountered safe references. @@ -74,7 +75,7 @@ struct IsStaticOrFn; /// `immutable` things might become mutable if `ty` is not frozen. /// `ty` can be `None` if there is no potential interior mutability /// to account for (e.g. for vtables). -fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>( +fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>>( ecx: &'rt mut InterpCx<'mir, 'tcx, M>, leftover_allocations: &'rt mut FxHashSet, alloc_id: AllocId, @@ -105,7 +106,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>( // changes in this function. match kind { MemoryKind::Stack - | MemoryKind::ConstHeap + | MemoryKind::Machine(const_eval::MemoryKind::Heap) | MemoryKind::Vtable | MemoryKind::CallerLocation => {} } @@ -141,7 +142,9 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>( None } -impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> InternVisitor<'rt, 'mir, 'tcx, M> { +impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>> + InternVisitor<'rt, 'mir, 'tcx, M> +{ fn intern_shallow( &mut self, alloc_id: AllocId, @@ -152,8 +155,8 @@ impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> InternVisitor<'rt, 'mir } } -impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> - for InternVisitor<'rt, 'mir, 'tcx, M> +impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>> + ValueVisitor<'mir, 'tcx, M> for InternVisitor<'rt, 'mir, 'tcx, M> { type V = MPlaceTy<'tcx>; @@ -290,7 +293,7 @@ pub enum InternKind { /// Any errors here would anyway be turned into `const_err` lints, whereas validation failures /// are hard errors. #[tracing::instrument(skip(ecx))] -pub fn intern_const_alloc_recursive>( +pub fn intern_const_alloc_recursive>( ecx: &mut InterpCx<'mir, 'tcx, M>, intern_kind: InternKind, ret: MPlaceTy<'tcx>, @@ -421,7 +424,9 @@ where Ok(()) } -impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { +impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>> + InterpCx<'mir, 'tcx, M> +{ /// A helper function that allocates memory for the layout given and gives you access to mutate /// it. Once your own mutation code is done, the backing `Allocation` is removed from the /// current `Memory` and returned. diff --git a/compiler/rustc_mir/src/interpret/machine.rs b/compiler/rustc_mir/src/interpret/machine.rs index 66dbacb2f9d4d..0bba027377229 100644 --- a/compiler/rustc_mir/src/interpret/machine.rs +++ b/compiler/rustc_mir/src/interpret/machine.rs @@ -366,9 +366,9 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { type PointerTag = (); type ExtraFnVal = !; - type MemoryKind = !; - type MemoryMap = rustc_data_structures::fx::FxHashMap, Allocation)>; - const GLOBAL_KIND: Option = None; // no copying of globals from `tcx` to machine memory + type MemoryMap = + rustc_data_structures::fx::FxHashMap, Allocation)>; + const GLOBAL_KIND: Option = None; // no copying of globals from `tcx` to machine memory type AllocExtra = (); type FrameExtra = (); @@ -407,7 +407,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { _memory_extra: &Self::MemoryExtra, _id: AllocId, alloc: Cow<'b, Allocation>, - _kind: Option>, + _kind: Option>, ) -> (Cow<'b, Allocation>, Self::PointerTag) { // We do not use a tag so we can just cheaply forward the allocation (alloc, ()) diff --git a/compiler/rustc_mir/src/interpret/memory.rs b/compiler/rustc_mir/src/interpret/memory.rs index 3294daabe6125..f3e373813ca53 100644 --- a/compiler/rustc_mir/src/interpret/memory.rs +++ b/compiler/rustc_mir/src/interpret/memory.rs @@ -27,9 +27,6 @@ use crate::util::pretty; pub enum MemoryKind { /// Stack memory. Error if deallocated except during a stack pop. Stack, - /// Heap memory. - /// FIXME: this variant should be in const_eval - ConstHeap, /// Memory backing vtables. Error if ever deallocated. Vtable, /// Memory allocated by `caller_location` intrinsic. Error if ever deallocated. @@ -43,7 +40,6 @@ impl MayLeak for MemoryKind { fn may_leak(self) -> bool { match self { MemoryKind::Stack => false, - MemoryKind::ConstHeap => false, MemoryKind::Vtable => true, MemoryKind::CallerLocation => true, MemoryKind::Machine(k) => k.may_leak(), @@ -55,7 +51,6 @@ impl fmt::Display for MemoryKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { MemoryKind::Stack => write!(f, "stack variable"), - MemoryKind::ConstHeap => write!(f, "heap allocation"), MemoryKind::Vtable => write!(f, "vtable"), MemoryKind::CallerLocation => write!(f, "caller location"), MemoryKind::Machine(m) => write!(f, "{}", m), diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs index abcf1862fd873..1d949e020ed5c 100644 --- a/compiler/rustc_mir/src/transform/const_prop.rs +++ b/compiler/rustc_mir/src/transform/const_prop.rs @@ -180,6 +180,8 @@ impl<'mir, 'tcx> ConstPropMachine<'mir, 'tcx> { impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> { compile_time_machine!(<'mir, 'tcx>); + type MemoryKind = !; + type MemoryExtra = (); fn find_mir_or_eval_fn( From 0ad3dce83a4506875e6b1381f5261e458b5c5d98 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 3 Dec 2020 17:06:58 -0500 Subject: [PATCH 13/19] Fix some clippy lints --- compiler/rustc_expand/src/base.rs | 10 ++++------ compiler/rustc_expand/src/expand.rs | 8 ++++++-- compiler/rustc_hir/src/hir.rs | 2 +- compiler/rustc_lexer/src/lib.rs | 10 +++++----- compiler/rustc_serialize/src/json.rs | 2 +- compiler/rustc_span/src/analyze_source_file.rs | 4 ++-- compiler/rustc_span/src/lib.rs | 5 +---- compiler/rustc_span/src/source_map.rs | 6 ++---- compiler/rustc_span/src/symbol.rs | 14 ++++++-------- 9 files changed, 28 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index b1071bf430851..335f3b7a9a011 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -235,12 +235,10 @@ impl Annotatable { pub fn derive_allowed(&self) -> bool { match *self { Annotatable::Stmt(ref stmt) => match stmt.kind { - ast::StmtKind::Item(ref item) => match item.kind { - ast::ItemKind::Struct(..) - | ast::ItemKind::Enum(..) - | ast::ItemKind::Union(..) => true, - _ => false, - }, + ast::StmtKind::Item(ref item) => matches!( + item.kind, + ast::ItemKind::Struct(..) | ast::ItemKind::Enum(..) | ast::ItemKind::Union(..) + ), _ => false, }, Annotatable::Item(ref item) => match item.kind { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 4ba75c21cf058..7870252231aee 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1134,7 +1134,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { if let Some(attr) = self.take_first_attr_no_derive(&mut expr) { // Collect the invoc regardless of whether or not attributes are permitted here // expansion will eat the attribute so it won't error later. - attr.0.as_ref().map(|attr| self.cfg.maybe_emit_expr_attr_err(attr)); + if let Some(attr) = attr.0.as_ref() { + self.cfg.maybe_emit_expr_attr_err(attr) + } // AstFragmentKind::Expr requires the macro to emit an expression. return self @@ -1231,7 +1233,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { self.cfg.configure_expr_kind(&mut expr.kind); if let Some(attr) = self.take_first_attr_no_derive(&mut expr) { - attr.0.as_ref().map(|attr| self.cfg.maybe_emit_expr_attr_err(attr)); + if let Some(attr) = attr.0.as_ref() { + self.cfg.maybe_emit_expr_attr_err(attr) + } return self .collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::OptExpr) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index f01d44171056f..44dc6673564a5 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2401,7 +2401,7 @@ impl StructField<'_> { // Still necessary in couple of places pub fn is_positional(&self) -> bool { let first = self.ident.as_str().as_bytes()[0]; - first >= b'0' && first <= b'9' + (b'0'..=b'9').contains(&first) } } diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 6539419aefb27..44fc4db7dc199 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -267,8 +267,8 @@ pub fn is_whitespace(c: char) -> bool { pub fn is_id_start(c: char) -> bool { // This is XID_Start OR '_' (which formally is not a XID_Start). // We also add fast-path for ascii idents - ('a' <= c && c <= 'z') - || ('A' <= c && c <= 'Z') + ('a'..='z').contains(&c) + || ('A'..='Z').contains(&c) || c == '_' || (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_start(c)) } @@ -279,9 +279,9 @@ pub fn is_id_start(c: char) -> bool { pub fn is_id_continue(c: char) -> bool { // This is exactly XID_Continue. // We also add fast-path for ascii idents - ('a' <= c && c <= 'z') - || ('A' <= c && c <= 'Z') - || ('0' <= c && c <= '9') + ('a'..='z').contains(&c) + || ('A'..='Z').contains(&c) + || ('0'..='9').contains(&c) || c == '_' || (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_continue(c)) } diff --git a/compiler/rustc_serialize/src/json.rs b/compiler/rustc_serialize/src/json.rs index 6c8965aa2e31f..bbbe568f17a8f 100644 --- a/compiler/rustc_serialize/src/json.rs +++ b/compiler/rustc_serialize/src/json.rs @@ -1859,7 +1859,7 @@ impl> Parser { } let n2 = self.decode_hex_escape()?; - if n2 < 0xDC00 || n2 > 0xDFFF { + if !(0xDC00..=0xDFFF).contains(&n2) { return self.error(LoneLeadingSurrogateInHexEscape); } let c = diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs index b4beb3dc37689..5987fb2a19897 100644 --- a/compiler/rustc_span/src/analyze_source_file.rs +++ b/compiler/rustc_span/src/analyze_source_file.rs @@ -97,7 +97,7 @@ cfg_if::cfg_if! { let ptr = src_bytes.as_ptr() as *const __m128i; // We don't know if the pointer is aligned to 16 bytes, so we // use `loadu`, which supports unaligned loading. - let chunk = _mm_loadu_si128(ptr.offset(chunk_index as isize)); + let chunk = _mm_loadu_si128(ptr.add(chunk_index)); // For character in the chunk, see if its byte value is < 0, which // indicates that it's part of a UTF-8 char. @@ -253,7 +253,7 @@ fn analyze_source_file_generic( let pos = BytePos::from_usize(i) + output_offset; if char_len > 1 { - assert!(char_len >= 2 && char_len <= 4); + assert!((2..=4).contains(&char_len)); let mbc = MultiByteChar { pos, bytes: char_len as u8 }; multi_byte_chars.push(mbc); } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 11a49d1ab887d..f63a73acbf4ba 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1015,10 +1015,7 @@ pub enum ExternalSourceKind { impl ExternalSource { pub fn is_absent(&self) -> bool { - match self { - ExternalSource::Foreign { kind: ExternalSourceKind::Present(_), .. } => false, - _ => true, - } + !matches!(self, ExternalSource::Foreign { kind: ExternalSourceKind::Present(_), .. }) } pub fn get_source(&self) -> Option<&Lrc> { diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index f067cdb730864..e9b4eb6e4abe0 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -623,7 +623,7 @@ impl SourceMap { self.span_to_source(sp, |src, start_index, end_index| { src.get(start_index..end_index) .map(|s| s.to_string()) - .ok_or_else(|| SpanSnippetError::IllFormedSpan(sp)) + .ok_or(SpanSnippetError::IllFormedSpan(sp)) }) } @@ -640,9 +640,7 @@ impl SourceMap { /// Returns the source snippet as `String` before the given `Span`. pub fn span_to_prev_source(&self, sp: Span) -> Result { self.span_to_source(sp, |src, start_index, _| { - src.get(..start_index) - .map(|s| s.to_string()) - .ok_or_else(|| SpanSnippetError::IllFormedSpan(sp)) + src.get(..start_index).map(|s| s.to_string()).ok_or(SpanSnippetError::IllFormedSpan(sp)) }) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 523628b70582f..00854d9a3fc16 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1362,15 +1362,13 @@ impl fmt::Display for IdentPrinter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.is_raw { f.write_str("r#")?; - } else { - if self.symbol == kw::DollarCrate { - if let Some(span) = self.convert_dollar_crate { - let converted = span.ctxt().dollar_crate_name(); - if !converted.is_path_segment_keyword() { - f.write_str("::")?; - } - return fmt::Display::fmt(&converted, f); + } else if self.symbol == kw::DollarCrate { + if let Some(span) = self.convert_dollar_crate { + let converted = span.ctxt().dollar_crate_name(); + if !converted.is_path_segment_keyword() { + f.write_str("::")?; } + return fmt::Display::fmt(&converted, f); } } fmt::Display::fmt(&self.symbol, f) From 5d4a7128d9929723769a7c674f49e9fe3fc0ff13 Mon Sep 17 00:00:00 2001 From: Camelid Date: Sun, 4 Oct 2020 20:42:34 -0700 Subject: [PATCH 14/19] Render Markdown in search results Previously Markdown documentation was not rendered to HTML for search results, which led to the output not being very readable, particularly for inline code. This PR fixes that by rendering Markdown to HTML with the help of pulldown-cmark (the library rustdoc uses to parse Markdown for the main text of documentation). However, the text for the title attribute (the text shown when you hover over an element) still uses the plain-text rendering since it is displayed in browsers as plain-text. Only these styles will be rendered; everything else is stripped away: * *italics* * **bold** * `inline code` --- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/formats/cache.rs | 8 +- src/librustdoc/html/markdown.rs | 92 ++++++++++++++++++- src/librustdoc/html/markdown/tests.rs | 33 ++++++- src/librustdoc/html/render/cache.rs | 6 +- src/librustdoc/html/render/mod.rs | 41 ++------- src/librustdoc/html/static/main.js | 25 ++++- ...ext-summaries.rs => markdown-summaries.rs} | 9 +- 8 files changed, 166 insertions(+), 50 deletions(-) rename src/test/rustdoc/{plain-text-summaries.rs => markdown-summaries.rs} (55%) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d294d8f02a80f..40218022a196e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1015,7 +1015,7 @@ impl<'tcx> Clean for (DefId, ty::PolyFnSig<'tcx>) { .iter() .map(|t| Argument { type_: t.clean(cx), - name: names.next().map_or(String::new(), |name| name.to_string()), + name: names.next().map_or_else(|| String::new(), |name| name.to_string()), }) .collect(), }, diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index c3153f2d4b6ff..e82bc540e95af 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -14,13 +14,13 @@ use crate::config::RenderInfo; use crate::fold::DocFolder; use crate::formats::item_type::ItemType; use crate::formats::Impl; +use crate::html::markdown::short_markdown_summary; use crate::html::render::cache::{extern_location, get_index_search_type, ExternalLocation}; use crate::html::render::IndexItem; -use crate::html::render::{plain_text_summary, shorten}; thread_local!(crate static CACHE_KEY: RefCell> = Default::default()); -/// This cache is used to store information about the `clean::Crate` being +/// This cache is used to store information about the [`clean::Crate`] being /// rendered in order to provide more useful documentation. This contains /// information like all implementors of a trait, all traits a type implements, /// documentation for all known traits, etc. @@ -313,7 +313,9 @@ impl DocFolder for Cache { ty: item.type_(), name: s.to_string(), path: path.join("::"), - desc: shorten(plain_text_summary(item.doc_value())), + desc: item + .doc_value() + .map_or_else(|| String::new(), short_markdown_summary), parent, parent_idx: None, search_type: get_index_search_type(&item), diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 8ce686c65502f..6bba503619120 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -17,8 +17,6 @@ //! // ... something using html //! ``` -#![allow(non_camel_case_types)] - use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; use rustc_hir::HirId; @@ -1037,7 +1035,97 @@ impl MarkdownSummaryLine<'_> { } } +/// Renders a subset of Markdown in the first paragraph of the provided Markdown. +/// +/// - *Italics*, **bold**, and `inline code` styles **are** rendered. +/// - Headings and links are stripped (though the text *is* rendered). +/// - HTML, code blocks, and everything else are ignored. +/// +/// Returns a tuple of the rendered HTML string and whether the output was shortened +/// due to the provided `length_limit`. +fn markdown_summary_with_limit(md: &str, length_limit: Option) -> (String, bool) { + if md.is_empty() { + return (String::new(), false); + } + + let length_limit = length_limit.unwrap_or(u16::MAX) as usize; + + let mut s = String::with_capacity(md.len() * 3 / 2); + let mut text_length = 0; + let mut stopped_early = false; + + fn push(s: &mut String, text_length: &mut usize, text: &str) { + s.push_str(text); + *text_length += text.len(); + }; + + 'outer: for event in Parser::new_ext(md, Options::ENABLE_STRIKETHROUGH) { + match &event { + Event::Text(text) => { + for word in text.split_inclusive(char::is_whitespace) { + if text_length + word.len() >= length_limit { + stopped_early = true; + break 'outer; + } + + push(&mut s, &mut text_length, word); + } + } + Event::Code(code) => { + if text_length + code.len() >= length_limit { + stopped_early = true; + break; + } + + s.push_str(""); + push(&mut s, &mut text_length, code); + s.push_str(""); + } + Event::Start(tag) => match tag { + Tag::Emphasis => s.push_str(""), + Tag::Strong => s.push_str(""), + Tag::CodeBlock(..) => break, + _ => {} + }, + Event::End(tag) => match tag { + Tag::Emphasis => s.push_str(""), + Tag::Strong => s.push_str(""), + Tag::Paragraph => break, + _ => {} + }, + Event::HardBreak | Event::SoftBreak => { + if text_length + 1 >= length_limit { + stopped_early = true; + break; + } + + push(&mut s, &mut text_length, " "); + } + _ => {} + } + } + + (s, stopped_early) +} + +/// Renders a shortened first paragraph of the given Markdown as a subset of Markdown, +/// making it suitable for contexts like the search index. +/// +/// Will shorten to 59 or 60 characters, including an ellipsis (…) if it was shortened. +/// +/// See [`markdown_summary_with_limit`] for details about what is rendered and what is not. +crate fn short_markdown_summary(markdown: &str) -> String { + let (mut s, was_shortened) = markdown_summary_with_limit(markdown, Some(59)); + + if was_shortened { + s.push('…'); + } + + s +} + /// Renders the first paragraph of the provided markdown as plain text. +/// Useful for alt-text. /// /// - Headings, links, and formatting are stripped. /// - Inline code is rendered as-is, surrounded by backticks. diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs index 8e618733f078e..9807d8632c75d 100644 --- a/src/librustdoc/html/markdown/tests.rs +++ b/src/librustdoc/html/markdown/tests.rs @@ -1,4 +1,4 @@ -use super::plain_text_summary; +use super::{plain_text_summary, short_markdown_summary}; use super::{ErrorCodes, IdMap, Ignore, LangString, Markdown, MarkdownHtml}; use rustc_span::edition::{Edition, DEFAULT_EDITION}; use std::cell::RefCell; @@ -204,6 +204,33 @@ fn test_header_ids_multiple_blocks() { ); } +#[test] +fn test_short_markdown_summary() { + fn t(input: &str, expect: &str) { + let output = short_markdown_summary(input); + assert_eq!(output, expect, "original: {}", input); + } + + t("hello [Rust](https://www.rust-lang.org) :)", "hello Rust :)"); + t("*italic*", "italic"); + t("**bold**", "bold"); + t("Multi-line\nsummary", "Multi-line summary"); + t("Hard-break \nsummary", "Hard-break summary"); + t("hello [Rust] :)\n\n[Rust]: https://www.rust-lang.org", "hello Rust :)"); + t("hello [Rust](https://www.rust-lang.org \"Rust\") :)", "hello Rust :)"); + t("code `let x = i32;` ...", "code let x = i32; ..."); + t("type `Type<'static>` ...", "type Type<'static> ..."); + t("# top header", "top header"); + t("## header", "header"); + t("first paragraph\n\nsecond paragraph", "first paragraph"); + t("```\nfn main() {}\n```", ""); + t("
hello
", ""); + t( + "a *very*, **very** long first paragraph. it has lots of `inline code: Vec`. and it has a [link](https://www.rust-lang.org).\nthat was a soft line break! \nthat was a hard one\n\nsecond paragraph.", + "a very, very long first paragraph. it has lots of …", + ); +} + #[test] fn test_plain_text_summary() { fn t(input: &str, expect: &str) { @@ -224,6 +251,10 @@ fn test_plain_text_summary() { t("first paragraph\n\nsecond paragraph", "first paragraph"); t("```\nfn main() {}\n```", ""); t("
hello
", ""); + t( + "a *very*, **very** long first paragraph. it has lots of `inline code: Vec`. and it has a [link](https://www.rust-lang.org).\nthat was a soft line break! \nthat was a hard one\n\nsecond paragraph.", + "a very, very long first paragraph. it has lots of `inline code: Vec`. and it has a link. that was a soft line break! that was a hard one", + ); } #[test] diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 085ca01f58daa..97f764517faf6 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -9,7 +9,7 @@ use crate::clean::types::GetDefId; use crate::clean::{self, AttributesExt}; use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; -use crate::html::render::{plain_text_summary, shorten}; +use crate::html::markdown::short_markdown_summary; use crate::html::render::{Generic, IndexItem, IndexItemFunctionType, RenderType, TypeWithKind}; /// Indicates where an external crate can be found. @@ -78,7 +78,7 @@ crate fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { ty: item.type_(), name: item.name.clone().unwrap(), path: fqp[..fqp.len() - 1].join("::"), - desc: shorten(plain_text_summary(item.doc_value())), + desc: item.doc_value().map_or_else(|| String::new(), short_markdown_summary), parent: Some(did), parent_idx: None, search_type: get_index_search_type(&item), @@ -127,7 +127,7 @@ crate fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { let crate_doc = krate .module .as_ref() - .map(|module| shorten(plain_text_summary(module.doc_value()))) + .map(|module| module.doc_value().map_or_else(|| String::new(), short_markdown_summary)) .unwrap_or_default(); #[derive(Serialize)] diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index de620a35c80d7..901f00b21da9d 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -76,7 +76,9 @@ use crate::html::format::fmt_impl_for_trait_page; use crate::html::format::Function; use crate::html::format::{href, print_default_space, print_generic_bounds, WhereClause}; use crate::html::format::{print_abi_with_space, Buffer, PrintWithSpace}; -use crate::html::markdown::{self, ErrorCodes, IdMap, Markdown, MarkdownHtml, MarkdownSummaryLine}; +use crate::html::markdown::{ + self, plain_text_summary, ErrorCodes, IdMap, Markdown, MarkdownHtml, MarkdownSummaryLine, +}; use crate::html::sources; use crate::html::{highlight, layout, static_files}; use cache::{build_index, ExternalLocation}; @@ -1604,9 +1606,10 @@ impl Context { Some(ref s) => s.to_string(), }; let short = short.to_string(); - map.entry(short) - .or_default() - .push((myname, Some(plain_text_summary(item.doc_value())))); + map.entry(short).or_default().push(( + myname, + Some(item.doc_value().map_or_else(|| String::new(), plain_text_summary)), + )); } if self.shared.sort_modules_alphabetically { @@ -1810,36 +1813,6 @@ fn full_path(cx: &Context, item: &clean::Item) -> String { s } -/// Renders the first paragraph of the given markdown as plain text, making it suitable for -/// contexts like alt-text or the search index. -/// -/// If no markdown is supplied, the empty string is returned. -/// -/// See [`markdown::plain_text_summary`] for further details. -#[inline] -crate fn plain_text_summary(s: Option<&str>) -> String { - s.map(markdown::plain_text_summary).unwrap_or_default() -} - -crate fn shorten(s: String) -> String { - if s.chars().count() > 60 { - let mut len = 0; - let mut ret = s - .split_whitespace() - .take_while(|p| { - // + 1 for the added character after the word. - len += p.chars().count() + 1; - len < 60 - }) - .collect::>() - .join(" "); - ret.push('…'); - ret - } else { - s - } -} - fn document(w: &mut Buffer, cx: &Context, item: &clean::Item, parent: Option<&clean::Item>) { if let Some(ref name) = item.name { info!("Documenting {}", name); diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 69984be5eb622..712ea044e48ff 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1611,7 +1611,7 @@ function defocusSearchBar() { item.displayPath + "" + name + "" + "" + - "" + escape(item.desc) + + "" + item.desc + " "; }); output += ""; @@ -2013,7 +2013,9 @@ function defocusSearchBar() { } var link = document.createElement("a"); link.href = rootPath + crates[i] + "/index.html"; - link.title = rawSearchIndex[crates[i]].doc; + // The summary in the search index has HTML, so we need to + // dynamically render it as plaintext. + link.title = convertHTMLToPlaintext(rawSearchIndex[crates[i]].doc); link.className = klass; link.textContent = crates[i]; @@ -2026,6 +2028,25 @@ function defocusSearchBar() { } }; + /** + * Convert HTML to plaintext: + * + * * Replace "foo" with "`foo`" + * * Strip all other HTML tags + * + * Used by the dynamic sidebar crate list renderer. + * + * @param {[string]} html [The HTML to convert] + * @return {[string]} [The resulting plaintext] + */ + function convertHTMLToPlaintext(html) { + var dom = new DOMParser().parseFromString( + html.replace('', '`').replace('', '`'), + 'text/html', + ); + return dom.body.innerText; + } + // delayed sidebar rendering. window.initSidebarItems = function(items) { diff --git a/src/test/rustdoc/plain-text-summaries.rs b/src/test/rustdoc/markdown-summaries.rs similarity index 55% rename from src/test/rustdoc/plain-text-summaries.rs rename to src/test/rustdoc/markdown-summaries.rs index c995ccbf0af67..b843e28e7b0d3 100644 --- a/src/test/rustdoc/plain-text-summaries.rs +++ b/src/test/rustdoc/markdown-summaries.rs @@ -1,21 +1,22 @@ #![crate_type = "lib"] #![crate_name = "summaries"] -//! This summary has a [link] and `code`. +//! This *summary* has a [link] and `code`. //! //! This is the second paragraph. //! //! [link]: https://example.com -// @has search-index.js 'This summary has a link and `code`.' +// @has search-index.js 'This summary has a link and code.' // @!has - 'second paragraph' -/// This `code` should be in backticks. +/// This `code` will be rendered in a code tag. /// /// This text should not be rendered. pub struct Sidebar; -// @has summaries/sidebar-items.js 'This `code` should be in backticks.' +// @has search-index.js 'This code will be rendered in a code tag.' +// @has summaries/sidebar-items.js 'This `code` will be rendered in a code tag.' // @!has - 'text should not be rendered' /// ```text From e178030ea4d1b3a1e38cc53141188d2249d33cf5 Mon Sep 17 00:00:00 2001 From: Camelid Date: Tue, 17 Nov 2020 12:24:16 -0800 Subject: [PATCH 15/19] Use `createElement` and `innerHTML` instead of `DOMParser` @GuillaumeGomez was concerned about browser compatibility. --- src/librustdoc/html/static/main.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 712ea044e48ff..0884351a9fd80 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -2040,11 +2040,9 @@ function defocusSearchBar() { * @return {[string]} [The resulting plaintext] */ function convertHTMLToPlaintext(html) { - var dom = new DOMParser().parseFromString( - html.replace('', '`').replace('', '`'), - 'text/html', - ); - return dom.body.innerText; + var x = document.createElement("div"); + x.innerHTML = html.replace('', '`').replace('', '`'); + return x.innerText; } From 07e9426efba69e8b662f2a896326b157f5d0ba2d Mon Sep 17 00:00:00 2001 From: Camelid Date: Mon, 23 Nov 2020 19:26:15 -0800 Subject: [PATCH 16/19] Make `length_limit` a `usize` --- src/librustdoc/html/markdown.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 6bba503619120..0e4c5410abe1e 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -1043,13 +1043,11 @@ impl MarkdownSummaryLine<'_> { /// /// Returns a tuple of the rendered HTML string and whether the output was shortened /// due to the provided `length_limit`. -fn markdown_summary_with_limit(md: &str, length_limit: Option) -> (String, bool) { +fn markdown_summary_with_limit(md: &str, length_limit: usize) -> (String, bool) { if md.is_empty() { return (String::new(), false); } - let length_limit = length_limit.unwrap_or(u16::MAX) as usize; - let mut s = String::with_capacity(md.len() * 3 / 2); let mut text_length = 0; let mut stopped_early = false; @@ -1115,7 +1113,7 @@ fn markdown_summary_with_limit(md: &str, length_limit: Option) -> (String, /// /// See [`markdown_summary_with_limit`] for details about what is rendered and what is not. crate fn short_markdown_summary(markdown: &str) -> String { - let (mut s, was_shortened) = markdown_summary_with_limit(markdown, Some(59)); + let (mut s, was_shortened) = markdown_summary_with_limit(markdown, 59); if was_shortened { s.push('…'); From b9035194c0c434d89ec776176a88406cc4af66cc Mon Sep 17 00:00:00 2001 From: Camelid Date: Mon, 23 Nov 2020 20:33:41 -0800 Subject: [PATCH 17/19] Add rustdoc-js test Finally! --- src/test/rustdoc-js/basic.rs | 2 +- src/test/rustdoc-js/summaries.js | 7 +++++++ src/test/rustdoc-js/summaries.rs | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/test/rustdoc-js/summaries.js create mode 100644 src/test/rustdoc-js/summaries.rs diff --git a/src/test/rustdoc-js/basic.rs b/src/test/rustdoc-js/basic.rs index 1b4963fcebea8..da946a58b1c88 100644 --- a/src/test/rustdoc-js/basic.rs +++ b/src/test/rustdoc-js/basic.rs @@ -1,2 +1,2 @@ -/// Foo +/// Docs for Foo pub struct Foo; diff --git a/src/test/rustdoc-js/summaries.js b/src/test/rustdoc-js/summaries.js new file mode 100644 index 0000000000000..773357610d78a --- /dev/null +++ b/src/test/rustdoc-js/summaries.js @@ -0,0 +1,7 @@ +const QUERY = 'summaries'; + +const EXPECTED = { + 'others': [ + { 'path': '', 'name': 'summaries', 'desc': 'This summary has a link and code.' }, + ], +}; diff --git a/src/test/rustdoc-js/summaries.rs b/src/test/rustdoc-js/summaries.rs new file mode 100644 index 0000000000000..beb91e286b610 --- /dev/null +++ b/src/test/rustdoc-js/summaries.rs @@ -0,0 +1,18 @@ +#![crate_type = "lib"] +#![crate_name = "summaries"] + +//! This *summary* has a [link] and `code`. +//! +//! This is the second paragraph. +//! +//! [link]: https://example.com + +/// This `code` will be rendered in a code tag. +/// +/// This text should not be rendered. +pub struct Sidebar; + +/// ```text +/// this block should not be rendered +/// ``` +pub struct Sidebar2; From f0cf5a974ec0730a512fa241dacf6e2c5659625f Mon Sep 17 00:00:00 2001 From: Camelid Date: Tue, 24 Nov 2020 11:18:45 -0800 Subject: [PATCH 18/19] Add more rustdoc-js test cases --- src/test/rustdoc-js/summaries.js | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/test/rustdoc-js/summaries.js b/src/test/rustdoc-js/summaries.js index 773357610d78a..f175e47342df6 100644 --- a/src/test/rustdoc-js/summaries.js +++ b/src/test/rustdoc-js/summaries.js @@ -1,7 +1,21 @@ -const QUERY = 'summaries'; +// ignore-tidy-linelength -const EXPECTED = { - 'others': [ - { 'path': '', 'name': 'summaries', 'desc': 'This summary has a link and code.' }, - ], -}; +const QUERY = ['summaries', 'summaries::Sidebar', 'summaries::Sidebar2']; + +const EXPECTED = [ + { + 'others': [ + { 'path': '', 'name': 'summaries', 'desc': 'This summary has a link and code.' }, + ], + }, + { + 'others': [ + { 'path': 'summaries', 'name': 'Sidebar', 'desc': 'This code will be rendered in a code tag.' }, + ], + }, + { + 'others': [ + { 'path': 'summaries', 'name': 'Sidebar2', 'desc': '' }, + ], + }, +]; From 376507f47b5f16c0a9c210005de2bcdb270d8920 Mon Sep 17 00:00:00 2001 From: Camelid Date: Thu, 3 Dec 2020 13:08:40 -0800 Subject: [PATCH 19/19] Add missing feature flag Accidentally removed in rebase. --- src/librustdoc/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 80a9c3811cf66..26bf4b569ff4b 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -15,6 +15,7 @@ #![feature(never_type)] #![feature(once_cell)] #![feature(type_ascription)] +#![feature(split_inclusive)] #![recursion_limit = "256"] #[macro_use]