From 728938346b02a9688c44253c19b15baa7551fd80 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Wed, 8 Jul 2020 16:23:38 -0400 Subject: [PATCH 01/32] Adjust rc::Weak::from_raw to support unsized T --- library/alloc/src/rc.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index f998e49dcfcde..27e6e11090353 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1841,17 +1841,18 @@ impl Weak { /// [`new`]: Weak::new #[stable(feature = "weak_into_raw", since = "1.45.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { - if ptr.is_null() { - Self::new() - } else { - // See Rc::from_raw for details - unsafe { - let offset = data_offset(ptr); - let fake_ptr = ptr as *mut RcBox; - let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)); - Weak { ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw") } - } - } + // SAFETY: data_offset is safe to call, because this pointer originates from a Weak. + // See Weak::as_ptr for context on how the input pointer is derived. + let offset = unsafe { data_offset(ptr) }; + + // Reverse the offset to find the original RcBox. + // SAFETY: we use wrapping_offset here because the pointer may be dangling (iff T: Sized). + let ptr = unsafe { + set_data_ptr(ptr as *mut RcBox, (ptr as *mut u8).wrapping_offset(-offset)) + }; + + // SAFETY: we now have recovered the original Weak pointer, so can create the Weak. + Weak { ptr: unsafe { NonNull::new_unchecked(ptr) } } } } From 0c61ce2cf0560577923abafab2e5bfce14516525 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Wed, 8 Jul 2020 16:24:56 -0400 Subject: [PATCH 02/32] ?Sized bounds for rc::Weak::as_ptr and friends --- library/alloc/src/rc.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 27e6e11090353..1d4ce8e268294 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1721,7 +1721,21 @@ impl Weak { pub fn new() -> Weak { Weak { ptr: NonNull::new(usize::MAX as *mut RcBox).expect("MAX is not 0") } } +} + +pub(crate) fn is_dangling(ptr: NonNull) -> bool { + let address = ptr.as_ptr() as *mut () as usize; + address == usize::MAX +} + +/// Helper type to allow accessing the reference counts without +/// making any assertions about the data field. +struct WeakInner<'a> { + weak: &'a Cell, + strong: &'a Cell, +} +impl Weak { /// Returns a raw pointer to the object `T` pointed to by this `Weak`. /// /// The pointer is valid only if there are some strong references. The pointer may be dangling, @@ -1854,21 +1868,7 @@ impl Weak { // SAFETY: we now have recovered the original Weak pointer, so can create the Weak. Weak { ptr: unsafe { NonNull::new_unchecked(ptr) } } } -} - -pub(crate) fn is_dangling(ptr: NonNull) -> bool { - let address = ptr.as_ptr() as *mut () as usize; - address == usize::MAX -} - -/// Helper type to allow accessing the reference counts without -/// making any assertions about the data field. -struct WeakInner<'a> { - weak: &'a Cell, - strong: &'a Cell, -} -impl Weak { /// Attempts to upgrade the `Weak` pointer to an [`Rc`], delaying /// dropping of the inner value if successful. /// From 5e7406c9569dce75a042ce079918cf03cfca842a Mon Sep 17 00:00:00 2001 From: CAD97 Date: Tue, 14 Jul 2020 15:17:55 -0400 Subject: [PATCH 03/32] Adjust sync::Weak::from_raw to support unsized T --- library/alloc/src/sync.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 6a240fbb42a99..06dec6f01f8d3 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1629,17 +1629,18 @@ impl Weak { /// [`forget`]: std::mem::forget #[stable(feature = "weak_into_raw", since = "1.45.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { - if ptr.is_null() { - Self::new() - } else { - // See Arc::from_raw for details - unsafe { - let offset = data_offset(ptr); - let fake_ptr = ptr as *mut ArcInner; - let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)); - Weak { ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw") } - } - } + // SAFETY: data_offset is safe to call, because this pointer originates from a Weak. + // See Weak::as_ptr for context on how the input pointer is derived. + let offset = unsafe { data_offset(ptr) }; + + // Reverse the offset to find the original ArcInner. + // SAFETY: we use wrapping_offset here because the pointer may be dangling (iff T: Sized) + let ptr = unsafe { + set_data_ptr(ptr as *mut ArcInner, (ptr as *mut u8).wrapping_offset(-offset)) + }; + + // SAFETY: we now have recovered the original Weak pointer, so can create the Weak. + unsafe { Weak { ptr: NonNull::new_unchecked(ptr) } } } } From 9d9903c5a50bb1f5b5fc3045b86172279eff7d30 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Tue, 14 Jul 2020 15:22:48 -0400 Subject: [PATCH 04/32] Allow Weak::as_ptr and friends for unsized T --- library/alloc/src/sync.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 06dec6f01f8d3..f064881717d63 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1509,7 +1509,16 @@ impl Weak { pub fn new() -> Weak { Weak { ptr: NonNull::new(usize::MAX as *mut ArcInner).expect("MAX is not 0") } } +} +/// Helper type to allow accessing the reference counts without +/// making any assertions about the data field. +struct WeakInner<'a> { + weak: &'a atomic::AtomicUsize, + strong: &'a atomic::AtomicUsize, +} + +impl Weak { /// Returns a raw pointer to the object `T` pointed to by this `Weak`. /// /// The pointer is valid only if there are some strong references. The pointer may be dangling, @@ -1642,16 +1651,7 @@ impl Weak { // SAFETY: we now have recovered the original Weak pointer, so can create the Weak. unsafe { Weak { ptr: NonNull::new_unchecked(ptr) } } } -} -/// Helper type to allow accessing the reference counts without -/// making any assertions about the data field. -struct WeakInner<'a> { - weak: &'a atomic::AtomicUsize, - strong: &'a atomic::AtomicUsize, -} - -impl Weak { /// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying /// dropping of the inner value if successful. /// From 3d07108d3600dff50e564f57dd390337dbe14d55 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Tue, 14 Jul 2020 15:35:14 -0400 Subject: [PATCH 05/32] Add tests for weak into/from raw --- library/alloc/src/rc/tests.rs | 42 +++++++++++++++++++++++++++++++++ library/alloc/src/sync/tests.rs | 42 +++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs index fed48a59f809e..bb5c3f4f90433 100644 --- a/library/alloc/src/rc/tests.rs +++ b/library/alloc/src/rc/tests.rs @@ -190,6 +190,48 @@ fn test_into_from_raw_unsized() { assert_eq!(rc2.to_string(), "123"); } +#[test] +fn into_from_weak_raw() { + let x = Rc::new(box "hello"); + let y = Rc::downgrade(&x); + + let y_ptr = Weak::into_raw(y); + unsafe { + assert_eq!(**y_ptr, "hello"); + + let y = Weak::from_raw(y_ptr); + let y_up = Weak::upgrade(&y).unwrap(); + assert_eq!(**y_up, "hello"); + drop(y_up); + + assert_eq!(Rc::try_unwrap(x).map(|x| *x), Ok("hello")); + } +} + +#[test] +fn test_into_from_weak_raw_unsized() { + use std::fmt::Display; + use std::string::ToString; + + let arc: Rc = Rc::from("foo"); + let weak: Weak = Rc::downgrade(&arc); + + let ptr = Weak::into_raw(weak.clone()); + let weak2 = unsafe { Weak::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }, "foo"); + assert!(weak.ptr_eq(&weak2)); + + let arc: Rc = Rc::new(123); + let weak: Weak = Rc::downgrade(&arc); + + let ptr = Weak::into_raw(weak.clone()); + let weak2 = unsafe { Weak::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }.to_string(), "123"); + assert!(weak.ptr_eq(&weak2)); +} + #[test] fn get_mut() { let mut x = Rc::new(3); diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs index d25171716061d..77f328d48f94d 100644 --- a/library/alloc/src/sync/tests.rs +++ b/library/alloc/src/sync/tests.rs @@ -140,6 +140,48 @@ fn test_into_from_raw_unsized() { assert_eq!(arc2.to_string(), "123"); } +#[test] +fn into_from_weak_raw() { + let x = Arc::new(box "hello"); + let y = Arc::downgrade(&x); + + let y_ptr = Weak::into_raw(y); + unsafe { + assert_eq!(**y_ptr, "hello"); + + let y = Weak::from_raw(y_ptr); + let y_up = Weak::upgrade(&y).unwrap(); + assert_eq!(**y_up, "hello"); + drop(y_up); + + assert_eq!(Arc::try_unwrap(x).map(|x| *x), Ok("hello")); + } +} + +#[test] +fn test_into_from_weak_raw_unsized() { + use std::fmt::Display; + use std::string::ToString; + + let arc: Arc = Arc::from("foo"); + let weak: Weak = Arc::downgrade(&arc); + + let ptr = Weak::into_raw(weak.clone()); + let weak2 = unsafe { Weak::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }, "foo"); + assert!(weak.ptr_eq(&weak2)); + + let arc: Arc = Arc::new(123); + let weak: Weak = Arc::downgrade(&arc); + + let ptr = Weak::into_raw(weak.clone()); + let weak2 = unsafe { Weak::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }.to_string(), "123"); + assert!(weak.ptr_eq(&weak2)); +} + #[test] fn test_cowarc_clone_make_mut() { let mut cow0 = Arc::new(75); From 43c181bac4d88dbe7bdd762688dcf18313f01093 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 4 Aug 2020 13:48:05 +0200 Subject: [PATCH 06/32] Use `tracing` spans to trace the entire MIR interp stack --- Cargo.lock | 15 +--- compiler/rustc_driver/Cargo.toml | 1 + compiler/rustc_driver/src/lib.rs | 20 +++-- compiler/rustc_mir/Cargo.toml | 1 - .../rustc_mir/src/interpret/eval_context.rs | 77 ++++++++++++++----- src/tools/tidy/src/deps.rs | 1 - 6 files changed, 75 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d23b29d39bf86..db072cbb7e709 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1723,15 +1723,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "log_settings" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19af41f0565d7c19b2058153ad0b42d4d5ce89ec4dbf06ed6741114a8b63e7cd" -dependencies = [ - "lazy_static", -] - [[package]] name = "lsp-codec" version = "0.1.2" @@ -3520,6 +3511,7 @@ dependencies = [ "rustc_target", "tracing", "tracing-subscriber", + "tracing-tree", "winapi 0.3.9", ] @@ -3807,7 +3799,6 @@ version = "0.0.0" dependencies = [ "either", "itertools 0.9.0", - "log_settings", "polonius-engine", "regex", "rustc_apfloat", @@ -5102,9 +5093,9 @@ dependencies = [ [[package]] name = "tracing-tree" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1a3dc4774db3a6b2d66a4f8d8de670e874ec3ed55615860c994927419b32c5f" +checksum = "43aac8afb493b08e1e1904956f7407c1e671b9c83b26a17e1bd83d6a3520e350" dependencies = [ "ansi_term 0.12.1", "atty", diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml index adfce1008e1ed..f610e88b7fce5 100644 --- a/compiler/rustc_driver/Cargo.toml +++ b/compiler/rustc_driver/Cargo.toml @@ -11,6 +11,7 @@ crate-type = ["dylib"] libc = "0.2" tracing = { version = "0.1.18" } tracing-subscriber = { version = "0.2.10", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] } +tracing-tree = "0.1.6" rustc_middle = { path = "../rustc_middle" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_target = { path = "../rustc_target" } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 7118437c0c850..7e12d783cb41e 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1241,11 +1241,21 @@ pub fn init_env_logger(env: &str) { Ok(s) if s.is_empty() => return, Ok(_) => {} } - let builder = tracing_subscriber::FmtSubscriber::builder(); - - let builder = builder.with_env_filter(tracing_subscriber::EnvFilter::from_env(env)); - - builder.init() + let filter = tracing_subscriber::EnvFilter::from_env(env); + let layer = tracing_tree::HierarchicalLayer::default() + .with_indent_lines(true) + .with_ansi(true) + .with_targets(true) + .with_thread_ids(true) + .with_thread_names(true) + .with_wraparound(10) + .with_verbose_exit(true) + .with_verbose_entry(true) + .with_indent_amount(2); + + use tracing_subscriber::layer::SubscriberExt; + let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer); + tracing::subscriber::set_global_default(subscriber).unwrap(); } pub fn main() -> ! { diff --git a/compiler/rustc_mir/Cargo.toml b/compiler/rustc_mir/Cargo.toml index a6d22243d6df6..487668cfa1109 100644 --- a/compiler/rustc_mir/Cargo.toml +++ b/compiler/rustc_mir/Cargo.toml @@ -12,7 +12,6 @@ either = "1.5.0" rustc_graphviz = { path = "../rustc_graphviz" } itertools = "0.9" tracing = "0.1" -log_settings = "0.1.1" polonius-engine = "0.12.0" regex = "1" rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index f97096984fa9b..45b5dd62479d9 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -48,8 +48,41 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> { FxHashMap<(Ty<'tcx>, Option>), Pointer>, } +// The Phantomdata exists to prevent this type from being `Send`. If it were sent across a thread +// boundary and dropped in the other thread, it would exit the span in the other thread. +struct SpanGuard(tracing::Span, std::marker::PhantomData<*const u8>); + +impl SpanGuard { + /// By default a `SpanGuard` does nothing. + fn new() -> Self { + Self(tracing::Span::none(), std::marker::PhantomData) + } + + /// If a span is entered, we exit the previous span (if any, normally none) and enter the + /// new span. This is mainly so we don't have to use `Option` for the `tracing_span` field of + /// `Frame` by creating a dummy span to being with and then entering it once the frame has + /// been pushed. + fn enter(&mut self, span: tracing::Span) { + // This executes the destructor on the previous instance of `SpanGuard`, ensuring that + // we never enter or exit more spans than vice versa. Unless you `mem::leak`, then we + // can't protect the tracing stack, but that'll just lead to weird logging, no actual + // problems. + *self = Self(span, std::marker::PhantomData); + self.0.with_subscriber(|(id, dispatch)| { + dispatch.enter(id); + }); + } +} + +impl Drop for SpanGuard { + fn drop(&mut self) { + self.0.with_subscriber(|(id, dispatch)| { + dispatch.exit(id); + }); + } +} + /// A stack frame. -#[derive(Clone)] pub struct Frame<'mir, 'tcx, Tag = (), Extra = ()> { //////////////////////////////////////////////////////////////////////////////// // Function and callsite information @@ -80,6 +113,11 @@ pub struct Frame<'mir, 'tcx, Tag = (), Extra = ()> { /// can either directly contain `Scalar` or refer to some part of an `Allocation`. pub locals: IndexVec>, + /// The span of the `tracing` crate is stored here. + /// When the guard is dropped, the span is exited. This gives us + /// a full stack trace on all tracing statements. + tracing_span: SpanGuard, + //////////////////////////////////////////////////////////////////////////////// // Current position within the function //////////////////////////////////////////////////////////////////////////////// @@ -184,6 +222,7 @@ impl<'mir, 'tcx, Tag> Frame<'mir, 'tcx, Tag> { locals: self.locals, loc: self.loc, extra, + tracing_span: self.tracing_span, } } } @@ -637,11 +676,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return_place: Option>, return_to_block: StackPopCleanup, ) -> InterpResult<'tcx> { - if !self.stack().is_empty() { - info!("PAUSING({}) {}", self.frame_idx(), self.frame().instance); - } - ::log_settings::settings().indentation += 1; - // first push a stack frame so we have access to the local substs let pre_frame = Frame { body, @@ -652,6 +686,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // all methods actually know about the frame locals: IndexVec::new(), instance, + tracing_span: SpanGuard::new(), extra: (), }; let frame = M::init_frame_extra(self, pre_frame)?; @@ -696,7 +731,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.frame_mut().locals = locals; M::after_stack_push(self)?; self.frame_mut().loc = Ok(mir::Location::START); - info!("ENTERING({}) {}", self.frame_idx(), self.frame().instance); + + let span = info_span!("frame", "{}", instance); + self.frame_mut().tracing_span.enter(span); Ok(()) } @@ -746,12 +783,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// The cleanup block ends with a special `Resume` terminator, which will /// cause us to continue unwinding. pub(super) fn pop_stack_frame(&mut self, unwinding: bool) -> InterpResult<'tcx> { - info!( - "LEAVING({}) {} (unwinding = {})", - self.frame_idx(), - self.frame().instance, - unwinding - ); + info!(unwinding); // Sanity check `unwinding`. assert_eq!( @@ -766,7 +798,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { throw_ub_format!("unwinding past the topmost frame of the stack"); } - ::log_settings::settings().indentation -= 1; let frame = self.stack_mut().pop().expect("tried to pop a stack frame, but there were none"); @@ -824,12 +855,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } if !self.stack().is_empty() { - info!( - "CONTINUING({}) {} (unwinding = {})", - self.frame_idx(), - self.frame().instance, - unwinding - ); + info!(unwinding); } Ok(()) @@ -995,7 +1021,16 @@ where { fn hash_stable(&self, hcx: &mut StableHashingContext<'ctx>, hasher: &mut StableHasher) { // Exhaustive match on fields to make sure we forget no field. - let Frame { body, instance, return_to_block, return_place, locals, loc, extra } = self; + let Frame { + body, + instance, + return_to_block, + return_place, + locals, + loc, + extra, + tracing_span: _, + } = self; body.hash_stable(hcx, hasher); instance.hash_stable(hcx, hasher); return_to_block.hash_stable(hcx, hasher); diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 356705305d78b..0c52fee68a968 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -116,7 +116,6 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[ "libz-sys", "lock_api", "log", - "log_settings", "maybe-uninit", "md-5", "measureme", From e05e2f9a94f4fa43f9a77bb59184eeb46fd49577 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 30 Sep 2020 13:54:12 +0200 Subject: [PATCH 07/32] bootstrap: add ./x.py run src/tools/build-manifest --- src/bootstrap/builder.rs | 2 +- src/bootstrap/dist.rs | 2 +- src/bootstrap/run.rs | 42 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 4beeb9c87c4fd..3de5797180cf2 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -477,7 +477,7 @@ impl<'a> Builder<'a> { install::Src, install::Rustc ), - Kind::Run => describe!(run::ExpandYamlAnchors,), + Kind::Run => describe!(run::ExpandYamlAnchors, run::BuildManifest,), } } diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index c846662fd5126..8cdd293239ec3 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -46,7 +46,7 @@ pub fn pkgname(builder: &Builder<'_>, component: &str) -> String { } } -fn distdir(builder: &Builder<'_>) -> PathBuf { +pub(crate) fn distdir(builder: &Builder<'_>) -> PathBuf { builder.out.join("dist") } diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs index ba593cadbad81..80c093e713eff 100644 --- a/src/bootstrap/run.rs +++ b/src/bootstrap/run.rs @@ -1,5 +1,7 @@ use crate::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::dist::distdir; use crate::tool::Tool; +use build_helper::output; use std::process::Command; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -41,3 +43,43 @@ fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool { } true } + +#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] +pub struct BuildManifest; + +impl Step for BuildManifest { + type Output = (); + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/build-manifest") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(BuildManifest); + } + + fn run(self, builder: &Builder<'_>) { + // This gets called by `promote-release` + // (https://github.com/rust-lang/promote-release). + let mut cmd = builder.tool_cmd(Tool::BuildManifest); + let sign = builder.config.dist_sign_folder.as_ref().unwrap_or_else(|| { + panic!("\n\nfailed to specify `dist.sign-folder` in `config.toml`\n\n") + }); + let addr = builder.config.dist_upload_addr.as_ref().unwrap_or_else(|| { + panic!("\n\nfailed to specify `dist.upload-addr` in `config.toml`\n\n") + }); + + let today = output(Command::new("date").arg("+%Y-%m-%d")); + + cmd.arg(sign); + cmd.arg(distdir(builder)); + cmd.arg(today.trim()); + cmd.arg(addr); + cmd.arg(&builder.config.channel); + cmd.arg(&builder.src); + + builder.create_dir(&distdir(builder)); + builder.run(&mut cmd); + } +} From d4928ad7fd6636f1a1f8d51209a70f0ee7a5f43e Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 30 Sep 2020 14:26:10 +0200 Subject: [PATCH 08/32] build-manifest: keep legacy behavior when invoking through ./x.py dist --- src/bootstrap/dist.rs | 1 + src/tools/build-manifest/README.md | 3 +-- src/tools/build-manifest/src/main.rs | 37 ++++++++++++++-------------- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 8cdd293239ec3..857e06d846de4 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -2371,6 +2371,7 @@ impl Step for HashSign { cmd.arg(addr); cmd.arg(&builder.config.channel); cmd.arg(&builder.src); + cmd.env("BUILD_MANIFEST_LEGACY", "1"); builder.create_dir(&distdir(builder)); diff --git a/src/tools/build-manifest/README.md b/src/tools/build-manifest/README.md index 4d7d9f7da1874..26e96c9fd8fda 100644 --- a/src/tools/build-manifest/README.md +++ b/src/tools/build-manifest/README.md @@ -20,8 +20,7 @@ Then, you can generate the manifest and all the packages from `path/to/dist` to `path/to/output` with: ``` -$ BUILD_MANIFEST_DISABLE_SIGNING=1 cargo +nightly run \ - path/to/dist path/to/output 1970-01-01 http://example.com \ +$ cargo +nightly run path/to/dist path/to/output 1970-01-01 http://example.com \ CHANNEL path/to/rust/repo ``` diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index be3e862e7aecd..7821994e117c5 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -232,26 +232,27 @@ struct Builder { input: PathBuf, output: PathBuf, - gpg_passphrase: String, digests: BTreeMap, s3_address: String, date: String, - should_sign: bool, + legacy: bool, + legacy_gpg_passphrase: String, } fn main() { - // Avoid signing packages while manually testing - // Do NOT set this envvar in CI - let should_sign = env::var("BUILD_MANIFEST_DISABLE_SIGNING").is_err(); - - // Safety check to ensure signing is always enabled on CI - // The CI environment variable is set by both Travis and AppVeyor - if !should_sign && env::var("CI").is_ok() { - println!("The 'BUILD_MANIFEST_DISABLE_SIGNING' env var can't be enabled on CI."); - println!("If you're not running this on CI, unset the 'CI' env var."); - panic!(); - } + // Up until Rust 1.48 the release process relied on build-manifest to create the SHA256 + // checksums of released files and to sign the tarballs. That was moved over to promote-release + // in time for the branching of Rust 1.48, but the old release process still had to work the + // old way. + // + // When running build-manifest through the old ./x.py dist hash-and-sign the environment + // variable will be set, enabling the legacy behavior of generating the .sha256 files and + // signing the tarballs. + // + // Once the old release process is fully decommissioned, the environment variable, all the + // related code in this tool and ./x.py dist hash-and-sign can be removed. + let legacy = env::var("BUILD_MANIFEST_LEGACY").is_ok(); let mut args = env::args().skip(1); let input = PathBuf::from(args.next().unwrap()); @@ -263,7 +264,7 @@ fn main() { // Do not ask for a passphrase while manually testing let mut passphrase = String::new(); - if should_sign { + if legacy { // `x.py` passes the passphrase via stdin. t!(io::stdin().read_to_string(&mut passphrase)); } @@ -273,12 +274,12 @@ fn main() { input, output, - gpg_passphrase: passphrase, digests: BTreeMap::new(), s3_address, date, - should_sign, + legacy, + legacy_gpg_passphrase: passphrase, } .build(); } @@ -604,7 +605,7 @@ impl Builder { } fn sign(&self, path: &Path) { - if !self.should_sign { + if !self.legacy { return; } @@ -627,7 +628,7 @@ impl Builder { .arg(path) .stdin(Stdio::piped()); let mut child = t!(cmd.spawn()); - t!(child.stdin.take().unwrap().write_all(self.gpg_passphrase.as_bytes())); + t!(child.stdin.take().unwrap().write_all(self.legacy_gpg_passphrase.as_bytes())); assert!(t!(child.wait()).success()); } From 6e15975540e46582fbc01110d8d4411c5490dc4b Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 30 Sep 2020 14:40:38 +0200 Subject: [PATCH 09/32] build-manifest: split the manifest struct definition in a separate file --- src/tools/build-manifest/src/main.rs | 54 +----------------------- src/tools/build-manifest/src/manifest.rs | 53 +++++++++++++++++++++++ 2 files changed, 55 insertions(+), 52 deletions(-) create mode 100644 src/tools/build-manifest/src/manifest.rs diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 7821994e117c5..240e120037b65 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -4,10 +4,11 @@ //! via `x.py dist hash-and-sign`; the cmdline arguments are set up //! by rustbuild (in `src/bootstrap/dist.rs`). +mod manifest; mod versions; +use crate::manifest::{Component, Manifest, Package, Rename, Target}; use crate::versions::{PkgType, Versions}; -use serde::Serialize; use std::collections::BTreeMap; use std::collections::HashMap; use std::env; @@ -167,57 +168,6 @@ static MINGW: &[&str] = &["i686-pc-windows-gnu", "x86_64-pc-windows-gnu"]; static NIGHTLY_ONLY_COMPONENTS: &[&str] = &["miri-preview", "rust-analyzer-preview"]; -#[derive(Serialize)] -#[serde(rename_all = "kebab-case")] -struct Manifest { - manifest_version: String, - date: String, - pkg: BTreeMap, - renames: BTreeMap, - profiles: BTreeMap>, -} - -#[derive(Serialize)] -struct Package { - version: String, - git_commit_hash: Option, - target: BTreeMap, -} - -#[derive(Serialize)] -struct Rename { - to: String, -} - -#[derive(Serialize, Default)] -struct Target { - available: bool, - url: Option, - hash: Option, - xz_url: Option, - xz_hash: Option, - components: Option>, - extensions: Option>, -} - -impl Target { - fn unavailable() -> Self { - Self::default() - } -} - -#[derive(Serialize)] -struct Component { - pkg: String, - target: String, -} - -impl Component { - fn from_str(pkg: &str, target: &str) -> Self { - Self { pkg: pkg.to_string(), target: target.to_string() } - } -} - macro_rules! t { ($e:expr) => { match $e { diff --git a/src/tools/build-manifest/src/manifest.rs b/src/tools/build-manifest/src/manifest.rs new file mode 100644 index 0000000000000..4e1890d06c159 --- /dev/null +++ b/src/tools/build-manifest/src/manifest.rs @@ -0,0 +1,53 @@ +use serde::Serialize; +use std::collections::BTreeMap; + +#[derive(Serialize)] +#[serde(rename_all = "kebab-case")] +pub(crate) struct Manifest { + pub(crate) manifest_version: String, + pub(crate) date: String, + pub(crate) pkg: BTreeMap, + pub(crate) renames: BTreeMap, + pub(crate) profiles: BTreeMap>, +} + +#[derive(Serialize)] +pub(crate) struct Package { + pub(crate) version: String, + pub(crate) git_commit_hash: Option, + pub(crate) target: BTreeMap, +} + +#[derive(Serialize)] +pub(crate) struct Rename { + pub(crate) to: String, +} + +#[derive(Serialize, Default)] +pub(crate) struct Target { + pub(crate) available: bool, + pub(crate) url: Option, + pub(crate) hash: Option, + pub(crate) xz_url: Option, + pub(crate) xz_hash: Option, + pub(crate) components: Option>, + pub(crate) extensions: Option>, +} + +impl Target { + pub(crate) fn unavailable() -> Self { + Self::default() + } +} + +#[derive(Serialize)] +pub(crate) struct Component { + pub(crate) pkg: String, + pub(crate) target: String, +} + +impl Component { + pub(crate) fn from_str(pkg: &str, target: &str) -> Self { + Self { pkg: pkg.to_string(), target: target.to_string() } + } +} From 5fdf436ad96099bb327b072e2c555533845478c9 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 20 Sep 2020 21:19:34 -0700 Subject: [PATCH 10/32] unwind: Move linux-gnu library linking to lib.rs and libc This unifies it with the handling of `target-feature=+crt-static` on other platforms, and allows for supporting static glibc in the future. --- library/unwind/Cargo.toml | 2 +- library/unwind/build.rs | 4 +--- library/unwind/src/lib.rs | 4 ++++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml index 8e2db217c3151..27e8afe00b1bd 100644 --- a/library/unwind/Cargo.toml +++ b/library/unwind/Cargo.toml @@ -14,7 +14,7 @@ doc = false [dependencies] core = { path = "../core" } -libc = { version = "0.2.51", features = ['rustc-dep-of-std'], default-features = false } +libc = { version = "0.2.78", features = ['rustc-dep-of-std'], default-features = false } compiler_builtins = "0.1.0" cfg-if = "0.1.8" diff --git a/library/unwind/build.rs b/library/unwind/build.rs index ab09a6e324d8b..24bcd40c3a8ee 100644 --- a/library/unwind/build.rs +++ b/library/unwind/build.rs @@ -12,11 +12,9 @@ fn main() { } else if target.contains("x86_64-fortanix-unknown-sgx") { llvm_libunwind::compile(); } else if target.contains("linux") { + // linking for Linux is handled in lib.rs if target.contains("musl") { - // linking for musl is handled in lib.rs llvm_libunwind::compile(); - } else if !target.contains("android") { - println!("cargo:rustc-link-lib=gcc_s"); } } else if target.contains("freebsd") { println!("cargo:rustc-link-lib=gcc_s"); diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 20a2ca984057e..d34abb7e73dba 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -42,6 +42,10 @@ cfg_if::cfg_if! { #[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))] extern "C" {} +#[cfg(all(target_os = "linux", target_env = "gnu", not(feature = "llvm-libunwind")))] +#[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))] +extern "C" {} + #[cfg(target_os = "redox")] #[link(name = "gcc_eh", kind = "static-nobundle", cfg(target_feature = "crt-static"))] #[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))] From 99557fcc660498a0b4fc14c5551aa948683cc866 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 20 Sep 2020 23:02:38 -0700 Subject: [PATCH 11/32] Support static linking with glibc and target-feature=+crt-static With this change, it's possible to build on a linux-gnu target and pass RUSTFLAGS='-C target-feature=+crt-static' or the equivalent via a `.cargo/config.toml` file, and get a statically linked executable. Update to libc 0.2.78, which adds support for static linking with glibc. Add `crt_static_respected` to the `linux_base` target spec. Update `android_base` and `linux_musl_base` accordingly. Avoid enabling crt_static_respected on Android platforms, since that hasn't been tested. --- compiler/rustc_target/src/spec/android_base.rs | 1 + compiler/rustc_target/src/spec/linux_base.rs | 1 + compiler/rustc_target/src/spec/linux_musl_base.rs | 2 -- library/std/Cargo.toml | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_target/src/spec/android_base.rs b/compiler/rustc_target/src/spec/android_base.rs index 0ea99af83a1ef..bb11ce8ef28c2 100644 --- a/compiler/rustc_target/src/spec/android_base.rs +++ b/compiler/rustc_target/src/spec/android_base.rs @@ -12,5 +12,6 @@ pub fn opts() -> TargetOptions { base.position_independent_executables = true; base.has_elf_tls = false; base.requires_uwtable = true; + base.crt_static_respected = false; base } diff --git a/compiler/rustc_target/src/spec/linux_base.rs b/compiler/rustc_target/src/spec/linux_base.rs index 52892fc35924e..7ad972b069210 100644 --- a/compiler/rustc_target/src/spec/linux_base.rs +++ b/compiler/rustc_target/src/spec/linux_base.rs @@ -28,6 +28,7 @@ pub fn opts() -> TargetOptions { position_independent_executables: true, relro_level: RelroLevel::Full, has_elf_tls: true, + crt_static_respected: true, ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/linux_musl_base.rs b/compiler/rustc_target/src/spec/linux_musl_base.rs index b90e91d2901a8..16cc3b762f623 100644 --- a/compiler/rustc_target/src/spec/linux_musl_base.rs +++ b/compiler/rustc_target/src/spec/linux_musl_base.rs @@ -10,8 +10,6 @@ pub fn opts() -> TargetOptions { // These targets statically link libc by default base.crt_static_default = true; - // These targets allow the user to choose between static and dynamic linking. - base.crt_static_respected = true; base } diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index b27b056086a64..33966409c8e04 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -16,7 +16,7 @@ cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core" } -libc = { version = "0.2.77", default-features = false, features = ['rustc-dep-of-std'] } +libc = { version = "0.2.78", default-features = false, features = ['rustc-dep-of-std'] } compiler_builtins = { version = "0.1.35" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } From 50ce45b9240bd730de6d8dfb925321a02c059c03 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 30 Sep 2020 21:30:07 -0700 Subject: [PATCH 12/32] Cargo.lock: Update libc --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 28bd57ef6735c..b85b42ad64588 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1623,9 +1623,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.77" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" +checksum = "aa7087f49d294270db4e1928fc110c976cd4b9e5a16348e0a1df09afa99e6c98" dependencies = [ "rustc-std-workspace-core", ] From c1e17f56ea1d3cc64cd7d1be6fc2557d0fd65f06 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 1 Oct 2020 14:09:57 +0900 Subject: [PATCH 13/32] Add a regression test for issue-66501 --- src/test/ui/pattern/issue-66501.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/test/ui/pattern/issue-66501.rs diff --git a/src/test/ui/pattern/issue-66501.rs b/src/test/ui/pattern/issue-66501.rs new file mode 100644 index 0000000000000..ffcfd4ad83e1f --- /dev/null +++ b/src/test/ui/pattern/issue-66501.rs @@ -0,0 +1,12 @@ +// check-pass + +#![allow(unreachable_patterns)] + +fn main() { + const CONST: &[Option<()>; 1] = &[Some(())]; + match &[Some(())] { + &[None] => {} + CONST => {} + &[Some(())] => {} + } +} From 8631e1c57504624824add1b059d12cdc86cdd87c Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 1 Oct 2020 14:10:23 +0900 Subject: [PATCH 14/32] Add a regression test for issue-68951 --- src/test/ui/issues/issue-68951.rs | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/test/ui/issues/issue-68951.rs diff --git a/src/test/ui/issues/issue-68951.rs b/src/test/ui/issues/issue-68951.rs new file mode 100644 index 0000000000000..1c1e92c5bbcbb --- /dev/null +++ b/src/test/ui/issues/issue-68951.rs @@ -0,0 +1,9 @@ +// check-pass + +fn main() { + let array = [0x42u8; 10]; + for b in &array { + let lo = b & 0xf; + let hi = (b >> 4) & 0xf; + } +} From 50ffd6b7cbdf6baedbd3a22f4ea79ebdf7c48af9 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 1 Oct 2020 14:10:33 +0900 Subject: [PATCH 15/32] Add a regression test for issue-72565 --- src/test/ui/pattern/issue-72565.rs | 8 ++++++++ src/test/ui/pattern/issue-72565.stderr | 8 ++++++++ 2 files changed, 16 insertions(+) create mode 100644 src/test/ui/pattern/issue-72565.rs create mode 100644 src/test/ui/pattern/issue-72565.stderr diff --git a/src/test/ui/pattern/issue-72565.rs b/src/test/ui/pattern/issue-72565.rs new file mode 100644 index 0000000000000..1e262fd506765 --- /dev/null +++ b/src/test/ui/pattern/issue-72565.rs @@ -0,0 +1,8 @@ +const F: &'static dyn PartialEq = &7u32; + +fn main() { + let a: &dyn PartialEq = &7u32; + match a { + F => panic!(), //~ ERROR: `&dyn PartialEq` cannot be used in patterns + } +} diff --git a/src/test/ui/pattern/issue-72565.stderr b/src/test/ui/pattern/issue-72565.stderr new file mode 100644 index 0000000000000..2f82616b27764 --- /dev/null +++ b/src/test/ui/pattern/issue-72565.stderr @@ -0,0 +1,8 @@ +error: `&dyn PartialEq` cannot be used in patterns + --> $DIR/issue-72565.rs:6:9 + | +LL | F => panic!(), + | ^ + +error: aborting due to previous error + From d4fdf6e7542941ab8d5b0d43f9c5bc0b278f638d Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 1 Oct 2020 14:10:44 +0900 Subject: [PATCH 16/32] Add a regression test for issue-74244 --- .../ui/type-alias-impl-trait/issue-74244.rs | 20 +++++++++++++++++++ .../type-alias-impl-trait/issue-74244.stderr | 9 +++++++++ 2 files changed, 29 insertions(+) create mode 100644 src/test/ui/type-alias-impl-trait/issue-74244.rs create mode 100644 src/test/ui/type-alias-impl-trait/issue-74244.stderr diff --git a/src/test/ui/type-alias-impl-trait/issue-74244.rs b/src/test/ui/type-alias-impl-trait/issue-74244.rs new file mode 100644 index 0000000000000..bb4104b3d2519 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-74244.rs @@ -0,0 +1,20 @@ +#![feature(type_alias_impl_trait)] + +trait Allocator { + type Buffer; +} + +struct DefaultAllocator; + +impl Allocator for DefaultAllocator { + //~^ ERROR: the type parameter `T` is not constrained + type Buffer = (); +} + +type A = impl Fn(::Buffer); + +fn foo() -> A { + |_| () +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-74244.stderr b/src/test/ui/type-alias-impl-trait/issue-74244.stderr new file mode 100644 index 0000000000000..ff6bacd277e1e --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-74244.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-74244.rs:9:6 + | +LL | impl Allocator for DefaultAllocator { + | ^ unconstrained type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. From 38f460f8669de8ee0d975ec89f06e89a5849ab65 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 1 Oct 2020 14:10:53 +0900 Subject: [PATCH 17/32] Add a regression test for issue-75299 --- src/test/ui/const-generics/issues/issue-75299.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/test/ui/const-generics/issues/issue-75299.rs diff --git a/src/test/ui/const-generics/issues/issue-75299.rs b/src/test/ui/const-generics/issues/issue-75299.rs new file mode 100644 index 0000000000000..23f30a1eea073 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-75299.rs @@ -0,0 +1,11 @@ +// compile-flags: -Zmir-opt-level=3 +// run-pass + +#![feature(const_generics)] +#![allow(incomplete_features)] +fn main() { + fn foo() -> [u8; N] { + [0; N] + } + let _x = foo::<1>(); +} From 8f9472cc9e372351964390bdf531cc65b13768c7 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 1 Oct 2020 08:32:24 +0200 Subject: [PATCH 18/32] Only mention that a stack frame is being popped when starting to do so --- compiler/rustc_mir/src/interpret/eval_context.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index 45b5dd62479d9..93da6e3d38a93 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -783,7 +783,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// The cleanup block ends with a special `Resume` terminator, which will /// cause us to continue unwinding. pub(super) fn pop_stack_frame(&mut self, unwinding: bool) -> InterpResult<'tcx> { - info!(unwinding); + info!( + "popping stack frame ({})", + if unwinding { "during unwinding" } else { "returning from function" } + ); // Sanity check `unwinding`. assert_eq!( @@ -854,10 +857,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - if !self.stack().is_empty() { - info!(unwinding); - } - Ok(()) } From 0375ee8b55becd14ca73ad420b7311fb6e9dfaeb Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 1 Oct 2020 17:02:47 +0200 Subject: [PATCH 19/32] build-manifest: move generating a target to the manifest mod --- src/tools/build-manifest/src/main.rs | 59 ++++++++---------------- src/tools/build-manifest/src/manifest.rs | 36 +++++++++++++++ 2 files changed, 55 insertions(+), 40 deletions(-) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 240e120037b65..5f01b46d70d54 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -9,8 +9,7 @@ mod versions; use crate::manifest::{Component, Manifest, Package, Rename, Target}; use crate::versions::{PkgType, Versions}; -use std::collections::BTreeMap; -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use std::env; use std::fs::{self, File}; use std::io::{self, Read, Write}; @@ -385,9 +384,12 @@ impl Builder { fn target_host_combination(&mut self, host: &str, manifest: &Manifest) -> Option { let filename = self.versions.tarball_name(&PkgType::Rust, host).unwrap(); - let digest = self.digests.remove(&filename)?; - let xz_filename = filename.replace(".tar.gz", ".tar.xz"); - let xz_digest = self.digests.remove(&xz_filename); + + let mut target = Target::from_compressed_tar(self, &filename); + if !target.available { + return None; + } + let mut components = Vec::new(); let mut extensions = Vec::new(); @@ -443,15 +445,9 @@ impl Builder { extensions.retain(&has_component); components.retain(&has_component); - Some(Target { - available: true, - url: Some(self.url(&filename)), - hash: Some(digest), - xz_url: xz_digest.as_ref().map(|_| self.url(&xz_filename)), - xz_hash: xz_digest, - components: Some(components), - extensions: Some(extensions), - }) + target.components = Some(components); + target.extensions = Some(extensions); + Some(target) } fn profile( @@ -489,37 +485,19 @@ impl Builder { let targets = targets .iter() .map(|name| { - if is_present { - // The component generally exists, but it might still be missing for this target. + let target = if is_present { let filename = self .versions .tarball_name(&PkgType::from_component(pkgname), name) .unwrap(); - let digest = match self.digests.remove(&filename) { - Some(digest) => digest, - // This component does not exist for this target -- skip it. - None => return (name.to_string(), Target::unavailable()), - }; - let xz_filename = filename.replace(".tar.gz", ".tar.xz"); - let xz_digest = self.digests.remove(&xz_filename); - - ( - name.to_string(), - Target { - available: true, - url: Some(self.url(&filename)), - hash: Some(digest), - xz_url: xz_digest.as_ref().map(|_| self.url(&xz_filename)), - xz_hash: xz_digest, - components: None, - extensions: None, - }, - ) + + Target::from_compressed_tar(self, &filename) } else { // If the component is not present for this build add it anyway but mark it as // unavailable -- this way rustup won't allow upgrades without --force - (name.to_string(), Target::unavailable()) - } + Target::unavailable() + }; + (name.to_string(), target) }) .collect(); @@ -533,8 +511,9 @@ impl Builder { ); } - fn url(&self, filename: &str) -> String { - format!("{}/{}/{}", self.s3_address, self.date, filename) + fn url(&self, path: &Path) -> String { + let file_name = path.file_name().unwrap().to_str().unwrap(); + format!("{}/{}/{}", self.s3_address, self.date, file_name) } fn hash(&self, path: &Path) -> String { diff --git a/src/tools/build-manifest/src/manifest.rs b/src/tools/build-manifest/src/manifest.rs index 4e1890d06c159..2a5755c1bf1da 100644 --- a/src/tools/build-manifest/src/manifest.rs +++ b/src/tools/build-manifest/src/manifest.rs @@ -1,5 +1,7 @@ +use crate::Builder; use serde::Serialize; use std::collections::BTreeMap; +use std::path::{Path, PathBuf}; #[derive(Serialize)] #[serde(rename_all = "kebab-case")] @@ -35,6 +37,40 @@ pub(crate) struct Target { } impl Target { + pub(crate) fn from_compressed_tar(builder: &Builder, base_path: &str) -> Self { + let base_path = builder.input.join(base_path); + let gz = Self::tarball_variant(&base_path, "gz"); + let xz = Self::tarball_variant(&base_path, "xz"); + + if gz.is_none() { + return Self::unavailable(); + } + + Self { + available: true, + components: None, + extensions: None, + // .gz + url: gz.as_ref().map(|path| builder.url(path)), + hash: gz.map(|path| Self::digest_of(builder, &path)), + // .xz + xz_url: xz.as_ref().map(|path| builder.url(path)), + xz_hash: xz.map(|path| Self::digest_of(builder, &path)), + } + } + + fn tarball_variant(base: &Path, ext: &str) -> Option { + let mut path = base.to_path_buf(); + path.set_extension(ext); + if path.is_file() { Some(path) } else { None } + } + + fn digest_of(builder: &Builder, path: &Path) -> String { + // TEMPORARY CODE -- DON'T REVIEW :) + let file_name = path.file_name().unwrap().to_str().unwrap(); + builder.digests.get(file_name).unwrap().clone() + } + pub(crate) fn unavailable() -> Self { Self::default() } From acd8e59b6650deab3979e82b49c8c26e0f4ceefa Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 1 Oct 2020 17:15:12 +0200 Subject: [PATCH 20/32] build-manifest: calculate checksums lazily and in parallel This commit improves the way build-manifest calculates the checksums included in the manifest, speeding it up: * Instead of calculating all the hashes beforehand and then using the ones we need, the manifest is first generated with placeholder hashes, and then a function walks through the manifest and calculates only the needed checksums. * Calculating the checksums is now done in parallel with rayon, to better utilize all the available disk bandwidth. * Calculating the checksums now uses the sha2 crate instead of the sha256sum CLI tool: this avoids the overhead of calling another process, but more importantly uses hardware acceleration whenever available (the CLI tool doesn't support it at all). --- Cargo.lock | 72 +++++++++++++++++++++--- src/tools/build-manifest/Cargo.toml | 3 + src/tools/build-manifest/src/main.rs | 71 +++++++++++++++++++---- src/tools/build-manifest/src/manifest.rs | 47 ++++++++++++---- 4 files changed, 164 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 28bd57ef6735c..649972e61d7e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -183,7 +183,16 @@ dependencies = [ "block-padding", "byte-tools", "byteorder", - "generic-array", + "generic-array 0.12.3", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array 0.14.4", ] [[package]] @@ -233,8 +242,11 @@ version = "0.1.0" dependencies = [ "anyhow", "flate2", + "hex 0.4.2", + "rayon", "serde", "serde_json", + "sha2", "tar", "toml", ] @@ -687,6 +699,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a21fa21941700a3cd8fcb4091f361a6a712fac632f85d9f487cc892045d55c6" +[[package]] +name = "cpuid-bool" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" + [[package]] name = "crates-io" version = "0.31.1" @@ -884,7 +902,16 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" dependencies = [ - "generic-array", + "generic-array 0.12.3", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array 0.14.4", ] [[package]] @@ -1166,6 +1193,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "generic-array" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getopts" version = "0.2.21" @@ -1844,9 +1881,9 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a18af3dcaf2b0219366cdb4e2af65a6101457b415c3d1a5c71dd9c2b7c77b9c8" dependencies = [ - "block-buffer", - "digest", - "opaque-debug", + "block-buffer 0.7.3", + "digest 0.8.1", + "opaque-debug 0.2.3", ] [[package]] @@ -2106,6 +2143,12 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + [[package]] name = "open" version = "1.4.0" @@ -4371,10 +4414,23 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" dependencies = [ - "block-buffer", - "digest", + "block-buffer 0.7.3", + "digest 0.8.1", "fake-simd", - "opaque-debug", + "opaque-debug 0.2.3", +] + +[[package]] +name = "sha2" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2933378ddfeda7ea26f48c555bdad8bb446bf8a3d17832dc83e380d444cfb8c1" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpuid-bool", + "digest 0.9.0", + "opaque-debug 0.3.0", ] [[package]] diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml index 4f89c31936dda..4ae4dbfc06ede 100644 --- a/src/tools/build-manifest/Cargo.toml +++ b/src/tools/build-manifest/Cargo.toml @@ -11,3 +11,6 @@ serde_json = "1.0" anyhow = "1.0.32" flate2 = "1.0.16" tar = "0.4.29" +sha2 = "0.9.1" +rayon = "1.3.1" +hex = "0.4.2" diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 5f01b46d70d54..91f042a07d4bb 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -7,14 +7,19 @@ mod manifest; mod versions; -use crate::manifest::{Component, Manifest, Package, Rename, Target}; +use crate::manifest::{Component, FileHash, Manifest, Package, Rename, Target}; use crate::versions::{PkgType, Versions}; -use std::collections::{BTreeMap, HashMap}; +use rayon::prelude::*; +use sha2::Digest; +use std::collections::{BTreeMap, HashMap, HashSet}; use std::env; +use std::error::Error; use std::fs::{self, File}; use std::io::{self, Read, Write}; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; +use std::sync::Mutex; +use std::time::Instant; static HOSTS: &[&str] = &[ "aarch64-unknown-linux-gnu", @@ -181,7 +186,6 @@ struct Builder { input: PathBuf, output: PathBuf, - digests: BTreeMap, s3_address: String, date: String, @@ -223,7 +227,6 @@ fn main() { input, output, - digests: BTreeMap::new(), s3_address, date, @@ -236,7 +239,9 @@ fn main() { impl Builder { fn build(&mut self) { self.check_toolstate(); - self.digest_and_sign(); + if self.legacy { + self.digest_and_sign(); + } let manifest = self.build_manifest(); let rust_version = self.versions.package_version(&PkgType::Rust).unwrap(); @@ -270,10 +275,9 @@ impl Builder { /// Hash all files, compute their signatures, and collect the hashes in `self.digests`. fn digest_and_sign(&mut self) { for file in t!(self.input.read_dir()).map(|e| t!(e).path()) { - let filename = file.file_name().unwrap().to_str().unwrap(); - let digest = self.hash(&file); + file.file_name().unwrap().to_str().unwrap(); + self.hash(&file); self.sign(&file); - assert!(self.digests.insert(filename.to_string(), digest).is_none()); } } @@ -289,6 +293,9 @@ impl Builder { self.add_profiles_to(&mut manifest); self.add_renames_to(&mut manifest); manifest.pkg.insert("rust".to_string(), self.rust_package(&manifest)); + + self.fill_missing_hashes(&mut manifest); + manifest } @@ -561,6 +568,41 @@ impl Builder { assert!(t!(child.wait()).success()); } + fn fill_missing_hashes(&self, manifest: &mut Manifest) { + // First collect all files that need hashes + let mut need_hashes = HashSet::new(); + crate::manifest::visit_file_hashes(manifest, |file_hash| { + if let FileHash::Missing(path) = file_hash { + need_hashes.insert(path.clone()); + } + }); + + let collected = Mutex::new(HashMap::new()); + let collection_start = Instant::now(); + println!( + "collecting hashes for {} tarballs across {} threads", + need_hashes.len(), + rayon::current_num_threads().min(need_hashes.len()), + ); + need_hashes.par_iter().for_each(|path| match fetch_hash(path) { + Ok(hash) => { + collected.lock().unwrap().insert(path, hash); + } + Err(err) => eprintln!("error while fetching the hash for {}: {}", path.display(), err), + }); + let collected = collected.into_inner().unwrap(); + println!("collected {} hashes in {:.2?}", collected.len(), collection_start.elapsed()); + + crate::manifest::visit_file_hashes(manifest, |file_hash| { + if let FileHash::Missing(path) = file_hash { + match collected.get(path) { + Some(hash) => *file_hash = FileHash::Present(hash.clone()), + None => panic!("missing hash for file {}", path.display()), + } + } + }) + } + fn write_channel_files(&self, channel_name: &str, manifest: &Manifest) { self.write(&toml::to_string(&manifest).unwrap(), channel_name, ".toml"); self.write(&manifest.date, channel_name, "-date.txt"); @@ -574,7 +616,16 @@ impl Builder { fn write(&self, contents: &str, channel_name: &str, suffix: &str) { let dst = self.output.join(format!("channel-rust-{}{}", channel_name, suffix)); t!(fs::write(&dst, contents)); - self.hash(&dst); - self.sign(&dst); + if self.legacy { + self.hash(&dst); + self.sign(&dst); + } } } + +fn fetch_hash(path: &Path) -> Result> { + let mut file = File::open(path)?; + let mut sha256 = sha2::Sha256::default(); + std::io::copy(&mut file, &mut sha256)?; + Ok(hex::encode(sha256.finalize())) +} diff --git a/src/tools/build-manifest/src/manifest.rs b/src/tools/build-manifest/src/manifest.rs index 2a5755c1bf1da..20e62abb54cfa 100644 --- a/src/tools/build-manifest/src/manifest.rs +++ b/src/tools/build-manifest/src/manifest.rs @@ -1,5 +1,5 @@ use crate::Builder; -use serde::Serialize; +use serde::{Serialize, Serializer}; use std::collections::BTreeMap; use std::path::{Path, PathBuf}; @@ -29,9 +29,9 @@ pub(crate) struct Rename { pub(crate) struct Target { pub(crate) available: bool, pub(crate) url: Option, - pub(crate) hash: Option, + pub(crate) hash: Option, pub(crate) xz_url: Option, - pub(crate) xz_hash: Option, + pub(crate) xz_hash: Option, pub(crate) components: Option>, pub(crate) extensions: Option>, } @@ -52,10 +52,10 @@ impl Target { extensions: None, // .gz url: gz.as_ref().map(|path| builder.url(path)), - hash: gz.map(|path| Self::digest_of(builder, &path)), + hash: gz.map(FileHash::Missing), // .xz xz_url: xz.as_ref().map(|path| builder.url(path)), - xz_hash: xz.map(|path| Self::digest_of(builder, &path)), + xz_hash: xz.map(FileHash::Missing), } } @@ -65,12 +65,6 @@ impl Target { if path.is_file() { Some(path) } else { None } } - fn digest_of(builder: &Builder, path: &Path) -> String { - // TEMPORARY CODE -- DON'T REVIEW :) - let file_name = path.file_name().unwrap().to_str().unwrap(); - builder.digests.get(file_name).unwrap().clone() - } - pub(crate) fn unavailable() -> Self { Self::default() } @@ -87,3 +81,34 @@ impl Component { Self { pkg: pkg.to_string(), target: target.to_string() } } } + +#[allow(unused)] +pub(crate) enum FileHash { + Missing(PathBuf), + Present(String), +} + +impl Serialize for FileHash { + fn serialize(&self, serializer: S) -> Result { + match self { + FileHash::Missing(path) => Err(serde::ser::Error::custom(format!( + "can't serialize a missing hash for file {}", + path.display() + ))), + FileHash::Present(inner) => inner.serialize(serializer), + } + } +} + +pub(crate) fn visit_file_hashes(manifest: &mut Manifest, mut f: impl FnMut(&mut FileHash)) { + for pkg in manifest.pkg.values_mut() { + for target in pkg.target.values_mut() { + if let Some(hash) = &mut target.hash { + f(hash); + } + if let Some(hash) = &mut target.xz_hash { + f(hash); + } + } + } +} From fde113591680c96459abdc4aae5d2b0dc21da87b Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 1 Oct 2020 17:25:54 +0200 Subject: [PATCH 21/32] build-manifest: avoid collecting SHAs in parallel on legacy mode This avoids overloading the old server, and disrupting the other programs running on it. --- src/tools/build-manifest/src/main.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 91f042a07d4bb..1a698bbac053e 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -207,6 +207,14 @@ fn main() { // related code in this tool and ./x.py dist hash-and-sign can be removed. let legacy = env::var("BUILD_MANIFEST_LEGACY").is_ok(); + // Avoid overloading the old server in legacy mode. + if legacy { + rayon::ThreadPoolBuilder::new() + .num_threads(1) + .build_global() + .expect("failed to initialize Rayon"); + } + let mut args = env::args().skip(1); let input = PathBuf::from(args.next().unwrap()); let output = PathBuf::from(args.next().unwrap()); From 9352062bc3aa3c1b3cc635069a806915fcba5b1e Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 1 Oct 2020 19:42:02 +0200 Subject: [PATCH 22/32] build-manifest: use BufReader --- src/tools/build-manifest/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 1a698bbac053e..6524398f5babf 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -15,7 +15,7 @@ use std::collections::{BTreeMap, HashMap, HashSet}; use std::env; use std::error::Error; use std::fs::{self, File}; -use std::io::{self, Read, Write}; +use std::io::{self, BufReader, Read, Write}; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::sync::Mutex; @@ -632,7 +632,7 @@ impl Builder { } fn fetch_hash(path: &Path) -> Result> { - let mut file = File::open(path)?; + let mut file = BufReader::new(File::open(path)?); let mut sha256 = sha2::Sha256::default(); std::io::copy(&mut file, &mut sha256)?; Ok(hex::encode(sha256.finalize())) From 2e8f7051e4714f51ecc9e1eaeb5af878fbd5d262 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Thu, 1 Oct 2020 11:13:13 -0700 Subject: [PATCH 23/32] Add comment explaining why libunwind doesn't need to link libgcc_eh --- library/unwind/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index d34abb7e73dba..e7fa37bc9db19 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -42,6 +42,9 @@ cfg_if::cfg_if! { #[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))] extern "C" {} +// When building with crt-static, we get `gcc_eh` from the `libc` crate, since +// glibc needs it, and needs it listed later on the linker command line. We +// don't want to duplicate it here. #[cfg(all(target_os = "linux", target_env = "gnu", not(feature = "llvm-libunwind")))] #[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))] extern "C" {} From cd159fd7f9f8eec5792e6fd7f1b347ea3e028301 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 19 Aug 2020 03:05:44 -0700 Subject: [PATCH 24/32] Uplift drop-bounds lint from clippy --- compiler/rustc_lint/src/lib.rs | 3 + compiler/rustc_lint/src/traits.rs | 79 +++++++++++++++++++ library/core/src/mem/mod.rs | 1 + .../ui/drop-bounds/drop-bounds-impl-drop.rs | 14 ++++ src/test/ui/drop-bounds/drop-bounds.rs | 19 +++++ src/test/ui/drop-bounds/drop-bounds.stderr | 50 ++++++++++++ 6 files changed, 166 insertions(+) create mode 100644 compiler/rustc_lint/src/traits.rs create mode 100644 src/test/ui/drop-bounds/drop-bounds-impl-drop.rs create mode 100644 src/test/ui/drop-bounds/drop-bounds.rs create mode 100644 src/test/ui/drop-bounds/drop-bounds.stderr diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 33caedfc19826..49e80f9d8a531 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -53,6 +53,7 @@ mod non_ascii_idents; mod nonstandard_style; mod passes; mod redundant_semicolon; +mod traits; mod types; mod unused; @@ -75,6 +76,7 @@ use internal::*; use non_ascii_idents::*; use nonstandard_style::*; use redundant_semicolon::*; +use traits::*; use types::*; use unused::*; @@ -157,6 +159,7 @@ macro_rules! late_lint_passes { MissingDebugImplementations: MissingDebugImplementations::default(), ArrayIntoIter: ArrayIntoIter, ClashingExternDeclarations: ClashingExternDeclarations::new(), + DropTraitConstraints: DropTraitConstraints, ] ); }; diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs new file mode 100644 index 0000000000000..d4f79036e5a18 --- /dev/null +++ b/compiler/rustc_lint/src/traits.rs @@ -0,0 +1,79 @@ +use crate::LateContext; +use crate::LateLintPass; +use crate::LintContext; +use rustc_hir as hir; +use rustc_span::symbol::sym; + +declare_lint! { + /// The `drop_bounds` lint checks for generics with `std::ops::Drop` as + /// bounds. + /// + /// ### Example + /// + /// ```rust + /// fn foo() {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// `Drop` bounds do not really accomplish anything. A type may have + /// compiler-generated drop glue without implementing the `Drop` trait + /// itself. The `Drop` trait also only has one method, `Drop::drop`, and + /// that function is by fiat not callable in user code. So there is really + /// no use case for using `Drop` in trait bounds. + /// + /// The most likely use case of a drop bound is to distinguish between + /// types that have destructors and types that don't. Combined with + /// specialization, a naive coder would write an implementation that + /// assumed a type could be trivially dropped, then write a specialization + /// for `T: Drop` that actually calls the destructor. Except that doing so + /// is not correct; String, for example, doesn't actually implement Drop, + /// but because String contains a Vec, assuming it can be trivially dropped + /// will leak memory. + pub DROP_BOUNDS, + Warn, + "bounds of the form `T: Drop` are useless" +} + +declare_lint_pass!( + /// Lint for bounds of the form `T: Drop`, which usually + /// indicate an attempt to emulate `std::mem::needs_drop`. + DropTraitConstraints => [DROP_BOUNDS] +); + +impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { + use rustc_middle::ty::PredicateAtom::*; + + let def_id = cx.tcx.hir().local_def_id(item.hir_id); + let predicates = cx.tcx.explicit_predicates_of(def_id); + for &(predicate, span) in predicates.predicates { + let trait_predicate = match predicate.skip_binders() { + Trait(trait_predicate, _constness) => trait_predicate, + _ => continue, + }; + let def_id = trait_predicate.trait_ref.def_id; + if cx.tcx.lang_items().drop_trait() == Some(def_id) { + // Explicitly allow `impl Drop`, a drop-guards-as-Voldemort-type pattern. + if trait_predicate.trait_ref.self_ty().is_impl_trait() { + continue; + } + cx.struct_span_lint(DROP_BOUNDS, span, |lint| { + let needs_drop = match cx.tcx.get_diagnostic_item(sym::needs_drop) { + Some(needs_drop) => needs_drop, + None => return, + }; + let msg = format!( + "bounds on `{}` are useless, consider instead \ + using `{}` to detect if a type has a destructor", + predicate, + cx.tcx.def_path_str(needs_drop) + ); + lint.build(&msg).emit() + }); + } + } + } +} diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index aa1b5529df222..a2c7da6e6958e 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -568,6 +568,7 @@ pub unsafe fn align_of_val_raw(val: *const T) -> usize { #[inline] #[stable(feature = "needs_drop", since = "1.21.0")] #[rustc_const_stable(feature = "const_needs_drop", since = "1.36.0")] +#[rustc_diagnostic_item = "needs_drop"] pub const fn needs_drop() -> bool { intrinsics::needs_drop::() } diff --git a/src/test/ui/drop-bounds/drop-bounds-impl-drop.rs b/src/test/ui/drop-bounds/drop-bounds-impl-drop.rs new file mode 100644 index 0000000000000..063efc7b31abd --- /dev/null +++ b/src/test/ui/drop-bounds/drop-bounds-impl-drop.rs @@ -0,0 +1,14 @@ +// run-pass +#![deny(drop_bounds)] +// As a special exemption, `impl Drop` in the return position raises no error. +// This allows a convenient way to return an unnamed drop guard. +fn voldemort_type() -> impl Drop { + struct Voldemort; + impl Drop for Voldemort { + fn drop(&mut self) {} + } + Voldemort +} +fn main() { + let _ = voldemort_type(); +} diff --git a/src/test/ui/drop-bounds/drop-bounds.rs b/src/test/ui/drop-bounds/drop-bounds.rs new file mode 100644 index 0000000000000..c73538278d3be --- /dev/null +++ b/src/test/ui/drop-bounds/drop-bounds.rs @@ -0,0 +1,19 @@ +#![deny(drop_bounds)] +fn foo() {} //~ ERROR +fn bar() +where + U: Drop, //~ ERROR +{ +} +fn baz(_x: impl Drop) {} //~ ERROR +struct Foo { //~ ERROR + _x: T +} +struct Bar where U: Drop { //~ ERROR + _x: U +} +trait Baz: Drop { //~ ERROR +} +impl Baz for T { //~ ERROR +} +fn main() {} diff --git a/src/test/ui/drop-bounds/drop-bounds.stderr b/src/test/ui/drop-bounds/drop-bounds.stderr new file mode 100644 index 0000000000000..15ba4c9a64989 --- /dev/null +++ b/src/test/ui/drop-bounds/drop-bounds.stderr @@ -0,0 +1,50 @@ +error: bounds on `T: Drop` are useless, consider instead using `std::mem::needs_drop` to detect if a type has a destructor + --> $DIR/drop-bounds.rs:2:11 + | +LL | fn foo() {} + | ^^^^ + | +note: the lint level is defined here + --> $DIR/drop-bounds.rs:1:9 + | +LL | #![deny(drop_bounds)] + | ^^^^^^^^^^^ + +error: bounds on `U: Drop` are useless, consider instead using `std::mem::needs_drop` to detect if a type has a destructor + --> $DIR/drop-bounds.rs:5:8 + | +LL | U: Drop, + | ^^^^ + +error: bounds on `impl Drop: Drop` are useless, consider instead using `std::mem::needs_drop` to detect if a type has a destructor + --> $DIR/drop-bounds.rs:8:17 + | +LL | fn baz(_x: impl Drop) {} + | ^^^^ + +error: bounds on `T: Drop` are useless, consider instead using `std::mem::needs_drop` to detect if a type has a destructor + --> $DIR/drop-bounds.rs:9:15 + | +LL | struct Foo { + | ^^^^ + +error: bounds on `U: Drop` are useless, consider instead using `std::mem::needs_drop` to detect if a type has a destructor + --> $DIR/drop-bounds.rs:12:24 + | +LL | struct Bar where U: Drop { + | ^^^^ + +error: bounds on `Self: Drop` are useless, consider instead using `std::mem::needs_drop` to detect if a type has a destructor + --> $DIR/drop-bounds.rs:15:12 + | +LL | trait Baz: Drop { + | ^^^^ + +error: bounds on `T: Drop` are useless, consider instead using `std::mem::needs_drop` to detect if a type has a destructor + --> $DIR/drop-bounds.rs:17:9 + | +LL | impl Baz for T { + | ^^^^ + +error: aborting due to 7 previous errors + From cadd12b5f020b9b2c7bb0c5e7078b81fbdcfb6d8 Mon Sep 17 00:00:00 2001 From: Harald Hoyer Date: Mon, 7 Sep 2020 10:45:20 +0200 Subject: [PATCH 25/32] Implement Make `handle_alloc_error` default to panic (for no_std + liballoc) Related: https://github.com/rust-lang/rust/issues/66741 Guarded with `#![feature(default_alloc_error_handler)]` a default `alloc_error_handler` is called, if a custom allocator is used and no other custom `#[alloc_error_handler]` is defined. The panic message does not contain the size anymore, because it would pull in the fmt machinery, which would blow up the code size significantly. --- compiler/rustc_codegen_llvm/src/allocator.rs | 45 ++++++++- compiler/rustc_codegen_llvm/src/lib.rs | 3 +- compiler/rustc_codegen_ssa/src/base.rs | 5 +- .../rustc_codegen_ssa/src/traits/backend.rs | 1 + compiler/rustc_feature/src/active.rs | 3 + compiler/rustc_passes/src/weak_lang_items.rs | 5 +- compiler/rustc_span/src/symbol.rs | 1 + library/alloc/src/alloc.rs | 47 +++++++++ src/test/ui/allocator/auxiliary/helper.rs | 4 +- .../no_std-alloc-error-handler-custom.rs | 97 +++++++++++++++++++ .../no_std-alloc-error-handler-default.rs | 84 ++++++++++++++++ .../missing-alloc_error_handler.stderr | 4 +- 12 files changed, 292 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/allocator/no_std-alloc-error-handler-custom.rs create mode 100644 src/test/ui/allocator/no_std-alloc-error-handler-default.rs diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index bc1d9e1818c2f..e028b2c2dc763 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -3,11 +3,17 @@ use libc::c_uint; use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; +use rustc_span::symbol::sym; use crate::llvm::{self, False, True}; use crate::ModuleLlvm; -pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut ModuleLlvm, kind: AllocatorKind) { +pub(crate) unsafe fn codegen( + tcx: TyCtxt<'_>, + mods: &mut ModuleLlvm, + kind: AllocatorKind, + has_alloc_error_handler: bool, +) { let llcx = &*mods.llcx; let llmod = mods.llmod(); let usize = match &tcx.sess.target.target.target_pointer_width[..] { @@ -82,4 +88,41 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut ModuleLlvm, kind: Alloc } llvm::LLVMDisposeBuilder(llbuilder); } + + // rust alloc error handler + let args = [usize, usize]; // size, align + + let ty = llvm::LLVMFunctionType(void, args.as_ptr(), args.len() as c_uint, False); + let name = format!("__rust_alloc_error_handler"); + let llfn = llvm::LLVMRustGetOrInsertFunction(llmod, name.as_ptr().cast(), name.len(), ty); + // -> ! DIFlagNoReturn + llvm::Attribute::NoReturn.apply_llfn(llvm::AttributePlace::Function, llfn); + + if tcx.sess.target.target.options.default_hidden_visibility { + llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden); + } + if tcx.sess.must_emit_unwind_tables() { + attributes::emit_uwtable(llfn, true); + } + + let kind = if has_alloc_error_handler { AllocatorKind::Global } else { AllocatorKind::Default }; + let callee = kind.fn_name(sym::oom); + let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty); + // -> ! DIFlagNoReturn + llvm::Attribute::NoReturn.apply_llfn(llvm::AttributePlace::Function, callee); + llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden); + + let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast()); + + let llbuilder = llvm::LLVMCreateBuilderInContext(llcx); + llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb); + let args = args + .iter() + .enumerate() + .map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint)) + .collect::>(); + let ret = llvm::LLVMRustBuildCall(llbuilder, callee, args.as_ptr(), args.len() as c_uint, None); + llvm::LLVMSetTailCall(ret, True); + llvm::LLVMBuildRetVoid(llbuilder); + llvm::LLVMDisposeBuilder(llbuilder); } diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index f14493e604368..1237b39b300ff 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -95,8 +95,9 @@ impl ExtraBackendMethods for LlvmCodegenBackend { tcx: TyCtxt<'tcx>, mods: &mut ModuleLlvm, kind: AllocatorKind, + has_alloc_error_handler: bool, ) { - unsafe { allocator::codegen(tcx, mods, kind) } + unsafe { allocator::codegen(tcx, mods, kind, has_alloc_error_handler) } } fn compile_codegen_unit( &self, diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index d82fc2c9f63d9..8e6f8e193c0e2 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -538,8 +538,9 @@ pub fn codegen_crate( let llmod_id = cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string(); let mut modules = backend.new_metadata(tcx, &llmod_id); - tcx.sess - .time("write_allocator_module", || backend.codegen_allocator(tcx, &mut modules, kind)); + tcx.sess.time("write_allocator_module", || { + backend.codegen_allocator(tcx, &mut modules, kind, tcx.lang_items().oom().is_some()) + }); Some(ModuleCodegen { name: llmod_id, module_llvm: modules, kind: ModuleKind::Allocator }) } else { diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 90520f77e3c04..48c07b0089420 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -109,6 +109,7 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se tcx: TyCtxt<'tcx>, mods: &mut Self::Module, kind: AllocatorKind, + has_alloc_error_handler: bool, ); /// This generates the codegen unit and returns it along with /// a `u64` giving an estimate of the unit's processing cost. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 060efd270dd51..5cd0a56d52414 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -593,6 +593,9 @@ declare_features! ( /// Allows to use the `#[cmse_nonsecure_entry]` attribute. (active, cmse_nonsecure_entry, "1.48.0", Some(75835), None), + /// Allows rustc to inject a default alloc_error_handler + (active, default_alloc_error_handler, "1.48.0", Some(66741), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index 6bc2110bfb3e6..effb25b022452 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -64,7 +64,10 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) { if item == LangItem::PanicImpl { tcx.sess.err("`#[panic_handler]` function required, but not found"); } else if item == LangItem::Oom { - tcx.sess.err("`#[alloc_error_handler]` function required, but not found"); + if !tcx.features().default_alloc_error_handler { + tcx.sess.err("`#[alloc_error_handler]` function required, but not found."); + tcx.sess.note_without_error("Use `#![feature(default_alloc_error_handler)]` for a default error handler."); + } } else { tcx.sess.err(&format!("language item required, but not found: `{}`", name)); } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e3ad31469b237..6309b00f5f514 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -415,6 +415,7 @@ symbols! { decl_macro, declare_lint_pass, decode, + default_alloc_error_handler, default_lib_allocator, default_type_parameter_fallback, default_type_params, diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 75158eefcac28..ce70de6ebdd63 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -26,6 +26,8 @@ extern "Rust" { fn __rust_realloc(ptr: *mut u8, old_size: usize, align: usize, new_size: usize) -> *mut u8; #[rustc_allocator_nounwind] fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8; + #[rustc_allocator_nounwind] + fn __rust_alloc_error_handler(size: usize, align: usize) -> !; } /// The global memory allocator. @@ -334,6 +336,24 @@ pub(crate) unsafe fn box_free(ptr: Unique) { /// [`set_alloc_error_hook`]: ../../std/alloc/fn.set_alloc_error_hook.html /// [`take_alloc_error_hook`]: ../../std/alloc/fn.take_alloc_error_hook.html #[stable(feature = "global_alloc", since = "1.28.0")] +#[cfg(not(any(test, bootstrap)))] +#[rustc_allocator_nounwind] +pub fn handle_alloc_error(layout: Layout) -> ! { + unsafe { + __rust_alloc_error_handler(layout.size(), layout.align()); + } +} + +// For alloc test `std::alloc::handle_alloc_error` can be used directly. +#[cfg(test)] +pub use std::alloc::handle_alloc_error; + +// In stage0 (bootstrap) `__rust_alloc_error_handler`, +// might not be generated yet, because an old compiler is used, +// so use the old direct call. +#[cfg(all(bootstrap, not(test)))] +#[stable(feature = "global_alloc", since = "1.28.0")] +#[doc(hidden)] #[rustc_allocator_nounwind] pub fn handle_alloc_error(layout: Layout) -> ! { extern "Rust" { @@ -342,3 +362,30 @@ pub fn handle_alloc_error(layout: Layout) -> ! { } unsafe { oom_impl(layout) } } + +#[cfg(not(any(test, bootstrap)))] +#[doc(hidden)] +#[allow(unused_attributes)] +#[unstable(feature = "alloc_internals", issue = "none")] +pub mod __default_lib_allocator { + use crate::alloc::Layout; + + // called via generated `__rust_alloc_error_handler` + + // if there is no `#[alloc_error_handler]` + #[rustc_std_internal_symbol] + pub unsafe extern "C" fn __rdl_oom(size: usize, _align: usize) -> ! { + panic!("memory allocation of {} bytes failed", size) + } + + // if there is a `#[alloc_error_handler]` + #[rustc_std_internal_symbol] + pub unsafe extern "C" fn __rg_oom(size: usize, align: usize) -> ! { + let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; + extern "Rust" { + #[lang = "oom"] + fn oom_impl(layout: Layout) -> !; + } + unsafe { oom_impl(layout) } + } +} diff --git a/src/test/ui/allocator/auxiliary/helper.rs b/src/test/ui/allocator/auxiliary/helper.rs index 7f6770c226a0c..008fb3501d90d 100644 --- a/src/test/ui/allocator/auxiliary/helper.rs +++ b/src/test/ui/allocator/auxiliary/helper.rs @@ -1,8 +1,10 @@ // no-prefer-dynamic #![crate_type = "rlib"] +#![no_std] -use std::fmt; +extern crate alloc; +use alloc::fmt; pub fn work_with(p: &fmt::Debug) { drop(p); diff --git a/src/test/ui/allocator/no_std-alloc-error-handler-custom.rs b/src/test/ui/allocator/no_std-alloc-error-handler-custom.rs new file mode 100644 index 0000000000000..f09fafbc98a18 --- /dev/null +++ b/src/test/ui/allocator/no_std-alloc-error-handler-custom.rs @@ -0,0 +1,97 @@ +// run-pass +// ignore-android no libc +// ignore-cloudabi no libc +// ignore-emscripten no libc +// ignore-sgx no libc +// ignore-wasm32 no libc +// only-linux +// compile-flags:-C panic=abort +// aux-build:helper.rs + +#![feature(start, rustc_private, new_uninit, panic_info_message)] +#![feature(alloc_error_handler)] +#![no_std] + +extern crate alloc; +extern crate libc; + +// ARM targets need these symbols +#[no_mangle] +pub fn __aeabi_unwind_cpp_pr0() {} + +#[no_mangle] +pub fn __aeabi_unwind_cpp_pr1() {} + +use core::ptr::null_mut; +use core::alloc::{GlobalAlloc, Layout}; +use alloc::boxed::Box; + +extern crate helper; + +struct MyAllocator; + +#[alloc_error_handler] +fn my_oom(layout: Layout) -> ! +{ + use alloc::fmt::write; + unsafe { + let size = layout.size(); + let mut s = alloc::string::String::new(); + write(&mut s, format_args!("My OOM: failed to allocate {} bytes!\n", size)).unwrap(); + let s = s.as_str(); + libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len()); + libc::exit(0) + } +} + +unsafe impl GlobalAlloc for MyAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + if layout.size() < 4096 { + libc::malloc(layout.size()) as _ + } else { + null_mut() + } + } + unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} +} + +#[global_allocator] +static A: MyAllocator = MyAllocator; + +#[panic_handler] +fn panic(panic_info: &core::panic::PanicInfo) -> ! { + unsafe { + if let Some(s) = panic_info.payload().downcast_ref::<&str>() { + const PSTR: &str = "panic occurred: "; + const CR: &str = "\n"; + libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len()); + libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len()); + libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len()); + } + if let Some(args) = panic_info.message() { + let mut s = alloc::string::String::new(); + alloc::fmt::write(&mut s, *args).unwrap(); + let s = s.as_str(); + const PSTR: &str = "panic occurred: "; + const CR: &str = "\n"; + libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len()); + libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len()); + libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len()); + } else { + const PSTR: &str = "panic occurred\n"; + libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len()); + } + libc::exit(1) + } +} + +#[derive(Debug)] +struct Page([[u64; 32]; 16]); + +#[start] +pub fn main(_argc: isize, _argv: *const *const u8) -> isize { + let zero = Box::::new_zeroed(); + let zero = unsafe { zero.assume_init() }; + helper::work_with(&zero); + 1 +} diff --git a/src/test/ui/allocator/no_std-alloc-error-handler-default.rs b/src/test/ui/allocator/no_std-alloc-error-handler-default.rs new file mode 100644 index 0000000000000..4d68160379d9c --- /dev/null +++ b/src/test/ui/allocator/no_std-alloc-error-handler-default.rs @@ -0,0 +1,84 @@ +// run-pass +// ignore-android no libc +// ignore-cloudabi no libc +// ignore-emscripten no libc +// ignore-sgx no libc +// ignore-wasm32 no libc +// only-linux +// compile-flags:-C panic=abort +// aux-build:helper.rs +// gate-test-default_alloc_error_handler + +#![feature(start, rustc_private, new_uninit, panic_info_message)] +#![feature(default_alloc_error_handler)] +#![no_std] + +extern crate alloc; +extern crate libc; + +// ARM targets need these symbols +#[no_mangle] +pub fn __aeabi_unwind_cpp_pr0() {} + +#[no_mangle] +pub fn __aeabi_unwind_cpp_pr1() {} + +use alloc::boxed::Box; +use core::alloc::{GlobalAlloc, Layout}; +use core::ptr::null_mut; + +extern crate helper; + +struct MyAllocator; + +unsafe impl GlobalAlloc for MyAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + if layout.size() < 4096 { + libc::malloc(layout.size()) as _ + } else { + null_mut() + } + } + unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} +} + +#[global_allocator] +static A: MyAllocator = MyAllocator; + +#[panic_handler] +fn panic(panic_info: &core::panic::PanicInfo) -> ! { + unsafe { + if let Some(s) = panic_info.payload().downcast_ref::<&str>() { + const PSTR: &str = "panic occurred: "; + const CR: &str = "\n"; + libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len()); + libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len()); + libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len()); + } + if let Some(args) = panic_info.message() { + let mut s = alloc::string::String::new(); + alloc::fmt::write(&mut s, *args).unwrap(); + let s = s.as_str(); + const PSTR: &str = "panic occurred: "; + const CR: &str = "\n"; + libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len()); + libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len()); + libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len()); + } else { + const PSTR: &str = "panic occurred\n"; + libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len()); + } + libc::exit(0) + } +} + +#[derive(Debug)] +struct Page([[u64; 32]; 16]); + +#[start] +pub fn main(_argc: isize, _argv: *const *const u8) -> isize { + let zero = Box::::new_zeroed(); + let zero = unsafe { zero.assume_init() }; + helper::work_with(&zero); + 1 +} diff --git a/src/test/ui/missing/missing-alloc_error_handler.stderr b/src/test/ui/missing/missing-alloc_error_handler.stderr index 5489b2cbbfad8..511d0788b40a7 100644 --- a/src/test/ui/missing/missing-alloc_error_handler.stderr +++ b/src/test/ui/missing/missing-alloc_error_handler.stderr @@ -1,4 +1,6 @@ -error: `#[alloc_error_handler]` function required, but not found +error: `#[alloc_error_handler]` function required, but not found. + +note: Use `#![feature(default_alloc_error_handler)]` for a default error handler. error: aborting due to previous error From dceb81af1ea4cbefd5e8bf49f738e03e9e3fac9c Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 2 Oct 2020 11:34:14 -0700 Subject: [PATCH 26/32] Deprecate clippy lint --- .../clippy_lints/src/deprecated_lints.rs | 9 +++ .../clippy/clippy_lints/src/drop_bounds.rs | 73 ------------------- src/tools/clippy/clippy_lints/src/lib.rs | 9 +-- .../clippy/clippy_lints/src/utils/paths.rs | 1 - src/tools/clippy/src/lintlist/mod.rs | 7 -- src/tools/clippy/tests/ui/deprecated.rs | 1 + src/tools/clippy/tests/ui/deprecated.stderr | 8 +- src/tools/clippy/tests/ui/drop_bounds.rs | 8 -- src/tools/clippy/tests/ui/drop_bounds.stderr | 16 ---- 9 files changed, 21 insertions(+), 111 deletions(-) delete mode 100644 src/tools/clippy/clippy_lints/src/drop_bounds.rs delete mode 100644 src/tools/clippy/tests/ui/drop_bounds.rs delete mode 100644 src/tools/clippy/tests/ui/drop_bounds.stderr diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs index c17a0e8333058..c5884361dff9d 100644 --- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs +++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs @@ -163,3 +163,12 @@ declare_deprecated_lint! { pub REGEX_MACRO, "the regex! macro has been removed from the regex crate in 2018" } + +declare_deprecated_lint! { + /// **What it does:** Nothing. This lint has been deprecated. + /// + /// **Deprecation reason:** This lint has been uplifted to rustc and is now called + /// `drop_bounds`. + pub DROP_BOUNDS, + "this lint has been uplifted to rustc and is now called `drop_bounds`" +} diff --git a/src/tools/clippy/clippy_lints/src/drop_bounds.rs b/src/tools/clippy/clippy_lints/src/drop_bounds.rs deleted file mode 100644 index ec3b6afa6300f..0000000000000 --- a/src/tools/clippy/clippy_lints/src/drop_bounds.rs +++ /dev/null @@ -1,73 +0,0 @@ -use crate::utils::{match_def_path, paths, span_lint}; -use if_chain::if_chain; -use rustc_hir::{GenericBound, GenericParam, WhereBoundPredicate, WherePredicate}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; - -declare_clippy_lint! { - /// **What it does:** Checks for generics with `std::ops::Drop` as bounds. - /// - /// **Why is this bad?** `Drop` bounds do not really accomplish anything. - /// A type may have compiler-generated drop glue without implementing the - /// `Drop` trait itself. The `Drop` trait also only has one method, - /// `Drop::drop`, and that function is by fiat not callable in user code. - /// So there is really no use case for using `Drop` in trait bounds. - /// - /// The most likely use case of a drop bound is to distinguish between types - /// that have destructors and types that don't. Combined with specialization, - /// a naive coder would write an implementation that assumed a type could be - /// trivially dropped, then write a specialization for `T: Drop` that actually - /// calls the destructor. Except that doing so is not correct; String, for - /// example, doesn't actually implement Drop, but because String contains a - /// Vec, assuming it can be trivially dropped will leak memory. - /// - /// **Known problems:** None. - /// - /// **Example:** - /// ```rust - /// fn foo() {} - /// ``` - /// Could be written as: - /// ```rust - /// fn foo() {} - /// ``` - pub DROP_BOUNDS, - correctness, - "bounds of the form `T: Drop` are useless" -} - -const DROP_BOUNDS_SUMMARY: &str = "bounds of the form `T: Drop` are useless, \ - use `std::mem::needs_drop` to detect if a type has drop glue"; - -declare_lint_pass!(DropBounds => [DROP_BOUNDS]); - -impl<'tcx> LateLintPass<'tcx> for DropBounds { - fn check_generic_param(&mut self, cx: &LateContext<'tcx>, p: &'tcx GenericParam<'_>) { - for bound in p.bounds.iter() { - lint_bound(cx, bound); - } - } - fn check_where_predicate(&mut self, cx: &LateContext<'tcx>, p: &'tcx WherePredicate<'_>) { - if let WherePredicate::BoundPredicate(WhereBoundPredicate { bounds, .. }) = p { - for bound in *bounds { - lint_bound(cx, bound); - } - } - } -} - -fn lint_bound<'tcx>(cx: &LateContext<'tcx>, bound: &'tcx GenericBound<'_>) { - if_chain! { - if let GenericBound::Trait(t, _) = bound; - if let Some(def_id) = t.trait_ref.path.res.opt_def_id(); - if match_def_path(cx, def_id, &paths::DROP_TRAIT); - then { - span_lint( - cx, - DROP_BOUNDS, - t.span, - DROP_BOUNDS_SUMMARY - ); - } - } -} diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index c3ff34e6e1eed..70efdaeb9c669 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -179,7 +179,6 @@ mod derive; mod doc; mod double_comparison; mod double_parens; -mod drop_bounds; mod drop_forget_ref; mod duration_subsec; mod else_if_without_else; @@ -478,6 +477,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: "clippy::regex_macro", "the regex! macro has been removed from the regex crate in 2018", ); + store.register_removed( + "clippy::drop_bounds", + "this lint has been uplifted to rustc and is now called `drop_bounds`", + ); // end deprecated lints, do not remove this comment, it’s used in `update_lints` // begin register lints, do not remove this comment, it’s used in `update_lints` @@ -532,7 +535,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &doc::NEEDLESS_DOCTEST_MAIN, &double_comparison::DOUBLE_COMPARISONS, &double_parens::DOUBLE_PARENS, - &drop_bounds::DROP_BOUNDS, &drop_forget_ref::DROP_COPY, &drop_forget_ref::DROP_REF, &drop_forget_ref::FORGET_COPY, @@ -959,7 +961,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box strings::StringLitAsBytes); store.register_late_pass(|| box derive::Derive); store.register_late_pass(|| box types::CharLitAsU8); - store.register_late_pass(|| box drop_bounds::DropBounds); store.register_late_pass(|| box get_last_with_len::GetLastWithLen); store.register_late_pass(|| box drop_forget_ref::DropForgetRef); store.register_late_pass(|| box empty_enum::EmptyEnum); @@ -1282,7 +1283,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&doc::NEEDLESS_DOCTEST_MAIN), LintId::of(&double_comparison::DOUBLE_COMPARISONS), LintId::of(&double_parens::DOUBLE_PARENS), - LintId::of(&drop_bounds::DROP_BOUNDS), LintId::of(&drop_forget_ref::DROP_COPY), LintId::of(&drop_forget_ref::DROP_REF), LintId::of(&drop_forget_ref::FORGET_COPY), @@ -1714,7 +1714,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&copies::IF_SAME_THEN_ELSE), LintId::of(&derive::DERIVE_HASH_XOR_EQ), LintId::of(&derive::DERIVE_ORD_XOR_PARTIAL_ORD), - LintId::of(&drop_bounds::DROP_BOUNDS), LintId::of(&drop_forget_ref::DROP_COPY), LintId::of(&drop_forget_ref::DROP_REF), LintId::of(&drop_forget_ref::FORGET_COPY), diff --git a/src/tools/clippy/clippy_lints/src/utils/paths.rs b/src/tools/clippy/clippy_lints/src/utils/paths.rs index 1583afad208ab..be837a61dc07e 100644 --- a/src/tools/clippy/clippy_lints/src/utils/paths.rs +++ b/src/tools/clippy/clippy_lints/src/utils/paths.rs @@ -31,7 +31,6 @@ pub const DISPLAY_FMT_METHOD: [&str; 4] = ["core", "fmt", "Display", "fmt"]; pub const DISPLAY_TRAIT: [&str; 3] = ["core", "fmt", "Display"]; pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"]; pub const DROP: [&str; 3] = ["core", "mem", "drop"]; -pub const DROP_TRAIT: [&str; 4] = ["core", "ops", "drop", "Drop"]; pub const DURATION: [&str; 3] = ["core", "time", "Duration"]; pub const EARLY_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "EarlyContext"]; pub const EXIT: [&str; 3] = ["std", "process", "exit"]; diff --git a/src/tools/clippy/src/lintlist/mod.rs b/src/tools/clippy/src/lintlist/mod.rs index 9603023ed0671..f6d529de9a3a2 100644 --- a/src/tools/clippy/src/lintlist/mod.rs +++ b/src/tools/clippy/src/lintlist/mod.rs @@ -423,13 +423,6 @@ pub static ref ALL_LINTS: Vec = vec![ deprecation: None, module: "double_parens", }, - Lint { - name: "drop_bounds", - group: "correctness", - desc: "bounds of the form `T: Drop` are useless", - deprecation: None, - module: "drop_bounds", - }, Lint { name: "drop_copy", group: "correctness", diff --git a/src/tools/clippy/tests/ui/deprecated.rs b/src/tools/clippy/tests/ui/deprecated.rs index 3eefb232780f1..9e32fe36ece4d 100644 --- a/src/tools/clippy/tests/ui/deprecated.rs +++ b/src/tools/clippy/tests/ui/deprecated.rs @@ -8,5 +8,6 @@ #[warn(clippy::into_iter_on_array)] #[warn(clippy::unused_label)] #[warn(clippy::regex_macro)] +#[warn(clippy::drop_bounds)] fn main() {} diff --git a/src/tools/clippy/tests/ui/deprecated.stderr b/src/tools/clippy/tests/ui/deprecated.stderr index a80e2bf31feb6..d3400a7be09fd 100644 --- a/src/tools/clippy/tests/ui/deprecated.stderr +++ b/src/tools/clippy/tests/ui/deprecated.stderr @@ -60,11 +60,17 @@ error: lint `clippy::regex_macro` has been removed: `the regex! macro has been r LL | #[warn(clippy::regex_macro)] | ^^^^^^^^^^^^^^^^^^^ +error: lint `clippy::drop_bounds` has been removed: `this lint has been uplifted to rustc and is now called `drop_bounds`` + --> $DIR/deprecated.rs:11:8 + | +LL | #[warn(clippy::drop_bounds)] + | ^^^^^^^^^^^^^^^^^^^ + error: lint `clippy::str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon` --> $DIR/deprecated.rs:1:8 | LL | #[warn(clippy::str_to_string)] | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 11 previous errors +error: aborting due to 12 previous errors diff --git a/src/tools/clippy/tests/ui/drop_bounds.rs b/src/tools/clippy/tests/ui/drop_bounds.rs deleted file mode 100644 index 6d6a9dc078399..0000000000000 --- a/src/tools/clippy/tests/ui/drop_bounds.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![allow(unused)] -fn foo() {} -fn bar() -where - T: Drop, -{ -} -fn main() {} diff --git a/src/tools/clippy/tests/ui/drop_bounds.stderr b/src/tools/clippy/tests/ui/drop_bounds.stderr deleted file mode 100644 index 8208c0ed7e398..0000000000000 --- a/src/tools/clippy/tests/ui/drop_bounds.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: bounds of the form `T: Drop` are useless, use `std::mem::needs_drop` to detect if a type has drop glue - --> $DIR/drop_bounds.rs:2:11 - | -LL | fn foo() {} - | ^^^^ - | - = note: `#[deny(clippy::drop_bounds)]` on by default - -error: bounds of the form `T: Drop` are useless, use `std::mem::needs_drop` to detect if a type has drop glue - --> $DIR/drop_bounds.rs:5:8 - | -LL | T: Drop, - | ^^^^ - -error: aborting due to 2 previous errors - From 4c9bcf3b39faa07afb40a79b0d932a4accaeb82b Mon Sep 17 00:00:00 2001 From: Camelid Date: Fri, 2 Oct 2020 14:33:23 -0700 Subject: [PATCH 27/32] Fix test name Remove trailing `-`. --- ...lify-arm-identity-.rs => issue-77359-simplify-arm-identity.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/mir/{issue-77359-simplify-arm-identity-.rs => issue-77359-simplify-arm-identity.rs} (100%) diff --git a/src/test/ui/mir/issue-77359-simplify-arm-identity-.rs b/src/test/ui/mir/issue-77359-simplify-arm-identity.rs similarity index 100% rename from src/test/ui/mir/issue-77359-simplify-arm-identity-.rs rename to src/test/ui/mir/issue-77359-simplify-arm-identity.rs From 87f3f81451f72fc7b5acb4a569bb79a51a8604c3 Mon Sep 17 00:00:00 2001 From: Camelid Date: Fri, 2 Oct 2020 14:32:14 -0700 Subject: [PATCH 28/32] Improve rustdoc error for failed intra-doc link resolution The previous error was confusing since it made it sound like you can't link to items that are defined outside the current module. Also suggested importing the item. --- .../passes/collect_intra_doc_links.rs | 8 +-- .../deny-intra-link-resolution-failure.stderr | 3 +- src/test/rustdoc-ui/intra-link-errors.rs | 15 +++-- src/test/rustdoc-ui/intra-link-errors.stderr | 57 ++++++++++-------- .../intra-link-span-ice-55723.stderr | 3 +- .../intra-links-warning-crlf.stderr | 12 ++-- .../rustdoc-ui/intra-links-warning.stderr | 59 +++++++++++++------ src/test/rustdoc-ui/lint-group.stderr | 3 +- 8 files changed, 102 insertions(+), 58 deletions(-) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index cf94ea384fd60..632e6c9f91c11 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1575,17 +1575,17 @@ fn resolution_failure( _ => None, }; // See if this was a module: `[path]` or `[std::io::nope]` - if let Some(module) = last_found_module { - let module_name = collector.cx.tcx.item_name(module); + if let Some(_module) = last_found_module { let note = format!( - "the module `{}` contains no item named `{}`", - module_name, unresolved + "there is no item named `{}` in scope", + unresolved ); if let Some(span) = sp { diag.span_label(span, ¬e); } else { diag.note(¬e); } + diag.help(&format!("did you mean to import `{}`?", unresolved)); // If the link has `::` in it, assume it was meant to be an intra-doc link. // Otherwise, the `[]` might be unrelated. // FIXME: don't show this for autolinks (`<>`), `()` style links, or reference links diff --git a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr index 33260fa0e1e66..96b805dbc82a3 100644 --- a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr +++ b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr @@ -2,13 +2,14 @@ error: unresolved link to `v2` --> $DIR/deny-intra-link-resolution-failure.rs:3:6 | LL | /// [v2] - | ^^ the module `deny_intra_link_resolution_failure` contains no item named `v2` + | ^^ there is no item named `v2` in scope | note: the lint level is defined here --> $DIR/deny-intra-link-resolution-failure.rs:1:9 | LL | #![deny(broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^ + = help: did you mean to import `v2`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` error: aborting due to previous error diff --git a/src/test/rustdoc-ui/intra-link-errors.rs b/src/test/rustdoc-ui/intra-link-errors.rs index 0278caf308776..babcc3c43b4ae 100644 --- a/src/test/rustdoc-ui/intra-link-errors.rs +++ b/src/test/rustdoc-ui/intra-link-errors.rs @@ -6,23 +6,28 @@ /// [path::to::nonexistent::module] //~^ ERROR unresolved link -//~| NOTE `intra_link_errors` contains no item named `path` +//~| NOTE there is no item named `path` in scope +//~| HELP did you mean to import `path`? /// [path::to::nonexistent::macro!] //~^ ERROR unresolved link -//~| NOTE `intra_link_errors` contains no item named `path` +//~| NOTE there is no item named `path` in scope +//~| HELP did you mean to import `path`? /// [type@path::to::nonexistent::type] //~^ ERROR unresolved link -//~| NOTE `intra_link_errors` contains no item named `path` +//~| NOTE there is no item named `path` in scope +//~| HELP did you mean to import `path`? /// [std::io::not::here] //~^ ERROR unresolved link -//~| NOTE `io` contains no item named `not` +//~| NOTE there is no item named `not` in scope +//~| HELP did you mean to import `not`? /// [type@std::io::not::here] //~^ ERROR unresolved link -//~| NOTE `io` contains no item named `not` +//~| NOTE there is no item named `not` in scope +//~| HELP did you mean to import `not`? /// [std::io::Error::x] //~^ ERROR unresolved link diff --git a/src/test/rustdoc-ui/intra-link-errors.stderr b/src/test/rustdoc-ui/intra-link-errors.stderr index b63f799535a1f..f9af1a9fb9385 100644 --- a/src/test/rustdoc-ui/intra-link-errors.stderr +++ b/src/test/rustdoc-ui/intra-link-errors.stderr @@ -2,94 +2,103 @@ error: unresolved link to `path::to::nonexistent::module` --> $DIR/intra-link-errors.rs:7:6 | LL | /// [path::to::nonexistent::module] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the module `intra_link_errors` contains no item named `path` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ there is no item named `path` in scope | note: the lint level is defined here --> $DIR/intra-link-errors.rs:1:9 | LL | #![deny(broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^ + = help: did you mean to import `path`? error: unresolved link to `path::to::nonexistent::macro` - --> $DIR/intra-link-errors.rs:11:6 + --> $DIR/intra-link-errors.rs:12:6 | LL | /// [path::to::nonexistent::macro!] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the module `intra_link_errors` contains no item named `path` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ there is no item named `path` in scope + | + = help: did you mean to import `path`? error: unresolved link to `path::to::nonexistent::type` - --> $DIR/intra-link-errors.rs:15:6 + --> $DIR/intra-link-errors.rs:17:6 | LL | /// [type@path::to::nonexistent::type] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the module `intra_link_errors` contains no item named `path` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ there is no item named `path` in scope + | + = help: did you mean to import `path`? error: unresolved link to `std::io::not::here` - --> $DIR/intra-link-errors.rs:19:6 + --> $DIR/intra-link-errors.rs:22:6 | LL | /// [std::io::not::here] - | ^^^^^^^^^^^^^^^^^^ the module `io` contains no item named `not` + | ^^^^^^^^^^^^^^^^^^ there is no item named `not` in scope + | + = help: did you mean to import `not`? error: unresolved link to `std::io::not::here` - --> $DIR/intra-link-errors.rs:23:6 + --> $DIR/intra-link-errors.rs:27:6 | LL | /// [type@std::io::not::here] - | ^^^^^^^^^^^^^^^^^^^^^^^ the module `io` contains no item named `not` + | ^^^^^^^^^^^^^^^^^^^^^^^ there is no item named `not` in scope + | + = help: did you mean to import `not`? error: unresolved link to `std::io::Error::x` - --> $DIR/intra-link-errors.rs:27:6 + --> $DIR/intra-link-errors.rs:32:6 | LL | /// [std::io::Error::x] | ^^^^^^^^^^^^^^^^^ the struct `Error` has no field or associated item named `x` error: unresolved link to `std::io::ErrorKind::x` - --> $DIR/intra-link-errors.rs:31:6 + --> $DIR/intra-link-errors.rs:36:6 | LL | /// [std::io::ErrorKind::x] | ^^^^^^^^^^^^^^^^^^^^^ the enum `ErrorKind` has no variant or associated item named `x` error: unresolved link to `f::A` - --> $DIR/intra-link-errors.rs:35:6 + --> $DIR/intra-link-errors.rs:40:6 | LL | /// [f::A] | ^^^^ `f` is a function, not a module or type, and cannot have associated items error: unresolved link to `f::A` - --> $DIR/intra-link-errors.rs:39:6 + --> $DIR/intra-link-errors.rs:44:6 | LL | /// [f::A!] | ^^^^^ `f` is a function, not a module or type, and cannot have associated items error: unresolved link to `S::A` - --> $DIR/intra-link-errors.rs:43:6 + --> $DIR/intra-link-errors.rs:48:6 | LL | /// [S::A] | ^^^^ the struct `S` has no field or associated item named `A` error: unresolved link to `S::fmt` - --> $DIR/intra-link-errors.rs:47:6 + --> $DIR/intra-link-errors.rs:52:6 | LL | /// [S::fmt] | ^^^^^^ the struct `S` has no field or associated item named `fmt` error: unresolved link to `E::D` - --> $DIR/intra-link-errors.rs:51:6 + --> $DIR/intra-link-errors.rs:56:6 | LL | /// [E::D] | ^^^^ the enum `E` has no variant or associated item named `D` error: unresolved link to `u8::not_found` - --> $DIR/intra-link-errors.rs:55:6 + --> $DIR/intra-link-errors.rs:60:6 | LL | /// [u8::not_found] | ^^^^^^^^^^^^^ the builtin type `u8` has no associated item named `not_found` error: unresolved link to `std::primitive::u8::not_found` - --> $DIR/intra-link-errors.rs:59:6 + --> $DIR/intra-link-errors.rs:64:6 | LL | /// [std::primitive::u8::not_found] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the builtin type `u8` has no associated item named `not_found` error: unresolved link to `Vec::into_iter` - --> $DIR/intra-link-errors.rs:63:6 + --> $DIR/intra-link-errors.rs:68:6 | LL | /// [type@Vec::into_iter] | ^^^^^^^^^^^^^^^^^^^ @@ -98,7 +107,7 @@ LL | /// [type@Vec::into_iter] | help: to link to the associated function, add parentheses: `Vec::into_iter()` error: unresolved link to `S` - --> $DIR/intra-link-errors.rs:68:6 + --> $DIR/intra-link-errors.rs:73:6 | LL | /// [S!] | ^^ @@ -107,7 +116,7 @@ LL | /// [S!] | help: to link to the struct, prefix with `struct@`: `struct@S` error: unresolved link to `T::g` - --> $DIR/intra-link-errors.rs:86:6 + --> $DIR/intra-link-errors.rs:91:6 | LL | /// [type@T::g] | ^^^^^^^^^ @@ -116,13 +125,13 @@ LL | /// [type@T::g] | help: to link to the associated function, add parentheses: `T::g()` error: unresolved link to `T::h` - --> $DIR/intra-link-errors.rs:91:6 + --> $DIR/intra-link-errors.rs:96:6 | LL | /// [T::h!] | ^^^^^ the trait `T` has no macro named `h` error: unresolved link to `S::h` - --> $DIR/intra-link-errors.rs:78:6 + --> $DIR/intra-link-errors.rs:83:6 | LL | /// [type@S::h] | ^^^^^^^^^ @@ -131,7 +140,7 @@ LL | /// [type@S::h] | help: to link to the associated function, add parentheses: `S::h()` error: unresolved link to `m` - --> $DIR/intra-link-errors.rs:98:6 + --> $DIR/intra-link-errors.rs:103:6 | LL | /// [m()] | ^^^ diff --git a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr index d946aa939800c..57061b6778c29 100644 --- a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr +++ b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr @@ -2,13 +2,14 @@ error: unresolved link to `i` --> $DIR/intra-link-span-ice-55723.rs:9:10 | LL | /// (arr[i]) - | ^ the module `intra_link_span_ice_55723` contains no item named `i` + | ^ there is no item named `i` in scope | note: the lint level is defined here --> $DIR/intra-link-span-ice-55723.rs:1:9 | LL | #![deny(broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^ + = help: did you mean to import `i`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` error: aborting due to previous error diff --git a/src/test/rustdoc-ui/intra-links-warning-crlf.stderr b/src/test/rustdoc-ui/intra-links-warning-crlf.stderr index 76a2ac0c8cf02..0c934e3bb082c 100644 --- a/src/test/rustdoc-ui/intra-links-warning-crlf.stderr +++ b/src/test/rustdoc-ui/intra-links-warning-crlf.stderr @@ -2,33 +2,37 @@ warning: unresolved link to `error` --> $DIR/intra-links-warning-crlf.rs:7:6 | LL | /// [error] - | ^^^^^ the module `intra_links_warning_crlf` contains no item named `error` + | ^^^^^ there is no item named `error` in scope | = note: `#[warn(broken_intra_doc_links)]` on by default + = help: did you mean to import `error`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error1` --> $DIR/intra-links-warning-crlf.rs:12:11 | LL | /// docs [error1] - | ^^^^^^ the module `intra_links_warning_crlf` contains no item named `error1` + | ^^^^^^ there is no item named `error1` in scope | + = help: did you mean to import `error1`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error2` --> $DIR/intra-links-warning-crlf.rs:15:11 | LL | /// docs [error2] - | ^^^^^^ the module `intra_links_warning_crlf` contains no item named `error2` + | ^^^^^^ there is no item named `error2` in scope | + = help: did you mean to import `error2`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error` --> $DIR/intra-links-warning-crlf.rs:23:20 | LL | * It also has an [error]. - | ^^^^^ the module `intra_links_warning_crlf` contains no item named `error` + | ^^^^^ there is no item named `error` in scope | + = help: did you mean to import `error`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: 4 warnings emitted diff --git a/src/test/rustdoc-ui/intra-links-warning.stderr b/src/test/rustdoc-ui/intra-links-warning.stderr index 09db465df59fb..d64f62924d3c2 100644 --- a/src/test/rustdoc-ui/intra-links-warning.stderr +++ b/src/test/rustdoc-ui/intra-links-warning.stderr @@ -10,54 +10,67 @@ warning: unresolved link to `Bar::foo` --> $DIR/intra-links-warning.rs:3:35 | LL | //! Test with [Foo::baz], [Bar::foo], ... - | ^^^^^^^^ the module `intra_links_warning` contains no item named `Bar` + | ^^^^^^^^ there is no item named `Bar` in scope + | + = help: did you mean to import `Bar`? warning: unresolved link to `Uniooon::X` --> $DIR/intra-links-warning.rs:6:13 | LL | //! , [Uniooon::X] and [Qux::Z]. - | ^^^^^^^^^^ the module `intra_links_warning` contains no item named `Uniooon` + | ^^^^^^^^^^ there is no item named `Uniooon` in scope + | + = help: did you mean to import `Uniooon`? warning: unresolved link to `Qux::Z` --> $DIR/intra-links-warning.rs:6:30 | LL | //! , [Uniooon::X] and [Qux::Z]. - | ^^^^^^ the module `intra_links_warning` contains no item named `Qux` + | ^^^^^^ there is no item named `Qux` in scope + | + = help: did you mean to import `Qux`? warning: unresolved link to `Uniooon::X` --> $DIR/intra-links-warning.rs:10:14 | LL | //! , [Uniooon::X] and [Qux::Z]. - | ^^^^^^^^^^ the module `intra_links_warning` contains no item named `Uniooon` + | ^^^^^^^^^^ there is no item named `Uniooon` in scope + | + = help: did you mean to import `Uniooon`? warning: unresolved link to `Qux::Z` --> $DIR/intra-links-warning.rs:10:31 | LL | //! , [Uniooon::X] and [Qux::Z]. - | ^^^^^^ the module `intra_links_warning` contains no item named `Qux` + | ^^^^^^ there is no item named `Qux` in scope + | + = help: did you mean to import `Qux`? warning: unresolved link to `Qux:Y` --> $DIR/intra-links-warning.rs:14:13 | LL | /// [Qux:Y] - | ^^^^^ the module `intra_links_warning` contains no item named `Qux:Y` + | ^^^^^ there is no item named `Qux:Y` in scope | + = help: did you mean to import `Qux:Y`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error` --> $DIR/intra-links-warning.rs:58:30 | LL | * time to introduce a link [error]*/ - | ^^^^^ the module `intra_links_warning` contains no item named `error` + | ^^^^^ there is no item named `error` in scope | + = help: did you mean to import `error`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error` --> $DIR/intra-links-warning.rs:64:30 | LL | * time to introduce a link [error] - | ^^^^^ the module `intra_links_warning` contains no item named `error` + | ^^^^^ there is no item named `error` in scope | + = help: did you mean to import `error`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error` @@ -70,7 +83,8 @@ LL | #[doc = "single line [error]"] single line [error] ^^^^^ - = note: the module `intra_links_warning` contains no item named `error` + = note: there is no item named `error` in scope + = help: did you mean to import `error`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error` @@ -83,7 +97,8 @@ LL | #[doc = "single line with \"escaping\" [error]"] single line with "escaping" [error] ^^^^^ - = note: the module `intra_links_warning` contains no item named `error` + = note: there is no item named `error` in scope + = help: did you mean to import `error`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error` @@ -98,47 +113,53 @@ LL | | /// [error] [error] ^^^^^ - = note: the module `intra_links_warning` contains no item named `error` + = note: there is no item named `error` in scope + = help: did you mean to import `error`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error1` --> $DIR/intra-links-warning.rs:80:11 | LL | /// docs [error1] - | ^^^^^^ the module `intra_links_warning` contains no item named `error1` + | ^^^^^^ there is no item named `error1` in scope | + = help: did you mean to import `error1`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error2` --> $DIR/intra-links-warning.rs:82:11 | LL | /// docs [error2] - | ^^^^^^ the module `intra_links_warning` contains no item named `error2` + | ^^^^^^ there is no item named `error2` in scope | + = help: did you mean to import `error2`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `BarA` --> $DIR/intra-links-warning.rs:21:10 | LL | /// bar [BarA] bar - | ^^^^ the module `intra_links_warning` contains no item named `BarA` + | ^^^^ there is no item named `BarA` in scope | + = help: did you mean to import `BarA`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `BarB` --> $DIR/intra-links-warning.rs:27:9 | LL | * bar [BarB] bar - | ^^^^ the module `intra_links_warning` contains no item named `BarB` + | ^^^^ there is no item named `BarB` in scope | + = help: did you mean to import `BarB`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `BarC` --> $DIR/intra-links-warning.rs:34:6 | LL | bar [BarC] bar - | ^^^^ the module `intra_links_warning` contains no item named `BarC` + | ^^^^ there is no item named `BarC` in scope | + = help: did you mean to import `BarC`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `BarD` @@ -151,7 +172,8 @@ LL | #[doc = "Foo\nbar [BarD] bar\nbaz"] bar [BarD] bar ^^^^ - = note: the module `intra_links_warning` contains no item named `BarD` + = note: there is no item named `BarD` in scope + = help: did you mean to import `BarD`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `BarF` @@ -167,7 +189,8 @@ LL | f!("Foo\nbar [BarF] bar\nbaz"); bar [BarF] bar ^^^^ - = note: the module `intra_links_warning` contains no item named `BarF` + = note: there is no item named `BarF` in scope + = help: did you mean to import `BarF`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/rustdoc-ui/lint-group.stderr b/src/test/rustdoc-ui/lint-group.stderr index 4e9134ea469bd..1fe33b4116733 100644 --- a/src/test/rustdoc-ui/lint-group.stderr +++ b/src/test/rustdoc-ui/lint-group.stderr @@ -32,7 +32,7 @@ error: unresolved link to `error` --> $DIR/lint-group.rs:9:29 | LL | /// what up, let's make an [error] - | ^^^^^ the module `lint_group` contains no item named `error` + | ^^^^^ there is no item named `error` in scope | note: the lint level is defined here --> $DIR/lint-group.rs:7:9 @@ -40,6 +40,7 @@ note: the lint level is defined here LL | #![deny(rustdoc)] | ^^^^^^^ = note: `#[deny(broken_intra_doc_links)]` implied by `#[deny(rustdoc)]` + = help: did you mean to import `error`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` error: aborting due to 3 previous errors From 0193a8871cc2c2cca2de03243097519ce6c910ce Mon Sep 17 00:00:00 2001 From: Camelid Date: Fri, 2 Oct 2020 14:47:41 -0700 Subject: [PATCH 29/32] Remove unhelpful help message --- .../passes/collect_intra_doc_links.rs | 3 +- .../deny-intra-link-resolution-failure.stderr | 1 - src/test/rustdoc-ui/intra-link-errors.rs | 5 -- src/test/rustdoc-ui/intra-link-errors.stderr | 47 ++++++++----------- .../intra-link-span-ice-55723.stderr | 1 - .../intra-links-warning-crlf.stderr | 4 -- .../rustdoc-ui/intra-links-warning.stderr | 23 --------- src/test/rustdoc-ui/lint-group.stderr | 1 - 8 files changed, 21 insertions(+), 64 deletions(-) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 632e6c9f91c11..56585919ec0a9 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1585,13 +1585,14 @@ fn resolution_failure( } else { diag.note(¬e); } - diag.help(&format!("did you mean to import `{}`?", unresolved)); + // If the link has `::` in it, assume it was meant to be an intra-doc link. // Otherwise, the `[]` might be unrelated. // FIXME: don't show this for autolinks (`<>`), `()` style links, or reference links if !path_str.contains("::") { diag.help(r#"to escape `[` and `]` characters, add '\' before them like `\[` or `\]`"#); } + continue; } diff --git a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr index 96b805dbc82a3..889658b0867c4 100644 --- a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr +++ b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr @@ -9,7 +9,6 @@ note: the lint level is defined here | LL | #![deny(broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^ - = help: did you mean to import `v2`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` error: aborting due to previous error diff --git a/src/test/rustdoc-ui/intra-link-errors.rs b/src/test/rustdoc-ui/intra-link-errors.rs index babcc3c43b4ae..872fb70bfc5b6 100644 --- a/src/test/rustdoc-ui/intra-link-errors.rs +++ b/src/test/rustdoc-ui/intra-link-errors.rs @@ -7,27 +7,22 @@ /// [path::to::nonexistent::module] //~^ ERROR unresolved link //~| NOTE there is no item named `path` in scope -//~| HELP did you mean to import `path`? /// [path::to::nonexistent::macro!] //~^ ERROR unresolved link //~| NOTE there is no item named `path` in scope -//~| HELP did you mean to import `path`? /// [type@path::to::nonexistent::type] //~^ ERROR unresolved link //~| NOTE there is no item named `path` in scope -//~| HELP did you mean to import `path`? /// [std::io::not::here] //~^ ERROR unresolved link //~| NOTE there is no item named `not` in scope -//~| HELP did you mean to import `not`? /// [type@std::io::not::here] //~^ ERROR unresolved link //~| NOTE there is no item named `not` in scope -//~| HELP did you mean to import `not`? /// [std::io::Error::x] //~^ ERROR unresolved link diff --git a/src/test/rustdoc-ui/intra-link-errors.stderr b/src/test/rustdoc-ui/intra-link-errors.stderr index f9af1a9fb9385..1299ec5af4b43 100644 --- a/src/test/rustdoc-ui/intra-link-errors.stderr +++ b/src/test/rustdoc-ui/intra-link-errors.stderr @@ -9,96 +9,87 @@ note: the lint level is defined here | LL | #![deny(broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^ - = help: did you mean to import `path`? error: unresolved link to `path::to::nonexistent::macro` - --> $DIR/intra-link-errors.rs:12:6 + --> $DIR/intra-link-errors.rs:11:6 | LL | /// [path::to::nonexistent::macro!] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ there is no item named `path` in scope - | - = help: did you mean to import `path`? error: unresolved link to `path::to::nonexistent::type` - --> $DIR/intra-link-errors.rs:17:6 + --> $DIR/intra-link-errors.rs:15:6 | LL | /// [type@path::to::nonexistent::type] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ there is no item named `path` in scope - | - = help: did you mean to import `path`? error: unresolved link to `std::io::not::here` - --> $DIR/intra-link-errors.rs:22:6 + --> $DIR/intra-link-errors.rs:19:6 | LL | /// [std::io::not::here] | ^^^^^^^^^^^^^^^^^^ there is no item named `not` in scope - | - = help: did you mean to import `not`? error: unresolved link to `std::io::not::here` - --> $DIR/intra-link-errors.rs:27:6 + --> $DIR/intra-link-errors.rs:23:6 | LL | /// [type@std::io::not::here] | ^^^^^^^^^^^^^^^^^^^^^^^ there is no item named `not` in scope - | - = help: did you mean to import `not`? error: unresolved link to `std::io::Error::x` - --> $DIR/intra-link-errors.rs:32:6 + --> $DIR/intra-link-errors.rs:27:6 | LL | /// [std::io::Error::x] | ^^^^^^^^^^^^^^^^^ the struct `Error` has no field or associated item named `x` error: unresolved link to `std::io::ErrorKind::x` - --> $DIR/intra-link-errors.rs:36:6 + --> $DIR/intra-link-errors.rs:31:6 | LL | /// [std::io::ErrorKind::x] | ^^^^^^^^^^^^^^^^^^^^^ the enum `ErrorKind` has no variant or associated item named `x` error: unresolved link to `f::A` - --> $DIR/intra-link-errors.rs:40:6 + --> $DIR/intra-link-errors.rs:35:6 | LL | /// [f::A] | ^^^^ `f` is a function, not a module or type, and cannot have associated items error: unresolved link to `f::A` - --> $DIR/intra-link-errors.rs:44:6 + --> $DIR/intra-link-errors.rs:39:6 | LL | /// [f::A!] | ^^^^^ `f` is a function, not a module or type, and cannot have associated items error: unresolved link to `S::A` - --> $DIR/intra-link-errors.rs:48:6 + --> $DIR/intra-link-errors.rs:43:6 | LL | /// [S::A] | ^^^^ the struct `S` has no field or associated item named `A` error: unresolved link to `S::fmt` - --> $DIR/intra-link-errors.rs:52:6 + --> $DIR/intra-link-errors.rs:47:6 | LL | /// [S::fmt] | ^^^^^^ the struct `S` has no field or associated item named `fmt` error: unresolved link to `E::D` - --> $DIR/intra-link-errors.rs:56:6 + --> $DIR/intra-link-errors.rs:51:6 | LL | /// [E::D] | ^^^^ the enum `E` has no variant or associated item named `D` error: unresolved link to `u8::not_found` - --> $DIR/intra-link-errors.rs:60:6 + --> $DIR/intra-link-errors.rs:55:6 | LL | /// [u8::not_found] | ^^^^^^^^^^^^^ the builtin type `u8` has no associated item named `not_found` error: unresolved link to `std::primitive::u8::not_found` - --> $DIR/intra-link-errors.rs:64:6 + --> $DIR/intra-link-errors.rs:59:6 | LL | /// [std::primitive::u8::not_found] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the builtin type `u8` has no associated item named `not_found` error: unresolved link to `Vec::into_iter` - --> $DIR/intra-link-errors.rs:68:6 + --> $DIR/intra-link-errors.rs:63:6 | LL | /// [type@Vec::into_iter] | ^^^^^^^^^^^^^^^^^^^ @@ -107,7 +98,7 @@ LL | /// [type@Vec::into_iter] | help: to link to the associated function, add parentheses: `Vec::into_iter()` error: unresolved link to `S` - --> $DIR/intra-link-errors.rs:73:6 + --> $DIR/intra-link-errors.rs:68:6 | LL | /// [S!] | ^^ @@ -116,7 +107,7 @@ LL | /// [S!] | help: to link to the struct, prefix with `struct@`: `struct@S` error: unresolved link to `T::g` - --> $DIR/intra-link-errors.rs:91:6 + --> $DIR/intra-link-errors.rs:86:6 | LL | /// [type@T::g] | ^^^^^^^^^ @@ -125,13 +116,13 @@ LL | /// [type@T::g] | help: to link to the associated function, add parentheses: `T::g()` error: unresolved link to `T::h` - --> $DIR/intra-link-errors.rs:96:6 + --> $DIR/intra-link-errors.rs:91:6 | LL | /// [T::h!] | ^^^^^ the trait `T` has no macro named `h` error: unresolved link to `S::h` - --> $DIR/intra-link-errors.rs:83:6 + --> $DIR/intra-link-errors.rs:78:6 | LL | /// [type@S::h] | ^^^^^^^^^ @@ -140,7 +131,7 @@ LL | /// [type@S::h] | help: to link to the associated function, add parentheses: `S::h()` error: unresolved link to `m` - --> $DIR/intra-link-errors.rs:103:6 + --> $DIR/intra-link-errors.rs:98:6 | LL | /// [m()] | ^^^ diff --git a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr index 57061b6778c29..1e4cfb5be012c 100644 --- a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr +++ b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr @@ -9,7 +9,6 @@ note: the lint level is defined here | LL | #![deny(broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^ - = help: did you mean to import `i`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` error: aborting due to previous error diff --git a/src/test/rustdoc-ui/intra-links-warning-crlf.stderr b/src/test/rustdoc-ui/intra-links-warning-crlf.stderr index 0c934e3bb082c..0bf820adbf6a8 100644 --- a/src/test/rustdoc-ui/intra-links-warning-crlf.stderr +++ b/src/test/rustdoc-ui/intra-links-warning-crlf.stderr @@ -5,7 +5,6 @@ LL | /// [error] | ^^^^^ there is no item named `error` in scope | = note: `#[warn(broken_intra_doc_links)]` on by default - = help: did you mean to import `error`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error1` @@ -14,7 +13,6 @@ warning: unresolved link to `error1` LL | /// docs [error1] | ^^^^^^ there is no item named `error1` in scope | - = help: did you mean to import `error1`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error2` @@ -23,7 +21,6 @@ warning: unresolved link to `error2` LL | /// docs [error2] | ^^^^^^ there is no item named `error2` in scope | - = help: did you mean to import `error2`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error` @@ -32,7 +29,6 @@ warning: unresolved link to `error` LL | * It also has an [error]. | ^^^^^ there is no item named `error` in scope | - = help: did you mean to import `error`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: 4 warnings emitted diff --git a/src/test/rustdoc-ui/intra-links-warning.stderr b/src/test/rustdoc-ui/intra-links-warning.stderr index d64f62924d3c2..b1b89dad8a372 100644 --- a/src/test/rustdoc-ui/intra-links-warning.stderr +++ b/src/test/rustdoc-ui/intra-links-warning.stderr @@ -11,40 +11,30 @@ warning: unresolved link to `Bar::foo` | LL | //! Test with [Foo::baz], [Bar::foo], ... | ^^^^^^^^ there is no item named `Bar` in scope - | - = help: did you mean to import `Bar`? warning: unresolved link to `Uniooon::X` --> $DIR/intra-links-warning.rs:6:13 | LL | //! , [Uniooon::X] and [Qux::Z]. | ^^^^^^^^^^ there is no item named `Uniooon` in scope - | - = help: did you mean to import `Uniooon`? warning: unresolved link to `Qux::Z` --> $DIR/intra-links-warning.rs:6:30 | LL | //! , [Uniooon::X] and [Qux::Z]. | ^^^^^^ there is no item named `Qux` in scope - | - = help: did you mean to import `Qux`? warning: unresolved link to `Uniooon::X` --> $DIR/intra-links-warning.rs:10:14 | LL | //! , [Uniooon::X] and [Qux::Z]. | ^^^^^^^^^^ there is no item named `Uniooon` in scope - | - = help: did you mean to import `Uniooon`? warning: unresolved link to `Qux::Z` --> $DIR/intra-links-warning.rs:10:31 | LL | //! , [Uniooon::X] and [Qux::Z]. | ^^^^^^ there is no item named `Qux` in scope - | - = help: did you mean to import `Qux`? warning: unresolved link to `Qux:Y` --> $DIR/intra-links-warning.rs:14:13 @@ -52,7 +42,6 @@ warning: unresolved link to `Qux:Y` LL | /// [Qux:Y] | ^^^^^ there is no item named `Qux:Y` in scope | - = help: did you mean to import `Qux:Y`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error` @@ -61,7 +50,6 @@ warning: unresolved link to `error` LL | * time to introduce a link [error]*/ | ^^^^^ there is no item named `error` in scope | - = help: did you mean to import `error`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error` @@ -70,7 +58,6 @@ warning: unresolved link to `error` LL | * time to introduce a link [error] | ^^^^^ there is no item named `error` in scope | - = help: did you mean to import `error`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error` @@ -84,7 +71,6 @@ LL | #[doc = "single line [error]"] single line [error] ^^^^^ = note: there is no item named `error` in scope - = help: did you mean to import `error`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error` @@ -98,7 +84,6 @@ LL | #[doc = "single line with \"escaping\" [error]"] single line with "escaping" [error] ^^^^^ = note: there is no item named `error` in scope - = help: did you mean to import `error`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error` @@ -114,7 +99,6 @@ LL | | /// [error] [error] ^^^^^ = note: there is no item named `error` in scope - = help: did you mean to import `error`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error1` @@ -123,7 +107,6 @@ warning: unresolved link to `error1` LL | /// docs [error1] | ^^^^^^ there is no item named `error1` in scope | - = help: did you mean to import `error1`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error2` @@ -132,7 +115,6 @@ warning: unresolved link to `error2` LL | /// docs [error2] | ^^^^^^ there is no item named `error2` in scope | - = help: did you mean to import `error2`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `BarA` @@ -141,7 +123,6 @@ warning: unresolved link to `BarA` LL | /// bar [BarA] bar | ^^^^ there is no item named `BarA` in scope | - = help: did you mean to import `BarA`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `BarB` @@ -150,7 +131,6 @@ warning: unresolved link to `BarB` LL | * bar [BarB] bar | ^^^^ there is no item named `BarB` in scope | - = help: did you mean to import `BarB`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `BarC` @@ -159,7 +139,6 @@ warning: unresolved link to `BarC` LL | bar [BarC] bar | ^^^^ there is no item named `BarC` in scope | - = help: did you mean to import `BarC`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `BarD` @@ -173,7 +152,6 @@ LL | #[doc = "Foo\nbar [BarD] bar\nbaz"] bar [BarD] bar ^^^^ = note: there is no item named `BarD` in scope - = help: did you mean to import `BarD`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `BarF` @@ -190,7 +168,6 @@ LL | f!("Foo\nbar [BarF] bar\nbaz"); bar [BarF] bar ^^^^ = note: there is no item named `BarF` in scope - = help: did you mean to import `BarF`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/rustdoc-ui/lint-group.stderr b/src/test/rustdoc-ui/lint-group.stderr index 1fe33b4116733..1cdd786acb419 100644 --- a/src/test/rustdoc-ui/lint-group.stderr +++ b/src/test/rustdoc-ui/lint-group.stderr @@ -40,7 +40,6 @@ note: the lint level is defined here LL | #![deny(rustdoc)] | ^^^^^^^ = note: `#[deny(broken_intra_doc_links)]` implied by `#[deny(rustdoc)]` - = help: did you mean to import `error`? = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` error: aborting due to 3 previous errors From 21fb9dfa8d49d6aa3e74dfcc7032badcd6f51b91 Mon Sep 17 00:00:00 2001 From: Camelid Date: Fri, 2 Oct 2020 18:00:57 -0700 Subject: [PATCH 30/32] Use old error when there's partial resolution The new error was confusing when there was partial resolution (something like `std::io::nonexistent`); the old one is better for those cases. --- src/librustdoc/passes/collect_intra_doc_links.rs | 15 ++++++++++----- src/test/rustdoc-ui/intra-link-errors.rs | 4 ++-- src/test/rustdoc-ui/intra-link-errors.stderr | 4 ++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 56585919ec0a9..024d333d8710d 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1575,11 +1575,16 @@ fn resolution_failure( _ => None, }; // See if this was a module: `[path]` or `[std::io::nope]` - if let Some(_module) = last_found_module { - let note = format!( - "there is no item named `{}` in scope", - unresolved - ); + if let Some(module) = last_found_module { + let note = if partial_res.is_some() { + let module_name = collector.cx.tcx.item_name(module); + format!( + "the module `{}` contains no item named `{}`", + module_name, unresolved + ) + } else { + format!("there is no item named `{}` in scope", unresolved) + }; if let Some(span) = sp { diag.span_label(span, ¬e); } else { diff --git a/src/test/rustdoc-ui/intra-link-errors.rs b/src/test/rustdoc-ui/intra-link-errors.rs index 872fb70bfc5b6..701fd6991c4ac 100644 --- a/src/test/rustdoc-ui/intra-link-errors.rs +++ b/src/test/rustdoc-ui/intra-link-errors.rs @@ -18,11 +18,11 @@ /// [std::io::not::here] //~^ ERROR unresolved link -//~| NOTE there is no item named `not` in scope +//~| NOTE `io` contains no item named `not` /// [type@std::io::not::here] //~^ ERROR unresolved link -//~| NOTE there is no item named `not` in scope +//~| NOTE `io` contains no item named `not` /// [std::io::Error::x] //~^ ERROR unresolved link diff --git a/src/test/rustdoc-ui/intra-link-errors.stderr b/src/test/rustdoc-ui/intra-link-errors.stderr index 1299ec5af4b43..8b12c721f7860 100644 --- a/src/test/rustdoc-ui/intra-link-errors.stderr +++ b/src/test/rustdoc-ui/intra-link-errors.stderr @@ -26,13 +26,13 @@ error: unresolved link to `std::io::not::here` --> $DIR/intra-link-errors.rs:19:6 | LL | /// [std::io::not::here] - | ^^^^^^^^^^^^^^^^^^ there is no item named `not` in scope + | ^^^^^^^^^^^^^^^^^^ the module `io` contains no item named `not` error: unresolved link to `std::io::not::here` --> $DIR/intra-link-errors.rs:23:6 | LL | /// [type@std::io::not::here] - | ^^^^^^^^^^^^^^^^^^^^^^^ there is no item named `not` in scope + | ^^^^^^^^^^^^^^^^^^^^^^^ the module `io` contains no item named `not` error: unresolved link to `std::io::Error::x` --> $DIR/intra-link-errors.rs:27:6 From aa9b718cf0d4157a81c5dcc8d59f2c4ed96b801e Mon Sep 17 00:00:00 2001 From: Camelid Date: Fri, 2 Oct 2020 19:53:09 -0700 Subject: [PATCH 31/32] Improve error messages --- .../passes/collect_intra_doc_links.rs | 9 +++-- .../deny-intra-link-resolution-failure.stderr | 2 +- src/test/rustdoc-ui/intra-link-errors.rs | 10 +++--- src/test/rustdoc-ui/intra-link-errors.stderr | 10 +++--- .../intra-link-span-ice-55723.stderr | 2 +- .../intra-links-warning-crlf.stderr | 8 ++--- .../rustdoc-ui/intra-links-warning.stderr | 36 +++++++++---------- src/test/rustdoc-ui/lint-group.stderr | 2 +- 8 files changed, 39 insertions(+), 40 deletions(-) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 024d333d8710d..f234dc5c03b31 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1577,13 +1577,12 @@ fn resolution_failure( // See if this was a module: `[path]` or `[std::io::nope]` if let Some(module) = last_found_module { let note = if partial_res.is_some() { + // Part of the link resolved; e.g. `std::io::nonexistent` let module_name = collector.cx.tcx.item_name(module); - format!( - "the module `{}` contains no item named `{}`", - module_name, unresolved - ) + format!("no item named `{}` in module `{}`", unresolved, module_name) } else { - format!("there is no item named `{}` in scope", unresolved) + // None of the link resolved; e.g. `Notimported` + format!("no item named `{}` in scope", unresolved) }; if let Some(span) = sp { diag.span_label(span, ¬e); diff --git a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr index 889658b0867c4..9ec9dd4bc9ab7 100644 --- a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr +++ b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr @@ -2,7 +2,7 @@ error: unresolved link to `v2` --> $DIR/deny-intra-link-resolution-failure.rs:3:6 | LL | /// [v2] - | ^^ there is no item named `v2` in scope + | ^^ no item named `v2` in scope | note: the lint level is defined here --> $DIR/deny-intra-link-resolution-failure.rs:1:9 diff --git a/src/test/rustdoc-ui/intra-link-errors.rs b/src/test/rustdoc-ui/intra-link-errors.rs index 701fd6991c4ac..ef928ae02f3e3 100644 --- a/src/test/rustdoc-ui/intra-link-errors.rs +++ b/src/test/rustdoc-ui/intra-link-errors.rs @@ -6,23 +6,23 @@ /// [path::to::nonexistent::module] //~^ ERROR unresolved link -//~| NOTE there is no item named `path` in scope +//~| NOTE no item named `path` in scope /// [path::to::nonexistent::macro!] //~^ ERROR unresolved link -//~| NOTE there is no item named `path` in scope +//~| NOTE no item named `path` in scope /// [type@path::to::nonexistent::type] //~^ ERROR unresolved link -//~| NOTE there is no item named `path` in scope +//~| NOTE no item named `path` in scope /// [std::io::not::here] //~^ ERROR unresolved link -//~| NOTE `io` contains no item named `not` +//~| NOTE no item named `not` in module `io` /// [type@std::io::not::here] //~^ ERROR unresolved link -//~| NOTE `io` contains no item named `not` +//~| NOTE no item named `not` in module `io` /// [std::io::Error::x] //~^ ERROR unresolved link diff --git a/src/test/rustdoc-ui/intra-link-errors.stderr b/src/test/rustdoc-ui/intra-link-errors.stderr index 8b12c721f7860..31e7fc48afde5 100644 --- a/src/test/rustdoc-ui/intra-link-errors.stderr +++ b/src/test/rustdoc-ui/intra-link-errors.stderr @@ -2,7 +2,7 @@ error: unresolved link to `path::to::nonexistent::module` --> $DIR/intra-link-errors.rs:7:6 | LL | /// [path::to::nonexistent::module] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ there is no item named `path` in scope + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `path` in scope | note: the lint level is defined here --> $DIR/intra-link-errors.rs:1:9 @@ -14,25 +14,25 @@ error: unresolved link to `path::to::nonexistent::macro` --> $DIR/intra-link-errors.rs:11:6 | LL | /// [path::to::nonexistent::macro!] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ there is no item named `path` in scope + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `path` in scope error: unresolved link to `path::to::nonexistent::type` --> $DIR/intra-link-errors.rs:15:6 | LL | /// [type@path::to::nonexistent::type] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ there is no item named `path` in scope + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `path` in scope error: unresolved link to `std::io::not::here` --> $DIR/intra-link-errors.rs:19:6 | LL | /// [std::io::not::here] - | ^^^^^^^^^^^^^^^^^^ the module `io` contains no item named `not` + | ^^^^^^^^^^^^^^^^^^ no item named `not` in module `io` error: unresolved link to `std::io::not::here` --> $DIR/intra-link-errors.rs:23:6 | LL | /// [type@std::io::not::here] - | ^^^^^^^^^^^^^^^^^^^^^^^ the module `io` contains no item named `not` + | ^^^^^^^^^^^^^^^^^^^^^^^ no item named `not` in module `io` error: unresolved link to `std::io::Error::x` --> $DIR/intra-link-errors.rs:27:6 diff --git a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr index 1e4cfb5be012c..d8afa9e7efd59 100644 --- a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr +++ b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr @@ -2,7 +2,7 @@ error: unresolved link to `i` --> $DIR/intra-link-span-ice-55723.rs:9:10 | LL | /// (arr[i]) - | ^ there is no item named `i` in scope + | ^ no item named `i` in scope | note: the lint level is defined here --> $DIR/intra-link-span-ice-55723.rs:1:9 diff --git a/src/test/rustdoc-ui/intra-links-warning-crlf.stderr b/src/test/rustdoc-ui/intra-links-warning-crlf.stderr index 0bf820adbf6a8..67c48378fd2f4 100644 --- a/src/test/rustdoc-ui/intra-links-warning-crlf.stderr +++ b/src/test/rustdoc-ui/intra-links-warning-crlf.stderr @@ -2,7 +2,7 @@ warning: unresolved link to `error` --> $DIR/intra-links-warning-crlf.rs:7:6 | LL | /// [error] - | ^^^^^ there is no item named `error` in scope + | ^^^^^ no item named `error` in scope | = note: `#[warn(broken_intra_doc_links)]` on by default = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` @@ -11,7 +11,7 @@ warning: unresolved link to `error1` --> $DIR/intra-links-warning-crlf.rs:12:11 | LL | /// docs [error1] - | ^^^^^^ there is no item named `error1` in scope + | ^^^^^^ no item named `error1` in scope | = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` @@ -19,7 +19,7 @@ warning: unresolved link to `error2` --> $DIR/intra-links-warning-crlf.rs:15:11 | LL | /// docs [error2] - | ^^^^^^ there is no item named `error2` in scope + | ^^^^^^ no item named `error2` in scope | = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` @@ -27,7 +27,7 @@ warning: unresolved link to `error` --> $DIR/intra-links-warning-crlf.rs:23:20 | LL | * It also has an [error]. - | ^^^^^ there is no item named `error` in scope + | ^^^^^ no item named `error` in scope | = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` diff --git a/src/test/rustdoc-ui/intra-links-warning.stderr b/src/test/rustdoc-ui/intra-links-warning.stderr index b1b89dad8a372..4cdb8bbdde782 100644 --- a/src/test/rustdoc-ui/intra-links-warning.stderr +++ b/src/test/rustdoc-ui/intra-links-warning.stderr @@ -10,37 +10,37 @@ warning: unresolved link to `Bar::foo` --> $DIR/intra-links-warning.rs:3:35 | LL | //! Test with [Foo::baz], [Bar::foo], ... - | ^^^^^^^^ there is no item named `Bar` in scope + | ^^^^^^^^ no item named `Bar` in scope warning: unresolved link to `Uniooon::X` --> $DIR/intra-links-warning.rs:6:13 | LL | //! , [Uniooon::X] and [Qux::Z]. - | ^^^^^^^^^^ there is no item named `Uniooon` in scope + | ^^^^^^^^^^ no item named `Uniooon` in scope warning: unresolved link to `Qux::Z` --> $DIR/intra-links-warning.rs:6:30 | LL | //! , [Uniooon::X] and [Qux::Z]. - | ^^^^^^ there is no item named `Qux` in scope + | ^^^^^^ no item named `Qux` in scope warning: unresolved link to `Uniooon::X` --> $DIR/intra-links-warning.rs:10:14 | LL | //! , [Uniooon::X] and [Qux::Z]. - | ^^^^^^^^^^ there is no item named `Uniooon` in scope + | ^^^^^^^^^^ no item named `Uniooon` in scope warning: unresolved link to `Qux::Z` --> $DIR/intra-links-warning.rs:10:31 | LL | //! , [Uniooon::X] and [Qux::Z]. - | ^^^^^^ there is no item named `Qux` in scope + | ^^^^^^ no item named `Qux` in scope warning: unresolved link to `Qux:Y` --> $DIR/intra-links-warning.rs:14:13 | LL | /// [Qux:Y] - | ^^^^^ there is no item named `Qux:Y` in scope + | ^^^^^ no item named `Qux:Y` in scope | = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` @@ -48,7 +48,7 @@ warning: unresolved link to `error` --> $DIR/intra-links-warning.rs:58:30 | LL | * time to introduce a link [error]*/ - | ^^^^^ there is no item named `error` in scope + | ^^^^^ no item named `error` in scope | = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` @@ -56,7 +56,7 @@ warning: unresolved link to `error` --> $DIR/intra-links-warning.rs:64:30 | LL | * time to introduce a link [error] - | ^^^^^ there is no item named `error` in scope + | ^^^^^ no item named `error` in scope | = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` @@ -70,7 +70,7 @@ LL | #[doc = "single line [error]"] single line [error] ^^^^^ - = note: there is no item named `error` in scope + = note: no item named `error` in scope = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error` @@ -83,7 +83,7 @@ LL | #[doc = "single line with \"escaping\" [error]"] single line with "escaping" [error] ^^^^^ - = note: there is no item named `error` in scope + = note: no item named `error` in scope = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error` @@ -98,14 +98,14 @@ LL | | /// [error] [error] ^^^^^ - = note: there is no item named `error` in scope + = note: no item named `error` in scope = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error1` --> $DIR/intra-links-warning.rs:80:11 | LL | /// docs [error1] - | ^^^^^^ there is no item named `error1` in scope + | ^^^^^^ no item named `error1` in scope | = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` @@ -113,7 +113,7 @@ warning: unresolved link to `error2` --> $DIR/intra-links-warning.rs:82:11 | LL | /// docs [error2] - | ^^^^^^ there is no item named `error2` in scope + | ^^^^^^ no item named `error2` in scope | = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` @@ -121,7 +121,7 @@ warning: unresolved link to `BarA` --> $DIR/intra-links-warning.rs:21:10 | LL | /// bar [BarA] bar - | ^^^^ there is no item named `BarA` in scope + | ^^^^ no item named `BarA` in scope | = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` @@ -129,7 +129,7 @@ warning: unresolved link to `BarB` --> $DIR/intra-links-warning.rs:27:9 | LL | * bar [BarB] bar - | ^^^^ there is no item named `BarB` in scope + | ^^^^ no item named `BarB` in scope | = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` @@ -137,7 +137,7 @@ warning: unresolved link to `BarC` --> $DIR/intra-links-warning.rs:34:6 | LL | bar [BarC] bar - | ^^^^ there is no item named `BarC` in scope + | ^^^^ no item named `BarC` in scope | = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` @@ -151,7 +151,7 @@ LL | #[doc = "Foo\nbar [BarD] bar\nbaz"] bar [BarD] bar ^^^^ - = note: there is no item named `BarD` in scope + = note: no item named `BarD` in scope = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `BarF` @@ -167,7 +167,7 @@ LL | f!("Foo\nbar [BarF] bar\nbaz"); bar [BarF] bar ^^^^ - = note: there is no item named `BarF` in scope + = note: no item named `BarF` in scope = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/rustdoc-ui/lint-group.stderr b/src/test/rustdoc-ui/lint-group.stderr index 1cdd786acb419..32be90193fe90 100644 --- a/src/test/rustdoc-ui/lint-group.stderr +++ b/src/test/rustdoc-ui/lint-group.stderr @@ -32,7 +32,7 @@ error: unresolved link to `error` --> $DIR/lint-group.rs:9:29 | LL | /// what up, let's make an [error] - | ^^^^^ there is no item named `error` in scope + | ^^^^^ no item named `error` in scope | note: the lint level is defined here --> $DIR/lint-group.rs:7:9 From e27ef130c1d1cc7d8c3779a4e66e413a7a943ad4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 3 Oct 2020 12:15:26 +0200 Subject: [PATCH 32/32] grammar nit --- library/alloc/src/rc.rs | 2 +- library/alloc/src/sync.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 1d4ce8e268294..0a2fe46e3ff95 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1860,7 +1860,7 @@ impl Weak { let offset = unsafe { data_offset(ptr) }; // Reverse the offset to find the original RcBox. - // SAFETY: we use wrapping_offset here because the pointer may be dangling (iff T: Sized). + // SAFETY: we use wrapping_offset here because the pointer may be dangling (but only if T: Sized). let ptr = unsafe { set_data_ptr(ptr as *mut RcBox, (ptr as *mut u8).wrapping_offset(-offset)) }; diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index f064881717d63..f7873b34c446e 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1643,7 +1643,7 @@ impl Weak { let offset = unsafe { data_offset(ptr) }; // Reverse the offset to find the original ArcInner. - // SAFETY: we use wrapping_offset here because the pointer may be dangling (iff T: Sized) + // SAFETY: we use wrapping_offset here because the pointer may be dangling (but only if T: Sized) let ptr = unsafe { set_data_ptr(ptr as *mut ArcInner, (ptr as *mut u8).wrapping_offset(-offset)) };