diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index c245b42c3e880..45b205356758f 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -365,6 +365,12 @@ impl Rc { unsafe { self.ptr.as_ref() } } + #[inline] + fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { + let this = mem::ManuallyDrop::new(this); + (this.ptr, unsafe { ptr::read(&this.alloc) }) + } + #[inline] unsafe fn from_inner_in(ptr: NonNull>, alloc: A) -> Self { Self { ptr, phantom: PhantomData, alloc } @@ -1145,12 +1151,9 @@ impl Rc, A> { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] #[inline] - pub unsafe fn assume_init(self) -> Rc - where - A: Clone, - { - let md_self = mem::ManuallyDrop::new(self); - unsafe { Rc::from_inner_in(md_self.ptr.cast(), md_self.alloc.clone()) } + pub unsafe fn assume_init(self) -> Rc { + let (ptr, alloc) = Rc::into_inner_with_allocator(self); + unsafe { Rc::from_inner_in(ptr.cast(), alloc) } } } @@ -1189,12 +1192,9 @@ impl Rc<[mem::MaybeUninit], A> { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] #[inline] - pub unsafe fn assume_init(self) -> Rc<[T], A> - where - A: Clone, - { - let md_self = mem::ManuallyDrop::new(self); - unsafe { Rc::from_ptr_in(md_self.ptr.as_ptr() as _, md_self.alloc.clone()) } + pub unsafe fn assume_init(self) -> Rc<[T], A> { + let (ptr, alloc) = Rc::into_inner_with_allocator(self); + unsafe { Rc::from_ptr_in(ptr.as_ptr() as _, alloc) } } } @@ -1809,7 +1809,9 @@ impl Rc { // reference to the allocation. unsafe { &mut this.ptr.as_mut().value } } +} +impl Rc { /// If we have the only reference to `T` then unwrap it. Otherwise, clone `T` and return the /// clone. /// @@ -1845,7 +1847,7 @@ impl Rc { } } -impl Rc { +impl Rc { /// Attempt to downcast the `Rc` to a concrete type. /// /// # Examples @@ -1869,10 +1871,8 @@ impl Rc { pub fn downcast(self) -> Result, Self> { if (*self).is::() { unsafe { - let ptr = self.ptr.cast::>(); - let alloc = self.alloc.clone(); - forget(self); - Ok(Rc::from_inner_in(ptr, alloc)) + let (ptr, alloc) = Rc::into_inner_with_allocator(self); + Ok(Rc::from_inner_in(ptr.cast(), alloc)) } } else { Err(self) @@ -1909,10 +1909,8 @@ impl Rc { #[unstable(feature = "downcast_unchecked", issue = "90850")] pub unsafe fn downcast_unchecked(self) -> Rc { unsafe { - let ptr = self.ptr.cast::>(); - let alloc = self.alloc.clone(); - mem::forget(self); - Rc::from_inner_in(ptr, alloc) + let (ptr, alloc) = Rc::into_inner_with_allocator(self); + Rc::from_inner_in(ptr.cast(), alloc) } } } @@ -2661,12 +2659,13 @@ impl From> for Rc<[u8]> { } #[stable(feature = "boxed_slice_try_from", since = "1.43.0")] -impl TryFrom> for Rc<[T; N]> { - type Error = Rc<[T]>; +impl TryFrom> for Rc<[T; N], A> { + type Error = Rc<[T], A>; - fn try_from(boxed_slice: Rc<[T]>) -> Result { + fn try_from(boxed_slice: Rc<[T], A>) -> Result { if boxed_slice.len() == N { - Ok(unsafe { Rc::from_raw(Rc::into_raw(boxed_slice) as *mut [T; N]) }) + let (ptr, alloc) = Rc::into_inner_with_allocator(boxed_slice); + Ok(unsafe { Rc::from_inner_in(ptr.cast(), alloc) }) } else { Err(boxed_slice) } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 297a273d274bf..a35c99849b343 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -280,8 +280,8 @@ impl Arc { impl Arc { #[inline] - fn internal_into_inner_with_allocator(self) -> (NonNull>, A) { - let this = mem::ManuallyDrop::new(self); + fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { + let this = mem::ManuallyDrop::new(this); (this.ptr, unsafe { ptr::read(&this.alloc) }) } @@ -1290,7 +1290,7 @@ impl Arc, A> { #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub unsafe fn assume_init(self) -> Arc { - let (ptr, alloc) = self.internal_into_inner_with_allocator(); + let (ptr, alloc) = Arc::into_inner_with_allocator(self); unsafe { Arc::from_inner_in(ptr.cast(), alloc) } } } @@ -1332,7 +1332,7 @@ impl Arc<[mem::MaybeUninit], A> { #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub unsafe fn assume_init(self) -> Arc<[T], A> { - let (ptr, alloc) = self.internal_into_inner_with_allocator(); + let (ptr, alloc) = Arc::into_inner_with_allocator(self); unsafe { Arc::from_ptr_in(ptr.as_ptr() as _, alloc) } } } @@ -2227,7 +2227,9 @@ impl Arc { // either unique to begin with, or became one upon cloning the contents. unsafe { Self::get_mut_unchecked(this) } } +} +impl Arc { /// If we have the only reference to `T` then unwrap it. Otherwise, clone `T` and return the /// clone. /// @@ -2499,7 +2501,7 @@ impl Arc { { if (*self).is::() { unsafe { - let (ptr, alloc) = self.internal_into_inner_with_allocator(); + let (ptr, alloc) = Arc::into_inner_with_allocator(self); Ok(Arc::from_inner_in(ptr.cast(), alloc)) } } else { @@ -2540,7 +2542,7 @@ impl Arc { T: Any + Send + Sync, { unsafe { - let (ptr, alloc) = self.internal_into_inner_with_allocator(); + let (ptr, alloc) = Arc::into_inner_with_allocator(self); Arc::from_inner_in(ptr.cast(), alloc) } } @@ -3506,7 +3508,7 @@ impl TryFrom> for Arc<[T; N], A> { fn try_from(boxed_slice: Arc<[T], A>) -> Result { if boxed_slice.len() == N { - let (ptr, alloc) = boxed_slice.internal_into_inner_with_allocator(); + let (ptr, alloc) = Arc::into_inner_with_allocator(boxed_slice); Ok(unsafe { Arc::from_inner_in(ptr.cast(), alloc) }) } else { Err(boxed_slice) diff --git a/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile index dab0667ed55c4..e718437aaaa39 100644 --- a/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile @@ -25,5 +25,5 @@ ENV CC_armv7_unknown_linux_gnueabihf=armv7-unknown-linux-gnueabihf-gcc \ ENV HOSTS=armv7-unknown-linux-gnueabihf -ENV RUST_CONFIGURE_ARGS --enable-full-tools --disable-docs +ENV RUST_CONFIGURE_ARGS --enable-full-tools --enable-profiler --disable-docs ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 4eeaaa2bb70a9..3a71dd82db88b 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -8,6 +8,9 @@ use crate::core::DocContext; mod stripper; pub(crate) use stripper::*; +mod strip_aliased_non_local; +pub(crate) use self::strip_aliased_non_local::STRIP_ALIASED_NON_LOCAL; + mod strip_hidden; pub(crate) use self::strip_hidden::STRIP_HIDDEN; @@ -71,6 +74,7 @@ pub(crate) enum Condition { pub(crate) const PASSES: &[Pass] = &[ CHECK_CUSTOM_CODE_CLASSES, CHECK_DOC_TEST_VISIBILITY, + STRIP_ALIASED_NON_LOCAL, STRIP_HIDDEN, STRIP_PRIVATE, STRIP_PRIV_IMPORTS, @@ -86,6 +90,7 @@ pub(crate) const DEFAULT_PASSES: &[ConditionalPass] = &[ ConditionalPass::always(CHECK_CUSTOM_CODE_CLASSES), ConditionalPass::always(COLLECT_TRAIT_IMPLS), ConditionalPass::always(CHECK_DOC_TEST_VISIBILITY), + ConditionalPass::always(STRIP_ALIASED_NON_LOCAL), ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden), ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate), ConditionalPass::new(STRIP_PRIV_IMPORTS, WhenDocumentPrivate), diff --git a/src/librustdoc/passes/strip_aliased_non_local.rs b/src/librustdoc/passes/strip_aliased_non_local.rs new file mode 100644 index 0000000000000..848cbd5ed99fc --- /dev/null +++ b/src/librustdoc/passes/strip_aliased_non_local.rs @@ -0,0 +1,57 @@ +use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::Visibility; + +use crate::clean; +use crate::clean::Item; +use crate::core::DocContext; +use crate::fold::{strip_item, DocFolder}; +use crate::passes::Pass; + +pub(crate) const STRIP_ALIASED_NON_LOCAL: Pass = Pass { + name: "strip-aliased-non-local", + run: strip_aliased_non_local, + description: "strips all non-local private aliased items from the output", +}; + +fn strip_aliased_non_local(krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate { + let mut stripper = AliasedNonLocalStripper { tcx: cx.tcx }; + stripper.fold_crate(krate) +} + +struct AliasedNonLocalStripper<'tcx> { + tcx: TyCtxt<'tcx>, +} + +impl<'tcx> DocFolder for AliasedNonLocalStripper<'tcx> { + fn fold_item(&mut self, i: Item) -> Option { + Some(match *i.kind { + clean::TypeAliasItem(..) => { + let mut stripper = NonLocalStripper { tcx: self.tcx }; + // don't call `fold_item` as that could strip the type-alias it-self + // which we don't want to strip out + stripper.fold_item_recur(i) + } + _ => self.fold_item_recur(i), + }) + } +} + +struct NonLocalStripper<'tcx> { + tcx: TyCtxt<'tcx>, +} + +impl<'tcx> DocFolder for NonLocalStripper<'tcx> { + fn fold_item(&mut self, i: Item) -> Option { + // If not local, we want to respect the original visibility of + // the field and not the one given by the user for the currrent crate. + // + // FIXME(#125009): Not-local should probably consider same Cargo workspace + if !i.def_id().map_or(true, |did| did.is_local()) { + if i.visibility(self.tcx) != Some(Visibility::Public) || i.is_doc_hidden() { + return Some(strip_item(i)); + } + } + + Some(self.fold_item_recur(i)) + } +} diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index e87950b36d9df..acf1a3e1ec11d 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -244,7 +244,6 @@ run-make/rlib-format-packed-bundled-libs-3/Makefile run-make/rlib-format-packed-bundled-libs/Makefile run-make/rmeta-preferred/Makefile run-make/rustc-macro-dep-files/Makefile -run-make/rustdoc-io-error/Makefile run-make/rustdoc-scrape-examples-invalid-expr/Makefile run-make/rustdoc-scrape-examples-macros/Makefile run-make/rustdoc-scrape-examples-multiple/Makefile @@ -252,7 +251,6 @@ run-make/rustdoc-scrape-examples-ordering/Makefile run-make/rustdoc-scrape-examples-remap/Makefile run-make/rustdoc-scrape-examples-test/Makefile run-make/rustdoc-scrape-examples-whitespace/Makefile -run-make/rustdoc-shared-flags/Makefile run-make/rustdoc-target-spec-json-path/Makefile run-make/rustdoc-themes/Makefile run-make/rustdoc-verify-output-files/Makefile diff --git a/tests/run-make/rustdoc-io-error/Makefile b/tests/run-make/rustdoc-io-error/Makefile deleted file mode 100644 index 27f5ecf94aba3..0000000000000 --- a/tests/run-make/rustdoc-io-error/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -include ../tools.mk - -# This test verifies that rustdoc doesn't ICE when it encounters an IO error -# while generating files. Ideally this would be a rustdoc-ui test, so we could -# verify the error message as well. - -# ignore-windows -# The test uses `chmod`. - -OUTPUT_DIR := "$(TMPDIR)/rustdoc-io-error" - -# This test operates by creating a temporary directory and modifying its -# permissions so that it is not writable. We have to take special care to set -# the permissions back to normal so that it's able to be deleted later. -all: - mkdir -p $(OUTPUT_DIR) - chmod u-w $(OUTPUT_DIR) - -$(shell $(RUSTDOC) -o $(OUTPUT_DIR) foo.rs) - chmod u+w $(OUTPUT_DIR) - exit $($(.SHELLSTATUS) -eq 1) diff --git a/tests/run-make/rustdoc-io-error/rmake.rs b/tests/run-make/rustdoc-io-error/rmake.rs new file mode 100644 index 0000000000000..a644f3808e2d7 --- /dev/null +++ b/tests/run-make/rustdoc-io-error/rmake.rs @@ -0,0 +1,32 @@ +// This test verifies that rustdoc doesn't ICE when it encounters an IO error +// while generating files. Ideally this would be a rustdoc-ui test, so we could +// verify the error message as well. +// +// It operates by creating a temporary directory and modifying its +// permissions so that it is not writable. We have to take special care to set +// the permissions back to normal so that it's able to be deleted later. + +use run_make_support::{rustdoc, tmp_dir}; +use std::fs; + +fn main() { + let out_dir = tmp_dir().join("rustdoc-io-error"); + let output = fs::create_dir(&out_dir).unwrap(); + let mut permissions = fs::metadata(&out_dir).unwrap().permissions(); + permissions.set_readonly(true); + fs::set_permissions(&out_dir, permissions.clone()).unwrap(); + + let output = rustdoc().input("foo.rs").output(&out_dir).command_output(); + + // Changing back permissions. + permissions.set_readonly(false); + fs::set_permissions(&out_dir, permissions).unwrap(); + + // Checks that rustdoc failed with the error code 1. + #[cfg(unix)] + assert_eq!(output.status.code().unwrap(), 1); + assert!(!output.status.success()); + let stderr = String::from_utf8(output.stderr).unwrap(); + + assert!(stderr.contains("error: couldn't generate documentation: Permission denied")); +} diff --git a/tests/run-make/rustdoc-shared-flags/Makefile b/tests/run-make/rustdoc-shared-flags/Makefile deleted file mode 100644 index a2a7d7b3634a9..0000000000000 --- a/tests/run-make/rustdoc-shared-flags/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -include ../tools.mk - -all: z_help c_help list_passes - -c_help: - $(RUSTC) -C help > $(TMPDIR)/rustc.c_help.txt - $(RUSTDOC) -C help > $(TMPDIR)/rustdoc.c_help.txt - $(DIFF) $(TMPDIR)/rustc.c_help.txt $(TMPDIR)/rustdoc.c_help.txt - -z_help: - $(RUSTC) -Z help > $(TMPDIR)/rustc.z_help.txt - $(RUSTDOC) -Z help > $(TMPDIR)/rustdoc.z_help.txt - $(DIFF) $(TMPDIR)/rustc.z_help.txt $(TMPDIR)/rustdoc.z_help.txt - -list_passes: - $(RUSTC) -C passes=list > $(TMPDIR)/rustc.passes.txt - $(RUSTDOC) -C passes=list > $(TMPDIR)/rustdoc.passes.txt - $(DIFF) $(TMPDIR)/rustc.passes.txt $(TMPDIR)/rustdoc.passes.txt diff --git a/tests/run-make/rustdoc-shared-flags/rmake.rs b/tests/run-make/rustdoc-shared-flags/rmake.rs new file mode 100644 index 0000000000000..2db613f781764 --- /dev/null +++ b/tests/run-make/rustdoc-shared-flags/rmake.rs @@ -0,0 +1,14 @@ +use run_make_support::{rustc, rustdoc, Diff}; + +fn compare_outputs(args: &[&str]) { + let rustc_output = String::from_utf8(rustc().args(args).command_output().stdout).unwrap(); + let rustdoc_output = String::from_utf8(rustdoc().args(args).command_output().stdout).unwrap(); + + Diff::new().expected_text("rustc", rustc_output).actual_text("rustdoc", rustdoc_output).run(); +} + +fn main() { + compare_outputs(&["-C", "help"]); + compare_outputs(&["-Z", "help"]); + compare_outputs(&["-C", "passes=list"]); +} diff --git a/tests/rustdoc-ui/issues/issue-91713.stdout b/tests/rustdoc-ui/issues/issue-91713.stdout index bbea7e5c212ef..cc3c8385d9a8e 100644 --- a/tests/rustdoc-ui/issues/issue-91713.stdout +++ b/tests/rustdoc-ui/issues/issue-91713.stdout @@ -1,6 +1,7 @@ Available passes for running rustdoc: check-custom-code-classes - check for custom code classes without the feature-gate enabled check_doc_test_visibility - run various visibility-related lints on doctests +strip-aliased-non-local - strips all non-local private aliased items from the output strip-hidden - strips all `#[doc(hidden)]` items from the output strip-private - strips all private items from a crate which cannot be seen externally, implies strip-priv-imports strip-priv-imports - strips all private import statements (`use`, `extern crate`) from a crate @@ -14,6 +15,7 @@ Default passes for rustdoc: check-custom-code-classes collect-trait-impls check_doc_test_visibility +strip-aliased-non-local strip-hidden (when not --document-hidden-items) strip-private (when not --document-private-items) strip-priv-imports (when --document-private-items) diff --git a/tests/rustdoc/private-non-local-fields-2.rs b/tests/rustdoc/private-non-local-fields-2.rs new file mode 100644 index 0000000000000..615b957f697e8 --- /dev/null +++ b/tests/rustdoc/private-non-local-fields-2.rs @@ -0,0 +1,11 @@ +//! This test makes sure that with never show the inner fields in the +//! aliased type view of type alias. + +//@ compile-flags: -Z unstable-options --document-private-items + +#![crate_name = "foo"] + +use std::collections::BTreeMap; + +// @has 'foo/type.FooBar.html' '//*[@class="rust item-decl"]/code' 'struct FooBar { /* private fields */ }' +pub type FooBar = BTreeMap; diff --git a/tests/rustdoc/private-non-local-fields.rs b/tests/rustdoc/private-non-local-fields.rs new file mode 100644 index 0000000000000..7922ce074dd1b --- /dev/null +++ b/tests/rustdoc/private-non-local-fields.rs @@ -0,0 +1,9 @@ +//! This test makes sure that with never show the inner fields in the +//! aliased type view of type alias. + +#![crate_name = "foo"] + +use std::collections::BTreeMap; + +// @has 'foo/type.FooBar.html' '//*[@class="rust item-decl"]/code' 'struct FooBar { /* private fields */ }' +pub type FooBar = BTreeMap; diff --git a/tests/ui/type-alias-impl-trait/static-lifetime-through-closure-issue-122775.rs b/tests/ui/type-alias-impl-trait/static-lifetime-through-closure-issue-122775.rs new file mode 100644 index 0000000000000..1bb0acf9b754e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/static-lifetime-through-closure-issue-122775.rs @@ -0,0 +1,17 @@ +//@ check-pass + +#![feature(type_alias_impl_trait)] + +fn spawn(future: F) -> impl Sized +where + F: FnOnce() -> T, +{ + future +} + +fn spawn_task(sender: &'static ()) -> impl Sized { + type Tait = impl Sized + 'static; + spawn::(move || sender) +} + +fn main() {}