From faf80ad3979e58d238f41c22e7be06ff1276a359 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 3 Sep 2018 21:50:03 +0100 Subject: [PATCH 01/29] remove base_place --- src/librustc_mir/borrow_check/mod.rs | 50 ++----------------- .../borrowck-box-insensitivity.nll.stderr | 35 +++++-------- .../ui/borrowck/borrowck-box-insensitivity.rs | 3 +- 3 files changed, 18 insertions(+), 70 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 3536947b25ebf..fd5ca0780e290 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1602,10 +1602,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { place_span: (&Place<'tcx>, Span), flow_state: &Flows<'cx, 'gcx, 'tcx>, ) { - // FIXME: analogous code in check_loans first maps `place` to - // its base_path ... but is that what we want here? - let place = self.base_path(place_span.0); - let maybe_uninits = &flow_state.uninits; // Bad scenarios: @@ -1643,8 +1639,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // // This code covers scenarios 1, 2, and 3. - debug!("check_if_full_path_is_moved place: {:?}", place); - match self.move_path_closest_to(place) { + debug!("check_if_full_path_is_moved place: {:?}", place_span.0); + match self.move_path_closest_to(place_span.0) { Ok(mpi) => { if maybe_uninits.contains(&mpi) { self.report_use_of_moved_or_uninitialized( @@ -1674,10 +1670,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { place_span: (&Place<'tcx>, Span), flow_state: &Flows<'cx, 'gcx, 'tcx>, ) { - // FIXME: analogous code in check_loans first maps `place` to - // its base_path ... but is that what we want here? - let place = self.base_path(place_span.0); - let maybe_uninits = &flow_state.uninits; // Bad scenarios: @@ -1706,8 +1698,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // // This code covers scenario 1. - debug!("check_if_path_or_subpath_is_moved place: {:?}", place); - if let Some(mpi) = self.move_path_for_place(place) { + debug!("check_if_path_or_subpath_is_moved place: {:?}", place_span.0); + if let Some(mpi) = self.move_path_for_place(place_span.0) { if let Some(child_mpi) = maybe_uninits.has_any_child_of(mpi) { self.report_use_of_moved_or_uninitialized( context, @@ -1810,11 +1802,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let tcx = self.tcx; match base.ty(self.mir, tcx).to_ty(tcx).sty { ty::Adt(def, _) if def.has_dtor(tcx) => { - - // FIXME: analogous code in - // check_loans.rs first maps - // `base` to its base_path. - self.check_if_path_or_subpath_is_moved( context, InitializationRequiringAction::Assignment, (base, span), flow_state); @@ -2187,35 +2174,6 @@ enum Overlap { Disjoint, } -impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { - // FIXME (#16118): function intended to allow the borrow checker - // to be less precise in its handling of Box while still allowing - // moves out of a Box. They should be removed when/if we stop - // treating Box specially (e.g. when/if DerefMove is added...) - - fn base_path<'d>(&self, place: &'d Place<'tcx>) -> &'d Place<'tcx> { - //! Returns the base of the leftmost (deepest) dereference of an - //! Box in `place`. If there is no dereference of an Box - //! in `place`, then it just returns `place` itself. - - let mut cursor = place; - let mut deepest = place; - loop { - let proj = match *cursor { - Place::Promoted(_) | - Place::Local(..) | Place::Static(..) => return deepest, - Place::Projection(ref proj) => proj, - }; - if proj.elem == ProjectionElem::Deref - && place.ty(self.mir, self.tcx).to_ty(self.tcx).is_box() - { - deepest = &proj.base; - } - cursor = &proj.base; - } - } -} - #[derive(Copy, Clone, PartialEq, Eq, Debug)] struct Context { kind: ContextKind, diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr b/src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr index 601f05b499c75..0e380e90e7591 100644 --- a/src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr +++ b/src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr @@ -1,25 +1,14 @@ -error[E0382]: use of moved value: `a.y` - --> $DIR/borrowck-box-insensitivity.rs:46:14 - | -LL | let _x = a.x; - | --- value moved here -LL | //~^ value moved here -LL | let _y = a.y; //~ ERROR use of moved - | ^^^ value used here after move - | - = note: move occurs because `a.x` has type `std::boxed::Box`, which does not implement the `Copy` trait - -error[E0382]: use of moved value: `a.y` - --> $DIR/borrowck-box-insensitivity.rs:108:14 - | -LL | let _x = a.x.x; - | ----- value moved here -LL | //~^ value moved here -LL | let _y = a.y; //~ ERROR use of collaterally moved - | ^^^ value used here after move - | - = note: move occurs because `a.x.x` has type `std::boxed::Box`, which does not implement the `Copy` trait +error: compilation successful + --> $DIR/borrowck-box-insensitivity.rs:160:1 + | +LL | / fn main() { +LL | | copy_after_move(); +LL | | move_after_move(); +LL | | borrow_after_move(); +... | +LL | | mut_borrow_after_borrow_nested(); +LL | | } + | |_^ -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.rs b/src/test/ui/borrowck/borrowck-box-insensitivity.rs index 75bf6bce04b39..eabb8d7bca3fa 100644 --- a/src/test/ui/borrowck/borrowck-box-insensitivity.rs +++ b/src/test/ui/borrowck/borrowck-box-insensitivity.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] +#![feature(box_syntax, rustc_attrs)] struct A { x: Box, @@ -156,6 +156,7 @@ fn mut_borrow_after_borrow_nested() { //~^ mutable borrow occurs here } +#[rustc_error] fn main() { copy_after_move(); move_after_move(); From fb307e529d217c6602c1c0359b14947b6897265c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 4 Sep 2018 16:44:04 +1000 Subject: [PATCH 02/29] Rewrite `precompute_borrows_out_of_scope` for fewer hash table lookups. It now does one hash table lookup per basic block, instead of one per statement. This is worthwhile because this function is hot for NLL builds of `ucd`. --- src/librustc_mir/dataflow/impls/borrows.rs | 120 ++++++++++++++------- 1 file changed, 79 insertions(+), 41 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 8f3595b17848c..0a6701fc2dbe3 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -21,7 +21,7 @@ use rustc::ty::{RegionKind, RegionVid}; use rustc::ty::RegionKind::ReScope; use rustc_data_structures::bitslice::{BitwiseOperator, Word}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_set::IdxSet; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::sync::Lrc; @@ -53,6 +53,13 @@ pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> { _nonlexical_regioncx: Rc>, } +struct StackEntry { + bb: mir::BasicBlock, + lo: usize, + hi: usize, + first_part_only: bool +} + fn precompute_borrows_out_of_scope<'tcx>( mir: &Mir<'tcx>, regioncx: &Rc>, @@ -61,48 +68,79 @@ fn precompute_borrows_out_of_scope<'tcx>( borrow_region: RegionVid, location: Location, ) { - // Keep track of places we've locations to check and locations that we have checked. - let mut stack = vec![ location ]; - let mut visited = FxHashSet(); - visited.insert(location); - - debug!( - "borrow {:?} has region {:?} with value {:?}", - borrow_index, - borrow_region, - regioncx.region_value_str(borrow_region), - ); - debug!("borrow {:?} starts at {:?}", borrow_index, location); - while let Some(location) = stack.pop() { - // If region does not contain a point at the location, then add to list and skip - // successor locations. - if !regioncx.region_contains(borrow_region, location) { - debug!("borrow {:?} gets killed at {:?}", borrow_index, location); - borrows_out_of_scope_at_location - .entry(location) - .or_default() - .push(borrow_index); - continue; + // We visit one BB at a time. The complication is that we may start in the + // middle of the first BB visited (the one containing `location`), in which + // case we may have to later on process the first part of that BB if there + // is a path back to its start. + + // For visited BBs, we record the index of the first statement processed. + // (In fully processed BBs this index is 0.) Note also that we add BBs to + // `visited` once they are added to `stack`, before they are actually + // processed, because this avoids the need to look them up again on + // completion. + let mut visited = FxHashMap(); + visited.insert(location.block, location.statement_index); + + let mut stack = vec![]; + stack.push(StackEntry { + bb: location.block, + lo: location.statement_index, + hi: mir[location.block].statements.len(), + first_part_only: false, + }); + + while let Some(StackEntry { bb, lo, hi, first_part_only }) = stack.pop() { + let mut finished_early = first_part_only; + for i in lo ..= hi { + let location = Location { block: bb, statement_index: i }; + // If region does not contain a point at the location, then add to list and skip + // successor locations. + if !regioncx.region_contains(borrow_region, location) { + debug!("borrow {:?} gets killed at {:?}", borrow_index, location); + borrows_out_of_scope_at_location + .entry(location) + .or_default() + .push(borrow_index); + finished_early = true; + break; + } } - let bb_data = &mir[location.block]; - // If this is the last statement in the block, then add the - // terminator successors next. - if location.statement_index == bb_data.statements.len() { - // Add successors to locations to visit, if not visited before. - if let Some(ref terminator) = bb_data.terminator { - for block in terminator.successors() { - let loc = block.start_location(); - if visited.insert(loc) { - stack.push(loc); - } - } - } - } else { - // Visit next statement in block. - let loc = location.successor_within_block(); - if visited.insert(loc) { - stack.push(loc); + if !finished_early { + // Add successor BBs to the work list, if necessary. + let bb_data = &mir[bb]; + assert!(hi == bb_data.statements.len()); + for &succ_bb in bb_data.terminator.as_ref().unwrap().successors() { + visited.entry(succ_bb) + .and_modify(|lo| { + // `succ_bb` has been seen before. If it wasn't + // fully processed, add its first part to `stack` + // for processing. + if *lo > 0 { + stack.push(StackEntry { + bb: succ_bb, + lo: 0, + hi: *lo - 1, + first_part_only: true, + }); + } + // And update this entry with 0, to represent the + // whole BB being processed. + *lo = 0; + }) + .or_insert_with(|| { + // succ_bb hasn't been seen before. Add it to + // `stack` for processing. + stack.push(StackEntry { + bb: succ_bb, + lo: 0, + hi: mir[succ_bb].statements.len(), + first_part_only: false, + }); + // Insert 0 for this BB, to represent the whole BB + // being processed. + 0 + }); } } } From 28745a6e190a8c61ba2f08b03ea8afed620c9735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Bernier?= Date: Wed, 5 Sep 2018 23:09:58 -0400 Subject: [PATCH 03/29] Implement initializer() for FileDesc in order to avoid constantly zeroing memory when it's not needed. --- src/libstd/sys/unix/fd.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index 12e14734ff515..db2ea6b660a7a 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -11,7 +11,7 @@ #![unstable(reason = "not public", issue = "0", feature = "fd")] use cmp; -use io::{self, Read}; +use io::{self, Read, Initializer}; use libc::{self, c_int, c_void, ssize_t}; use mem; use sync::atomic::{AtomicBool, Ordering}; @@ -270,6 +270,11 @@ impl<'a> Read for &'a FileDesc { fn read(&mut self, buf: &mut [u8]) -> io::Result { (**self).read(buf) } + + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() + } } impl AsInner for FileDesc { From c34dd37f854dc4fcb8c2e3eebe4f9dae6b24784a Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 6 Sep 2018 15:04:21 +0300 Subject: [PATCH 04/29] rustc_resolve: don't record uniform_paths canaries as reexports. --- src/librustc_resolve/resolve_imports.rs | 10 +++++++++- .../uniform-paths/auxiliary/issue-53691.rs | 19 +++++++++++++++++++ .../run-pass/uniform-paths/issue-53691.rs | 18 ++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/uniform-paths/auxiliary/issue-53691.rs create mode 100644 src/test/run-pass/uniform-paths/issue-53691.rs diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index c60f9293d58e7..3e7f33265d1fd 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -1155,7 +1155,15 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { None => continue, }; - if binding.is_import() || binding.is_macro_def() { + // Don't reexport `uniform_path` canaries. + let non_canary_import = match binding.kind { + NameBindingKind::Import { directive, .. } => { + !directive.is_uniform_paths_canary + } + _ => false, + }; + + if non_canary_import || binding.is_macro_def() { let def = binding.def(); if def != Def::Err { if !def.def_id().is_local() { diff --git a/src/test/run-pass/uniform-paths/auxiliary/issue-53691.rs b/src/test/run-pass/uniform-paths/auxiliary/issue-53691.rs new file mode 100644 index 0000000000000..5845afd72fbe7 --- /dev/null +++ b/src/test/run-pass/uniform-paths/auxiliary/issue-53691.rs @@ -0,0 +1,19 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// edition:2018 + +#![feature(uniform_paths)] + +mod m { pub fn f() {} } +mod n { pub fn g() {} } + +pub use m::f; +pub use n::g; diff --git a/src/test/run-pass/uniform-paths/issue-53691.rs b/src/test/run-pass/uniform-paths/issue-53691.rs new file mode 100644 index 0000000000000..62be31d6b85fe --- /dev/null +++ b/src/test/run-pass/uniform-paths/issue-53691.rs @@ -0,0 +1,18 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:issue-53691.rs + +extern crate issue_53691; + +fn main() { + issue_53691::f(); + issue_53691::g(); +} From 9b764c319046d9a4115054e55941c228988f8674 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Thu, 6 Sep 2018 21:24:33 +0200 Subject: [PATCH 05/29] crates that provide a `panic_handler` are exempt from `unused_extern_crates` fixes the *first* false positive reported in #53964 --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/session/mod.rs | 4 ++++ src/librustc/ty/query/config.rs | 6 ++++++ src/librustc/ty/query/mod.rs | 1 + src/librustc/ty/query/plumbing.rs | 1 + src/librustc_metadata/cstore_impl.rs | 1 + src/librustc_metadata/encoder.rs | 2 ++ src/librustc_metadata/schema.rs | 1 + src/librustc_typeck/check/mod.rs | 5 +++++ src/librustc_typeck/check_unused.rs | 1 + .../run-make-fulldeps/issue-53964/Makefile | 5 +++++ src/test/run-make-fulldeps/issue-53964/app.rs | 8 ++++++++ .../run-make-fulldeps/issue-53964/panic.rs | 20 +++++++++++++++++++ 13 files changed, 56 insertions(+) create mode 100644 src/test/run-make-fulldeps/issue-53964/Makefile create mode 100644 src/test/run-make-fulldeps/issue-53964/app.rs create mode 100644 src/test/run-make-fulldeps/issue-53964/panic.rs diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index dfe0a395ca140..d15568af6aebe 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -574,6 +574,7 @@ define_dep_nodes!( <'tcx> [] IsPanicRuntime(CrateNum), [] IsCompilerBuiltins(CrateNum), [] HasGlobalAllocator(CrateNum), + [] HasPanicHandler(CrateNum), [input] ExternCrate(DefId), [eval_always] LintLevels, [] Specializes { impl1: DefId, impl2: DefId }, diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 778c388c7dec7..272967282e03b 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -159,6 +159,9 @@ pub struct Session { /// Metadata about the allocators for the current crate being compiled pub has_global_allocator: Once, + /// Metadata about the panic handlers for the current crate being compiled + pub has_panic_handler: Once, + /// Cap lint level specified by a driver specifically. pub driver_lint_caps: FxHashMap, } @@ -1160,6 +1163,7 @@ pub fn build_session_( (*GLOBAL_JOBSERVER).clone() }, has_global_allocator: Once::new(), + has_panic_handler: Once::new(), driver_lint_caps: FxHashMap(), }; diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index 837354bfcaf36..2bbf5aacc1aca 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -464,6 +464,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::has_global_allocator<'tcx> { } } +impl<'tcx> QueryDescription<'tcx> for queries::has_panic_handler<'tcx> { + fn describe(_: TyCtxt, _: CrateNum) -> String { + "checking if the crate has_panic_handler".to_string() + } +} + impl<'tcx> QueryDescription<'tcx> for queries::extern_crate<'tcx> { fn describe(_: TyCtxt, _: DefId) -> String { "getting crate's ExternCrateData".to_string() diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 993ba2fd13d0d..f0ca168e9e467 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -381,6 +381,7 @@ define_queries! { <'tcx> [fatal_cycle] fn is_panic_runtime: IsPanicRuntime(CrateNum) -> bool, [fatal_cycle] fn is_compiler_builtins: IsCompilerBuiltins(CrateNum) -> bool, [fatal_cycle] fn has_global_allocator: HasGlobalAllocator(CrateNum) -> bool, + [fatal_cycle] fn has_panic_handler: HasPanicHandler(CrateNum) -> bool, [fatal_cycle] fn is_sanitizer_runtime: IsSanitizerRuntime(CrateNum) -> bool, [fatal_cycle] fn is_profiler_runtime: IsProfilerRuntime(CrateNum) -> bool, [fatal_cycle] fn panic_strategy: GetPanicStrategy(CrateNum) -> PanicStrategy, diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 215fba54499b7..3c26732fbac67 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -1168,6 +1168,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::IsPanicRuntime => { force!(is_panic_runtime, krate!()); } DepKind::IsCompilerBuiltins => { force!(is_compiler_builtins, krate!()); } DepKind::HasGlobalAllocator => { force!(has_global_allocator, krate!()); } + DepKind::HasPanicHandler => { force!(has_panic_handler, krate!()); } DepKind::ExternCrate => { force!(extern_crate, def_id!()); } DepKind::LintLevels => { force!(lint_levels, LOCAL_CRATE); } DepKind::InScopeTraits => { force!(in_scope_traits_map, def_id!().index); } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 5aa05270a2a0b..87a32b5a53e7a 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -173,6 +173,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, is_panic_runtime => { cdata.root.panic_runtime } is_compiler_builtins => { cdata.root.compiler_builtins } has_global_allocator => { cdata.root.has_global_allocator } + has_panic_handler => { cdata.root.has_panic_handler } is_sanitizer_runtime => { cdata.root.sanitizer_runtime } is_profiler_runtime => { cdata.root.profiler_runtime } panic_strategy => { cdata.root.panic_strategy } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0fd43c592c853..aae45c17c6771 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -484,6 +484,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro); let has_default_lib_allocator = attr::contains_name(&attrs, "default_lib_allocator"); let has_global_allocator = *tcx.sess.has_global_allocator.get(); + let has_panic_handler = *tcx.sess.has_panic_handler.try_get().unwrap_or(&false); let root = self.lazy(&CrateRoot { name: tcx.crate_name(LOCAL_CRATE), @@ -494,6 +495,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { panic_strategy: tcx.sess.panic_strategy(), edition: hygiene::default_edition(), has_global_allocator: has_global_allocator, + has_panic_handler: has_panic_handler, has_default_lib_allocator: has_default_lib_allocator, plugin_registrar_fn: tcx.sess .plugin_registrar_fn diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 8e454ddc0adc4..ab22a8e4db919 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -193,6 +193,7 @@ pub struct CrateRoot { pub panic_strategy: PanicStrategy, pub edition: Edition, pub has_global_allocator: bool, + pub has_panic_handler: bool, pub has_default_lib_allocator: bool, pub plugin_registrar_fn: Option, pub macro_derive_registrar: Option, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a45e5c8ec2a45..a1e4c85f82141 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1138,6 +1138,11 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, if let Some(panic_impl_did) = fcx.tcx.lang_items().panic_impl() { if panic_impl_did == fcx.tcx.hir.local_def_id(fn_id) { if let Some(panic_info_did) = fcx.tcx.lang_items().panic_info() { + // at this point we don't care if there are duplicate handlers or if the handler has + // the wrong signature as this value we'll be used when writing metadata and that + // only happens if compilation succeeded + fcx.tcx.sess.has_panic_handler.try_set_same(true); + if declared_ret_ty.sty != ty::Never { fcx.tcx.sess.span_err( decl.output.span(), diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index fa152b386a825..5967bd1ba3eea 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -117,6 +117,7 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) { !tcx.is_compiler_builtins(cnum) && !tcx.is_panic_runtime(cnum) && !tcx.has_global_allocator(cnum) + && !tcx.has_panic_handler(cnum) }) .cloned() .collect(); diff --git a/src/test/run-make-fulldeps/issue-53964/Makefile b/src/test/run-make-fulldeps/issue-53964/Makefile new file mode 100644 index 0000000000000..c56beb52fdd61 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-53964/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) panic.rs + $(RUSTC) -C panic=abort --emit=obj app.rs -L $(TMPDIR) diff --git a/src/test/run-make-fulldeps/issue-53964/app.rs b/src/test/run-make-fulldeps/issue-53964/app.rs new file mode 100644 index 0000000000000..8127b9578bfee --- /dev/null +++ b/src/test/run-make-fulldeps/issue-53964/app.rs @@ -0,0 +1,8 @@ +#![crate_type = "bin"] +#![no_main] +#![no_std] + +#![deny(unused_extern_crates)] + +// `panic` provides a `panic_handler` so it shouldn't trip the `unused_extern_crates` lint +extern crate panic; diff --git a/src/test/run-make-fulldeps/issue-53964/panic.rs b/src/test/run-make-fulldeps/issue-53964/panic.rs new file mode 100644 index 0000000000000..87c7b218822a0 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-53964/panic.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "lib"] +#![feature(panic_handler)] +#![no_std] + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(_: &PanicInfo) -> ! { + loop {} +} From 6c4f3f512e65742367bb84880465460e74a8a24e Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Thu, 6 Sep 2018 23:01:35 +0200 Subject: [PATCH 06/29] update UI test --- src/test/ui/removing-extern-crate.rs | 6 +++--- src/test/ui/removing-extern-crate.stderr | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/test/ui/removing-extern-crate.rs b/src/test/ui/removing-extern-crate.rs index 3905d285becb5..9762db38a1ca6 100644 --- a/src/test/ui/removing-extern-crate.rs +++ b/src/test/ui/removing-extern-crate.rs @@ -16,12 +16,12 @@ #![warn(rust_2018_idioms)] #![allow(unused_imports)] -extern crate std as foo; +extern crate removing_extern_crate as foo; extern crate core; mod another { - extern crate std as foo; - extern crate std; + extern crate removing_extern_crate as foo; + extern crate core; } fn main() {} diff --git a/src/test/ui/removing-extern-crate.stderr b/src/test/ui/removing-extern-crate.stderr index f2eed27a26693..758ec67d17823 100644 --- a/src/test/ui/removing-extern-crate.stderr +++ b/src/test/ui/removing-extern-crate.stderr @@ -1,8 +1,8 @@ warning: unused extern crate --> $DIR/removing-extern-crate.rs:19:1 | -LL | extern crate std as foo; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it +LL | extern crate removing_extern_crate as foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it | note: lint level defined here --> $DIR/removing-extern-crate.rs:16:9 @@ -20,12 +20,12 @@ LL | extern crate core; warning: unused extern crate --> $DIR/removing-extern-crate.rs:23:5 | -LL | extern crate std as foo; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it +LL | extern crate removing_extern_crate as foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it warning: unused extern crate --> $DIR/removing-extern-crate.rs:24:5 | -LL | extern crate std; - | ^^^^^^^^^^^^^^^^^ help: remove it +LL | extern crate core; + | ^^^^^^^^^^^^^^^^^^ help: remove it From 1adfdefca2e18b5d7c65f0d19a75b15534e45e6b Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Tue, 7 Aug 2018 10:10:05 -0500 Subject: [PATCH 07/29] rustdoc: collect trait impls as an early pass --- src/librustdoc/clean/inline.rs | 86 +++-------------- src/librustdoc/core.rs | 4 +- src/librustdoc/passes/collect_trait_impls.rs | 99 ++++++++++++++++++++ src/librustdoc/passes/mod.rs | 6 ++ src/librustdoc/visit_ast.rs | 6 +- src/test/rustdoc/traits-in-bodies.rs | 18 +++- 6 files changed, 137 insertions(+), 82 deletions(-) create mode 100644 src/librustdoc/passes/collect_trait_impls.rs diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 75d7488d26a75..f9c631fcfcdb6 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -290,78 +290,12 @@ pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec = auto_impls.into_iter() - .chain(blanket_impls.into_iter()) - .filter(|i| renderinfo.inlined.insert(i.def_id)) - .collect(); - - impls.extend(new_impls); - } - } - impls } pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { if !cx.renderinfo.borrow_mut().inlined.insert(did) { + debug!("already inlined, bailing: {:?}", did); return } @@ -371,9 +305,12 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { // Only inline impl if the implemented trait is // reachable in rustdoc generated documentation - if let Some(traitref) = associated_trait { - if !cx.access_levels.borrow().is_doc_reachable(traitref.def_id) { - return + if !did.is_local() { + if let Some(traitref) = associated_trait { + if !cx.access_levels.borrow().is_doc_reachable(traitref.def_id) { + debug!("trait {:?} not reachable, bailing: {:?}", traitref.def_id, did); + return + } } } @@ -381,9 +318,12 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { // Only inline impl if the implementing type is // reachable in rustdoc generated documentation - if let Some(did) = for_.def_id() { - if !cx.access_levels.borrow().is_doc_reachable(did) { - return + if !did.is_local() { + if let Some(did) = for_.def_id() { + if !cx.access_levels.borrow().is_doc_reachable(did) { + debug!("impl type {:?} not accessible, bailing", did); + return + } } } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index a312913a69c17..623ff4c46e9fa 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -37,7 +37,7 @@ use syntax_pos::DUMMY_SP; use errors; use errors::emitter::{Emitter, EmitterWriter}; -use std::cell::{RefCell, Cell}; +use std::cell::RefCell; use std::mem; use rustc_data_structures::sync::{self, Lrc}; use std::rc::Rc; @@ -60,7 +60,6 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { /// The stack of module NodeIds up till this point pub crate_name: Option, pub cstore: Rc, - pub populated_all_crate_impls: Cell, // Note that external items for which `doc(hidden)` applies to are shown as // non-reachable while local items aren't. This is because we're reusing // the access levels from crateanalysis. @@ -511,7 +510,6 @@ pub fn run_core(search_paths: SearchPaths, resolver: &resolver, crate_name, cstore: cstore.clone(), - populated_all_crate_impls: Cell::new(false), access_levels: RefCell::new(access_levels), external_traits: Default::default(), active_extern_traits: Default::default(), diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs new file mode 100644 index 0000000000000..0be5ab07dea76 --- /dev/null +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -0,0 +1,99 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use clean::*; + +use super::Pass; +use core::DocContext; + +pub const COLLECT_TRAIT_IMPLS: Pass = + Pass::early("collect-trait-impls", collect_trait_impls, + "retrieves trait impls for items in the crate"); + +pub fn collect_trait_impls(mut krate: Crate, cx: &DocContext) -> Crate { + if let Some(ref mut it) = krate.module { + if let ModuleItem(Module { ref mut items, .. }) = it.inner { + for &cnum in cx.tcx.crates().iter() { + for &did in cx.tcx.all_trait_implementations(cnum).iter() { + inline::build_impl(cx, did, items); + } + } + + // `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations` + // doesn't work with it anyway, so pull them from the HIR map instead + for &trait_did in cx.all_traits.iter() { + for &impl_node in cx.tcx.hir.trait_impls(trait_did) { + let impl_did = cx.tcx.hir.local_def_id(impl_node); + inline::build_impl(cx, impl_did, items); + } + } + + // Also try to inline primitive impls from other crates. + let lang_items = cx.tcx.lang_items(); + let primitive_impls = [ + lang_items.isize_impl(), + lang_items.i8_impl(), + lang_items.i16_impl(), + lang_items.i32_impl(), + lang_items.i64_impl(), + lang_items.i128_impl(), + lang_items.usize_impl(), + lang_items.u8_impl(), + lang_items.u16_impl(), + lang_items.u32_impl(), + lang_items.u64_impl(), + lang_items.u128_impl(), + lang_items.f32_impl(), + lang_items.f64_impl(), + lang_items.f32_runtime_impl(), + lang_items.f64_runtime_impl(), + lang_items.char_impl(), + lang_items.str_impl(), + lang_items.slice_impl(), + lang_items.slice_u8_impl(), + lang_items.str_alloc_impl(), + lang_items.slice_alloc_impl(), + lang_items.slice_u8_alloc_impl(), + lang_items.const_ptr_impl(), + lang_items.mut_ptr_impl(), + ]; + + for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) { + if !def_id.is_local() { + inline::build_impl(cx, def_id, items); + + let auto_impls = get_auto_traits_with_def_id(cx, def_id); + let blanket_impls = get_blanket_impls_with_def_id(cx, def_id); + let mut renderinfo = cx.renderinfo.borrow_mut(); + + let new_impls: Vec = auto_impls.into_iter() + .chain(blanket_impls.into_iter()) + .filter(|i| renderinfo.inlined.insert(i.def_id)) + .collect(); + + items.extend(new_impls); + } + } + } else { + panic!("collect-trait-impls can't run"); + } + } else { + panic!("collect-trait-impls can't run"); + } + + // pulling in the impls puts their trait info into the DocContext, but that's already been + // drained by now, so stuff that info into the Crate so the rendering can pick it up + let mut external_traits = cx.external_traits.borrow_mut(); + for (did, trait_) in external_traits.drain() { + krate.external_traits.entry(did).or_insert(trait_); + } + + krate +} diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 16251877bb106..09281aa7cfaf4 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -43,6 +43,9 @@ pub use self::propagate_doc_cfg::PROPAGATE_DOC_CFG; mod collect_intra_doc_links; pub use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS; +mod collect_trait_impls; +pub use self::collect_trait_impls::COLLECT_TRAIT_IMPLS; + /// Represents a single pass. #[derive(Copy, Clone)] pub enum Pass { @@ -132,10 +135,12 @@ pub const PASSES: &'static [Pass] = &[ STRIP_PRIV_IMPORTS, PROPAGATE_DOC_CFG, COLLECT_INTRA_DOC_LINKS, + COLLECT_TRAIT_IMPLS, ]; /// The list of passes run by default. pub const DEFAULT_PASSES: &'static [&'static str] = &[ + "collect-trait-impls", "strip-hidden", "strip-private", "collect-intra-doc-links", @@ -146,6 +151,7 @@ pub const DEFAULT_PASSES: &'static [&'static str] = &[ /// The list of default passes run with `--document-private-items` is passed to rustdoc. pub const DEFAULT_PRIVATE_PASSES: &'static [&'static str] = &[ + "collect-trait-impls", "strip-priv-imports", "collect-intra-doc-links", "collapse-docs", diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 451e24d6c0dc9..ce438cd99a4b6 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -510,9 +510,9 @@ impl<'a, 'tcx, 'rcx, 'cstore> RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> { ref tr, ref ty, ref item_ids) => { - // Don't duplicate impls when inlining, we'll pick them up - // regardless of where they're located. - if !self.inlining { + // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick + // them up regardless of where they're located. + if !self.inlining && tr.is_none() { let items = item_ids.iter() .map(|ii| self.cx.tcx.hir.impl_item(ii.id).clone()) .collect(); diff --git a/src/test/rustdoc/traits-in-bodies.rs b/src/test/rustdoc/traits-in-bodies.rs index 3acf4af5fd247..26ed544412275 100644 --- a/src/test/rustdoc/traits-in-bodies.rs +++ b/src/test/rustdoc/traits-in-bodies.rs @@ -11,11 +11,10 @@ //prior to fixing `everybody_loops` to preserve items, rustdoc would crash on this file, as it //didn't see that `SomeStruct` implemented `Clone` -//FIXME(misdreavus): whenever rustdoc shows traits impl'd inside bodies, make sure this test -//reflects that - pub struct Bounded(T); +// @has traits_in_bodies/struct.SomeStruct.html +// @has - '//code' 'impl Clone for SomeStruct' pub struct SomeStruct; fn asdf() -> Bounded { @@ -27,3 +26,16 @@ fn asdf() -> Bounded { Bounded(SomeStruct) } + +// @has traits_in_bodies/struct.Point.html +// @has - '//code' 'impl Copy for Point' +#[derive(Clone)] +pub struct Point { + x: i32, + y: i32, +} + +const _FOO: () = { + impl Copy for Point {} + () +}; From f1566f7b0ff6943c329d06e9582d6344d8e21da5 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Tue, 7 Aug 2018 11:30:57 -0500 Subject: [PATCH 08/29] print local inlined consts via the HIR map --- src/librustdoc/clean/inline.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index f9c631fcfcdb6..2c3714ee0c2ab 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -404,7 +404,11 @@ fn build_module(cx: &DocContext, did: DefId, visited: &mut FxHashSet) -> } pub fn print_inlined_const(cx: &DocContext, did: DefId) -> String { - cx.tcx.rendered_const(did) + if let Some(node_id) = cx.tcx.hir.as_local_node_id(did) { + cx.tcx.hir.node_to_pretty_string(node_id) + } else { + cx.tcx.rendered_const(did) + } } fn build_const(cx: &DocContext, did: DefId) -> clean::Constant { From c66547855806be71eba875af27aac1218b0ad90d Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Tue, 7 Aug 2018 15:17:27 -0500 Subject: [PATCH 09/29] ignore rustdoc/doc-proc-macro on stage1 --- src/test/rustdoc/doc-proc-macro.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/rustdoc/doc-proc-macro.rs b/src/test/rustdoc/doc-proc-macro.rs index b3b403a7b86aa..01a4a410b03fb 100644 --- a/src/test/rustdoc/doc-proc-macro.rs +++ b/src/test/rustdoc/doc-proc-macro.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-stage1 + // Issue #52129: ICE when trying to document the `quote` proc-macro from proc_macro // As of this writing, we don't currently attempt to document proc-macros. However, we shouldn't From ce5e4e57c754ddd9d11af0b8a245ef0b34cbaf1a Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Fri, 10 Aug 2018 17:24:40 -0500 Subject: [PATCH 10/29] only move access_levels/external_traits after early passes --- src/librustdoc/clean/mod.rs | 7 ++----- src/librustdoc/core.rs | 4 ++++ src/librustdoc/passes/collect_trait_impls.rs | 7 ------- src/librustdoc/passes/strip_private.rs | 4 ++-- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index da18e3e6b91b3..68d812762a96c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -209,9 +209,6 @@ impl<'a, 'tcx, 'rcx, 'cstore> Clean for visit_ast::RustdocVisitor<'a, 'tc })); } - let mut access_levels = cx.access_levels.borrow_mut(); - let mut external_traits = cx.external_traits.borrow_mut(); - Crate { name, version: None, @@ -219,8 +216,8 @@ impl<'a, 'tcx, 'rcx, 'cstore> Clean for visit_ast::RustdocVisitor<'a, 'tc module: Some(module), externs, primitives, - access_levels: Arc::new(mem::replace(&mut access_levels, Default::default())), - external_traits: mem::replace(&mut external_traits, Default::default()), + access_levels: Arc::new(Default::default()), + external_traits: Default::default(), masked_crates, } } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 623ff4c46e9fa..3a942aa6c8db1 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -41,6 +41,7 @@ use std::cell::RefCell; use std::mem; use rustc_data_structures::sync::{self, Lrc}; use std::rc::Rc; +use std::sync::Arc; use std::path::PathBuf; use visit_ast::RustdocVisitor; @@ -596,6 +597,9 @@ pub fn run_core(search_paths: SearchPaths, ctxt.sess().abort_if_errors(); + krate.access_levels = Arc::new(ctxt.access_levels.into_inner()); + krate.external_traits = ctxt.external_traits.into_inner(); + (krate, ctxt.renderinfo.into_inner(), passes) }), &sess) }) diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 0be5ab07dea76..0ee1657f21516 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -88,12 +88,5 @@ pub fn collect_trait_impls(mut krate: Crate, cx: &DocContext) -> Crate { panic!("collect-trait-impls can't run"); } - // pulling in the impls puts their trait info into the DocContext, but that's already been - // drained by now, so stuff that info into the Crate so the rendering can pick it up - let mut external_traits = cx.external_traits.borrow_mut(); - for (did, trait_) in external_traits.drain() { - krate.external_traits.entry(did).or_insert(trait_); - } - krate } diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs index 3b17a768ffdee..4fa5943faca07 100644 --- a/src/librustdoc/passes/strip_private.rs +++ b/src/librustdoc/passes/strip_private.rs @@ -22,10 +22,10 @@ pub const STRIP_PRIVATE: Pass = /// Strip private items from the point of view of a crate or externally from a /// crate, specified by the `xcrate` flag. -pub fn strip_private(mut krate: clean::Crate, _: &DocContext) -> clean::Crate { +pub fn strip_private(mut krate: clean::Crate, cx: &DocContext) -> clean::Crate { // This stripper collects all *retained* nodes. let mut retained = DefIdSet(); - let access_levels = krate.access_levels.clone(); + let access_levels = cx.access_levels.borrow().clone(); // strip all private items { From 033fd7a5e9bbdee292502a55083cfd7ac8b07c38 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Tue, 14 Aug 2018 12:08:12 -0500 Subject: [PATCH 11/29] don't record an external trait if it's not external --- src/librustdoc/clean/inline.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 2c3714ee0c2ab..20c5a9febed9e 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -519,6 +519,10 @@ fn separate_supertrait_bounds(mut g: clean::Generics) } pub fn record_extern_trait(cx: &DocContext, did: DefId) { + if did.is_local() { + return; + } + if cx.external_traits.borrow().contains_key(&did) || cx.active_extern_traits.borrow().contains(&did) { From dc3899ecf33f19db9a60e585c54daecac6a078ca Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Tue, 14 Aug 2018 14:41:07 -0500 Subject: [PATCH 12/29] undo some tweaks to build_impl --- src/librustdoc/clean/inline.rs | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 20c5a9febed9e..1f5174f84359a 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -295,7 +295,6 @@ pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec) { if !cx.renderinfo.borrow_mut().inlined.insert(did) { - debug!("already inlined, bailing: {:?}", did); return } @@ -305,12 +304,9 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { // Only inline impl if the implemented trait is // reachable in rustdoc generated documentation - if !did.is_local() { - if let Some(traitref) = associated_trait { - if !cx.access_levels.borrow().is_doc_reachable(traitref.def_id) { - debug!("trait {:?} not reachable, bailing: {:?}", traitref.def_id, did); - return - } + if let Some(traitref) = associated_trait { + if !cx.access_levels.borrow().is_doc_reachable(traitref.def_id) { + return } } @@ -318,12 +314,9 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { // Only inline impl if the implementing type is // reachable in rustdoc generated documentation - if !did.is_local() { - if let Some(did) = for_.def_id() { - if !cx.access_levels.borrow().is_doc_reachable(did) { - debug!("impl type {:?} not accessible, bailing", did); - return - } + if let Some(did) = for_.def_id() { + if !cx.access_levels.borrow().is_doc_reachable(did) { + return } } @@ -356,6 +349,8 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { .collect() }).unwrap_or(FxHashSet()); + debug!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id()); + ret.push(clean::Item { inner: clean::ImplItem(clean::Impl { unsafety: hir::Unsafety::Normal, From 825126a599d5a42aa1fe6d73a66883a202492593 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Tue, 14 Aug 2018 14:43:03 -0500 Subject: [PATCH 13/29] add a bunch of debug prints --- src/librustdoc/clean/inline.rs | 1 + src/librustdoc/html/render.rs | 4 ++++ src/librustdoc/passes/mod.rs | 7 +++++++ 3 files changed, 12 insertions(+) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 1f5174f84359a..4d47ec8c84aed 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -526,6 +526,7 @@ pub fn record_extern_trait(cx: &DocContext, did: DefId) { cx.active_extern_traits.borrow_mut().push(did); + debug!("record_extern_trait: {:?}", did); let trait_ = build_external_trait(cx, did); cx.external_traits.borrow_mut().insert(did, trait_); diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 368c056f021c1..9d6ea70ed6563 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1223,6 +1223,10 @@ impl<'a> SourceCollector<'a> { impl DocFolder for Cache { fn fold_item(&mut self, item: clean::Item) -> Option { + if item.def_id.is_local() { + debug!("folding item \"{:?}\", a {}", item.name, item.type_()); + } + // If this is a stripped module, // we don't want it or its children in the search index. let orig_stripped_mod = match item.inner { diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 09281aa7cfaf4..95c613cc14d11 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -195,6 +195,7 @@ impl<'a> fold::DocFolder for Stripper<'a> { // We need to recurse into stripped modules to strip things // like impl methods but when doing so we must not add any // items to the `retained` set. + debug!("Stripper: recursing into stripped {} {:?}", i.type_(), i.name); let old = mem::replace(&mut self.update_retained, false); let ret = self.fold_item_recur(i); self.update_retained = old; @@ -218,6 +219,7 @@ impl<'a> fold::DocFolder for Stripper<'a> { | clean::ForeignTypeItem => { if i.def_id.is_local() { if !self.access_levels.is_exported(i.def_id) { + debug!("Stripper: stripping {} {:?}", i.type_(), i.name); return None; } } @@ -231,6 +233,7 @@ impl<'a> fold::DocFolder for Stripper<'a> { clean::ModuleItem(..) => { if i.def_id.is_local() && i.visibility != Some(clean::Public) { + debug!("Stripper: stripping module {:?}", i.name); let old = mem::replace(&mut self.update_retained, false); let ret = StripItem(self.fold_item_recur(i).unwrap()).strip(); self.update_retained = old; @@ -302,11 +305,13 @@ impl<'a> fold::DocFolder for ImplStripper<'a> { } if let Some(did) = imp.for_.def_id() { if did.is_local() && !imp.for_.is_generic() && !self.retained.contains(&did) { + debug!("ImplStripper: impl item for stripped type; removing"); return None; } } if let Some(did) = imp.trait_.def_id() { if did.is_local() && !self.retained.contains(&did) { + debug!("ImplStripper: impl item for stripped trait; removing"); return None; } } @@ -314,6 +319,8 @@ impl<'a> fold::DocFolder for ImplStripper<'a> { for typaram in generics { if let Some(did) = typaram.def_id() { if did.is_local() && !self.retained.contains(&did) { + debug!("ImplStripper: stripped item in trait's generics; \ + removing impl"); return None; } } From 5254548e597ecc8d34e379dbe59206fa61d66e47 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Tue, 14 Aug 2018 14:44:45 -0500 Subject: [PATCH 14/29] handle local names when registering FQNs --- src/librustdoc/clean/inline.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 4d47ec8c84aed..17f1a8120abf1 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -158,12 +158,11 @@ pub fn load_attrs(cx: &DocContext, did: DefId) -> clean::Attributes { /// These names are used later on by HTML rendering to generate things like /// source links back to the original item. pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) { + let mut crate_name = cx.tcx.crate_name(did.krate).to_string(); if did.is_local() { - debug!("record_extern_fqn(did={:?}, kind+{:?}): def_id is local, aborting", did, kind); - return; + crate_name = cx.crate_name.clone().unwrap_or(crate_name); } - let crate_name = cx.tcx.crate_name(did.krate).to_string(); let relative = cx.tcx.def_path(did).data.into_iter().filter_map(|elem| { // extern blocks have an empty name let s = elem.data.to_string(); @@ -178,7 +177,12 @@ pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) { } else { once(crate_name).chain(relative).collect() }; - cx.renderinfo.borrow_mut().external_paths.insert(did, (fqn, kind)); + + if did.is_local() { + cx.renderinfo.borrow_mut().exact_paths.insert(did, fqn); + } else { + cx.renderinfo.borrow_mut().external_paths.insert(did, (fqn, kind)); + } } pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait { From ca612863cd2cf6d11b6daf39188c97375767dfba Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Tue, 14 Aug 2018 15:19:15 -0500 Subject: [PATCH 15/29] pull local types from the HIR instead of tcx --- src/librustdoc/clean/inline.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 17f1a8120abf1..b773a59b16b1e 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -314,7 +314,16 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { } } - let for_ = tcx.type_of(did).clean(cx); + let for_ = if let Some(nodeid) = tcx.hir.as_local_node_id(did) { + match tcx.hir.expect_item(nodeid).node { + hir::ItemKind::Impl(.., ref t, _) => { + t.clean(cx) + } + _ => panic!("did given to build_impl was not an impl"), + } + } else { + tcx.type_of(did).clean(cx) + }; // Only inline impl if the implementing type is // reachable in rustdoc generated documentation From eaacf59681c85ddf6c60a14df9752db77ce907c0 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Tue, 14 Aug 2018 16:42:34 -0500 Subject: [PATCH 16/29] collect impl items from the HIR if available --- src/librustdoc/clean/inline.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index b773a59b16b1e..89516a1a7dc0f 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -334,13 +334,24 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { } let predicates = tcx.predicates_of(did); - let trait_items = tcx.associated_items(did).filter_map(|item| { - if associated_trait.is_some() || item.vis == ty::Visibility::Public { - Some(item.clean(cx)) - } else { - None + let trait_items = if let Some(nodeid) = tcx.hir.as_local_node_id(did) { + match tcx.hir.expect_item(nodeid).node { + hir::ItemKind::Impl(.., ref item_ids) => { + item_ids.iter() + .map(|ii| tcx.hir.impl_item(ii.id).clean(cx)) + .collect::>() + } + _ => panic!("did given to build_impl was not an impl"), } - }).collect::>(); + } else { + tcx.associated_items(did).filter_map(|item| { + if associated_trait.is_some() || item.vis == ty::Visibility::Public { + Some(item.clean(cx)) + } else { + None + } + }).collect::>() + }; let polarity = tcx.impl_polarity(did); let trait_ = associated_trait.clean(cx).map(|bound| { match bound { From 17d48343f5fb91f630c71a3bdf451e70cd0289ce Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Tue, 14 Aug 2018 17:38:41 -0500 Subject: [PATCH 17/29] pull impl generics from HIR if available --- src/librustdoc/clean/inline.rs | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 89516a1a7dc0f..7e8d32f991ce7 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -334,23 +334,29 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { } let predicates = tcx.predicates_of(did); - let trait_items = if let Some(nodeid) = tcx.hir.as_local_node_id(did) { + let (trait_items, generics) = if let Some(nodeid) = tcx.hir.as_local_node_id(did) { match tcx.hir.expect_item(nodeid).node { - hir::ItemKind::Impl(.., ref item_ids) => { - item_ids.iter() - .map(|ii| tcx.hir.impl_item(ii.id).clean(cx)) - .collect::>() + hir::ItemKind::Impl(.., ref gen, _, _, ref item_ids) => { + ( + item_ids.iter() + .map(|ii| tcx.hir.impl_item(ii.id).clean(cx)) + .collect::>(), + gen.clean(cx), + ) } _ => panic!("did given to build_impl was not an impl"), } } else { - tcx.associated_items(did).filter_map(|item| { - if associated_trait.is_some() || item.vis == ty::Visibility::Public { - Some(item.clean(cx)) - } else { - None - } - }).collect::>() + ( + tcx.associated_items(did).filter_map(|item| { + if associated_trait.is_some() || item.vis == ty::Visibility::Public { + Some(item.clean(cx)) + } else { + None + } + }).collect::>(), + (tcx.generics_of(did), &predicates).clean(cx), + ) }; let polarity = tcx.impl_polarity(did); let trait_ = associated_trait.clean(cx).map(|bound| { @@ -378,7 +384,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { ret.push(clean::Item { inner: clean::ImplItem(clean::Impl { unsafety: hir::Unsafety::Normal, - generics: (tcx.generics_of(did), &predicates).clean(cx), + generics, provided_trait_methods: provided, trait_, for_, From 15dba89730c1826c2a6e602ffd24e45939584085 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Wed, 15 Aug 2018 10:41:15 -0500 Subject: [PATCH 18/29] swap external_traits into the crate before running strip_hidden --- src/librustdoc/passes/strip_hidden.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index cc0b6fb6d6705..eab4022a3389f 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -24,9 +24,13 @@ pub const STRIP_HIDDEN: Pass = "strips all doc(hidden) items from the output"); /// Strip items marked `#[doc(hidden)]` -pub fn strip_hidden(krate: clean::Crate, _: &DocContext) -> clean::Crate { +pub fn strip_hidden(mut krate: clean::Crate, cx: &DocContext) -> clean::Crate { let mut retained = DefIdSet(); + // as an early pass, the external traits haven't been swapped in, so we need to do that ahead + // of time + mem::swap(&mut krate.external_traits, &mut cx.external_traits.borrow_mut()); + // strip all #[doc(hidden)] items let krate = { let mut stripper = Stripper{ retained: &mut retained, update_retained: true }; @@ -35,7 +39,10 @@ pub fn strip_hidden(krate: clean::Crate, _: &DocContext) -> clean::Crate { // strip all impls referencing stripped items let mut stripper = ImplStripper { retained: &retained }; - stripper.fold_crate(krate) + let mut krate = stripper.fold_crate(krate); + mem::swap(&mut krate.external_traits, &mut cx.external_traits.borrow_mut()); + + krate } struct Stripper<'a> { @@ -46,7 +53,7 @@ struct Stripper<'a> { impl<'a> fold::DocFolder for Stripper<'a> { fn fold_item(&mut self, i: Item) -> Option { if i.attrs.lists("doc").has_word("hidden") { - debug!("found one in strip_hidden; removing"); + debug!("strip_hidden: stripping {} {:?}", i.type_(), i.name); // use a dedicated hidden item for given item type if any match i.inner { clean::StructFieldItem(..) | clean::ModuleItem(..) => { From c39de06fe10461a369eabeff51784a7d3b82ccb2 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Tue, 21 Aug 2018 16:22:20 -0500 Subject: [PATCH 19/29] don't check visibility when inlining local impls those get handled properly in strip-hidden anyway --- src/librustdoc/clean/inline.rs | 16 ++++++++----- src/test/rustdoc/inline_local/trait-vis.rs | 28 ++++++++++++++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 src/test/rustdoc/inline_local/trait-vis.rs diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 7e8d32f991ce7..d248bb58fc599 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -308,9 +308,11 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { // Only inline impl if the implemented trait is // reachable in rustdoc generated documentation - if let Some(traitref) = associated_trait { - if !cx.access_levels.borrow().is_doc_reachable(traitref.def_id) { - return + if !did.is_local() { + if let Some(traitref) = associated_trait { + if !cx.access_levels.borrow().is_doc_reachable(traitref.def_id) { + return + } } } @@ -327,9 +329,11 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { // Only inline impl if the implementing type is // reachable in rustdoc generated documentation - if let Some(did) = for_.def_id() { - if !cx.access_levels.borrow().is_doc_reachable(did) { - return + if !did.is_local() { + if let Some(did) = for_.def_id() { + if !cx.access_levels.borrow().is_doc_reachable(did) { + return + } } } diff --git a/src/test/rustdoc/inline_local/trait-vis.rs b/src/test/rustdoc/inline_local/trait-vis.rs new file mode 100644 index 0000000000000..1035e357ef649 --- /dev/null +++ b/src/test/rustdoc/inline_local/trait-vis.rs @@ -0,0 +1,28 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub trait ThisTrait {} + +mod asdf { + use ThisTrait; + + pub struct SomeStruct; + + impl ThisTrait for SomeStruct {} + + trait PrivateTrait {} + + impl PrivateTrait for SomeStruct {} +} + +// @has trait_vis/struct.SomeStruct.html +// @has - '//code' 'impl ThisTrait for SomeStruct' +// !@has - '//code' 'impl PrivateTrait for SomeStruct' +pub use asdf::SomeStruct; From 810332f3673f362f97e3a911f3fec9e49eb8383a Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Mon, 27 Aug 2018 12:42:43 -0500 Subject: [PATCH 20/29] add more tests for traits-in-non-module-scope --- src/librustdoc/passes/mod.rs | 2 +- .../inline_cross/auxiliary/trait-vis.rs | 23 +++++++++++++++++++ src/test/rustdoc/inline_cross/trait-vis.rs | 17 ++++++++++++++ src/test/rustdoc/inline_local/trait-vis.rs | 2 +- src/test/rustdoc/primitive-generic-impl.rs | 3 --- src/test/rustdoc/traits-in-bodies.rs | 21 +++++++++++++++++ 6 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 src/test/rustdoc/inline_cross/auxiliary/trait-vis.rs create mode 100644 src/test/rustdoc/inline_cross/trait-vis.rs diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 95c613cc14d11..24fec62dd573a 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -320,7 +320,7 @@ impl<'a> fold::DocFolder for ImplStripper<'a> { if let Some(did) = typaram.def_id() { if did.is_local() && !self.retained.contains(&did) { debug!("ImplStripper: stripped item in trait's generics; \ - removing impl"); + removing impl"); return None; } } diff --git a/src/test/rustdoc/inline_cross/auxiliary/trait-vis.rs b/src/test/rustdoc/inline_cross/auxiliary/trait-vis.rs new file mode 100644 index 0000000000000..7457a5d4899fe --- /dev/null +++ b/src/test/rustdoc/inline_cross/auxiliary/trait-vis.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "inner"] + +pub struct SomeStruct; + +fn asdf() { + const _FOO: () = { + impl Clone for SomeStruct { + fn clone(&self) -> Self { + SomeStruct + } + } + }; +} diff --git a/src/test/rustdoc/inline_cross/trait-vis.rs b/src/test/rustdoc/inline_cross/trait-vis.rs new file mode 100644 index 0000000000000..5b5410b1da44d --- /dev/null +++ b/src/test/rustdoc/inline_cross/trait-vis.rs @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:trait-vis.rs + +extern crate inner; + +// @has trait_vis/struct.SomeStruct.html +// @has - '//code' 'impl Clone for SomeStruct' +pub use inner::SomeStruct; diff --git a/src/test/rustdoc/inline_local/trait-vis.rs b/src/test/rustdoc/inline_local/trait-vis.rs index 1035e357ef649..73b1cc2ce8f2d 100644 --- a/src/test/rustdoc/inline_local/trait-vis.rs +++ b/src/test/rustdoc/inline_local/trait-vis.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/test/rustdoc/primitive-generic-impl.rs b/src/test/rustdoc/primitive-generic-impl.rs index b4351b8268c8b..a771b1b15ce4d 100644 --- a/src/test/rustdoc/primitive-generic-impl.rs +++ b/src/test/rustdoc/primitive-generic-impl.rs @@ -10,9 +10,6 @@ #![crate_name = "foo"] -// we need to reexport something from libstd so that `all_trait_implementations` is called. -pub use std::string::String; - include!("primitive/primitive-generic-impl.rs"); // @has foo/primitive.i32.html '//h3[@id="impl-ToString"]//code' 'impl ToString for T' diff --git a/src/test/rustdoc/traits-in-bodies.rs b/src/test/rustdoc/traits-in-bodies.rs index 26ed544412275..a1d4019bba2bf 100644 --- a/src/test/rustdoc/traits-in-bodies.rs +++ b/src/test/rustdoc/traits-in-bodies.rs @@ -39,3 +39,24 @@ const _FOO: () = { impl Copy for Point {} () }; + +// @has traits_in_bodies/struct.Inception.html +// @has - '//code' 'impl Clone for Inception' +pub struct Inception; + +static _BAR: usize = { + trait HiddenTrait { + fn hidden_fn(&self) { + for _ in 0..5 { + impl Clone for Inception { + fn clone(&self) -> Self { + // we need to go deeper + Inception + } + } + } + } + } + + 5 +}; From 5fd1d8357ee94bc6b49ec975e1ab4f37ac4b487a Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Tue, 28 Aug 2018 11:33:45 -0500 Subject: [PATCH 21/29] don't index trait impls if the trait isn't also documented --- src/librustdoc/html/render.rs | 34 +++++++++++++++++--- src/librustdoc/lib.rs | 1 + src/test/rustdoc/traits-in-bodies-private.rs | 23 +++++++++++++ 3 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 src/test/rustdoc/traits-in-bodies-private.rs diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 9d6ea70ed6563..d052760724e67 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -337,6 +337,15 @@ pub struct Cache { // and their parent id here and indexes them at the end of crate parsing. orphan_impl_items: Vec<(DefId, clean::Item)>, + // Similarly to `orphan_impl_items`, sometimes trait impls are picked up + // even though the trait itself is not exported. This can happen if a trait + // was defined in function/expression scope, since the impl will be picked + // up by `collect-trait-impls` but the trait won't be scraped out in the HIR + // crawl. In order to prevent crashes when looking for spotlight traits or + // when gathering trait documentation on a type, hold impls here while + // folding and add them to the cache later on if we find the trait. + orphan_trait_impls: Vec<(DefId, FxHashSet, Impl)>, + /// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias, /// we need the alias element to have an array of items. aliases: FxHashMap>, @@ -594,6 +603,7 @@ pub fn run(mut krate: clean::Crate, access_levels: krate.access_levels.clone(), crate_version: krate.version.take(), orphan_impl_items: Vec::new(), + orphan_trait_impls: Vec::new(), traits: mem::replace(&mut krate.external_traits, FxHashMap()), deref_trait_did, deref_mut_trait_did, @@ -636,6 +646,14 @@ pub fn run(mut krate: clean::Crate, cache.stack.push(krate.name.clone()); krate = cache.fold_crate(krate); + for (trait_did, dids, impl_) in cache.orphan_trait_impls.drain(..) { + if cache.traits.contains_key(&trait_did) { + for did in dids { + cache.impls.entry(did).or_insert(vec![]).push(impl_.clone()); + } + } + } + // Build our search index let index = build_index(&krate, &mut cache); @@ -1224,7 +1242,7 @@ impl<'a> SourceCollector<'a> { impl DocFolder for Cache { fn fold_item(&mut self, item: clean::Item) -> Option { if item.def_id.is_local() { - debug!("folding item \"{:?}\", a {}", item.name, item.type_()); + debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.def_id); } // If this is a stripped module, @@ -1455,10 +1473,16 @@ impl DocFolder for Cache { } else { unreachable!() }; - for did in dids { - self.impls.entry(did).or_default().push(Impl { - impl_item: item.clone(), - }); + let impl_item = Impl { + impl_item: item, + }; + if impl_item.trait_did().map_or(true, |d| self.traits.contains_key(&d)) { + for did in dids { + self.impls.entry(did).or_insert(vec![]).push(impl_item.clone()); + } + } else { + let trait_did = impl_item.trait_did().unwrap(); + self.orphan_trait_impls.push((trait_did, dids, impl_item)); } None } else { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 1acae86f0068f..11cf43dad4a92 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -25,6 +25,7 @@ #![feature(ptr_offset_from)] #![feature(crate_visibility_modifier)] #![feature(const_fn)] +#![feature(drain_filter)] #![recursion_limit="256"] diff --git a/src/test/rustdoc/traits-in-bodies-private.rs b/src/test/rustdoc/traits-in-bodies-private.rs new file mode 100644 index 0000000000000..ac3be7e61e9a0 --- /dev/null +++ b/src/test/rustdoc/traits-in-bodies-private.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// when implementing the fix for traits-in-bodies, there was an ICE when documenting private items +// and a trait was defined in non-module scope + +// compile-flags:--document-private-items + +// @has traits_in_bodies_private/struct.SomeStruct.html +// @!has - '//code' 'impl HiddenTrait for SomeStruct' +pub struct SomeStruct; + +fn __implementation_details() { + trait HiddenTrait {} + impl HiddenTrait for SomeStruct {} +} From ce70d912c175520232e26d56b0e3d1ed93f408d2 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Thu, 30 Aug 2018 12:10:15 -0500 Subject: [PATCH 22/29] collect auto-/blanket-impls during collect-trait-impls --- src/librustdoc/clean/inline.rs | 28 +++------ src/librustdoc/clean/mod.rs | 60 +++++++------------- src/librustdoc/passes/collect_trait_impls.rs | 40 ++++++++++++- 3 files changed, 65 insertions(+), 63 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index d248bb58fc599..a91336dced398 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -29,8 +29,6 @@ use clean::{ self, GetDefId, ToSource, - get_auto_traits_with_def_id, - get_blanket_impls_with_def_id, }; use super::Clean; @@ -56,7 +54,7 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa let inner = match def { Def::Trait(did) => { record_extern_fqn(cx, did, clean::TypeKind::Trait); - ret.extend(build_impls(cx, did, false)); + ret.extend(build_impls(cx, did)); clean::TraitItem(build_external_trait(cx, did)) } Def::Fn(did) => { @@ -65,27 +63,27 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa } Def::Struct(did) => { record_extern_fqn(cx, did, clean::TypeKind::Struct); - ret.extend(build_impls(cx, did, true)); + ret.extend(build_impls(cx, did)); clean::StructItem(build_struct(cx, did)) } Def::Union(did) => { record_extern_fqn(cx, did, clean::TypeKind::Union); - ret.extend(build_impls(cx, did, true)); + ret.extend(build_impls(cx, did)); clean::UnionItem(build_union(cx, did)) } Def::TyAlias(did) => { record_extern_fqn(cx, did, clean::TypeKind::Typedef); - ret.extend(build_impls(cx, did, false)); + ret.extend(build_impls(cx, did)); clean::TypedefItem(build_type_alias(cx, did), false) } Def::Enum(did) => { record_extern_fqn(cx, did, clean::TypeKind::Enum); - ret.extend(build_impls(cx, did, true)); + ret.extend(build_impls(cx, did)); clean::EnumItem(build_enum(cx, did)) } Def::ForeignTy(did) => { record_extern_fqn(cx, did, clean::TypeKind::Foreign); - ret.extend(build_impls(cx, did, false)); + ret.extend(build_impls(cx, did)); clean::ForeignTypeItem } // Never inline enum variants but leave them shown as re-exports. @@ -274,7 +272,7 @@ fn build_type_alias(cx: &DocContext, did: DefId) -> clean::Typedef { } } -pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec { +pub fn build_impls(cx: &DocContext, did: DefId) -> Vec { let tcx = cx.tcx; let mut impls = Vec::new(); @@ -282,18 +280,6 @@ pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec = auto_impls.into_iter() - .filter(|i| renderinfo.inlined.insert(i.def_id)).collect(); - - impls.extend(new_impls); - } - impls.extend(get_blanket_impls_with_def_id(cx, did)); - } - impls } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 68d812762a96c..20e1f3f3beae1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -576,9 +576,9 @@ impl Clean for doctree::Module { let mut items: Vec = vec![]; items.extend(self.extern_crates.iter().map(|x| x.clean(cx))); items.extend(self.imports.iter().flat_map(|x| x.clean(cx))); - items.extend(self.structs.iter().flat_map(|x| x.clean(cx))); - items.extend(self.unions.iter().flat_map(|x| x.clean(cx))); - items.extend(self.enums.iter().flat_map(|x| x.clean(cx))); + items.extend(self.structs.iter().map(|x| x.clean(cx))); + items.extend(self.unions.iter().map(|x| x.clean(cx))); + items.extend(self.enums.iter().map(|x| x.clean(cx))); items.extend(self.fns.iter().map(|x| x.clean(cx))); items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx))); items.extend(self.mods.iter().map(|x| x.clean(cx))); @@ -2813,14 +2813,10 @@ pub struct Union { pub fields_stripped: bool, } -impl Clean> for doctree::Struct { - fn clean(&self, cx: &DocContext) -> Vec { - let name = self.name.clean(cx); - let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone()); - ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone())); - - ret.push(Item { - name: Some(name), +impl Clean for doctree::Struct { + fn clean(&self, cx: &DocContext) -> Item { + Item { + name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), source: self.whence.clean(cx), def_id: cx.tcx.hir.local_def_id(self.id), @@ -2833,20 +2829,14 @@ impl Clean> for doctree::Struct { fields: self.fields.clean(cx), fields_stripped: false, }), - }); - - ret + } } } -impl Clean> for doctree::Union { - fn clean(&self, cx: &DocContext) -> Vec { - let name = self.name.clean(cx); - let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone()); - ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone())); - - ret.push(Item { - name: Some(name), +impl Clean for doctree::Union { + fn clean(&self, cx: &DocContext) -> Item { + Item { + name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), source: self.whence.clean(cx), def_id: cx.tcx.hir.local_def_id(self.id), @@ -2859,9 +2849,7 @@ impl Clean> for doctree::Union { fields: self.fields.clean(cx), fields_stripped: false, }), - }); - - ret + } } } @@ -2892,14 +2880,10 @@ pub struct Enum { pub variants_stripped: bool, } -impl Clean> for doctree::Enum { - fn clean(&self, cx: &DocContext) -> Vec { - let name = self.name.clean(cx); - let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone()); - ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone())); - - ret.push(Item { - name: Some(name), +impl Clean for doctree::Enum { + fn clean(&self, cx: &DocContext) -> Item { + Item { + name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), source: self.whence.clean(cx), def_id: cx.tcx.hir.local_def_id(self.id), @@ -2911,9 +2895,7 @@ impl Clean> for doctree::Enum { generics: self.generics.clean(cx), variants_stripped: false, }), - }); - - ret + } } } @@ -3442,11 +3424,7 @@ fn build_deref_target_impls(cx: &DocContext, let primitive = match *target { ResolvedPath { did, .. } if did.is_local() => continue, ResolvedPath { did, .. } => { - // We set the last parameter to false to avoid looking for auto-impls for traits - // and therefore avoid an ICE. - // The reason behind this is that auto-traits don't propagate through Deref so - // we're not supposed to synthesise impls for them. - ret.extend(inline::build_impls(cx, did, false)); + ret.extend(inline::build_impls(cx, did)); continue } _ => match target.primitive_type() { diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 0ee1657f21516..56940483d7be2 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -12,14 +12,20 @@ use clean::*; use super::Pass; use core::DocContext; +use fold::DocFolder; pub const COLLECT_TRAIT_IMPLS: Pass = Pass::early("collect-trait-impls", collect_trait_impls, "retrieves trait impls for items in the crate"); -pub fn collect_trait_impls(mut krate: Crate, cx: &DocContext) -> Crate { +pub fn collect_trait_impls(krate: Crate, cx: &DocContext) -> Crate { + let mut synth = SyntheticImplCollector::new(cx); + let mut krate = synth.fold_crate(krate); + if let Some(ref mut it) = krate.module { if let ModuleItem(Module { ref mut items, .. }) = it.inner { + items.extend(synth.impls); + for &cnum in cx.tcx.crates().iter() { for &did in cx.tcx.all_trait_implementations(cnum).iter() { inline::build_impl(cx, did, items); @@ -90,3 +96,35 @@ pub fn collect_trait_impls(mut krate: Crate, cx: &DocContext) -> Crate { krate } + +struct SyntheticImplCollector<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { + cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>, + impls: Vec, +} + +impl<'a, 'tcx, 'rcx, 'cstore> SyntheticImplCollector<'a, 'tcx, 'rcx, 'cstore> { + fn new(cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>) -> Self { + SyntheticImplCollector { + cx, + impls: Vec::new(), + } + } +} + +impl<'a, 'tcx, 'rcx, 'cstore> DocFolder for SyntheticImplCollector<'a, 'tcx, 'rcx, 'cstore> { + fn fold_item(&mut self, i: Item) -> Option { + if i.is_struct() || i.is_enum() || i.is_union() { + if let (Some(node_id), Some(name)) = + (self.cx.tcx.hir.as_local_node_id(i.def_id), i.name.clone()) + { + self.impls.extend(get_auto_traits_with_node_id(self.cx, node_id, name.clone())); + self.impls.extend(get_blanket_impls_with_node_id(self.cx, node_id, name)); + } else { + self.impls.extend(get_auto_traits_with_def_id(self.cx, i.def_id)); + self.impls.extend(get_blanket_impls_with_def_id(self.cx, i.def_id)); + } + } + + self.fold_item_recur(i) + } +} From 9e75db4da0af7347e36f892e706574d9d1a6b52f Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Thu, 30 Aug 2018 16:46:10 -0500 Subject: [PATCH 23/29] refactor: move `access_levels` into RenderInfo --- src/librustdoc/clean/blanket_impl.rs | 2 +- src/librustdoc/clean/inline.rs | 4 ++-- src/librustdoc/clean/mod.rs | 5 +---- src/librustdoc/core.rs | 10 ++++------ src/librustdoc/html/render.rs | 6 ++++-- src/librustdoc/passes/strip_private.rs | 2 +- src/librustdoc/visit_ast.rs | 7 +++++-- src/librustdoc/visit_lib.rs | 2 +- 8 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index e7e371cd56785..34c4c70159f3a 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -69,7 +69,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { let real_name = name.clone().map(|name| Ident::from_str(&name)); let param_env = self.cx.tcx.param_env(def_id); for &trait_def_id in self.cx.all_traits.iter() { - if !self.cx.access_levels.borrow().is_doc_reachable(trait_def_id) || + if !self.cx.renderinfo.borrow().access_levels.is_doc_reachable(trait_def_id) || self.cx.generated_synthetics .borrow_mut() .get(&(def_id, trait_def_id)) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index a91336dced398..a29c62f474fa0 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -296,7 +296,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { // reachable in rustdoc generated documentation if !did.is_local() { if let Some(traitref) = associated_trait { - if !cx.access_levels.borrow().is_doc_reachable(traitref.def_id) { + if !cx.renderinfo.borrow().access_levels.is_doc_reachable(traitref.def_id) { return } } @@ -317,7 +317,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { // reachable in rustdoc generated documentation if !did.is_local() { if let Some(did) = for_.def_id() { - if !cx.access_levels.borrow().is_doc_reachable(did) { + if !cx.renderinfo.borrow().access_levels.is_doc_reachable(did) { return } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 20e1f3f3beae1..8ec4b7bcee8ee 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -28,7 +28,6 @@ use syntax::symbol::InternedString; use syntax_pos::{self, DUMMY_SP, Pos, FileName}; use rustc::mir::interpret::ConstValue; -use rustc::middle::privacy::AccessLevels; use rustc::middle::resolve_lifetime as rl; use rustc::ty::fold::TypeFolder; use rustc::middle::lang_items; @@ -135,7 +134,6 @@ pub struct Crate { pub module: Option, pub externs: Vec<(CrateNum, ExternalCrate)>, pub primitives: Vec<(DefId, PrimitiveType, Attributes)>, - pub access_levels: Arc>, // These are later on moved into `CACHEKEY`, leaving the map empty. // Only here so that they can be filtered through the rustdoc passes. pub external_traits: FxHashMap, @@ -216,7 +214,6 @@ impl<'a, 'tcx, 'rcx, 'cstore> Clean for visit_ast::RustdocVisitor<'a, 'tc module: Some(module), externs, primitives, - access_levels: Arc::new(Default::default()), external_traits: Default::default(), masked_crates, } @@ -2433,7 +2430,7 @@ impl Clean for hir::Ty { if let Def::TyAlias(def_id) = path.def { // Substitute private type aliases if let Some(node_id) = cx.tcx.hir.as_local_node_id(def_id) { - if !cx.access_levels.borrow().is_exported(def_id) { + if !cx.renderinfo.borrow().access_levels.is_exported(def_id) { alias = Some(&cx.tcx.hir.expect_item(node_id).node); } } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 3a942aa6c8db1..08142a77471d7 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -41,7 +41,6 @@ use std::cell::RefCell; use std::mem; use rustc_data_structures::sync::{self, Lrc}; use std::rc::Rc; -use std::sync::Arc; use std::path::PathBuf; use visit_ast::RustdocVisitor; @@ -64,8 +63,6 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { // Note that external items for which `doc(hidden)` applies to are shown as // non-reachable while local items aren't. This is because we're reusing // the access levels from crateanalysis. - /// Later on moved into `clean::Crate` - pub access_levels: RefCell>, /// Later on moved into `html::render::CACHE_KEY` pub renderinfo: RefCell, /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY` @@ -506,15 +503,17 @@ pub fn run_core(search_paths: SearchPaths, clean::path_to_def(&tcx, &["core", "marker", "Send"]) }; + let mut renderinfo = RenderInfo::default(); + renderinfo.access_levels = access_levels; + let ctxt = DocContext { tcx, resolver: &resolver, crate_name, cstore: cstore.clone(), - access_levels: RefCell::new(access_levels), external_traits: Default::default(), active_extern_traits: Default::default(), - renderinfo: Default::default(), + renderinfo: RefCell::new(renderinfo), ty_substs: Default::default(), lt_substs: Default::default(), impl_trait_bounds: Default::default(), @@ -597,7 +596,6 @@ pub fn run_core(search_paths: SearchPaths, ctxt.sess().abort_if_errors(); - krate.access_levels = Arc::new(ctxt.access_levels.into_inner()); krate.external_traits = ctxt.external_traits.into_inner(); (krate, ctxt.renderinfo.into_inner(), passes) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index d052760724e67..f188fccdb3cbe 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -313,7 +313,7 @@ pub struct Cache { // Note that external items for which `doc(hidden)` applies to are shown as // non-reachable while local items aren't. This is because we're reusing // the access levels from crateanalysis. - pub access_levels: Arc>, + pub access_levels: AccessLevels, /// The version of the crate being documented, if given from the `--crate-version` flag. pub crate_version: Option, @@ -359,6 +359,7 @@ pub struct RenderInfo { pub external_paths: ::core::ExternalPaths, pub external_typarams: FxHashMap, pub exact_paths: FxHashMap>, + pub access_levels: AccessLevels, pub deref_trait_did: Option, pub deref_mut_trait_did: Option, pub owned_box_did: Option, @@ -578,6 +579,7 @@ pub fn run(mut krate: clean::Crate, external_paths, external_typarams, exact_paths, + access_levels, deref_trait_did, deref_mut_trait_did, owned_box_did, @@ -600,7 +602,7 @@ pub fn run(mut krate: clean::Crate, extern_locations: FxHashMap(), primitive_locations: FxHashMap(), stripped_mod: false, - access_levels: krate.access_levels.clone(), + access_levels, crate_version: krate.version.take(), orphan_impl_items: Vec::new(), orphan_trait_impls: Vec::new(), diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs index 4fa5943faca07..46d0034497e28 100644 --- a/src/librustdoc/passes/strip_private.rs +++ b/src/librustdoc/passes/strip_private.rs @@ -25,7 +25,7 @@ pub const STRIP_PRIVATE: Pass = pub fn strip_private(mut krate: clean::Crate, cx: &DocContext) -> clean::Crate { // This stripper collects all *retained* nodes. let mut retained = DefIdSet(); - let access_levels = cx.access_levels.borrow().clone(); + let access_levels = cx.renderinfo.borrow().access_levels.clone(); // strip all private items { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index ce438cd99a4b6..3f8b13d145856 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -269,7 +269,10 @@ impl<'a, 'tcx, 'rcx, 'cstore> RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> { Def::Enum(did) | Def::ForeignTy(did) | Def::TyAlias(did) if !self_is_hidden => { - self.cx.access_levels.borrow_mut().map.insert(did, AccessLevel::Public); + self.cx.renderinfo + .borrow_mut() + .access_levels.map + .insert(did, AccessLevel::Public); }, Def::Mod(did) => if !self_is_hidden { ::visit_lib::LibEmbargoVisitor::new(self.cx).visit_mod(did); @@ -284,7 +287,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> { Some(n) => n, None => return false }; - let is_private = !self.cx.access_levels.borrow().is_public(def_did); + let is_private = !self.cx.renderinfo.borrow().access_levels.is_public(def_did); let is_hidden = inherits_doc_hidden(self.cx, def_node_id); // Only inline if requested or if the item would otherwise be stripped diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 10a4e69dcc6cd..fd81f937f30c7 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -38,7 +38,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> LibEmbargoVisitor<'a, 'tcx, 'rcx, 'cstore> { ) -> LibEmbargoVisitor<'a, 'tcx, 'rcx, 'cstore> { LibEmbargoVisitor { cx, - access_levels: cx.access_levels.borrow_mut(), + access_levels: RefMut::map(cx.renderinfo.borrow_mut(), |ri| &mut ri.access_levels), prev_level: Some(AccessLevel::Public), visited_mods: FxHashSet() } From 8aba29a5cf25f9c84e4f753a7ea4b5c0d6446e32 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Sat, 1 Sep 2018 21:20:39 -0500 Subject: [PATCH 24/29] shuffle ownership of `external_traits` constraints: - clean/inline.rs needs this map to fill in traits when inlining - fold.rs needs this map to allow passes to fold trait items - html/render.rs needs this map to seed the Cache.traits map of all known traits The first two are the real problem, since `DocFolder` only operates on `clean::Crate` but `clean/inline.rs` only sees the `DocContext`. The introduction of early passes means that these two now exist at the same time, so they need to share ownership of the map. Even better, the use of `Crate` in a rustc thread pool means that it needs to be Sync, so it can't use `Lrc` to manually activate thread-safety. `parking_lot` is reused from elsewhere in the tree to allow use of its `ReentrantMutex`, as the relevant parts of rustdoc are still single-threaded and this allows for easier use in that context. --- src/Cargo.lock | 1 + src/librustdoc/Cargo.toml | 1 + src/librustdoc/clean/inline.rs | 14 ++++++++++---- src/librustdoc/clean/mod.rs | 6 ++++-- src/librustdoc/core.rs | 6 +++--- src/librustdoc/fold.rs | 15 ++++++++------- src/librustdoc/html/render.rs | 2 +- src/librustdoc/lib.rs | 1 + src/librustdoc/passes/strip_hidden.rs | 9 ++------- 9 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index a4f9082c284cd..56efe5c5fb499 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2417,6 +2417,7 @@ name = "rustdoc" version = "0.0.0" dependencies = [ "minifier 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index e163fc68cbda7..845bfad7807d3 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -11,3 +11,4 @@ path = "lib.rs" pulldown-cmark = { version = "0.1.2", default-features = false } minifier = "0.0.19" tempfile = "3" +parking_lot = "0.6.4" diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index a29c62f474fa0..6e1c1d17d6e15 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -538,10 +538,13 @@ pub fn record_extern_trait(cx: &DocContext, did: DefId) { return; } - if cx.external_traits.borrow().contains_key(&did) || - cx.active_extern_traits.borrow().contains(&did) { - return; + let external_traits = cx.external_traits.lock(); + if external_traits.borrow().contains_key(&did) || + cx.active_extern_traits.borrow().contains(&did) + { + return; + } } cx.active_extern_traits.borrow_mut().push(did); @@ -549,6 +552,9 @@ pub fn record_extern_trait(cx: &DocContext, did: DefId) { debug!("record_extern_trait: {:?}", did); let trait_ = build_external_trait(cx, did); - cx.external_traits.borrow_mut().insert(did, trait_); + { + let external_traits = cx.external_traits.lock(); + external_traits.borrow_mut().insert(did, trait_); + } cx.active_extern_traits.borrow_mut().remove_item(&did); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8ec4b7bcee8ee..943bd2526c9c2 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -55,6 +55,8 @@ use std::cell::RefCell; use std::sync::Arc; use std::u32; +use parking_lot::ReentrantMutex; + use core::{self, DocContext}; use doctree; use visit_ast; @@ -136,7 +138,7 @@ pub struct Crate { pub primitives: Vec<(DefId, PrimitiveType, Attributes)>, // These are later on moved into `CACHEKEY`, leaving the map empty. // Only here so that they can be filtered through the rustdoc passes. - pub external_traits: FxHashMap, + pub external_traits: Arc>>>, pub masked_crates: FxHashSet, } @@ -214,7 +216,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> Clean for visit_ast::RustdocVisitor<'a, 'tc module: Some(module), externs, primitives, - external_traits: Default::default(), + external_traits: cx.external_traits.clone(), masked_crates, } } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 08142a77471d7..253d8b93c667b 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -36,11 +36,13 @@ use syntax::symbol::keywords; use syntax_pos::DUMMY_SP; use errors; use errors::emitter::{Emitter, EmitterWriter}; +use parking_lot::ReentrantMutex; use std::cell::RefCell; use std::mem; use rustc_data_structures::sync::{self, Lrc}; use std::rc::Rc; +use std::sync::Arc; use std::path::PathBuf; use visit_ast::RustdocVisitor; @@ -66,7 +68,7 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { /// Later on moved into `html::render::CACHE_KEY` pub renderinfo: RefCell, /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY` - pub external_traits: RefCell>, + pub external_traits: Arc>>>, /// Used while populating `external_traits` to ensure we don't process the same trait twice at /// the same time. pub active_extern_traits: RefCell>, @@ -596,8 +598,6 @@ pub fn run_core(search_paths: SearchPaths, ctxt.sess().abort_if_errors(); - krate.external_traits = ctxt.external_traits.into_inner(); - (krate, ctxt.renderinfo.into_inner(), passes) }), &sess) }) diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 6d96bc8e36038..b8e27c5317083 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::mem; - use clean::*; pub struct StripItem(pub Item); @@ -116,11 +114,14 @@ pub trait DocFolder : Sized { fn fold_crate(&mut self, mut c: Crate) -> Crate { c.module = c.module.take().and_then(|module| self.fold_item(module)); - let traits = mem::replace(&mut c.external_traits, Default::default()); - c.external_traits.extend(traits.into_iter().map(|(k, mut v)| { - v.items = v.items.into_iter().filter_map(|i| self.fold_item(i)).collect(); - (k, v) - })); + { + let guard = c.external_traits.lock(); + let traits = guard.replace(Default::default()); + guard.borrow_mut().extend(traits.into_iter().map(|(k, mut v)| { + v.items = v.items.into_iter().filter_map(|i| self.fold_item(i)).collect(); + (k, v) + })); + } c } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index f188fccdb3cbe..ed71d13009d63 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -606,7 +606,7 @@ pub fn run(mut krate: clean::Crate, crate_version: krate.version.take(), orphan_impl_items: Vec::new(), orphan_trait_impls: Vec::new(), - traits: mem::replace(&mut krate.external_traits, FxHashMap()), + traits: krate.external_traits.lock().replace(FxHashMap()), deref_trait_did, deref_mut_trait_did, owned_box_did, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 11cf43dad4a92..d0b00fd52ee77 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -50,6 +50,7 @@ extern crate rustc_errors as errors; extern crate pulldown_cmark; extern crate tempfile; extern crate minifier; +extern crate parking_lot; extern crate serialize as rustc_serialize; // used by deriving diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index eab4022a3389f..24dd4cc13bfe8 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -24,13 +24,9 @@ pub const STRIP_HIDDEN: Pass = "strips all doc(hidden) items from the output"); /// Strip items marked `#[doc(hidden)]` -pub fn strip_hidden(mut krate: clean::Crate, cx: &DocContext) -> clean::Crate { +pub fn strip_hidden(krate: clean::Crate, _: &DocContext) -> clean::Crate { let mut retained = DefIdSet(); - // as an early pass, the external traits haven't been swapped in, so we need to do that ahead - // of time - mem::swap(&mut krate.external_traits, &mut cx.external_traits.borrow_mut()); - // strip all #[doc(hidden)] items let krate = { let mut stripper = Stripper{ retained: &mut retained, update_retained: true }; @@ -39,8 +35,7 @@ pub fn strip_hidden(mut krate: clean::Crate, cx: &DocContext) -> clean::Crate { // strip all impls referencing stripped items let mut stripper = ImplStripper { retained: &retained }; - let mut krate = stripper.fold_crate(krate); - mem::swap(&mut krate.external_traits, &mut cx.external_traits.borrow_mut()); + let krate = stripper.fold_crate(krate); krate } From 358fc5b62126f997a1c38ba4c8be60ae16e4a2c4 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 7 Sep 2018 12:43:39 +0200 Subject: [PATCH 25/29] stabilize `#[panic_handler]` --- src/libstd/lib.rs | 1 - src/libsyntax/feature_gate.rs | 7 ++----- .../compile-fail/auxiliary/some-panic-impl.rs | 1 - src/test/compile-fail/panic-handler-twice.rs | 1 - src/test/run-make-fulldeps/issue-51671/app.rs | 1 - .../panic-impl-provider.rs | 1 - .../const-eval/const_panic_libcore_main.rs | 1 - .../const_panic_libcore_main.stderr | 12 +++++------ .../feature-gate-panic-handler.rs | 21 ------------------- .../feature-gate-panic-handler.stderr | 11 ---------- .../auxiliary/some-panic-impl.rs | 1 - .../panic-handler-bad-signature-1.rs | 1 - .../panic-handler-bad-signature-1.stderr | 4 ++-- .../panic-handler-bad-signature-2.rs | 1 - .../panic-handler-bad-signature-2.stderr | 2 +- .../panic-handler-bad-signature-3.rs | 1 - .../panic-handler-bad-signature-3.stderr | 2 +- .../panic-handler-bad-signature-4.rs | 1 - .../panic-handler-bad-signature-4.stderr | 2 +- .../panic-handler/panic-handler-duplicate.rs | 1 - .../panic-handler-duplicate.stderr | 4 ++-- .../panic-handler-requires-panic-info.rs | 1 - .../ui/panic-handler/panic-handler-std.rs | 1 - .../ui/panic-handler/panic-handler-std.stderr | 4 ++-- src/test/ui/panic_implementation-closures.rs | 1 - 25 files changed, 17 insertions(+), 67 deletions(-) delete mode 100644 src/test/ui/feature-gates/feature-gate-panic-handler.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-panic-handler.stderr diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index e7195b3e21ee3..4278926b042f3 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -312,7 +312,6 @@ #![feature(doc_keyword)] #![feature(panic_info_message)] #![cfg_attr(stage0, feature(panic_implementation))] -#![cfg_attr(not(stage0), feature(panic_handler))] #![feature(non_exhaustive)] #![default_lib_allocator] diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index e3ea3563d853b..0270e36db1177 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -487,7 +487,6 @@ declare_features! ( // RFC 2070: #[panic_implementation] / #[panic_handler] (active, panic_implementation, "1.28.0", Some(44489), None), - (active, panic_handler, "1.30.0", Some(44489), None), // #[doc(keyword = "...")] (active, doc_keyword, "1.28.0", Some(51315), None), @@ -674,6 +673,7 @@ declare_features! ( (accepted, proc_macro_path_invoc, "1.30.0", Some(38356), None), // Allows all literals in attribute lists and values of key-value pairs. (accepted, attr_literals, "1.30.0", Some(34981), None), + (accepted, panic_handler, "1.30.0", Some(44489), None), ); // If you change this, please modify src/doc/unstable-book as well. You must @@ -1143,10 +1143,7 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG cfg_fn!(panic_implementation))), // RFC 2070 - ("panic_handler", Normal, Gated(Stability::Unstable, - "panic_handler", - "#[panic_handler] is an unstable feature", - cfg_fn!(panic_handler))), + ("panic_handler", Normal, Ungated), ("alloc_error_handler", Normal, Gated(Stability::Unstable, "alloc_error_handler", diff --git a/src/test/compile-fail/auxiliary/some-panic-impl.rs b/src/test/compile-fail/auxiliary/some-panic-impl.rs index e3b4fba176e3c..090123198d175 100644 --- a/src/test/compile-fail/auxiliary/some-panic-impl.rs +++ b/src/test/compile-fail/auxiliary/some-panic-impl.rs @@ -11,7 +11,6 @@ // no-prefer-dynamic #![crate_type = "rlib"] -#![feature(panic_handler)] #![no_std] use core::panic::PanicInfo; diff --git a/src/test/compile-fail/panic-handler-twice.rs b/src/test/compile-fail/panic-handler-twice.rs index 6c9515ca90994..10e0453cf5ed4 100644 --- a/src/test/compile-fail/panic-handler-twice.rs +++ b/src/test/compile-fail/panic-handler-twice.rs @@ -10,7 +10,6 @@ // aux-build:some-panic-impl.rs -#![feature(panic_handler)] #![feature(lang_items)] #![no_std] #![no_main] diff --git a/src/test/run-make-fulldeps/issue-51671/app.rs b/src/test/run-make-fulldeps/issue-51671/app.rs index e980b12039e96..4066214f4b47e 100644 --- a/src/test/run-make-fulldeps/issue-51671/app.rs +++ b/src/test/run-make-fulldeps/issue-51671/app.rs @@ -10,7 +10,6 @@ #![crate_type = "bin"] #![feature(lang_items)] -#![feature(panic_handler)] #![no_main] #![no_std] diff --git a/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs index 065b2b6bf18fa..77aae7ee2c06b 100644 --- a/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs +++ b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs @@ -9,7 +9,6 @@ // except according to those terms. #![crate_type = "rlib"] -#![feature(panic_handler)] #![no_std] use core::panic::PanicInfo; diff --git a/src/test/ui/consts/const-eval/const_panic_libcore_main.rs b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs index f5e5f9778faed..0364123994dff 100644 --- a/src/test/ui/consts/const-eval/const_panic_libcore_main.rs +++ b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs @@ -10,7 +10,6 @@ #![crate_type = "bin"] #![feature(lang_items)] -#![feature(panic_handler)] #![feature(const_panic)] #![no_main] #![no_std] diff --git a/src/test/ui/consts/const-eval/const_panic_libcore_main.stderr b/src/test/ui/consts/const-eval/const_panic_libcore_main.stderr index 7cb9f51c427a7..44b30c08cdea2 100644 --- a/src/test/ui/consts/const-eval/const_panic_libcore_main.stderr +++ b/src/test/ui/consts/const-eval/const_panic_libcore_main.stderr @@ -1,31 +1,31 @@ error: this constant cannot be used - --> $DIR/const_panic_libcore_main.rs:20:1 + --> $DIR/const_panic_libcore_main.rs:19:1 | LL | const Z: () = panic!("cheese"); | ^^^^^^^^^^^^^^----------------^ | | - | the evaluated program panicked at 'cheese', $DIR/const_panic_libcore_main.rs:20:15 + | the evaluated program panicked at 'cheese', $DIR/const_panic_libcore_main.rs:19:15 | = note: #[deny(const_err)] on by default = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this constant cannot be used - --> $DIR/const_panic_libcore_main.rs:23:1 + --> $DIR/const_panic_libcore_main.rs:22:1 | LL | const Y: () = unreachable!(); | ^^^^^^^^^^^^^^--------------^ | | - | the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_libcore_main.rs:23:15 + | the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_libcore_main.rs:22:15 | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this constant cannot be used - --> $DIR/const_panic_libcore_main.rs:26:1 + --> $DIR/const_panic_libcore_main.rs:25:1 | LL | const X: () = unimplemented!(); | ^^^^^^^^^^^^^^----------------^ | | - | the evaluated program panicked at 'not yet implemented', $DIR/const_panic_libcore_main.rs:26:15 + | the evaluated program panicked at 'not yet implemented', $DIR/const_panic_libcore_main.rs:25:15 | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) diff --git a/src/test/ui/feature-gates/feature-gate-panic-handler.rs b/src/test/ui/feature-gates/feature-gate-panic-handler.rs deleted file mode 100644 index fd16268ef8b4e..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-panic-handler.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags:-C panic=abort - -#![no_std] -#![no_main] - -use core::panic::PanicInfo; - -#[panic_handler] //~ ERROR #[panic_handler] is an unstable feature (see issue #44489) -fn panic(info: &PanicInfo) -> ! { - loop {} -} diff --git a/src/test/ui/feature-gates/feature-gate-panic-handler.stderr b/src/test/ui/feature-gates/feature-gate-panic-handler.stderr deleted file mode 100644 index 9680a240a9925..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-panic-handler.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: #[panic_handler] is an unstable feature (see issue #44489) - --> $DIR/feature-gate-panic-handler.rs:18:1 - | -LL | #[panic_handler] //~ ERROR #[panic_handler] is an unstable feature (see issue #44489) - | ^^^^^^^^^^^^^^^^ - | - = help: add #![feature(panic_handler)] to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/panic-handler/auxiliary/some-panic-impl.rs b/src/test/ui/panic-handler/auxiliary/some-panic-impl.rs index e3b4fba176e3c..090123198d175 100644 --- a/src/test/ui/panic-handler/auxiliary/some-panic-impl.rs +++ b/src/test/ui/panic-handler/auxiliary/some-panic-impl.rs @@ -11,7 +11,6 @@ // no-prefer-dynamic #![crate_type = "rlib"] -#![feature(panic_handler)] #![no_std] use core::panic::PanicInfo; diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs index cc7e337fc9e65..8d53c66adbd93 100644 --- a/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs +++ b/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs @@ -10,7 +10,6 @@ // compile-flags:-C panic=abort -#![feature(panic_handler)] #![no_std] #![no_main] diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-1.stderr b/src/test/ui/panic-handler/panic-handler-bad-signature-1.stderr index 5771f4277b46d..72b85da028f1f 100644 --- a/src/test/ui/panic-handler/panic-handler-bad-signature-1.stderr +++ b/src/test/ui/panic-handler/panic-handler-bad-signature-1.stderr @@ -1,11 +1,11 @@ error: return type should be `!` - --> $DIR/panic-handler-bad-signature-1.rs:22:6 + --> $DIR/panic-handler-bad-signature-1.rs:21:6 | LL | ) -> () //~ ERROR return type should be `!` | ^^ error: argument should be `&PanicInfo` - --> $DIR/panic-handler-bad-signature-1.rs:21:11 + --> $DIR/panic-handler-bad-signature-1.rs:20:11 | LL | info: PanicInfo, //~ ERROR argument should be `&PanicInfo` | ^^^^^^^^^ diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs index ec698903c846e..0e8b3d5e855cb 100644 --- a/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs +++ b/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs @@ -10,7 +10,6 @@ // compile-flags:-C panic=abort -#![feature(panic_handler)] #![no_std] #![no_main] diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-2.stderr b/src/test/ui/panic-handler/panic-handler-bad-signature-2.stderr index 4823f8a2781b0..f2bcb6b680952 100644 --- a/src/test/ui/panic-handler/panic-handler-bad-signature-2.stderr +++ b/src/test/ui/panic-handler/panic-handler-bad-signature-2.stderr @@ -1,5 +1,5 @@ error: argument should be `&PanicInfo` - --> $DIR/panic-handler-bad-signature-2.rs:21:11 + --> $DIR/panic-handler-bad-signature-2.rs:20:11 | LL | info: &'static PanicInfo, //~ ERROR argument should be `&PanicInfo` | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs index 585716c7c7569..ac1b19105b62e 100644 --- a/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs +++ b/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs @@ -10,7 +10,6 @@ // compile-flags:-C panic=abort -#![feature(panic_handler)] #![no_std] #![no_main] diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr b/src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr index 5d0395e17f54d..77227e0d5a61c 100644 --- a/src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr +++ b/src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr @@ -1,5 +1,5 @@ error: function should have one argument - --> $DIR/panic-handler-bad-signature-3.rs:20:1 + --> $DIR/panic-handler-bad-signature-3.rs:19:1 | LL | fn panic() -> ! { //~ ERROR function should have one argument | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs index 9cda37f27b332..f4728408a1afa 100644 --- a/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs +++ b/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs @@ -10,7 +10,6 @@ // compile-flags:-C panic=abort -#![feature(panic_handler)] #![no_std] #![no_main] diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-4.stderr b/src/test/ui/panic-handler/panic-handler-bad-signature-4.stderr index a61b9b3743c7d..0dd47cafd7553 100644 --- a/src/test/ui/panic-handler/panic-handler-bad-signature-4.stderr +++ b/src/test/ui/panic-handler/panic-handler-bad-signature-4.stderr @@ -1,5 +1,5 @@ error: should have no type parameters - --> $DIR/panic-handler-bad-signature-4.rs:20:1 + --> $DIR/panic-handler-bad-signature-4.rs:19:1 | LL | / fn panic(pi: &PanicInfo) -> ! { LL | | //~^ ERROR should have no type parameters diff --git a/src/test/ui/panic-handler/panic-handler-duplicate.rs b/src/test/ui/panic-handler/panic-handler-duplicate.rs index 7d7fe251869f1..c4fb4903e0031 100644 --- a/src/test/ui/panic-handler/panic-handler-duplicate.rs +++ b/src/test/ui/panic-handler/panic-handler-duplicate.rs @@ -11,7 +11,6 @@ // compile-flags:-C panic=abort #![feature(lang_items)] -#![feature(panic_handler)] #![no_std] #![no_main] diff --git a/src/test/ui/panic-handler/panic-handler-duplicate.stderr b/src/test/ui/panic-handler/panic-handler-duplicate.stderr index d8afaa27e2662..e243d9079d851 100644 --- a/src/test/ui/panic-handler/panic-handler-duplicate.stderr +++ b/src/test/ui/panic-handler/panic-handler-duplicate.stderr @@ -1,5 +1,5 @@ error[E0152]: duplicate lang item found: `panic_impl`. - --> $DIR/panic-handler-duplicate.rs:26:1 + --> $DIR/panic-handler-duplicate.rs:25:1 | LL | / fn panic2(info: &PanicInfo) -> ! { //~ ERROR duplicate lang item found: `panic_impl`. LL | | loop {} @@ -7,7 +7,7 @@ LL | | } | |_^ | note: first defined here. - --> $DIR/panic-handler-duplicate.rs:21:1 + --> $DIR/panic-handler-duplicate.rs:20:1 | LL | / fn panic(info: &PanicInfo) -> ! { LL | | loop {} diff --git a/src/test/ui/panic-handler/panic-handler-requires-panic-info.rs b/src/test/ui/panic-handler/panic-handler-requires-panic-info.rs index ec68a414f54d5..133d6c0557ab6 100644 --- a/src/test/ui/panic-handler/panic-handler-requires-panic-info.rs +++ b/src/test/ui/panic-handler/panic-handler-requires-panic-info.rs @@ -13,7 +13,6 @@ #![feature(lang_items)] #![feature(no_core)] -#![feature(panic_handler)] #![no_core] #![no_main] diff --git a/src/test/ui/panic-handler/panic-handler-std.rs b/src/test/ui/panic-handler/panic-handler-std.rs index 7cbe0a35baed8..ff5995237cf21 100644 --- a/src/test/ui/panic-handler/panic-handler-std.rs +++ b/src/test/ui/panic-handler/panic-handler-std.rs @@ -10,7 +10,6 @@ // error-pattern: duplicate lang item found: `panic_impl`. -#![feature(panic_handler)] use std::panic::PanicInfo; diff --git a/src/test/ui/panic-handler/panic-handler-std.stderr b/src/test/ui/panic-handler/panic-handler-std.stderr index b141a2171646c..4ec1c6df35522 100644 --- a/src/test/ui/panic-handler/panic-handler-std.stderr +++ b/src/test/ui/panic-handler/panic-handler-std.stderr @@ -1,5 +1,5 @@ error[E0152]: duplicate lang item found: `panic_impl`. - --> $DIR/panic-handler-std.rs:18:1 + --> $DIR/panic-handler-std.rs:17:1 | LL | / fn panic(info: PanicInfo) -> ! { LL | | loop {} @@ -9,7 +9,7 @@ LL | | } = note: first defined in crate `std`. error: argument should be `&PanicInfo` - --> $DIR/panic-handler-std.rs:18:16 + --> $DIR/panic-handler-std.rs:17:16 | LL | fn panic(info: PanicInfo) -> ! { | ^^^^^^^^^ diff --git a/src/test/ui/panic_implementation-closures.rs b/src/test/ui/panic_implementation-closures.rs index 6642db6ee76bf..5902a1ae1b023 100644 --- a/src/test/ui/panic_implementation-closures.rs +++ b/src/test/ui/panic_implementation-closures.rs @@ -12,7 +12,6 @@ #![crate_type = "rlib"] #![no_std] -#![feature(panic_handler)] #[panic_handler] pub fn panic_fmt(_: &::core::panic::PanicInfo) -> ! { From 8aae6ca44a1bea64e2be3f2ce5a4581bb65d43ef Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 5 Sep 2018 13:05:46 -0600 Subject: [PATCH 26/29] Have rust-lldb look for the rust-enabled lldb We're shipping a rust-enabled lldb, but the "lldb" executable is not installed into the "bin" directory by rustup. See the discussion in https://github.com/rust-lang-nursery/rustup.rs/pull/1492 for background on this decision. There, we agreed to have rust-lldb prefer the rust-enabled lldb if it is installed. This patch changes dist.rs to put lldb into rustlib, following what was done for the other LLVM tools in #53955, and then fixes rust-lldb to prefer that lldb, if it exists. See issue #48168 --- src/bootstrap/dist.rs | 7 ++++--- src/etc/rust-lldb | 26 +++++++++++++++++--------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 167e4a78edaf8..2d94704fda7d6 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -2056,7 +2056,8 @@ impl Step for Lldb { drop(fs::remove_dir_all(&image)); // Prepare the image directory - let dst = image.join("bin"); + let root = image.join("lib/rustlib").join(&*target); + let dst = root.join("bin"); t!(fs::create_dir_all(&dst)); for program in &["lldb", "lldb-argdumper", "lldb-mi", "lldb-server"] { let exe = bindir.join(exe(program, &target)); @@ -2065,7 +2066,7 @@ impl Step for Lldb { // The libraries. let libdir = builder.llvm_out(target).join("lib"); - let dst = image.join("lib"); + let dst = root.join("lib"); t!(fs::create_dir_all(&dst)); for entry in t!(fs::read_dir(&libdir)) { let entry = entry.unwrap(); @@ -2093,7 +2094,7 @@ impl Step for Lldb { let entry = t!(entry); if let Ok(name) = entry.file_name().into_string() { if name.starts_with("python") { - let dst = image.join(libdir_name) + let dst = root.join(libdir_name) .join(entry.file_name()); t!(fs::create_dir_all(&dst)); builder.cp_r(&entry.path(), &dst); diff --git a/src/etc/rust-lldb b/src/etc/rust-lldb index 6a2849b55485e..6ed8210349e17 100755 --- a/src/etc/rust-lldb +++ b/src/etc/rust-lldb @@ -12,27 +12,35 @@ # Exit if anything fails set -e -LLDB_VERSION=`lldb --version 2>/dev/null | head -1 | cut -d. -f1` +# Find out where to look for the pretty printer Python module +RUSTC_SYSROOT=`rustc --print sysroot` + +# Find the host triple so we can find lldb in rustlib. +host=`rustc -vV | sed -n -e 's/^host: //p'` + +lldb=lldb +if [ -f "$RUSTC_SYSROOT/lib/rustlib/$host/bin/lldb" ]; then + lldb="$RUSTC_SYSROOT/lib/rustlib/$host/bin/lldb" +else + LLDB_VERSION=`"$lldb" --version 2>/dev/null | head -1 | cut -d. -f1` -if [ "$LLDB_VERSION" = "lldb-350" ] -then - echo "***" + if [ "$LLDB_VERSION" = "lldb-350" ] + then + echo "***" echo \ "WARNING: This version of LLDB has known issues with Rust and cannot \ display the contents of local variables!" - echo "***" + echo "***" + fi fi -# Find out where to look for the pretty printer Python module -RUSTC_SYSROOT=`rustc --print sysroot` - # Prepare commands that will be loaded before any file on the command line has been loaded script_import="command script import \"$RUSTC_SYSROOT/lib/rustlib/etc/lldb_rust_formatters.py\"" category_definition="type summary add --no-value --python-function lldb_rust_formatters.print_val -x \".*\" --category Rust" category_enable="type category enable Rust" # Call LLDB with the commands added to the argument list -exec lldb --one-line-before-file="$script_import" \ +exec "$lldb" --one-line-before-file="$script_import" \ --one-line-before-file="$category_definition" \ --one-line-before-file="$category_enable" \ "$@" From ef440686131096e08635df418a70507bfc621a30 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Thu, 6 Sep 2018 11:06:32 +0200 Subject: [PATCH 27/29] rustbuild: allow configuring llvm version suffix Signed-off-by: Marc-Antoine Perennou --- config.toml.example | 4 ++++ src/bootstrap/config.rs | 3 +++ src/bootstrap/native.rs | 4 ++++ 3 files changed, 11 insertions(+) diff --git a/config.toml.example b/config.toml.example index 35f69cd05b607..087dc418e2dce 100644 --- a/config.toml.example +++ b/config.toml.example @@ -82,6 +82,10 @@ # passed to prefer linking to shared libraries. #link-shared = false +# When building llvm, this configures what is being appended to the version. +# If absent, we let the version as-is. +#version-suffix = "-rust" + # On MSVC you can compile LLVM with clang-cl, but the test suite doesn't pass # with clang-cl, so this is special in that it only compiles LLVM with clang-cl #clang-cl = '/path/to/clang-cl.exe' diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index bf4d39c4947e5..70b21a1567b0f 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -86,6 +86,7 @@ pub struct Config { pub llvm_targets: Option, pub llvm_experimental_targets: String, pub llvm_link_jobs: Option, + pub llvm_version_suffix: Option, pub lld_enabled: bool, pub lldb_enabled: bool, @@ -256,6 +257,7 @@ struct Llvm { experimental_targets: Option, link_jobs: Option, link_shared: Option, + version_suffix: Option, clang_cl: Option } @@ -516,6 +518,7 @@ impl Config { config.llvm_experimental_targets = llvm.experimental_targets.clone() .unwrap_or("WebAssembly;RISCV".to_string()); config.llvm_link_jobs = llvm.link_jobs; + config.llvm_version_suffix = llvm.version_suffix.clone(); config.llvm_clang_cl = llvm.clang_cl.clone(); } diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index caf38d766f54e..828a7d14c0437 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -239,6 +239,10 @@ impl Step for Llvm { cfg.define("LLVM_NATIVE_BUILD", builder.llvm_out(builder.config.build).join("build")); } + if let Some(ref suffix) = builder.config.llvm_version_suffix { + cfg.define("LLVM_VERSION_SUFFIX", suffix); + } + if let Some(ref python) = builder.config.python { cfg.define("PYTHON_EXECUTABLE", python); } From de6a61110c7aeff82ee347216efe76f4bfefc45d Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Thu, 6 Sep 2018 10:42:38 -0400 Subject: [PATCH 28/29] update books for next release --- src/doc/book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/book b/src/doc/book index 16c9dee7666c2..cff0930664b68 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 16c9dee7666c2b2766fd98d89003e028679d1207 +Subproject commit cff0930664b688f1dd22aefb3d16944eb4cdbfd5 diff --git a/src/doc/nomicon b/src/doc/nomicon index ae42ad7aa4d79..7fd493465b7dd 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit ae42ad7aa4d7907cca941371c9eee8de8c2ee40d +Subproject commit 7fd493465b7dd6cf3476f0b834884059bbdd1d93 diff --git a/src/doc/reference b/src/doc/reference index 219e261ddb833..821355a6fd642 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 219e261ddb833a5683627b0a9be87a0f4486abb9 +Subproject commit 821355a6fd642b71988a2f88a3162fb358732012 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index e3719fc78ff4a..e459fb3f07f2b 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit e3719fc78ff4a21dfd13cfcc9e2ca42cb5de29f4 +Subproject commit e459fb3f07f2b930ccd25d348671b8eae233fd64 From b31eaa4a080c8f1cdeb5e3730f12a0f9905dbb98 Mon Sep 17 00:00:00 2001 From: Gabriel Majeri Date: Sat, 8 Sep 2018 09:04:29 +0300 Subject: [PATCH 29/29] Update `petgraph` dependency to 0.4.13 This fixes building `bootstrap` using a local Rust nightly. --- src/Cargo.lock | 6 +++--- src/bootstrap/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index fc2dfcfd8604c..9828966fa9539 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -138,7 +138,7 @@ dependencies = [ "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1471,7 +1471,7 @@ dependencies = [ [[package]] name = "petgraph" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3243,7 +3243,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc" "checksum pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ab94faafeb93f4c5e3ce81ca0e5a779529a602ad5d09ae6d21996bfb8b6a52bf" -"checksum petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "8b30dc85588cd02b9b76f5e386535db546d21dc68506cff2abebee0b6445e8e4" +"checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" "checksum phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "7d37a244c75a9748e049225155f56dbcb98fe71b192fd25fd23cb914b5ad62f2" "checksum phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "4e4048fe7dd7a06b8127ecd6d3803149126e9b33c7558879846da3a63f734f2b" "checksum phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "05a079dd052e7b674d21cb31cbb6c05efd56a2cd2827db7692e2f1a507ebd998" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 57a526038041e..3e91c2b3e86c8 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -47,7 +47,7 @@ serde_json = "1.0.2" toml = "0.4" lazy_static = "0.2" time = "0.1" -petgraph = "0.4.12" +petgraph = "0.4.13" [dev-dependencies] pretty_assertions = "0.5"